Experimental new redoconf C/C++ build/autoconfiguration system.

To test it out, try this:
	./do -j10 build
	cd docs/cookbook/c
	redo -j10 test

It should detect all the compilers on your system and make three
separate builds for each one: normal, debug, and optimized.  Then it
tries to run a test program under each one.

If there are windows cross compilers and you also have 'wine'
installed, it'll try running the test program under wine as well.

redoconf currently has no documentation other than the example program.
We'll fix that later.
This commit is contained in:
Avery Pennarun 2019-02-03 01:14:51 -05:00
commit 6dae51f4d2
67 changed files with 1777 additions and 1 deletions

6
docs/cookbook/c/.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
hello
/when.c
/allconfig
/arches
/out
/out.*

1
docs/cookbook/c/all.do Normal file
View file

@ -0,0 +1 @@
redo-ifchange all.each

4
docs/cookbook/c/all.h Normal file
View file

@ -0,0 +1,4 @@
#include "main.h"
#include "libhello/hello.h"
#include "monotime.h"
#include <stdio.h>

4
docs/cookbook/c/all.hpp Normal file
View file

@ -0,0 +1,4 @@
#include <algorithm>
#include <string>
#include <list>
#include <map>

1
docs/cookbook/c/all.od Normal file
View file

@ -0,0 +1 @@
redo-ifchange "hello world"

23
docs/cookbook/c/all.rc.od Normal file
View file

@ -0,0 +1,23 @@
. ./redoconf.rc
rc_include \
rc/CC.rc \
rc/CXX.rc \
rc/libqt4.rc \
rc/libgtk2.rc \
rc/Wextra.rc \
rc/Wall.rc \
rc/libm.rc \
rc/rt.autolib.rc \
rc/libpng.rc \
rc/clock_gettime.func.rc \
rc/mach_time.h.rc \
rc/windows.h.rc \
rc/posix.rc \
rc/printf_lld.rc \
rc/extra.rc \
rc/all.h.precompiled.rc \
rc/all.hpp.precompiled.rc
rc_appendln LIBS "$LIBRT"
rc_appendln LIBS "$LIBM"
rc_save

View file

@ -0,0 +1,27 @@
redo-ifchange arches configure redoconf/utils.sh
config() {
local dir="$1" arch="$2"
shift
shift
[ -d "$dir" ] || mkdir "$dir"
(
cd "$dir" &&
../configure --host="$arch" "$@" &&
redo-ifchange rc/CC.rc &&
echo "$dir"
) || :
}
for d in $(cat arches); do
if [ "$d" = "native" ]; then
arch=""
else
arch="$d"
fi
config "out.$d" "$arch" &
config "out.$d.static" "$arch" "--enable-static" &
config "out.$d.opt" "$arch" "--enable-optimization" &
done
wait

14
docs/cookbook/c/arches.do Normal file
View file

@ -0,0 +1,14 @@
IFS=:
echo native >$3
if [ -z "$NO_SLOW_TESTS" ]; then
for dir in $PATH; do
for d in "$dir"/*-cc "$dir"/*-gcc; do
base=${d##*/}
arch=${base%-*}
if [ -x "$d" ]; then echo "$arch"; fi
done
done >>$3
fi
redo-always
redo-stamp <$3

6
docs/cookbook/c/clean.od Normal file
View file

@ -0,0 +1,6 @@
# runs from the output directory
rm -f *~ .*~ *.rc *.log *.gch *.stamp \
*.[oa] *.deps \
*.so *.so.* *.ver \
*.exe *.list \
hello

3
docs/cookbook/c/configure vendored Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
S="$(dirname "$0")"
. "$S/redoconf/configure.sh"

View file

@ -0,0 +1,17 @@
# Automatically generated by redoconf/_all.rc.od - do not edit
ARCH Architecture prefix for output (eg. i686-w64-mingw32-)
CC C compiler name (cc)
CPPFLAGS Extra C preprocessor flags (eg. -I... -D...)
CFLAGS Extra C compiler flags (eg. -O2 -g)
OPTFLAGS C/C++ compiler flag overrides (eg. -g0)
LINK Linker name (cc)
LDFLAGS Extra linker options (eg. -s -static)
LIBS Extra libraries to always link against (eg. -lsocket)
STATIC Link libraries and binaries statically
CXX C++ compiler name (c++)
CXXFLAGS Extra C++ compiler flags (eg. -O2 -g)
LIBQT4 Extra linker options for 'QtCore'
LIBGTK2 Extra linker options for 'gtk+-2.0 gio-2.0 gdk-2.0 gdk-pixbuf-2.0'
LIBM Extra linker options for 'libm'
LIBPNG Extra linker options for 'libpng'
PREFIX Change installation prefix (usually /usr/local)

View file

@ -0,0 +1,10 @@
# redo $2 in each of the registered output dirs.
# This way you can run commands or depend on targets like:
# redo clean.each.do
# redo all.each.do
# etc.
redo-ifchange allconfig
for dir in $(cat allconfig); do
echo "$dir/$2"
done | xargs redo-ifchange

View file

@ -0,0 +1,10 @@
#include "main.h"
#include <stdio.h>
#ifdef EXTRA_RC_INCLUDED
#error "rc/extra.rc should not be included when compiling flagtest.c"
#endif
void flag_test(void) {
printf("flagtest included\n");
}

View file

@ -0,0 +1,9 @@
# Demonstrate how to compile .o files using nonstandard
# compiler flags. You could also do this for a whole
# directory using default.o.od.
. ./redoconf.rc
rc_include all.rc
src="$S/${1%.o}.c"
redo-ifchange "_compile" "$src"
CC="$CC" CPPFLAGS="-DFLAGTEST_SET=42" ./_compile "$3" "$1.deps" "$src"

View file

@ -0,0 +1,30 @@
# This script is run from the output dir,
# which contains a src/ symlink to the source dir.
. ./redoconf.rc
rc_include all.rc
(
cd "$S"
echo "main.c"
echo "monotime.c"
echo "when.c" # auto-generated source
echo "flagtest.c" # source with different compiler flags
if [ -n "$CXX" ]; then
echo "slow.cc"
fi
# This is unnecessarily fancy.
# We're just using it as an example of
# how to dynamically generate a .list
# file.
for d in lib*/*.list lib*/*.list.od; do
[ -e "$d" ] && echo "${d%%.*}.so"
done | uniq
printf '%s\n' "$LIBGTK2" "$LIBQT4"
) >$3
redo-always
redo-stamp <$3

View file

@ -0,0 +1,6 @@
#include "hello.h"
#include <stdio.h>
void hello(void) {
printf("Hello, world!\n");
}

View file

@ -0,0 +1,6 @@
#ifndef __HELLO_H
#define __HELLO_H
void hello(void);
#endif /* __HELLO_H */

View file

@ -0,0 +1 @@
hello.c

View file

@ -0,0 +1 @@
1.2.5

22
docs/cookbook/c/main.c Normal file
View file

@ -0,0 +1,22 @@
#include "main.h"
#include "libhello/hello.h"
#include "monotime.h"
#include "redoconf.h"
#include <stdio.h>
#if EXTRA_RC_INCLUDED != 1
#error "EXTRA_RC was not included!"
#endif
int main() {
hello();
printf("Timestamp: %s\n", stamp_time());
printf("Monotime: %lld\n", monotime());
#ifdef CXX
printf("Length of 'hello world': %d\n", cpp_test());
#else
printf("No C++ compiler found.\n");
#endif
flag_test();
return 0;
}

19
docs/cookbook/c/main.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
#define CDEF extern "C"
#else
#define CDEF
#endif
/* when.c */
CDEF const char *stamp_time(void);
/* slow.cc */
CDEF int cpp_test(void);
/* flagtest.c */
CDEF void flag_test(void);
#endif /* __MAIN_H */

View file

@ -0,0 +1,58 @@
#define __GNU_SOURCE
/*
* Returns the kernel monotonic timestamp in microseconds.
* This function never returns the value 0; it returns 1 instead, so that
* 0 can be used as a magic value.
*/
#include "monotime.h"
#include "redoconf.h"
#if HAVE_CLOCK_GETTIME
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
long long monotime(void) {
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
perror("clock_gettime");
exit(98); /* really should never happen, so don't try to recover */
}
long long result = ts.tv_sec * 1000000LL + ts.tv_nsec / 1000;
return !result ? 1 : result;
}
#elif HAVE_MACH_TIME_H
#include <mach/mach.h>
#include <mach/mach_time.h>
long long monotime(void) {
static mach_timebase_info_data_t timebase;
if (!timebase.denom) mach_timebase_info(&timebase);
long long result = (mach_absolute_time() * timebase.numer /
timebase.denom / 1000);
return !result ? 1 : result;
}
#elif HAVE_WINDOWS_H
#include <windows.h>
/* WARNING: Not carefully tested. It might wrap around unexpectedly.
* Based on suggestions from:
* https://stackoverflow.com/questions/211257/windows-monotonic-clock
*/
long long monotime(void) {
LARGE_INTEGER tps, t;
QueryPerformanceFrequency(&tps);
QueryPerformanceCounter(&t);
return t.QuadPart * 1000000LL / tps.QuadPart;
}
#else
#error "No monotonic time function is available"
#endif

View file

@ -0,0 +1,6 @@
#ifndef __MONOTIME_H
#define __MONOTIME_H
long long monotime(void);
#endif /* __MONOTIME_H */

View file

@ -0,0 +1,5 @@
. ./redoconf.rc
rc_include
rc_appendln CPPFLAGS "-DEXTRA_RC_INCLUDED=1"
rc_save

View file

@ -0,0 +1,16 @@
. ./redoconf.rc
rc_include rc/CC.rc
prog='
#include <time.h>
struct timespec x;
'
x=
if ! rc_compile cc link "$prog"; then
x="-D_XOPEN_SOURCE=500"
rc_appendln CPPFLAGS "$x"
rc_compile cc link "$prog"
fi
rc_save

View file

@ -0,0 +1,16 @@
. ./redoconf.rc
rc_include rc/CC.rc rc/windows.h.rc rc/Wall.rc
appendln CPPFLAGS "-Werror" # abort if any warnings
prog='
#include <stdio.h>
void test() { printf("%lld", (long long)1); }
'
x=
if ! rc_compile cc link "$prog"; then
x="-D__USE_MINGW_ANSI_STDIO=1"
rc_appendln CPPFLAGS "$x"
rc_compile cc link "$prog"
fi
rc_save

1
docs/cookbook/c/redoconf Symbolic link
View file

@ -0,0 +1 @@
../../../redoconf

10
docs/cookbook/c/slow.cc Normal file
View file

@ -0,0 +1,10 @@
#include <algorithm>
#include <string>
#include <list>
#include <map>
#include "main.h"
int cpp_test() {
std::string a = "hello ", b = "world";
return a.length() + b.length();
}

1
docs/cookbook/c/test.do Normal file
View file

@ -0,0 +1 @@
redo-ifchange test.each

16
docs/cookbook/c/test.od Normal file
View file

@ -0,0 +1,16 @@
exec >&2
redo-always
redo-ifchange all run
if [ -x ./run ]; then
echo "Running: ./run ./hello\\ world"
./run './hello world' >"$1.out" 2>&1
cat "$1.out"
if grep -F -q 'Hello, world!' "$1.out"; then
echo "-- Test successful."
else
echo "-- Test failed."
exit 1
fi
else
echo "Non-native platform: test skipped."
fi

View file

@ -0,0 +1,7 @@
cat >$3 <<-EOF
const char *stamp_time(void) {
return "$(date +%Y-%m-%d)";
}
EOF
redo-always
redo-stamp <$3