Similar to how compiler/linker/assembler/archiver names and flags are part of the redo build system proper, so too are platform dependencies.
The simplest form of platform dependency is something like a program module that only should be part of the program on certain platforms.
This is just a question of a case statement in a (shell script) .do program using the output of uname.
For example:
# In mylib.a.do:
case "`uname`" in
(Linux) platform_objects='object/kqueue_linux.o';;
(*) platform_objects='';;
esac
redo-ifchange ./archive ${objects} ${platform_objects}
./archive "$3" ${objects} ${platform_objects}
A similar test can be used to choose one of several source code file implementations to use for something according to platform, by treating the source code file as a redo target file, that is "built" by copying or linking one of a selection of source files into place. For example:
# In myheader.h.do:
case "`uname`" in
(Linux) ext="linux" ;;
(NetBSD) ext="netbsd" ;;
(*BSD) ext="bsd" ;;
(*) ext="unknown" ;;
esac
redo-ifchange "$1.${ext}"
ln -s -f "`basename \"$1\"`.${ext}" "$3"
Commonly, platform dependencies involve conditional compilation across multiple source code files, controlled by a macro. The redo way of doing this is an adaptation of one of Bernstein's pre-redo mechanisms:
The platform feature is designated by a macro, such as (for example) HAS_READ_TSC.
This is not set via compiler flags but by the inclusion of a header named "has_read_tsc.h", which is included in the source code files that need to be conditionally compiled according to the macro.
// In some_module.cpp: #include "has_read_tsc.h" … #if defined(HAS_READ_TSC) … #else … #endif
This header is not a redo source file, but is a redo target file, generated by a has_read_tsc.h.do program, which is along the lines of:
# In has_read_tsc.h.do: redo-ifchange try_read_tsc.c compile link if ./compile object/try_read_tsc.o try_read_tsc.c object/try_read_tsc.d && ./link command/try_read_tsc object/try_read_tsc.o then echo '#define HAS_READ_TSC 1' > "$3" else echo '/* sysdep: -read_tsc */' > "$3" fi
The try_read_tsc.c program is a test program that only successfully compiles and links (and, perhaps, if necessary for the test, runs and exits success) if the feature is available on the platform:
# In has_read_tsc.h.do:
int main(void)
{
…
asm volatile("rdtsc" : "=a"(x[0]),"=d"(x[1]) );
asm volatile("rdtsc" : "=a"(y[0]),"=d"(y[1]) );
…
}
The final part of the mechanism is ensuring that has_read_tsc.h is actually built before any program that tries to #include it is compiled.
This is done by simply declaring a dependency at the start of the top‐level .do program:
# In all.do: redo-ifchange has_read_tsc.h