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:
parent
5db883ac58
commit
6dae51f4d2
67 changed files with 1777 additions and 1 deletions
|
|
@ -1,4 +1,4 @@
|
|||
export NO_SLOW_TESTS=1
|
||||
for d in */all.do; do
|
||||
for d in */all.do */test.do; do
|
||||
echo "${d%.do}"
|
||||
done | xargs redo-ifchange
|
||||
|
|
|
|||
6
docs/cookbook/c/.gitignore
vendored
Normal file
6
docs/cookbook/c/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
hello
|
||||
/when.c
|
||||
/allconfig
|
||||
/arches
|
||||
/out
|
||||
/out.*
|
||||
1
docs/cookbook/c/all.do
Normal file
1
docs/cookbook/c/all.do
Normal file
|
|
@ -0,0 +1 @@
|
|||
redo-ifchange all.each
|
||||
4
docs/cookbook/c/all.h
Normal file
4
docs/cookbook/c/all.h
Normal 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
4
docs/cookbook/c/all.hpp
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
1
docs/cookbook/c/all.od
Normal file
1
docs/cookbook/c/all.od
Normal file
|
|
@ -0,0 +1 @@
|
|||
redo-ifchange "hello world"
|
||||
23
docs/cookbook/c/all.rc.od
Normal file
23
docs/cookbook/c/all.rc.od
Normal 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
|
||||
27
docs/cookbook/c/allconfig.do
Normal file
27
docs/cookbook/c/allconfig.do
Normal 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
14
docs/cookbook/c/arches.do
Normal 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
6
docs/cookbook/c/clean.od
Normal 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
3
docs/cookbook/c/configure
vendored
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
S="$(dirname "$0")"
|
||||
. "$S/redoconf/configure.sh"
|
||||
17
docs/cookbook/c/configure.help
Normal file
17
docs/cookbook/c/configure.help
Normal 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)
|
||||
10
docs/cookbook/c/default.each.do
Normal file
10
docs/cookbook/c/default.each.do
Normal 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
|
||||
10
docs/cookbook/c/flagtest.c
Normal file
10
docs/cookbook/c/flagtest.c
Normal 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");
|
||||
}
|
||||
9
docs/cookbook/c/flagtest.o.od
Normal file
9
docs/cookbook/c/flagtest.o.od
Normal 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"
|
||||
30
docs/cookbook/c/hello world.list.od
Normal file
30
docs/cookbook/c/hello world.list.od
Normal 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
|
||||
6
docs/cookbook/c/libhello/hello.c
Normal file
6
docs/cookbook/c/libhello/hello.c
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#include "hello.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void hello(void) {
|
||||
printf("Hello, world!\n");
|
||||
}
|
||||
6
docs/cookbook/c/libhello/hello.h
Normal file
6
docs/cookbook/c/libhello/hello.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef __HELLO_H
|
||||
#define __HELLO_H
|
||||
|
||||
void hello(void);
|
||||
|
||||
#endif /* __HELLO_H */
|
||||
1
docs/cookbook/c/libhello/lib hello.list
Normal file
1
docs/cookbook/c/libhello/lib hello.list
Normal file
|
|
@ -0,0 +1 @@
|
|||
hello.c
|
||||
1
docs/cookbook/c/libhello/lib hello.ver
Normal file
1
docs/cookbook/c/libhello/lib hello.ver
Normal file
|
|
@ -0,0 +1 @@
|
|||
1.2.5
|
||||
22
docs/cookbook/c/main.c
Normal file
22
docs/cookbook/c/main.c
Normal 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
19
docs/cookbook/c/main.h
Normal 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 */
|
||||
58
docs/cookbook/c/monotime.c
Normal file
58
docs/cookbook/c/monotime.c
Normal 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
|
||||
6
docs/cookbook/c/monotime.h
Normal file
6
docs/cookbook/c/monotime.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef __MONOTIME_H
|
||||
#define __MONOTIME_H
|
||||
|
||||
long long monotime(void);
|
||||
|
||||
#endif /* __MONOTIME_H */
|
||||
5
docs/cookbook/c/rc/extra.rc.od
Normal file
5
docs/cookbook/c/rc/extra.rc.od
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
. ./redoconf.rc
|
||||
rc_include
|
||||
|
||||
rc_appendln CPPFLAGS "-DEXTRA_RC_INCLUDED=1"
|
||||
rc_save
|
||||
16
docs/cookbook/c/rc/posix.rc.od
Normal file
16
docs/cookbook/c/rc/posix.rc.od
Normal 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
|
||||
16
docs/cookbook/c/rc/printf_lld.rc.od
Normal file
16
docs/cookbook/c/rc/printf_lld.rc.od
Normal 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
1
docs/cookbook/c/redoconf
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../../redoconf
|
||||
10
docs/cookbook/c/slow.cc
Normal file
10
docs/cookbook/c/slow.cc
Normal 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
1
docs/cookbook/c/test.do
Normal file
|
|
@ -0,0 +1 @@
|
|||
redo-ifchange test.each
|
||||
16
docs/cookbook/c/test.od
Normal file
16
docs/cookbook/c/test.od
Normal 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
|
||||
7
docs/cookbook/c/when.c.do
Normal file
7
docs/cookbook/c/when.c.do
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
cat >$3 <<-EOF
|
||||
const char *stamp_time(void) {
|
||||
return "$(date +%Y-%m-%d)";
|
||||
}
|
||||
EOF
|
||||
redo-always
|
||||
redo-stamp <$3
|
||||
51
redoconf/_all.rc.od
Normal file
51
redoconf/_all.rc.od
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
. ./redoconf.rc
|
||||
|
||||
# replace the placeholder for this function with
|
||||
# one that will save help messages for later.
|
||||
HELP="configure.help.new"
|
||||
rm -f "$HELP"
|
||||
echo '# Automatically generated by redoconf/_all.rc.od - do not edit' >"$HELP"
|
||||
helpmsg() {
|
||||
printf '%-11s %s\n' "$1" "$2" >>"$HELP"
|
||||
rc_hook "$1"
|
||||
}
|
||||
|
||||
# Remember initial set of keys provided by ./configure
|
||||
orig_keys=""
|
||||
rc_hook() {
|
||||
contains_line "$orig_keys" "$1" || orig_keys="$orig_keys$NL$1"
|
||||
}
|
||||
|
||||
# Include the rest of the necessary .rc files
|
||||
keys=""
|
||||
rc_hook() {
|
||||
contains_line "$new_keys" "$1" || new_keys="$new_keys$NL$1"
|
||||
}
|
||||
allrc=
|
||||
if [ -e "$S/all.rc.od" ]; then
|
||||
allrc=all.rc
|
||||
else
|
||||
allrc=
|
||||
redo-ifcreate "$S/all.rc.od"
|
||||
fi
|
||||
rc_include rc/_init.rc rc/CC.rc rc/zdefs.rc $allrc
|
||||
|
||||
rc_helpmsg PREFIX "Change installation prefix (usually /usr/local)"
|
||||
|
||||
IFS="$NL"
|
||||
unused=
|
||||
for d in $orig_keys; do
|
||||
if ! contains_line "$new_keys" "$d"; then
|
||||
unused=1
|
||||
xecho "Error: '$d' was given to ./configure but not used." >&2
|
||||
fi
|
||||
done
|
||||
[ -z "$unused" ] || exit 1
|
||||
|
||||
rc_save
|
||||
|
||||
# Now that all the rc files have run, update $S/configure.help with the
|
||||
# newly-generated help text, so it's available to new users.
|
||||
# Even if multiple output dirs are building at once, this replaces the
|
||||
# file atomically, so it should be safe.
|
||||
mv "$HELP" "$S/configure.help"
|
||||
14
redoconf/_compile.od
Normal file
14
redoconf/_compile.od
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# See compile.od for more explanation.
|
||||
cat >$3 <<-EOF
|
||||
#!/bin/sh -e
|
||||
# Run the C/C++ compiler.
|
||||
# Assumes config variables (CFLAGS, etc) are already set.
|
||||
t="\$1" d="\$2" i="\$3"
|
||||
IFS="$NL"
|
||||
set -f
|
||||
\$CC -o "\$t" -c "\$i" \\
|
||||
-MMD -MF "\$d" \\
|
||||
\$CPPFLAGS \$CFLAGS \$CXXFLAGS \$FLAGS_PCH \$xCFLAGS \$OPTFLAGS
|
||||
EOF
|
||||
chmod a+x "$3"
|
||||
redo-stamp <$3
|
||||
51
redoconf/compile.od
Normal file
51
redoconf/compile.od
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
. ./redoconf.rc
|
||||
rc_include _all.rc
|
||||
redo-ifchange _compile
|
||||
|
||||
# Subtle:
|
||||
# - un-backslashed $ expansions ($foo, $(cmd)) are
|
||||
# done *now*, while writing the script contents.
|
||||
# - backslashed $ expansions (\$foo) are written
|
||||
# verbatim into the script, to be interpreted at
|
||||
# the time the script is run.
|
||||
#
|
||||
# We want to insert the variable contents into the
|
||||
# script near the top, making sure they are not
|
||||
# split or interpreted at that point (hence the
|
||||
# $(shquote)).
|
||||
#
|
||||
# Further down, we want to disable wildcard expansion
|
||||
# (set -f) and split on $NL (so we change $IFS),
|
||||
# so we use backslash escapes but *not* quoting.
|
||||
|
||||
cat >$3 <<-EOF
|
||||
#!/bin/sh -e
|
||||
# Run the C/++ compiler.
|
||||
t="\$1" d="\$2" i="\$3"
|
||||
CPPFLAGS=$(shquote "$CPPFLAGS")
|
||||
OPTFLAGS=$(shquote "$OPTFLAGS")
|
||||
case \$i in
|
||||
*.c|*.h)
|
||||
CC=$(shquote "$CC")
|
||||
CFLAGS=$(shquote "$CFLAGS")
|
||||
CXXFLAGS=
|
||||
PCH1=$(shquote "$CFLAGS_PCH")
|
||||
PCH2=$(shquote "$CFLAGS_PCH_FPIC")
|
||||
;;
|
||||
*)
|
||||
CC=$(shquote "$CXX")
|
||||
[ -n "\$CC" ] || (echo "No C++ compiler available." >&2; exit 1)
|
||||
CFLAGS=
|
||||
CXXFLAGS=$(shquote "$CXXFLAGS")
|
||||
PCH1=$(shquote "$CXXFLAGS_PCH")
|
||||
PCH2=$(shquote "$CXXFLAGS_PCH_FPIC")
|
||||
;;
|
||||
esac
|
||||
case \$PCH in
|
||||
1) FLAGS_PCH=\$PCH1 ;;
|
||||
2) FLAGS_PCH=\$PCH2 ;;
|
||||
esac
|
||||
. ./_compile
|
||||
EOF
|
||||
chmod a+x "$3"
|
||||
redo-stamp <$3
|
||||
200
redoconf/configure.sh
Normal file
200
redoconf/configure.sh
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
#!/bin/sh -e
|
||||
if [ -z "$S" ]; then
|
||||
exec >&2
|
||||
echo "configure.sh: must include this from a 'configure' script"
|
||||
exit 99
|
||||
fi
|
||||
if [ -e "configure" ] || [ -e "rc.sh" ]; then
|
||||
exec >&2
|
||||
echo "$0: run this script from an empty output directory."
|
||||
echo " For example:"
|
||||
echo " (mkdir out && cd out && ../configure && redo -j10)"
|
||||
exit 99
|
||||
fi
|
||||
|
||||
S="$(dirname "$0")"
|
||||
rm -f src Makefile
|
||||
echo "$S" >src
|
||||
|
||||
# Don't regenerate these files unless they're missing. Otherwise redo
|
||||
# will treat it as a changed dependency and rebuild a bunch of files
|
||||
# unnecessarily.
|
||||
[ -e redoconf.rc ] || cat >redoconf.rc <<-EOF
|
||||
# Automatically generated by $0
|
||||
read -r S <src
|
||||
. "\$S/redoconf/rc.sh"
|
||||
EOF
|
||||
|
||||
# Instead of a symlink, we could make this a script like redoconf.rc,
|
||||
# except then we would have to redi-ifchange default.do.sh, which would
|
||||
# greatly increase the number of calls to redo-ifchange in the fast path.
|
||||
# That turns out to slow things down quite a bit. So let redo follow
|
||||
# the symlink and note the dependency internally, which is faster.
|
||||
[ -e default.do ] || ln -sf "$S/redoconf/default.do.sh" default.do
|
||||
|
||||
cat >Makefile <<'EOF'
|
||||
# A wrapper for people who like to type 'make' instead of 'redo'
|
||||
all $(filter-out all,$(MAKECMDGOALS)):
|
||||
+redo "$@"
|
||||
.PHONY: $(MAKECMDGOALS) all
|
||||
EOF
|
||||
|
||||
# Don't include rc.sh here, because that might call redo-ifchange,
|
||||
# and we're not ready for that yet.
|
||||
. "$S/redoconf/utils.sh"
|
||||
|
||||
usage() {
|
||||
exec >&2
|
||||
printf 'Usage: %s %s' "$0" \
|
||||
'[options...] [KEY=value] [--with-key=value]
|
||||
|
||||
--prefix= Change installation prefix (usually /usr/local)
|
||||
--host= Architecture prefix for output (eg. i686-w64-mingw32-)
|
||||
--enable-static Link libraries and binaries statically
|
||||
--{dis,en}able-optimization Disable/enable optimization for C/C++
|
||||
--{dis,en}able-debug Disable/enable debugging flags for C/C++
|
||||
-h, --help This help message
|
||||
'
|
||||
if [ -e "$S/configure.help" ]; then
|
||||
printf '\nProject-specific flags:\n'
|
||||
sort "$S/configure.help" |
|
||||
while read k msg; do
|
||||
# skip blanks and comments
|
||||
[ -n "${k%%\#*}" ] || continue
|
||||
# skip options with syntax already explained above
|
||||
[ "$k" != "ARCH" ] || continue
|
||||
[ "$k" != "PREFIX" ] || continue
|
||||
[ "$k" != "STATIC" ] || continue
|
||||
printf ' %-15s %s\n' "$k=..." "$msg"
|
||||
done
|
||||
else
|
||||
printf '\nNo extra help yet: configure.help is missing.\n'
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
upper() {
|
||||
xecho "$1" | tr 'a-z' 'A-Z' | sed 's/[^A-Z0-9]/_/g'
|
||||
}
|
||||
|
||||
lower() {
|
||||
xecho "$1" | tr 'A-Z' 'a-z' | sed 's/[^a-z0-9]/-/g'
|
||||
}
|
||||
|
||||
emit() {
|
||||
xecho "replaceln" "$1" "$(shquote "$(rc_splitwords "$2")")"
|
||||
}
|
||||
|
||||
emit_append() {
|
||||
xecho "appendln" "$1" "$(shquote "$(rc_splitwords "$2")")"
|
||||
}
|
||||
|
||||
for k in ARCH CC CXX CPPFLAGS CFLAGS CXXFLAGS \
|
||||
OPTFLAGS LINK LDFLAGS LIBS xCFLAGS; do
|
||||
eval v=\$$k
|
||||
if [ -n "$v" ]; then
|
||||
echo "$0: Fatal: '$k' environment variable is set." >&2
|
||||
echo " This can cause inconsistent builds." >&2
|
||||
echo " Pass variables as arguments to $0 instead." >&2
|
||||
echo " Example: $0 $k=$(shquote "$v")" >&2
|
||||
exit 4
|
||||
fi
|
||||
done
|
||||
|
||||
rm -f _flags.tmp
|
||||
echo "# Auto-generated by $0" >_flags.tmp
|
||||
for d in "$@"; do
|
||||
case $d in
|
||||
--help|-h|-\?)
|
||||
usage
|
||||
;;
|
||||
--host=*)
|
||||
v="${d#*=}"
|
||||
emit "ARCH" "$v"
|
||||
;;
|
||||
--enable-static)
|
||||
emit "STATIC" "1"
|
||||
;;
|
||||
--enable-optimization)
|
||||
emit_append OPTFLAGS "-O2"
|
||||
;;
|
||||
--disable-optimization)
|
||||
emit_append OPTFLAGS "-O0"
|
||||
;;
|
||||
--enable-debug)
|
||||
emit_append OPTFLAGS "-g"
|
||||
;;
|
||||
--disable-debug)
|
||||
emit_append OPTFLAGS "-g0"
|
||||
;;
|
||||
--prefix=*)
|
||||
v="${d#*=}"
|
||||
emit "PREFIX" "$v"
|
||||
;;
|
||||
--with-[A-Za-z]*)
|
||||
if [ "$d" = "${d%%=*}" ]; then
|
||||
xecho "$0: in $(shquote "$d"):" \
|
||||
"must supply '--with-<key>=<value>'" >&2
|
||||
exit 3
|
||||
fi
|
||||
k="${d%%=*}"
|
||||
k="${k#--with-}"
|
||||
v="${d#*=}"
|
||||
kl=$(lower "$k")
|
||||
if [ "$k" != "$kl" ]; then
|
||||
xecho "$0: in $(shquote "--with-$k=..."):" \
|
||||
"must be all lowercase and dashes" >&2
|
||||
exit 3
|
||||
fi
|
||||
ku=$(upper "$k")
|
||||
emit "$ku" "$v"
|
||||
;;
|
||||
--without-[A-Za-z]*)
|
||||
if [ "$d" != "${d%%=*}" ]; then
|
||||
xecho "$0: in $(shquote "$d"):" \
|
||||
"do not supply '=...' with --without" >&2
|
||||
exit 3
|
||||
fi
|
||||
k="${d#--without-}"
|
||||
kl=$(lower "$k")
|
||||
if [ "$k" != "$kl" ]; then
|
||||
xecho "$0: in $(shquote "$d"):" \
|
||||
"must be all lowercase and dashes" >&2
|
||||
exit 3
|
||||
fi
|
||||
ku=$(upper "$k")
|
||||
# This causes tests to try to link using an extra
|
||||
# option "NONE", which will fail, thus making the
|
||||
# package appear missing.
|
||||
emit "$ku" "NONE"
|
||||
;;
|
||||
[A-Za-z_]*=*)
|
||||
k="${d%%=*}"
|
||||
v="${d#*=}"
|
||||
ku=$(upper "$k")
|
||||
if [ "$k" != "$ku" ]; then
|
||||
xecho "$0: in $(shquote "$d"):" \
|
||||
"invalid KEY=value;" \
|
||||
"must be all caps and underscores" >&2
|
||||
exit 3
|
||||
fi
|
||||
emit "$ku" "$v"
|
||||
;;
|
||||
*)
|
||||
xecho "$0: in $(shquote "$d"):" \
|
||||
"invalid option; use --help for help." >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done >>_flags.tmp
|
||||
|
||||
# Avoid replacing the file if it's identical, so we don't trigger
|
||||
# unnecessary rebuilds. redo-stamp can do this for a redo target,
|
||||
# but _flags is being generated by this configure script, which is
|
||||
# not a redo target.
|
||||
if [ -e _flags ] && cmp _flags.tmp _flags >/dev/null; then
|
||||
rm -f _flags.tmp
|
||||
else
|
||||
rm -f _flags
|
||||
mv _flags.tmp _flags
|
||||
fi
|
||||
181
redoconf/default.do.sh
Normal file
181
redoconf/default.do.sh
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
# This script starts with $PWD=output dir, $S=input dir.
|
||||
read -r S <src
|
||||
REDOCONF="$S/redoconf"
|
||||
if [ ! -d "$S" ] || [ ! -f "$REDOCONF/default.do.sh" ]; then
|
||||
echo "default.do.sh: \$S is not set correctly." >&2
|
||||
exit 99
|
||||
fi
|
||||
|
||||
NL="
|
||||
"
|
||||
|
||||
_mkdir_of() {
|
||||
local dir="${1%/*}"
|
||||
[ "$dir" = "$1" ] ||
|
||||
[ -z "$dir" ] ||
|
||||
[ -d "$dir" ] ||
|
||||
mkdir -p "$dir"
|
||||
}
|
||||
|
||||
# Delegate to .od files specifically for this target, if any.
|
||||
_base1=${1##*/}
|
||||
_dir1=${1%"$_base1"}
|
||||
_missing=""
|
||||
for d in "$S/$1.od" \
|
||||
"$S/${_dir1}default.${_base1#*.}.od" \
|
||||
"$REDOCONF/$1.od" \
|
||||
"$REDOCONF/${_dir1}default.${_base1#*.}.od"; do
|
||||
if [ -e "$d" ]; then
|
||||
redo-ifchange "$d"
|
||||
_mkdir_of "$3"
|
||||
( PS4="$PS4[$d] "; . "$d" )
|
||||
exit
|
||||
else
|
||||
missing="$missing$NL$d"
|
||||
fi
|
||||
done
|
||||
|
||||
_add_missing() {
|
||||
[ -n "$missing" ] && (IFS="$NL"; set -f; redo-ifcreate $missing)
|
||||
missing=
|
||||
}
|
||||
|
||||
_pick_src() {
|
||||
# Look for the source file corresponding to a given .o file.
|
||||
# If the source file is missing, we can also build it from
|
||||
# eg. a .c.do script.
|
||||
#
|
||||
# Returns the matching source file in $src, the compiler
|
||||
# mode in $lang, and appends any redo-ifcreate targets to
|
||||
# $missing.
|
||||
lang=cc
|
||||
for src in "$1.c"; do
|
||||
[ -e "$src" ] && return
|
||||
[ -e "$src.do" ] && return
|
||||
missing="$missing$NL$src"
|
||||
done
|
||||
lang=cxx
|
||||
for src in "$1.cc" "$1.cpp" "$1.cxx" "$1.C" "$1.c++"; do
|
||||
[ -e "$src" ] && return
|
||||
[ -e "$src.do" ] && return
|
||||
missing="$missing$NL$src"
|
||||
done
|
||||
echo "default.do.sh: _pick_src: no source file found for '$1.*'" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
_objlist() {
|
||||
local suffix="$1" list="$2" base="${2##*/}"
|
||||
local dir="${2%"$base"}"
|
||||
sed -Ee 's/\.(c|cc|cpp|cxx|C|c\+\+)$/'"$suffix/" <"$2" |
|
||||
while read -r d; do
|
||||
[ "$d" = "${d#-}" ] || continue
|
||||
echo "$dir$d"
|
||||
done
|
||||
}
|
||||
|
||||
_flaglist() {
|
||||
while read -r d; do
|
||||
[ "$d" != "${d#-}" ] || continue
|
||||
echo "$d"
|
||||
done <"$1"
|
||||
}
|
||||
|
||||
compile() {
|
||||
redo-ifchange compile "$src" $dep
|
||||
rm -f "$1.deps"
|
||||
_mkdir_of "$3"
|
||||
xCFLAGS="$xCFLAGS" PCH="$PCH" ./compile "$3" "$1.deps" "$src"
|
||||
# TODO: make work with dependency filenames containing whitespace.
|
||||
# gcc writes whitespace-containing filenames with spaces
|
||||
# prefixed by backslash. read (without -r) will remove the
|
||||
# backslashes but still use spaces for word splitting, so
|
||||
# it loses the distinction. rc_splitwords() is the right
|
||||
# function, but currently has a max word limit.
|
||||
read deps <"$2.deps"
|
||||
redo-ifchange ${deps#*:}
|
||||
}
|
||||
|
||||
case $1 in
|
||||
*.fpic.o)
|
||||
_pick_src "$S/${1%.fpic.o}"
|
||||
_add_missing
|
||||
xCFLAGS="-fPIC" PCH="2" dep="$lang-fpic.precompile" compile "$@"
|
||||
exit # fast path: exit as early as possible
|
||||
;;
|
||||
*.o)
|
||||
_pick_src "$S/${1%.o}"
|
||||
_add_missing
|
||||
xCFLAGS="" PCH="1" dep="$lang.precompile" compile "$@"
|
||||
exit # fast path: exit as early as possible
|
||||
;;
|
||||
*.h.fpic.gch|*.hpp.fpic.gch)
|
||||
src="$S/${1%.fpic.gch}"
|
||||
xCFLAGS="-fPIC" PCH="" dep="" compile "$@"
|
||||
# precompiled header is "unchanged" if its component
|
||||
# headers are unchanged.
|
||||
cat ${deps#*:} | tee $1.stamp | redo-stamp
|
||||
;;
|
||||
*.h.gch|*.hpp.gch)
|
||||
src="$S/${1%.gch}"
|
||||
xCFLAGS="" PCH="" dep="" compile "$@"
|
||||
# precompiled header is "unchanged" if its component
|
||||
# headers are unchanged.
|
||||
cat ${deps#*:} | tee $1.stamp | redo-stamp
|
||||
;;
|
||||
*.a)
|
||||
listf="${1%.a}.list"
|
||||
redo-ifchange "$listf"
|
||||
files=$(_objlist .o "$listf")
|
||||
IFS="$NL"
|
||||
redo-ifchange $files
|
||||
ar q "$3" $files
|
||||
;;
|
||||
*.so)
|
||||
verf="${1%.so}.ver"
|
||||
listf="${1%.so}.list"
|
||||
redo-ifchange link-shlib "$verf" "$listf"
|
||||
read ver <"$verf"
|
||||
files=$(_objlist .fpic.o "$listf")
|
||||
xLIBS=$(_flaglist "$listf")
|
||||
IFS="$NL"
|
||||
redo-ifchange $files
|
||||
xLIBS="$xLIBS" ./link-shlib "$1.$ver" $files
|
||||
ln -s "$(basename "$1.$ver")" "$3"
|
||||
ln -sf "$1.$ver" .
|
||||
;;
|
||||
*.list|*.ver)
|
||||
if [ -e "$S/$1" ]; then
|
||||
redo-ifchange "$S/$1"
|
||||
_mkdir_of "$3"
|
||||
cp "$S/$1" "$3"
|
||||
else
|
||||
echo "default.do.sh: no rule to build '$1'" >&2
|
||||
exit 99
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# In unix, binary names typically don't have any special filename
|
||||
# pattern, so we have to handle them in a catch-all here.
|
||||
# We detect that it's intended as a binary, and not just a typo,
|
||||
# by the existence of a .list or .list.od file with the same name,
|
||||
# defining the list of input files.
|
||||
#
|
||||
# Some people like to name their binaries *.exe, eg. on Windows,
|
||||
# even though that doesn't matter anymore, even on Windows.
|
||||
# So use the same rules for generating a .exe as a non-.exe.
|
||||
bin="${1%.exe}"
|
||||
if [ -e "$S/$bin.list" -o -e "$S/$bin.list.od" ]; then
|
||||
# a final program binary
|
||||
redo-ifchange link "$bin.list"
|
||||
files=$(_objlist .o "$bin.list")
|
||||
xLIBS=$(_flaglist "$bin.list")
|
||||
IFS="$NL"
|
||||
redo-ifchange $files
|
||||
xLIBS="$xLIBS" ./link "$3" $files
|
||||
else
|
||||
echo "default.do.sh: no rule to build '$1' or '$1.list'" >&2
|
||||
exit 99
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
31
redoconf/default.precompile.od
Normal file
31
redoconf/default.precompile.od
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Run the extra steps necessary before compiling
|
||||
# C/C++ programs of the specified type.
|
||||
#
|
||||
# Notably, we have to precompile any precompiled
|
||||
# headers. We also generate redoconf.h in case
|
||||
# programs want to include it.
|
||||
. ./redoconf.rc
|
||||
rc_include _all.rc
|
||||
|
||||
case ${1%.precompile} in
|
||||
cc) pch_files="$PRE_CC_TARGETS" ;;
|
||||
cc-fpic) pch_files="$PRE_CC_TARGETS_FPIC" ;;
|
||||
cxx) pch_files="$PRE_CXX_TARGETS" ;;
|
||||
cxx-fpic) pch_files="$PRE_CXX_TARGETS_FPIC" ;;
|
||||
*) exit 42 ;;
|
||||
esac
|
||||
|
||||
IFS="$NL"
|
||||
set -f
|
||||
redo-ifchange "redoconf.h" $pch_files
|
||||
|
||||
# Subtle:
|
||||
# Don't consider this target to have changed unless
|
||||
# the precompiled header's stamp has changed.
|
||||
# We generate redoconf.h, in case
|
||||
# a C program wants to include it, but we
|
||||
# don't care if it has changed, because the C program
|
||||
# will have its own dependency on that file.
|
||||
for d in $t; do
|
||||
cat "$d.stamp"
|
||||
done | redo-stamp
|
||||
36
redoconf/link-shlib.od
Normal file
36
redoconf/link-shlib.od
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
. ./redoconf.rc
|
||||
rc_include _all.rc rc/shlib.rc
|
||||
|
||||
# Tricky quoting: see _compile.od for details.
|
||||
if [ "$HAVE_SHLIB" = 1 ]; then
|
||||
cat >$3 <<-EOF
|
||||
#!/bin/sh -e
|
||||
LINK=$(shquote "$LINK")
|
||||
LDFLAGS=$(shquote "$LDFLAGS")
|
||||
OPTFLAGS=$(shquote "$OPTFLAGS")
|
||||
LIBS=$(shquote "$LIBS")
|
||||
o="\$1"
|
||||
ob="\${o#*/}"
|
||||
shift
|
||||
IFS="$NL"
|
||||
set -f
|
||||
\$LINK -shared -o "\$o" \\
|
||||
-Wl,-soname,"\$ob" \\
|
||||
\$LDFLAGS \$OPTFLAGS \\
|
||||
"\$@" \\
|
||||
\$LIBS
|
||||
EOF
|
||||
else
|
||||
# If no shared library support and we try to build one,
|
||||
# compensate by building a static library instead in the
|
||||
# same place.
|
||||
cat >$3 <<-EOF
|
||||
#!/bin/sh -e
|
||||
o="\$1"
|
||||
shift
|
||||
rm -f "\$o"
|
||||
ar q "\$o" "\$@"
|
||||
EOF
|
||||
fi
|
||||
chmod a+x "$3"
|
||||
redo-stamp <$3
|
||||
22
redoconf/link.od
Normal file
22
redoconf/link.od
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
. ./redoconf.rc
|
||||
rc_include _all.rc
|
||||
|
||||
# Tricky quoting: see _compile.od for details.
|
||||
cat >$3 <<-EOF
|
||||
#!/bin/sh -e
|
||||
LINK=$(shquote "$LINK")
|
||||
LDFLAGS=$(shquote "$LDFLAGS")
|
||||
OPTFLAGS=$(shquote "$OPTFLAGS")
|
||||
LIBS=$(shquote "$LIBS")
|
||||
o="\$1"
|
||||
shift
|
||||
IFS="$NL"
|
||||
set -f
|
||||
\$LINK -o "\$o" \\
|
||||
-Wl,-rpath,'\$ORIGIN' \\
|
||||
\$LDFLAGS \$OPTFLAGS \\
|
||||
"\$@" \\
|
||||
\$LIBS
|
||||
EOF
|
||||
chmod a+x "$3"
|
||||
redo-stamp <$3
|
||||
240
redoconf/rc.sh
Normal file
240
redoconf/rc.sh
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
# This script starts with $PWD=output dir, $S=input dir.
|
||||
REDOCONF="$S/redoconf"
|
||||
if [ ! -d "$S" ] || [ ! -f "$REDOCONF/default.do.sh" ]; then
|
||||
echo "default.do.sh: \$S is not set correctly." >&2
|
||||
exit 99
|
||||
fi
|
||||
. "$REDOCONF/utils.sh"
|
||||
RC_TARGET="$1"
|
||||
rm -f "$RC_TARGET.log"
|
||||
|
||||
redo-ifchange "$REDOCONF/rc.sh" "$REDOCONF/utils.sh"
|
||||
|
||||
_rc_exit_check() {
|
||||
if [ -z "$RC_INCLUDE_RAN" ]; then
|
||||
echo "Fatal: used redoconf/rc.sh but didn't call rc_include." >&2
|
||||
exit 99
|
||||
elif [ -n "$RC_QUEUE" ]; then
|
||||
echo "Fatal: must call rc_save or rc_undo before ending." >&2
|
||||
exit 99
|
||||
fi
|
||||
}
|
||||
trap _rc_exit_check EXIT
|
||||
|
||||
rc_hook() {
|
||||
# nothing by default; can be overridden
|
||||
:
|
||||
}
|
||||
|
||||
# Declare that a variable *named* $1 is used
|
||||
# as input for the current script, and provide
|
||||
# a help message in $2 for use with
|
||||
# configure --help-flags.
|
||||
helpmsg() {
|
||||
# Nothing to do by default
|
||||
rc_hook "$1"
|
||||
}
|
||||
|
||||
# Assign the string $2 to the global variable
|
||||
# *named* by $1.
|
||||
replaceln() {
|
||||
rc_hook "$1"
|
||||
eval $1=\$2
|
||||
}
|
||||
|
||||
# If $2 is nonempty, append a newline and $2 to
|
||||
# the global variable *named* by $1
|
||||
appendln() {
|
||||
rc_hook "$1"
|
||||
eval local tmp=\"\$$1\$NL\$2\"
|
||||
eval $1='${tmp#$NL}'
|
||||
}
|
||||
|
||||
# Write a command line that calls "uses $1",
|
||||
# including proper sh-escaping.
|
||||
rc_helpmsg() {
|
||||
local cmd="helpmsg"
|
||||
cmd="helpmsg $1 $(shquote "$2")"
|
||||
eval "$cmd"
|
||||
appendln RC_HELP_QUEUE "$cmd"
|
||||
}
|
||||
|
||||
_rc_record() {
|
||||
if ! contains_line "$RC_CHANGED" "$1"; then
|
||||
local oldv=
|
||||
eval oldv="\$$1"
|
||||
eval "old$1=\$oldv"
|
||||
RC_CHANGED="$RC_CHANGED$NL$1"
|
||||
fi
|
||||
}
|
||||
|
||||
# Write a command line that calls "appendln $1 $2",
|
||||
# including properly sh-escaping $2.
|
||||
rc_appendln() {
|
||||
RC_LOG="$RC_LOG $1 += $(shquote "$2")$NL"
|
||||
_rc_record "$1"
|
||||
local cmd="appendln $1 $(shquote "$2")"
|
||||
eval "$cmd"
|
||||
appendln RC_QUEUE "$cmd"
|
||||
}
|
||||
|
||||
# Write a command line that replaces $1 with $2,
|
||||
# including properly sh-escaping $2.
|
||||
# This is good for variables like CC and CXX, where
|
||||
# appending isn't what we want.
|
||||
rc_replaceln() {
|
||||
RC_LOG="$RC_LOG $1 = $(shquote "$2")$NL"
|
||||
_rc_record "$1"
|
||||
local cmd="replaceln $1 $(shquote "$2")"
|
||||
eval "$cmd"
|
||||
appendln RC_QUEUE "$cmd"
|
||||
}
|
||||
|
||||
# Read compiler variables from _init.rc and the listed .rc files.
|
||||
# Runs redo-ifchange to generate the .rc files as needed.
|
||||
rc_include() {
|
||||
local d="" want="" target="$RC_TARGET" ops4="$PS4"
|
||||
RC_INCLUDE_RAN=1
|
||||
for d in rc/_init.rc "$@"; do
|
||||
if [ "$d" = "${d%.rc}" ]; then
|
||||
xecho "$0: rc_include: '$d' must end in .rc" >&2
|
||||
exit 99
|
||||
fi
|
||||
if ! contains_line "$RC_INCLUDES" "$d"; then
|
||||
want="$want$NL$d"
|
||||
RC_INCLUDES="$RC_INCLUDES$NL$d"
|
||||
fi
|
||||
done
|
||||
want="${want#$NL}"
|
||||
if [ -n "$want" ]; then
|
||||
xIFS="$IFS"
|
||||
IFS="$NL"
|
||||
set -f
|
||||
redo-ifchange $want
|
||||
for d in $want; do
|
||||
IFS="$xIFS"
|
||||
set +f
|
||||
RC_TARGET="$d"
|
||||
PS4="$PS4[$d] "
|
||||
[ ! -e "$d" ] || { :; . "./$d"; }
|
||||
PS4="$ops4"
|
||||
done
|
||||
IFS="$xIFS"
|
||||
set +f
|
||||
fi
|
||||
unset RC_QUEUE
|
||||
PS4="$ops4"
|
||||
RC_TARGET="$target"
|
||||
}
|
||||
|
||||
# Undo the currently enqueued rc_appendln and rc_replaceln
|
||||
# actions, restoring the affected variables back to their
|
||||
# original values.
|
||||
rc_undo() {
|
||||
local xIFS="$IFS" v=
|
||||
IFS="$NL"
|
||||
for k in $RC_CHANGED; do
|
||||
eval v="\$old$k"
|
||||
eval "$k=\$v"
|
||||
done
|
||||
unset RC_CHANGED
|
||||
unset RC_QUEUE
|
||||
unset RC_LOG
|
||||
}
|
||||
|
||||
# Write the currently active rc_include,
|
||||
# rc_replaceln, and rc_appendln commands to stdout,
|
||||
# to produce the final .rc file.
|
||||
rc_save() {
|
||||
printf '%s' "${RC_LOG}" >&2
|
||||
if [ -n "$RC_INCLUDES" ]; then
|
||||
(
|
||||
xIFS="$IFS"
|
||||
IFS="$NL"
|
||||
printf 'rc_include '
|
||||
for d in $RC_INCLUDES; do
|
||||
printf '%s ' "$d"
|
||||
done
|
||||
printf '\n'
|
||||
)
|
||||
fi
|
||||
xecho "$RC_HELP_QUEUE"
|
||||
xecho "$RC_QUEUE"
|
||||
unset RC_QUEUE
|
||||
unset RC_CHANGED
|
||||
}
|
||||
|
||||
rc_compile() {
|
||||
redo-ifchange "$REDOCONF/trycompile"
|
||||
( . "$REDOCONF/trycompile" "$@" ) >>"$RC_TARGET.log" 2>&1
|
||||
}
|
||||
|
||||
_pkg_config() {
|
||||
(
|
||||
IFS="$NL"
|
||||
set -f
|
||||
$PKG_CONFIG $PKG_CONFIG_FLAGS "$@"
|
||||
)
|
||||
}
|
||||
|
||||
_rc_pkg_add() {
|
||||
local var="$1" vvar= want=
|
||||
shift
|
||||
if [ -n "$HAVE_PKG_CONFIG" ]; then
|
||||
for d in "$@"; do
|
||||
if _pkg_config --exists "$d"; then
|
||||
want="$want $d"
|
||||
fi
|
||||
done
|
||||
if [ -n "$want" ]; then
|
||||
rc_appendln CPPFLAGS \
|
||||
"$(rc_splitwords \
|
||||
"$(_pkg_config --cflags $want)")"
|
||||
vvar="$(rc_splitwords \
|
||||
"$(_pkg_config --libs $want)")"
|
||||
rc_appendln "$var" "$vvar"
|
||||
fi
|
||||
else
|
||||
echo "(pkg-config is missing)" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
# Determine whether packages listed in $2 all exists and are functional,
|
||||
# by finding them using pkg-config and running the command in $3..$n.
|
||||
#
|
||||
# If the package works:
|
||||
# HAVE_$1 is set to 1
|
||||
# CPPFLAGS and the variable named by $1 are updated with compiler and
|
||||
# linker flags, respectively.
|
||||
# else:
|
||||
# HAVE_$1 is set to blank.
|
||||
#
|
||||
# Returns success in either case. Check detection results in the
|
||||
# HAVE_$1 variable if needed.
|
||||
rc_pkg_detect() {
|
||||
if ! contains_line "$RC_INCLUDES" rc/pkg-config.rc; then
|
||||
echo "Error: include pkg-config.rc before using rc_pkg_*" >&2
|
||||
return 1
|
||||
fi
|
||||
if [ "$#" -lt 3 ]; then
|
||||
echo "Error: rc_pkg_detect needs a command to test." >&2
|
||||
return 1
|
||||
fi
|
||||
local var="$1" vvar="" pkgs="$2"
|
||||
shift
|
||||
shift
|
||||
eval vvar="\$$var"
|
||||
rc_helpmsg "$var" "Extra linker options for '$pkgs'"
|
||||
if [ -z "$vvar" ]; then
|
||||
_rc_pkg_add "$var" $pkgs
|
||||
eval vvar="\$$var"
|
||||
fi
|
||||
appendln LIBS "$vvar"
|
||||
if ("$@"); then
|
||||
rc_replaceln "HAVE_$var" 1
|
||||
else
|
||||
rc_undo
|
||||
rc_replaceln "HAVE_$var" ""
|
||||
rc_replaceln "$var" ""
|
||||
fi
|
||||
}
|
||||
68
redoconf/rc/CC.rc.od
Normal file
68
redoconf/rc/CC.rc.od
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
. ./redoconf.rc
|
||||
rc_include
|
||||
|
||||
rc_helpmsg ARCH "Architecture prefix for output (eg. i686-w64-mingw32-)"
|
||||
rc_helpmsg CC "C compiler name (cc)"
|
||||
rc_helpmsg CPPFLAGS "Extra C preprocessor flags (eg. -I... -D...)"
|
||||
rc_helpmsg CFLAGS "Extra C compiler flags (eg. -O2 -g)"
|
||||
rc_helpmsg OPTFLAGS "C/C++ compiler flag overrides (eg. -g0)"
|
||||
rc_helpmsg LINK "Linker name (cc)"
|
||||
rc_helpmsg LDFLAGS "Extra linker options (eg. -s -static)"
|
||||
rc_helpmsg LIBS "Extra libraries to always link against (eg. -lsocket)"
|
||||
rc_helpmsg STATIC "Link libraries and binaries statically"
|
||||
|
||||
if [ -n "$CC" ]; then
|
||||
set -- "$CC"
|
||||
else
|
||||
if [ -n "$ARCH" ] && [ "$ARCH" = "${ARCH%-}" ]; then
|
||||
# Make sure arch name includes trailing dash if nonempty
|
||||
ARCH="$ARCH-"
|
||||
fi
|
||||
set -- \
|
||||
"${ARCH}cc" "${ARCH}gcc" \
|
||||
"${ARCH}clang" "/usr/bin/${ARCH}clang"-[0-9]* \
|
||||
"${ARCH}c++" "${ARCH}g++" \
|
||||
"${ARCH}clang++" "/usr/bin/${ARCH}clang++"-[0-9]*
|
||||
fi
|
||||
|
||||
rc_appendln CPPFLAGS "-I."
|
||||
[ -n "$STATIC" ] && rc_appendln LDFLAGS "-static"
|
||||
|
||||
for d in "$@"; do
|
||||
echo "Trying C compiler: '$d'" >&2
|
||||
if CC="$d" CXX="" LINK="$d" rc_compile cc link 'extern int i;'; then
|
||||
rc_replaceln CC "$d"
|
||||
rc_replaceln LINK "$d"
|
||||
|
||||
# mingw32 (not mingw64) generates binaries that need
|
||||
# a dynamic libgcc at runtime for certain operations
|
||||
# (like 64-bit integer division), which is non-obvious.
|
||||
# Include it statically if possible, but only on Windows,
|
||||
# which we'll detect by whether windows.h exists.
|
||||
#
|
||||
# If adding the option fails, maybe it's some
|
||||
# compiler other than gcc, so that's fine.
|
||||
x="-static-libgcc$NL-static-libstdc++"
|
||||
appendln LDFLAGS "$x"
|
||||
prog='#include <windows.h>'
|
||||
if CC="$d" LINK="$d" rc_compile cc link "$prog"; then
|
||||
rc_appendln LDFLAGS "$x"
|
||||
fi
|
||||
|
||||
# Set ARCH= to the right compiler prefix, either empty
|
||||
# (use native compiler) or something like "i686-w64-mingw32-"
|
||||
# (terminating dash), based on the compiler name.
|
||||
x="-${CC##*/}"
|
||||
x="${x%-*}"
|
||||
x="${x#-}"
|
||||
[ -n "$x" ] && x="$x-"
|
||||
rc_replaceln ARCH "$x"
|
||||
|
||||
rc_save
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Can't find a working C compiler." >&2
|
||||
rc_undo
|
||||
exit 1
|
||||
35
redoconf/rc/CXX.rc.od
Normal file
35
redoconf/rc/CXX.rc.od
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc
|
||||
|
||||
rc_helpmsg CXX "C++ compiler name (c++)"
|
||||
rc_helpmsg CXXFLAGS "Extra C++ compiler flags (eg. -O2 -g)"
|
||||
|
||||
if [ -n "$CXX" ]; then
|
||||
set -- "$CXX"
|
||||
else
|
||||
# Note: $ARCH has already been set correctly by CC.rc
|
||||
set -- \
|
||||
"${ARCH}c++" "${ARCH}g++" \
|
||||
"${ARCH}clang++" "/usr/bin/${ARCH}clang++"-[0-9]*
|
||||
fi
|
||||
|
||||
for d in "$@"; do
|
||||
[ -n "$d" ] || continue
|
||||
echo "Trying C++ compiler: '$d'" >&2
|
||||
if CC="" CXX="$d" LINK="$d" rc_compile cxx link 'class A {};'; then
|
||||
rc_replaceln CXX "$d"
|
||||
# If the project activates CXX.rc, then we
|
||||
# replace the C linker with C++. This causes
|
||||
# it to include -lstdc++, etc.
|
||||
# A future .rc could override this again.
|
||||
rc_replaceln LINK "$d"
|
||||
rc_save
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Warning: Can't find a working C++ compiler." >&2
|
||||
rc_undo
|
||||
rc_replaceln CXX ""
|
||||
rc_save
|
||||
exit 0
|
||||
9
redoconf/rc/Wall.rc.od
Normal file
9
redoconf/rc/Wall.rc.od
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc
|
||||
|
||||
rc_appendln CPPFLAGS "-Wall"
|
||||
if rc_compile cc nolink; then
|
||||
rc_save
|
||||
else
|
||||
rc_undo
|
||||
fi
|
||||
9
redoconf/rc/Wextra.rc.od
Normal file
9
redoconf/rc/Wextra.rc.od
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc
|
||||
|
||||
rc_appendln CPPFLAGS "-Wextra"
|
||||
if rc_compile cc nolink; then
|
||||
rc_save
|
||||
else
|
||||
rc_undo
|
||||
fi
|
||||
8
redoconf/rc/_init.rc.od
Normal file
8
redoconf/rc/_init.rc.od
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
if [ -e _flags ]; then
|
||||
redo-ifchange _flags
|
||||
cat _flags >$3
|
||||
redo-stamp <_flags
|
||||
else
|
||||
redo-ifcreate _flags
|
||||
redo-stamp </dev/null
|
||||
fi
|
||||
18
redoconf/rc/default.autolib.rc.od
Normal file
18
redoconf/rc/default.autolib.rc.od
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc
|
||||
|
||||
base="${1#*/}"
|
||||
lib="${base%.autolib.rc}"
|
||||
LIB=$(echo "$lib" | tr 'a-z.' 'A-Z_')
|
||||
|
||||
x="-l$lib"
|
||||
rc_appendln "LIB$LIB" "$x"
|
||||
appendln LIBS "$x"
|
||||
if rc_compile cc link ""; then
|
||||
rc_replaceln "HAVE_$LIB" 1
|
||||
else
|
||||
rc_undo
|
||||
rc_replaceln "HAVE_$LIB" ""
|
||||
rc_replaceln "LIB$LIB" ""
|
||||
fi
|
||||
rc_save
|
||||
13
redoconf/rc/default.func.rc.od
Normal file
13
redoconf/rc/default.func.rc.od
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc
|
||||
|
||||
base="${1#*/}"
|
||||
f="${base%.func.rc}"
|
||||
F=$(echo "$f" | tr 'a-z.' 'A-Z_')
|
||||
|
||||
if rc_compile cc link "void $f(); void test() { $f(); }"; then
|
||||
rc_replaceln "HAVE_$F" 1
|
||||
else
|
||||
rc_replaceln "HAVE_$F" ""
|
||||
fi
|
||||
rc_save
|
||||
23
redoconf/rc/default.h.precompiled.rc.od
Normal file
23
redoconf/rc/default.h.precompiled.rc.od
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc
|
||||
|
||||
base="${1#rc/}"
|
||||
src="${base%.h.precompiled.rc}"
|
||||
|
||||
# The existence of the specific gcc warning about
|
||||
# precompiled headers is a pretty good indicator
|
||||
# that they are supported in the way we expect.
|
||||
rc_appendln CFLAGS "-Winvalid-pch"
|
||||
if rc_compile cc nolink; then
|
||||
rc_appendln CFLAGS "$x"
|
||||
|
||||
rc_appendln CFLAGS_PCH "-include$NL$src.h"
|
||||
rc_appendln CFLAGS_PCH_FPIC "-include$NL$src.h.fpic"
|
||||
|
||||
rc_appendln PRE_CC_TARGETS "$src.h.gch"
|
||||
rc_appendln PRE_CC_TARGETS_FPIC "$src.h.fpic.gch"
|
||||
rc_save
|
||||
else
|
||||
echo "Precompiled C headers not supported." >&2
|
||||
rc_undo
|
||||
fi
|
||||
13
redoconf/rc/default.h.rc.od
Normal file
13
redoconf/rc/default.h.rc.od
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc
|
||||
|
||||
base="${1#*/}"
|
||||
h="${base%.rc}"
|
||||
H=$(echo "$h" | tr 'a-z.' 'A-Z_')
|
||||
|
||||
if rc_compile cc nolink "#include <$h>"; then
|
||||
rc_replaceln "HAVE_$H" 1
|
||||
else
|
||||
rc_replaceln "HAVE_$H" ""
|
||||
fi
|
||||
rc_save
|
||||
23
redoconf/rc/default.hpp.precompiled.rc.od
Normal file
23
redoconf/rc/default.hpp.precompiled.rc.od
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CXX.rc
|
||||
|
||||
base="${1#rc/}"
|
||||
src="${base%.hpp.precompiled.rc}"
|
||||
|
||||
# The existence of the specific gcc warning about
|
||||
# precompiled headers is a pretty good indicator
|
||||
# that they are supported in the way we expect.
|
||||
appendln CXXFLAGS "-Winvalid-pch"
|
||||
if rc_compile cxx nolink; then
|
||||
rc_appendln CXXFLAGS "$x"
|
||||
|
||||
rc_appendln CXXFLAGS_PCH "-include$NL$src.hpp"
|
||||
rc_appendln CXXFLAGS_PCH_FPIC "-include$NL$src.hpp.fpic"
|
||||
|
||||
rc_appendln PRE_CXX_TARGETS "$src.hpp.gch"
|
||||
rc_appendln PRE_CXX_TARGETS_FPIC "$src.hpp.fpic.gch"
|
||||
rc_save
|
||||
else
|
||||
echo "Precompiled C++ headers not supported." >&2
|
||||
rc_undo
|
||||
fi
|
||||
12
redoconf/rc/libgl.rc.od
Normal file
12
redoconf/rc/libgl.rc.od
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc rc/pkg-config.rc
|
||||
|
||||
prog='
|
||||
#include <GL/gl.h>
|
||||
int x = GL_VERSION_1_1;
|
||||
void f() { glPopMatrix(); }
|
||||
'
|
||||
|
||||
rc_pkg_detect LIBGL "gl" \
|
||||
rc_compile cc link "$prog"
|
||||
rc_save
|
||||
12
redoconf/rc/libgtk2.rc.od
Normal file
12
redoconf/rc/libgtk2.rc.od
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc rc/pkg-config.rc
|
||||
|
||||
prog='
|
||||
#include <gtk/gtk.h>
|
||||
int x = GTK_MAJOR_VERSION;
|
||||
void f() { gtk_widget_child_focus(0, 0); }
|
||||
'
|
||||
|
||||
rc_pkg_detect LIBGTK2 "gtk+-2.0 gio-2.0 gdk-2.0 gdk-pixbuf-2.0" \
|
||||
rc_compile cc link "$prog"
|
||||
rc_save
|
||||
25
redoconf/rc/libm.rc.od
Normal file
25
redoconf/rc/libm.rc.od
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc rc/pkg-config.rc
|
||||
|
||||
prog='
|
||||
#include <math.h>
|
||||
int x = FP_NORMAL;
|
||||
volatile float y;
|
||||
void f() { y = sin(y); }
|
||||
'
|
||||
|
||||
rc_pkg_detect LIBM libm \
|
||||
rc_compile cc link "$prog"
|
||||
if [ -z "$HAVE_LIBM" ]; then
|
||||
rc_undo
|
||||
rc_replaceln HAVE_LIBM 1
|
||||
rc_appendln LIBM "-lm"
|
||||
appendln LIBS "$LIBM"
|
||||
if ! rc_compile cc link "$prog"; then
|
||||
rc_undo
|
||||
rc_replaceln HAVE_LIBM ""
|
||||
rc_replaceln LIBM ""
|
||||
fi
|
||||
fi
|
||||
|
||||
rc_save
|
||||
12
redoconf/rc/libpng.rc.od
Normal file
12
redoconf/rc/libpng.rc.od
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc rc/pkg-config.rc
|
||||
|
||||
prog='
|
||||
#include <png.h>
|
||||
const char *x = PNG_LIBPNG_VER_STRING;
|
||||
void f() { png_access_version_number(); }
|
||||
'
|
||||
|
||||
rc_pkg_detect LIBPNG libpng \
|
||||
rc_compile cc link "$prog"
|
||||
rc_save
|
||||
10
redoconf/rc/libqt4.rc.od
Normal file
10
redoconf/rc/libqt4.rc.od
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CXX.rc rc/pkg-config.rc
|
||||
|
||||
prog='
|
||||
#include <QVector>
|
||||
'
|
||||
|
||||
rc_pkg_detect LIBQT4 QtCore \
|
||||
rc_compile cxx link "$prog"
|
||||
rc_save
|
||||
12
redoconf/rc/libsdl.rc.od
Normal file
12
redoconf/rc/libsdl.rc.od
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc rc/pkg-config.rc
|
||||
|
||||
prog='
|
||||
#include <SDL.h>
|
||||
int x = SDL_INIT_TIMER;
|
||||
void f() { SDL_Init(0); }
|
||||
'
|
||||
|
||||
rc_pkg_detect LIBSDL "sdl" \
|
||||
rc_compile cc link "$prog"
|
||||
rc_save
|
||||
12
redoconf/rc/libx11.rc.od
Normal file
12
redoconf/rc/libx11.rc.od
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc rc/pkg-config.rc
|
||||
|
||||
prog='
|
||||
#include <X11/Xutil.h>
|
||||
int x = XYBitmap;
|
||||
void f() { XCreateRegion(); }
|
||||
'
|
||||
|
||||
rc_pkg_detect LIBX11 "x11" \
|
||||
rc_compile cc link "$prog"
|
||||
rc_save
|
||||
17
redoconf/rc/pkg-config.rc.od
Normal file
17
redoconf/rc/pkg-config.rc.od
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
. ./redoconf.rc
|
||||
rc_include
|
||||
|
||||
for d in "$PKG_CONFIG" pkg-config; do
|
||||
rc_undo
|
||||
if "$d" --version >/dev/null 2>&1; then
|
||||
rc_replaceln PKG_CONFIG "$d"
|
||||
rc_replaceln HAVE_PKG_CONFIG 1
|
||||
rc_save
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Failed
|
||||
rc_replaceln HAVE_PKG_CONFIG ""
|
||||
rc_replaceln PKG_CONFIG ""
|
||||
rc_save
|
||||
27
redoconf/rc/run.rc.od
Normal file
27
redoconf/rc/run.rc.od
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc rc/windows.h.rc
|
||||
|
||||
consider() {
|
||||
echo "Considering RUN=$(shquote "$1")" >&2
|
||||
if [ -z "$1" ] || type "$1" >/dev/null 2>&1; then
|
||||
rc_undo
|
||||
rc_replaceln RUN "$1"
|
||||
if RUN="$RUN" rc_compile cc run ""; then
|
||||
rc_replaceln CAN_RUN 1
|
||||
rc_save
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
consider ""
|
||||
if [ -n "$HAVE_WINDOWS_H" ]; then
|
||||
consider "wine64"
|
||||
consider "wine"
|
||||
consider "wine32"
|
||||
fi
|
||||
|
||||
rc_undo
|
||||
rc_replaceln RUN ""
|
||||
rc_replaceln CAN_RUN ""
|
||||
rc_save
|
||||
21
redoconf/rc/shlib.rc.od
Normal file
21
redoconf/rc/shlib.rc.od
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc
|
||||
|
||||
appendln CFLAGS "-fPIC"
|
||||
appendln LDFLAGS "-shared"
|
||||
|
||||
prog='
|
||||
#include <stdlib.h>
|
||||
void f() { atoi(""); }
|
||||
'
|
||||
|
||||
if [ -n "$STATIC" ]; then
|
||||
echo "--enable-static specified; not building shared libraries." >&2
|
||||
rc_replaceln HAVE_SHLIB ""
|
||||
elif RCC_NO_MAIN=1 rc_compile cc link "$prog"; then
|
||||
rc_replaceln HAVE_SHLIB 1
|
||||
else
|
||||
echo "Not building shared libraries on this platform." >&2
|
||||
rc_replaceln HAVE_SHLIB ""
|
||||
fi
|
||||
rc_save
|
||||
11
redoconf/rc/zdefs.rc.od
Normal file
11
redoconf/rc/zdefs.rc.od
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/CC.rc
|
||||
|
||||
x="-Wl,-z,defs"
|
||||
rc_appendln LDFLAGS "$x"
|
||||
if rc_compile cc link; then
|
||||
rc_save
|
||||
else
|
||||
echo "'$x' doesn't work on this platform; skipped." >&2
|
||||
rc_undo
|
||||
fi
|
||||
25
redoconf/rc_vars.od
Normal file
25
redoconf/rc_vars.od
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
. ./redoconf.rc
|
||||
|
||||
# this is called by each call to replaceln() and appendln().
|
||||
RC_KEYS="RC_KEYS"
|
||||
rc_hook() {
|
||||
contains_line "$RC_KEYS" "$1" || RC_KEYS="$RC_KEYS$NL$1"
|
||||
}
|
||||
rc_include _all.rc
|
||||
|
||||
# Escape double-quote and backslash so they can
|
||||
# be included as a C-style double-quoted string.
|
||||
cquote() {
|
||||
local v="$(xecho "$1" | sed -e 's,[\"\\],\\&,g' -e 's,$, \\,')"
|
||||
printf '"%s"' "${v% \\}"
|
||||
}
|
||||
|
||||
(
|
||||
echo "# Automatically generated by autovars.od"
|
||||
for k in $(echo "$RC_KEYS" | sort); do
|
||||
[ "$k" != "RC_INCLUDES" ] || continue
|
||||
eval v=\$$k
|
||||
echo "$k=$(shquote "$v")"
|
||||
done
|
||||
) >$3
|
||||
redo-stamp <$3
|
||||
34
redoconf/redoconf.h.od
Normal file
34
redoconf/redoconf.h.od
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
redo-ifchange rc_vars
|
||||
. ./rc_vars
|
||||
|
||||
NL="
|
||||
"
|
||||
|
||||
# Escape double-quote and backslash so they can
|
||||
# be included as a C-style double-quoted string.
|
||||
cquote() {
|
||||
local v="$(printf '%s' "$1" | sed -e 's,[\"\\],\\&,g' -e 's,$, \\,')"
|
||||
printf '"%s"' "${v% \\}"
|
||||
}
|
||||
|
||||
is_number() {
|
||||
expr "$1" + 1 >/dev/null 2>&1
|
||||
}
|
||||
|
||||
(
|
||||
echo "/* Automatically generated by redoconf.h.od */"
|
||||
IFS="$NL"
|
||||
for k in $RC_KEYS; do
|
||||
[ "$k" != "RC_KEYS" ] || continue
|
||||
[ "$k" != "RC_INCLUDES" ] || continue
|
||||
eval v=\$$k
|
||||
if [ -z "$v" ]; then
|
||||
echo "#undef $k"
|
||||
elif is_number "$v"; then
|
||||
echo "#define $k $v"
|
||||
else
|
||||
echo "#define $k $(cquote "$v")"
|
||||
fi
|
||||
done
|
||||
) >$3
|
||||
redo-stamp <$3
|
||||
16
redoconf/run.od
Normal file
16
redoconf/run.od
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
. ./redoconf.rc
|
||||
rc_include rc/run.rc
|
||||
|
||||
if [ -n "$CAN_RUN" ]; then
|
||||
cat >$3 <<-EOF
|
||||
#!/bin/sh -e
|
||||
# Run the given program, possibly under an emulator.
|
||||
[ -n "\$1" ]
|
||||
unset DISPLAY
|
||||
exec $RUN "\$@"
|
||||
EOF
|
||||
chmod a+x "$3"
|
||||
redo-stamp <$3
|
||||
else
|
||||
echo "Cannot run programs; not creating run script." >&2
|
||||
fi
|
||||
71
redoconf/trycompile
Normal file
71
redoconf/trycompile
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#!/bin/sh -e
|
||||
die() {
|
||||
echo "$0: trycompile: $*" >&2
|
||||
exit 99
|
||||
}
|
||||
|
||||
ctype=$1
|
||||
linktype=$2
|
||||
code=$3
|
||||
case $ctype in
|
||||
cc)
|
||||
[ -n "$CC" ] || die 'must set $CC first.'
|
||||
useCC="$CC"
|
||||
useCF="$CFLAGS"
|
||||
useExt=".c"
|
||||
;;
|
||||
cxx)
|
||||
[ -n "$CXX" ] || die 'must set $CXX first.'
|
||||
useCC="$CXX"
|
||||
useCF="$CXXFLAGS"
|
||||
useExt=".cc"
|
||||
;;
|
||||
*)
|
||||
die "unknown compile type '$ctype'"
|
||||
;;
|
||||
esac
|
||||
case $linktype in
|
||||
link|run)
|
||||
[ -n "$LINK" ] || die 'must set $LINK first.'
|
||||
;;
|
||||
nolink)
|
||||
;;
|
||||
*)
|
||||
die "unknown link type '$linktype'"
|
||||
;;
|
||||
esac
|
||||
base="try.$$.tmp"
|
||||
out="$base.o"
|
||||
out2="$base.exe"
|
||||
src="$base$useExt"
|
||||
rm -f "$src" "$out" "$out2"
|
||||
set -x
|
||||
: "[trycompile]" "$@"
|
||||
main=
|
||||
[ -n "$RCC_NO_MAIN" ] || main="int main() { return 0; }"
|
||||
printf '%s' "
|
||||
$code
|
||||
|
||||
$main
|
||||
" >"$src"
|
||||
NL="
|
||||
"
|
||||
IFS="$NL"
|
||||
set +e
|
||||
set -f
|
||||
# We intentionally want to split the variables here,
|
||||
# splitting on $NL, so we don't quote them.
|
||||
# 'set -f' prevents interpreting wildcards, which
|
||||
# we don't want to treat as special.
|
||||
(
|
||||
$useCC $CPPFLAGS $useCF -o "$out" -c "$src" || exit
|
||||
if [ "$linktype" = "link" -o "$linktype" = "run" ]; then
|
||||
$LINK $LDFLAGS -o "$out2" "$out" $LIBS || exit
|
||||
fi
|
||||
if [ "$linktype" = "run" ]; then
|
||||
$RUN "./$out2" || exit
|
||||
fi
|
||||
)
|
||||
rv=$?
|
||||
rm -f "$src" "$out" "$out2"
|
||||
exit "$rv"
|
||||
58
redoconf/utils.sh
Normal file
58
redoconf/utils.sh
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
NL="
|
||||
"
|
||||
|
||||
# Like 'echo', but never processes backslash escapes.
|
||||
# (Some shells' builtin echo do, and some don't, so this
|
||||
# is safer.)
|
||||
xecho() {
|
||||
printf '%s\n' "$*"
|
||||
}
|
||||
|
||||
# Returns true if string $1 contains the line $2.
|
||||
# Lines are delimited by $NL.
|
||||
contains_line() {
|
||||
case "$NL$1$NL" in
|
||||
*"$NL$2$NL"*) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Split the first (up to) 20 words from $1,
|
||||
# returning a string where the words are separated
|
||||
# by $NL instead.
|
||||
#
|
||||
# To allow words including whitespace, you can backslash
|
||||
# escape the whitespace (eg. hello\ world). Backslashes
|
||||
# will be removed from the output string.
|
||||
#
|
||||
# We can use this to read pkg-config output, among other
|
||||
# things.
|
||||
#
|
||||
# TODO: find a POSIX sh way to eliminate the word limit.
|
||||
# I couldn't find an easy way to split on non-backslashed
|
||||
# whitespace without a fork-exec, which is too slow.
|
||||
# If we resorted to bashisms, we could use 'read -a',
|
||||
# but that's not portable.
|
||||
rc_splitwords() {
|
||||
xecho "$1" | (
|
||||
read v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 \
|
||||
v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 \
|
||||
x
|
||||
if [ -n "$x" ]; then
|
||||
echo "rc_splitwords: too many words" >&2
|
||||
exit 97
|
||||
fi
|
||||
for d in "$v0" "$v1" "$v2" "$v3" "$v4" \
|
||||
"$v5" "$v6" "$v7" "$v8" "$v9" \
|
||||
"$v10" "$v11" "$v12" "$v13" "$v14" \
|
||||
"$v15" "$v16" "$v17" "$v18" "$v19"; do
|
||||
[ -z "$d" ] || xecho "$d"
|
||||
done
|
||||
)
|
||||
}
|
||||
|
||||
# Escape single-quote characters so they can
|
||||
# be included as a sh-style single-quoted string.
|
||||
shquote() {
|
||||
printf "'%s'" "$(xecho "$1" | sed -e "s,','\\\\'',g")"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue