Help with use of criterion unit tests in C

Hello, I have to use criterion for unit test.
I have this in my Makefile

CC = gcc
CFLAGS = -Wall -Wextra -Werror -std=gnu17 -g -I./include
OBJ = my_alloc.o

all: ${OBJ}

test ${OBJ}: test.o
	${CC} -L./lib -lcriterion -o test test.o my_alloc.o
	./test

clean:
	$(RM) *.o .*.swp .*.swo

distclean: clean
	$(RM) test

.PHONY: all clean distclean test

in my usual linux I use this command inside include/ to symlink include with criterion

include$ ln -s /usr/local/include/criterion
include$ ll 
total 16
drwxr-xr-x 2 lol users 4096 May  3 13:15 ./
drwxr-xr-x 4 lol users 4096 May  3 15:30 ../
lrwxrwxrwx 1 lol lol     28 May  3 12:18 criterion -> /usr/local/include/criterion
-rw-r--r-- 1 lol users   98 Apr 29 14:57 my_alloc.h
-rw-r--r-- 1 lol users  291 May  3 13:15 my_alloc.private.h

and now on Nixos I got this error with criterion installed:

sgcc -L./lib -lcriterion -o test test.o my_alloc.o
/nix/store/vj57s3h2za2qrfccrvc9b6i7s8mw3ndn-binutils-2.41/bin/ld: cannot find crt1.o: No such file or directory
/nix/store/vj57s3h2za2qrfccrvc9b6i7s8mw3ndn-binutils-2.41/bin/ld: cannot find crti.o: No such file or directory
/nix/store/vj57s3h2za2qrfccrvc9b6i7s8mw3ndn-binutils-2.41/bin/ld: cannot find -lcriterion: No such file or directory
/nix/store/vj57s3h2za2qrfccrvc9b6i7s8mw3ndn-binutils-2.41/bin/ld: cannot find my_alloc.o: No such file or directory
/nix/store/vj57s3h2za2qrfccrvc9b6i7s8mw3ndn-binutils-2.41/bin/ld: cannot find -lgcc_s: No such file or directory
collect2: error: ld returned 1 exit status
make: *** [Makefile:8: test] Error 1

how I can translate it in Nixos?

thank you in advance!

Nix’s approach is quite different from other OSs. I think a small example might illustrate the first steps to take. (Or at least give you something to work with, or maybe some more specific things to ask questions about).

With a simple test using criterion in test.c:

#include <string.h>
#include <criterion/criterion.h>

Test(sample, test) {
    cr_expect(strlen("Test") == 4, "Expected \"Test\" to have a length of 4.");
    cr_expect(strlen("Hello") == 4, "This will always fail, why did I add this?");
    cr_assert(strlen("") == 0);
}

and a simple Makefile (some discussion below):

CFLAGS=-g -Wall -Wextra `pkg-config --cflags criterion`
LDFLAGS=`pkg-config --libs criterion`

test:
	gcc ${CFLAGS} -o test test.c ${LDFLAGS}
	./test

The nix-specific part can be done with a shell.nix:

{ pkgs ? import <nixpkgs> {} }:

pkgs.mkShell {
  buildInputs = [ pkgs.pkg-config pkgs.criterion ];
}

Here, we’re using the criterion provided by nixpkgs. (If you need a specific version, there are ways of achieving that). The shell.nix file declares what dependencies we need for the project.

The compiler needs to know where to find the headers, where to look for the libraries, and what libraries to link against. The pkg-config commands in the Makefile provide that information.

With those files in the same directory, you should be able to enter the nix-shell with nix-shell, then run make test.

2 Likes

hello, thank you for taking the time to answer!

nix-shell is something that I would like to understand better. for example if I have several projects on different languages, how to create separate nix shells for each project?

The shell.nix is pretty much intended to provide a shell with the tools/dependencies for some project. Kinda like the VSCode devcontainers, but without using containers. So, ideally, you have a shell.nix in each project. (With direnv, it can even load the shell automatically).

The contents of the shell.nix might vary a bit by language.

Some links for further reading:

This tutorial from nix.dev:
https://nix.dev/tutorials/first-steps/declarative-shell

Searching whatever language you’re interested in on the NixOS wiki:
https://wiki.nixos.org/wiki/NixOS_Wiki

1 Like