Skip to content

Prima​Materia's

Experiment Sudoku - init

A personal experiment to solve a Sudoku in C language. In this first part I am setting up my development environment.

§ Introduction

During the vacation, I found a small Sudoku book that my father enjoys solving. Since there was no pen nearby, I simply kept looking at it. I wondered if I could write an algorithm to solve it. To make it more interesting, could I write it in C? Besides some tutorials I did as a teenager and some light Arduino programming, I am not experienced in C.

§ Basics

In web development, I am used to following the holy trinity: formatter, linter, and language server. Let's see what I can find to fill these roles in the world of C.

  • Language server - I found either ccls or clangd. They seem to be similar, but I chose ccls because it was mentioned in a GitHub thread to have some additional C++ support (which I will probably never find myself using anyway).
  • Linter - clangtidy
  • Formatter - clang-format

clangtidy and clang-format come from the same nix package clang-tools.

In order for ccls to function properly, it needs compile-commands.json, which is generated by cmake. cmake is similar to npm install, and CMakeLists.txt is similar to package.json.

§ C Neovim edition

I have initialized new C Neovim edition. Added ccls, clang and clang-tools dependencies, and extended treesitter with C grammar.

local nvim_lsp = require("lspconfig")
local blink = require("blink.cmp")

local capabilities = {}
capabilities = vim.tbl_extend("keep", capabilities, blink.get_lsp_capabilities())

nvim_lsp["ccls"].setup({
    capabilities = capabilities,
    init_options = {
        compilationDatabaseDirectory = "build",
        index = {
            threads = 0,
        },
        clang = {
            excludeArgs = { "-frounding-math" },
        },
    },
})

For the LSP setup, I used the example provided by lspconfig. I believe that the compilationDatabaseDirectory is crucial for ccls to access the compile-commands.json file in the /build directory.

local conform = require("conform")
conform.formatters_by_ft.c = { "clang-format" }

local lint = require("lint")
lint.linters_by_ft.c = { "clangtidy" }

During the setup of the linter and formatter, I realized that I forgot to extract prettier and eslintd to the Web Neovim edition. I have also tested that the above configuration does not discard the configuration from the Base edition - the flake.nix is still being formatted.

§ Dev toolkit nix

I added a new "c" profile to the dev-toolkit-nix that simply adds dependencies clang, clang-tools, and cmake. I also decided to create a dev-toolint-nix flake template. Is it possible to use it with:

nix flake init github:PrimaMateria/dev-toolkit-nix#default

§ Project init

Github repository

.
├── build
├── CMakeLists.txt
├── flake.lock
├── flake.nix
├── README.md
└── src
    └── hello.c

Started with "Hello world".

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

cmake_minimum_required(VERSION 3.10)
project(HelloWorld LANGUAGES C VERSION 1.0)
add_executable(hello src/hello.c)

Simple CMakeLists.txt. The first line instructs to provide the necessary file for ccls to work.

mkdir build
cd build
cmake ..

This will generate the required items.

cd build
cmake .

This will compile the C file into an executable.

I ensured that linting and formatting are run automatically when saving. Autocompletion and documentation also function properly.

§ Conclusion

Taking a small step out of my comfort zone and testing the flexibility of my nix-backed development. Everything is holding up well so far. The next step will be to attempt to solve the Sudoku problem.

GitHub comments