2026/07/26: rbemake: functional build vs command runner

make, while being one of the most widely used build tools, has a very operational semantics: it looks at time stamps and, depending on which file is newer, runs commands. Those commands do whatever they do, creating whatever side effect on the file system.

Modern build tools understand a build as computing a function from sources to final artifacts, composed of individual steps ("actions") with well-defined inputs (including command line and environment) and outputs, assumed to behave like a mathematical function.

Therefore, an intersting way to compare these approaches to builds is to translate Makefiles into a functional build description. Of course, this requires some heuristics (and we need to allow the user to override the default heuristics), but with rbemake I have a prototype (using justbuild (packages) as underlying modern build tool) that works well enough to demonstrate the difference on simple examples.

Let's consider the following Makefile.


PREFIX ?= /usr
BINDIR = ${PREFIX}/bin

CC ?= cc

.SUFFIXES: .c .o

.c.o:
    ${CC} ${CFLAGS} -c -o $@ $<

all: programs/foo programs/bar

programs/%:
    mkdir -p programs
    ${CC} ${CFLAGS} -o $@ $^

programs/foo: foo.o common.o
programs/bar: bar.o common.o

SRCS = $(wildcard *.c)
${SRCS:.c=.o}: $(wildcard *.h)

install: all
    mkdir -p ${DESTDIR}${BINDIR}
    install programs/foo programs/bar ${DESTDIR}${BINDIR}

clean:
    rm -rf programs *.o

The difference between timestamps and the functional approach can be best demontrated by the role of CFLAGS. Consider a regular build of programs/foo followed by a debug build of programs/bar. As the timestamp of common.o is newer than source and header, it will not be rebuilt; so the debugging can be fun.
$ make programs/foo
cc  -c -o foo.o foo.c
cc  -c -o common.o common.c
mkdir -p programs
cc  -o programs/foo foo.o common.o
$ CFLAGS=-g make programs/bar
cc -g -c -o bar.o bar.c
mkdir -p programs
cc -g -o programs/bar bar.o common.o
$ 

The functional approach, however, notices the difference in the command line and also builds a debug version of common.o
$ rbemake -v programs/foo
Wrote targets file '/home/aehlig/.cache/rbemake/targets/deb9b4991c2a6beef38597d83d0936f4e12d686b_TARGETS'
DEBUG: Roots for "", total of 0:
INFO: Requested target is [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}]
INFO: Analysed target [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}]
DEBUG: Export targets found: 0 cached, 0 uncached, 0 not eligible for caching
INFO: Discovered 3 actions, 0 tree overlays, 0 trees, 0 blobs
INFO: Building [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}].
DEBUG (action:8e1dbdad0ec83f2b6cfe3f43a707d5241e29a281c0e636dc61c6c52c5b602ad0):
     ["sh","-c","cc  -c -o foo.o foo.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
DEBUG (action:2b1f944f1ea88dcea8d83469e273ec3c9fdce5c27bf8b98e380e3fa99a459c1a):
     ["sh","-c","cc  -c -o common.o common.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
DEBUG (action:c44165ead15daee77ed9565b7617c9e0da3e5854a9b0259d1b9171a7ed4a091f):
     ["sh","-c","set -e\nmkdir -p programs\ncc  -o programs/foo foo.o common.o"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
INFO: Processed 3 actions, 0 cache hits.
INFO: Artifacts built, logical paths are:
        programs/foo [65fb9c02920a2598c36f17ff08ce3d2c5943a13a:15960:x]
DEBUG: Finished backing up artifacts of export targets
$ CFLAGS=-g rbemake -v programs/bar
Wrote targets file '/home/aehlig/.cache/rbemake/targets/8c403264e58391af6f6a132af80256f1a764db65_TARGETS'
DEBUG: Roots for "", total of 0:
INFO: Requested target is [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}]
INFO: Analysed target [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}]
DEBUG: Export targets found: 0 cached, 0 uncached, 0 not eligible for caching
INFO: Discovered 3 actions, 0 tree overlays, 0 trees, 0 blobs
INFO: Building [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}].
DEBUG (action:5ef43fdd171d5104134d3c6e9eb833629150e5a621c13f9b83efaa4327d96cf5):
     ["sh","-c","cc -g -c -o bar.o bar.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
DEBUG (action:0f7d371ef94927d17f5b580cd12bb1867f50af9e012467759713f5e1a4c4f1ad):
     ["sh","-c","cc -g -c -o common.o common.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
DEBUG (action:acd3537559be16c93dca78071bbcde99058c938f93a46b6a5eac837aa50253f9):
     ["sh","-c","set -e\nmkdir -p programs\ncc -g -o programs/bar bar.o common.o"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
INFO: Processed 3 actions, 0 cache hits.
INFO: Artifacts built, logical paths are:
        programs/bar [e9e77e8b9b1a6b2dc68208ba07b28aba38d51f5f:18112:x]
DEBUG: Finished backing up artifacts of export targets
$ 

A similar form of stale build will happen when first properly debugging programs/bar, fixing an issue, and then installing everything. The fixed file gets recompiled for a regular build, but the common dependency remains in its state, still built for debug.
$ make clean # recover to get a proper debug build of programs/bar
rm -rf programs *.o
$ CFLAGS=-g make programs/bar
cc -g -c -o bar.o bar.c
cc -g -c -o common.o common.c
mkdir -p programs
cc -g -o programs/bar bar.o common.o
$ vi bar.c # fix bug
$ DESTDIR=/tmp/dest make install
cc  -c -o foo.o foo.c
mkdir -p programs
cc  -o programs/foo foo.o common.o
cc  -c -o bar.o bar.c
mkdir -p programs
cc  -o programs/bar bar.o common.o
mkdir -p /tmp/dest/usr/bin
install programs/foo programs/bar /tmp/dest/usr/bin
$ 

Again, the functional approach recognizes the difference in command line. Oh, and remember that earlier non-debug build step.
$ vi bar.c # fix bug
$ rbemake -v -o /tmp/dest install
Wrote targets file '/home/aehlig/.cache/rbemake/targets/9bac42fa189ff2772bc36e56a9c661ca527397c0_TARGETS'
DEBUG: Roots for "", total of 0:
INFO: Requested target is [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}]
INFO: Analysed target [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}]
DEBUG: Export targets found: 0 cached, 0 uncached, 0 not eligible for caching
INFO: Discovered 6 actions, 0 tree overlays, 0 trees, 0 blobs
INFO: Building [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}].
DEBUG (action:2b1f944f1ea88dcea8d83469e273ec3c9fdce5c27bf8b98e380e3fa99a459c1a):
     ["sh","-c","cc  -c -o common.o common.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"} (cached)
DEBUG (action:8e1dbdad0ec83f2b6cfe3f43a707d5241e29a281c0e636dc61c6c52c5b602ad0):
     ["sh","-c","cc  -c -o foo.o foo.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"} (cached)
DEBUG (action:c44165ead15daee77ed9565b7617c9e0da3e5854a9b0259d1b9171a7ed4a091f):
     ["sh","-c","set -e\nmkdir -p programs\ncc  -o programs/foo foo.o common.o"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"} (cached)
DEBUG (action:6286ea860ca97c5cbf5e8a6bcbf627860493f4bb93dddd926f2b71dd7e82bbdd):
     ["sh","-c","cc  -c -o bar.o bar.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
DEBUG (action:c355956b55fea9d8b6e7e9c89a33bca72f6762609ed0ef433da0154ee030e9bc):
     ["sh","-c","set -e\nmkdir -p programs\ncc  -o programs/bar bar.o common.o"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
DEBUG (action:57fc70f0f4f4fe69619e04c206c889ce75c5ae9ebbe34e8a6f869ef0cc4dbf69):
     ["sh","-c","export DESTDIR=\"`pwd`/destdir\"\n\ncd work\nset -e\nmkdir -p ${DESTDIR}/usr/bin\ninstall programs/foo programs/bar ${DESTDIR}/usr/bin"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
INFO: Processed 6 actions, 3 cache hits.
INFO: Artifacts can be found in:
        /tmp/dest/. [c66e522f85c2209856eecaadb6081f4417a74f11:30:t]
DEBUG: Finished backing up artifacts of export targets
$ 

In case you wonder, yes install is a regular, cachable, build step with a directory as output; and we may of may not request that directory to be installed to the file system (like we may request or not for the output of any other target).

But it is not only that make forgets to redo build steps. Being based on timestamps, it can also do too many. Let's consider a cleanly built state and we add a comment to common.c. As both programs transitively depend on that file, both a relinked.


$ make clean
rm -rf programs *.o
$ DESTDIR=/tmp/dest make install
cc  -c -o foo.o foo.c
cc  -c -o common.o common.c
mkdir -p programs
cc  -o programs/foo foo.o common.o
cc  -c -o bar.o bar.c
mkdir -p programs
cc  -o programs/bar bar.o common.o
mkdir -p /tmp/dest/usr/bin
install programs/foo programs/bar /tmp/dest/usr/bin
$ echo '/* comment! */' >> common.c
$ DESTDIR=/tmp/dest make install
cc  -c -o common.o common.c
mkdir -p programs
cc  -o programs/foo foo.o common.o
mkdir -p programs
cc  -o programs/bar bar.o common.o
mkdir -p /tmp/dest/usr/bin
install programs/foo programs/bar /tmp/dest/usr/bin
$ 

But in reality, they only depend on common.o and that will be the same after it was rebuilt. So the linking can be taken from cache.
$ echo '/* comment! */' >> common.c
$ rbemake -v install
Wrote targets file '/home/aehlig/.cache/rbemake/targets/9bac42fa189ff2772bc36e56a9c661ca527397c0_TARGETS'
DEBUG: Roots for "", total of 0:
INFO: Requested target is [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}]
INFO: Analysed target [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}]
DEBUG: Export targets found: 0 cached, 0 uncached, 0 not eligible for caching
INFO: Discovered 6 actions, 0 tree overlays, 0 trees, 0 blobs
INFO: Building [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}].
DEBUG (action:8e1dbdad0ec83f2b6cfe3f43a707d5241e29a281c0e636dc61c6c52c5b602ad0):
     ["sh","-c","cc  -c -o foo.o foo.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"} (cached)
DEBUG (action:6286ea860ca97c5cbf5e8a6bcbf627860493f4bb93dddd926f2b71dd7e82bbdd):
     ["sh","-c","cc  -c -o bar.o bar.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"} (cached)
DEBUG (action:2b1f944f1ea88dcea8d83469e273ec3c9fdce5c27bf8b98e380e3fa99a459c1a):
     ["sh","-c","cc  -c -o common.o common.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
DEBUG (action:c355956b55fea9d8b6e7e9c89a33bca72f6762609ed0ef433da0154ee030e9bc):
     ["sh","-c","set -e\nmkdir -p programs\ncc  -o programs/bar bar.o common.o"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"} (cached)
DEBUG (action:c44165ead15daee77ed9565b7617c9e0da3e5854a9b0259d1b9171a7ed4a091f):
     ["sh","-c","set -e\nmkdir -p programs\ncc  -o programs/foo foo.o common.o"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"} (cached)
DEBUG (action:57fc70f0f4f4fe69619e04c206c889ce75c5ae9ebbe34e8a6f869ef0cc4dbf69):
     ["sh","-c","export DESTDIR=\"`pwd`/destdir\"\n\ncd work\nset -e\nmkdir -p ${DESTDIR}/usr/bin\ninstall programs/foo programs/bar ${DESTDIR}/usr/bin"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"} (cached)
INFO: Processed 6 actions, 5 cache hits.
INFO: Artifacts built, logical paths are:
        . [c66e522f85c2209856eecaadb6081f4417a74f11:30:t]
DEBUG: Finished backing up artifacts of export targets
$ 

The functional approach is also good in discovering incorrect build descriptions. Say, we forgot the dependency declaration on the header files. make will happily run the commands and, as the header files are there, the build will succeed; however, changes of the header file will not trigger a rebuild. In the functional world, on the other hand, even with the very weak isolation of local builds, a build error will be discovered.


$ vi Makefile # pretend we forgot the dependency declaration of the header files
$ cat Makefile
PREFIX ?= /usr
BINDIR = ${PREFIX}/bin

CC ?= cc

.SUFFIXES: .c .o

.c.o:
        ${CC} ${CFLAGS} -c -o $@ $<

all: programs/foo programs/bar

programs/%:
        mkdir -p programs
        ${CC} ${CFLAGS} -o $@ $^

programs/foo: foo.o common.o
programs/bar: bar.o common.o

SRCS = $(wildcard *.c)
# ${SRCS:.c=.o}: $(wildcard *.h)

install: all
        mkdir -p ${DESTDIR}${BINDIR}
        install programs/foo programs/bar ${DESTDIR}${BINDIR}

clean:
        rm -rf programs *.o
$ rbemake -v
Wrote targets file '/home/aehlig/.cache/rbemake/targets/aee3ce08a2d3407e0be2cdbdc648723cbad9c249_TARGETS'
DEBUG: Roots for "", total of 0:
INFO: Requested target is [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}]
INFO: Analysed target [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}]
DEBUG: Export targets found: 0 cached, 0 uncached, 0 not eligible for caching
INFO: Discovered 5 actions, 0 tree overlays, 0 trees, 0 blobs
INFO: Building [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}].
ERROR (LocalExecution): expected known type at foo.o
ERROR (LocalExecution): could not collect output file or symlink foo.o
ERROR (LocalExecution): expected known type at bar.o
ERROR (LocalExecution): could not collect output file or symlink bar.o
INFO (action:e7cb03e431d4d00378ea98f9c79136f9fbae577f10aec1bc8afa85a821d1cd83):
     Stderr of command ["sh","-c","cc  -c -o foo.o foo.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
       foo.c:1:10: fatal error: 'common.h' file not found
           1 | #include "common.h"
             |          ^~~~~~~~~~
       1 error generated.
ERROR (action:e7cb03e431d4d00378ea98f9c79136f9fbae577f10aec1bc8afa85a821d1cd83): action returned non-zero exit code 1
ERROR (action:e7cb03e431d4d00378ea98f9c79136f9fbae577f10aec1bc8afa85a821d1cd83):
     Failed to execute command ["sh","-c","cc  -c -o foo.o foo.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
     requested by
      - [["@","","","foo.o"],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}]#0
INFO (action:0e0736d17193d6d17abbda5c4a26bb192f03f5fd679c87c81991c51714ee8a54):
     Stderr of command ["sh","-c","cc  -c -o bar.o bar.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
       bar.c:1:10: fatal error: 'common.h' file not found
           1 | #include "common.h"
             |          ^~~~~~~~~~
       1 error generated.
ERROR (action:0e0736d17193d6d17abbda5c4a26bb192f03f5fd679c87c81991c51714ee8a54): action returned non-zero exit code 1
ERROR (action:0e0736d17193d6d17abbda5c4a26bb192f03f5fd679c87c81991c51714ee8a54):
     Failed to execute command ["sh","-c","cc  -c -o bar.o bar.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
     requested by
      - [["@","","","bar.o"],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}]#0
ERROR (LocalExecution): expected known type at common.o
ERROR (LocalExecution): could not collect output file or symlink common.o
INFO (action:667cd307615a4d668f9c0b11e276aa4b1b6fa161f24c85b958788651dd52be70):
     Stderr of command ["sh","-c","cc  -c -o common.o common.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
       common.c:1:10: fatal error: 'common.h' file not found
           1 | #include "common.h"
             |          ^~~~~~~~~~
       1 error generated.
ERROR (action:667cd307615a4d668f9c0b11e276aa4b1b6fa161f24c85b958788651dd52be70): action returned non-zero exit code 1
ERROR (action:667cd307615a4d668f9c0b11e276aa4b1b6fa161f24c85b958788651dd52be70):
     Failed to execute command ["sh","-c","cc  -c -o common.o common.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin"}
     requested by
      - [["@","","","common.o"],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin"}}]#0
ERROR: Build failed.
$ 

Inputs can also go through worflow targets. Consider the following test example. Here, the file .done_data indicates that the generated header files (in the directory data) declaring data structures are up to date. In this case, the inputs to build actions are trees.


 
$ cat Makefile 

all: main

CC ?= cc

HEADERS = $(wildcard *.h)
SRCS = $(wildcard *.c)

%.o: %.c ${HEADERS} .done_data
        ${CC} ${CFLAGS} -I . -c -o $@ $<

.done_data: gen-hdrs.py data.json
        ./gen-hdrs.py data.json data
        touch $@

main: ${SRCS:.c=.o}
        ${CC} -lm -o $@ $^

clean:
        rm -rf data *.o main .done_*
$ rbemake -v
Wrote targets file '/home/aehlig/.cache/rbemake/targets/7dd27296783312950491b8e31e7fe7e8e80e94a9_TARGETS'
DEBUG: Roots for "", total of 0:
INFO: Requested target is [["@","","",""],{"MAKE_ENV":{"PATH":"/home/aehlig/.nix-profile/bin:/home/aehlig/Projects/ISILMAR/unlock/bin:/home/aehlig/bin:/run/wrappers/bin:/nix/profile/bin:/home/aehlig/.local/state/nix/profile/bin:/etc/profiles/per-user/aehlig/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin"}}]
INFO: Analysed target [["@","","",""],{"MAKE_ENV":{"PATH":*}}]
DEBUG: Export targets found: 0 cached, 0 uncached, 0 not eligible for caching
INFO: Discovered 5 actions, 3 tree overlays, 6 trees, 0 blobs
INFO: Building [["@","","",""],{"MAKE_ENV":{"PATH":*}}].
DEBUG (action:c84340ff7f6f659ff9e0c2ad2dc6b5d870680e877d99e291b385a5c174ca9a95):
     ["sh","-c","set -e\n./gen-hdrs.py data.json data\ntouch .done_data"] in environment {"PATH":"/home/aehlig/.nix-profile/bin:/home/aehlig/Projects/ISILMAR/unlock/bin:/home/aehlig/bin:/run/wrappers/bin:/nix/profile/bin:/home/aehlig/.local/state/nix/profile/bin:/etc/profiles/per-user/aehlig/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin"}
DEBUG (action:6e4a95f2b98b5473625f86337efb52b5b812c9b25844490d6aaad081de2de96e):
     Requested tree-overlay action is 6e4a95f2b98b5473625f86337efb52b5b812c9b25844490d6aaad081de2de96e
     Trees to overlay:
      - 0ef495ee038be22889b401bae76a9b7490b63146:34:t
      - 158a7e28e40287b3704521633483feeaa759355e:38:t
      - 22f5ccd65374636ce5ba07eee83f80b708931e19:43:t
      - 3a4cbc10eebffde33717b934eeb47416bc0defd5:145:t
DEBUG (action:b989404a9a8e099ce27887cabf0dd80dd4689cc983e7f11164cbd10624e8a049):
     Requested tree-overlay action is b989404a9a8e099ce27887cabf0dd80dd4689cc983e7f11164cbd10624e8a049
     Trees to overlay:
      - 1a1e51443969612cea07a8bbe7761f9af2efc2aa:43:t
      - 158a7e28e40287b3704521633483feeaa759355e:38:t
      - 22f5ccd65374636ce5ba07eee83f80b708931e19:43:t
      - 3a4cbc10eebffde33717b934eeb47416bc0defd5:145:t
DEBUG (action:cc6b891f85b4ce21543864e63bd7c2c39a05cfca4508e071569d40e9f3403351):
     Requested tree-overlay action is cc6b891f85b4ce21543864e63bd7c2c39a05cfca4508e071569d40e9f3403351
     Trees to overlay:
      - faefce200b19bcc9daff9b23a87e8ad7e864c643:38:t
      - 158a7e28e40287b3704521633483feeaa759355e:38:t
      - 22f5ccd65374636ce5ba07eee83f80b708931e19:43:t
      - 3a4cbc10eebffde33717b934eeb47416bc0defd5:145:t
DEBUG (action:2e5d10bfdd44505b4d9b6b5e5114f985abd435de5ee5c42fc97ecb7e617b2f8f):
     ["sh","-c","cc  -I . -c -o circumference.o circumference.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin:/home/aehlig/Projects/ISILMAR/unlock/bin:/home/aehlig/bin:/run/wrappers/bin:/nix/profile/bin:/home/aehlig/.local/state/nix/profile/bin:/etc/profiles/per-user/aehlig/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin"}
DEBUG (action:ddadda55d7b9dbaaf8f40db25ab151699c2c0f46217bb7afa496ff2203e57583):
     ["sh","-c","cc  -I . -c -o main.o main.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin:/home/aehlig/Projects/ISILMAR/unlock/bin:/home/aehlig/bin:/run/wrappers/bin:/nix/profile/bin:/home/aehlig/.local/state/nix/profile/bin:/etc/profiles/per-user/aehlig/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin"}
DEBUG (action:24601fda0db4d288990168aa75bda520d7bf6cb89e0143a029c3c792dfd35afd):
     ["sh","-c","cc  -I . -c -o distance.o distance.c"] in environment {"PATH":"/home/aehlig/.nix-profile/bin:/home/aehlig/Projects/ISILMAR/unlock/bin:/home/aehlig/bin:/run/wrappers/bin:/nix/profile/bin:/home/aehlig/.local/state/nix/profile/bin:/etc/profiles/per-user/aehlig/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin"}
DEBUG (action:e3a3f319eaca1eb2d38ad1e7cf58857cc8e2b977f430f29984d9ca6dfe0e5293):
     ["sh","-c","cc -lm -o main main.o distance.o circumference.o"] in environment {"PATH":"/home/aehlig/.nix-profile/bin:/home/aehlig/Projects/ISILMAR/unlock/bin:/home/aehlig/bin:/run/wrappers/bin:/nix/profile/bin:/home/aehlig/.local/state/nix/profile/bin:/etc/profiles/per-user/aehlig/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin"}
INFO: Processed 5 actions, 0 cache hits.
INFO: Artifacts built, logical paths are:
        main [9f124f43ef5c54d8144dcde5cbe64f4789522c6a:16136:x]
DEBUG: Finished backing up artifacts of export targets
$ rbemake --install-cas 3a4cbc10eebffde33717b934eeb47416bc0defd5:145:t
{
  ".done_data": "[e69de29bb2d1d6434b8b29ae775ad8c2e48c5391::f]",
  "data": "[7593d86f190908c11ba4a7d355dea28935e16176::t]",
  "data.json": "[59873f2882fdd7c74ad753ae6631fc87c6476160::f]",
  "gen-hdrs.py": "[1c7bddaec94d4fc372c67a581288ff236cac1366::x]"
}
$ rbemake --install-cas 3a4cbc10eebffde33717b934eeb47416bc0defd5:145:t -P data
{
  "point.h": "[f8184114da6c541240bdb5494330c4eaa20651db::f]",
  "triangle.h": "[e8d01fd0ea81cd8688a74d027f242e24d32fe2b9::f]"
}
$