💾 Archived View for ew.srht.site › en › 2022 › 20221219-redo-3.gmi captured on 2024-03-21 at 15:12:03. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-01-29)

➡️ Next capture (2024-06-16)

-=-=-=-=-=-=-

2022-12-19

Tools: redo (part 3) CFLAGS and friends, config.sh, compile.do

tags: software

Content

Part 0: Intro

Part 1: Hello, world!

Part 2: Automatic Recording of Dependencies on Header Files

Part 3: CFLAGS and friends, config.sh, compile.do

Part 4: CFLAGS and friends, env/VAR, default.run.do

Part 5: Auto-update BUILDDATE in version.h

Part 6: The yacc/bison problem: one call produces two artifacts

Part 7: Test: Generator for N source files

My code featured in this series can be found at

https://git.sr.ht/~ew/ew.redo/

Part 3: How about CFLAGS and friends? config.sh and compile.do

Of course I was wondering, how to deal with our old friends like CFLAGS and their kin. Looking into the documentation and projects using redo, I came up with two possible solutions --- there are more, of course.

config.sh

Our friends the make variables convert to shell variables and are living in a shell script named config.sh

# config.sh --- define/set used variables
CC="gcc"
CFLAGS="-O2 -g -Wpedantic -Wall"

This file is being sourced (evaluated) in order to make their values known before calling gcc. So we change default.o.do accordingly:

# default.o.do
redo-ifchange config.sh $2.c
source ./config.sh
${CC} ${CFLAGS} -MMD -MF $2.d  -o $3 -c $2.c
read DEPS <$2.d
redo-ifchange ${DEPS#*:}

Calling redo in verbose mode will show, that config.sh is indeed sourced.

shell$ redo clean ; redo -xx all
redo clean (0.002s)
+ redo-ifchange hello
+ OBJS='hello.o resources.o'
+ redo-ifchange hello.o resources.o
+ redo-ifchange config.sh hello.c
+ redo-ifchange config.sh resources.c
+ source ./config.sh
++ CC=gcc
++ CFLAGS='-O3 -g -Wpedantic -Wall'
+ gcc -O3 -g -Wpedantic -Wall -MMD -MF hello.d -o .redo.hello.o.2613144615.3 -c hello.c
+ read DEPS
+ redo-ifchange hello.c resources.h
+ source ./config.sh
++ CC=gcc
++ CFLAGS='-O3 -g -Wpedantic -Wall'
+ gcc -O3 -g -Wpedantic -Wall -MMD -MF resources.d -o .redo.resources.o.1407379196.3 -c resources.c
+ read DEPS
+ redo-ifchange resources.c
redo . . hello.o (default.o.do) (0.045s)
redo . . resources.o (default.o.do) (0.049s)
+ gcc -o .redo.hello.309219992.3 hello.o resources.o
redo . hello (0.084s)
redo all (0.097s)

shell$ grep CFLAGS config.sh
CFLAGS="-O3 -g -Wpedantic -Wall"
shell$ # edit config.sh
shell$ grep CFLAGS config.sh
CFLAGS="-O2 -g -Wpedantic -Wall"
shell$ redo -xx all
+ redo-ifchange hello
+ OBJS='hello.o resources.o'
+ redo-ifchange hello.o resources.o
+ redo-ifchange config.sh hello.c
+ redo-ifchange config.sh resources.c
+ source ./config.sh
++ CC=gcc
++ CFLAGS='-O2 -g -Wpedantic -Wall'
+ gcc -O2 -g -Wpedantic -Wall -MMD -MF hello.d -o .redo.hello.o.2777614334.3 -c hello.c
+ read DEPS
+ redo-ifchange hello.c resources.h
+ source ./config.sh
++ CC=gcc
++ CFLAGS='-O2 -g -Wpedantic -Wall'
+ gcc -O2 -g -Wpedantic -Wall -MMD -MF resources.d -o .redo.resources.o.3139069011.3 -c resources.c
+ read DEPS
+ redo-ifchange resources.c
redo . . hello.o (default.o.do) (0.048s)
redo . . resources.o (default.o.do) (0.053s)
+ gcc -o .redo.hello.2275538568.3 hello.o resources.o
redo . hello (0.087s)
redo all (0.099s)
shell$ redo -xx all
+ redo-ifchange hello
redo all (0.004s)
shell$

config.sh and compile.do

While this works, it is fairly obvious that "source config.sh" is being run every single time, the commands in default.o.do are executed. And it might not work with every shell or environment, even if source is replaced by a dot '.'.

In order to avoid, that CFLAGS and friends are evaluated more often than absolutely needed, one can produce a compile script from a template. There are variables in the template, and they are expanded to create the script only once per build. The script itself does not have variables any more. So this is the plan:

# compile.do
redo-ifchange config.sh
. ./config.sh
touch $3 && chmod ug+x $3 && \
cat <<EOF > $3
${CC} ${CFLAGS} -c -MMD -MF \$2.d  -o \$3 \$2.c
read DEPS < \$2.d
redo-ifchange \${DEPS#*:}
EOF

This is a short, but not a particularly nice script. You must watch the quoting at all times. The output of this script is captured as compile.

shell$ redo -xx compile
+ redo-ifchange config.sh
+ . ./config.sh
++ CC=gcc
++ CFLAGS='-O2 -g -Wpedantic -Wall'
+ touch .redo.compile.3766532193.3
+ chmod ug+x .redo.compile.3766532193.3
+ cat
redo compile (0.012s)
shell$ cat compile
gcc -O2 -g -Wpedantic -Wall -c -MMD -MF $2.d  -o $3 $2.c
read DEPS < $2.d
redo-ifchange ${DEPS#*:}

So one more change is needed, call the freshly generated script in default.o.do:

# default.o.do -*-shell-script-*-
# - all magic commands are hidden in generated script ./compile via ./compile.do
redo-ifchange compile $2.c
./compile $1 $2 $3

Calling redo to build everything from scratch works as expected:

shell$ redo clean; redo -xx all
redo clean (0.002s)
+ redo-ifchange hello
+ OBJS='hello.o resources.o'
+ redo-ifchange hello.o resources.o
+ redo-ifchange compile hello.c
+ redo-ifchange compile resources.c
+ redo-ifchange config.sh
+ . ./config.sh
++ CC=gcc
++ CFLAGS='-O2 -g -Wpedantic -Wall'
+ touch .redo.compile.1615745472.3
+ chmod ug+x .redo.compile.1615745472.3
+ cat
redo . . . compile (0.007s)
+ ./compile hello.o hello .redo.hello.o.2194970874.3
+ ./compile resources.o resources .redo.resources.o.3986075340.3
redo . . hello.o (default.o.do) (0.062s)
redo . . resources.o (default.o.do) (0.067s)
+ gcc -o .redo.hello.2517927474.3 hello.o resources.o
redo . hello (0.103s)
redo all (0.115s)
shell$ ./hello
Hello, world!

Home