2 # vim: ts=2 sts=2 sw=2 et:
10 # all_c_obj will be filled by print_objects
13 # executables is an array of variable names used in the makefile to
14 # name an executable; the list of objects is assumed to be
16 executables=(GMQCC QCVM TESTSUITE PAK)
19 for i in "${executables[@]}"; do
25 # create all the object variables:
27 local common=(ansi.o util.o hash.o stat.o fs.o opts.o conout.o)
28 all_c_obj+=("${common[@]}")
29 local gmqcc=(main.o utf8.o
30 lexer.o parser.o ftepp.o
31 fold.o intrin.o correct.o
33 all_c_obj+=("${gmqcc[@]}")
35 all_c_obj+=("${qcvm[@]}")
36 local testsuite=(test.o)
37 all_c_obj+=("${testsuite[@]}")
39 all_c_obj+=("${pak[@]}")
41 GMQCC = gmqcc${cf_exesuffix}
42 QCVM = qcvm${cf_exesuffix}
43 TESTSUITE = testsuite${cf_exesuffix}
44 PAK = pak${cf_exesuffix}
46 QCVM_OBJ := ${common[@]} ${qcvm[@]}
47 GMQCC_OBJ := ${common[@]} ${gmqcc[@]}
48 TESTSUITE_OBJ := ${common[@]} ${testsuite[@]}
49 PAK_OBJ := ${common[@]} ${pak[@]}
52 printf 'ALL_PROGRAMS ='
53 for i in "${executables[@]}"; do
59 # generate the commands used to build objects and executables
60 # in a way that works with both BSD make and gmake by not relying
61 # on special vars like - also generate the .d files
63 # generate object rules to get the right path: $cf_dir
64 for obj in "${all_c_obj[@]}"; do
65 local c_src="${cf_dir}/${obj%.o}.c"
66 local d_inc="${obj}.d"
67 echo "${obj}: ${c_src}"
68 echo $'\t'"\$(CC) \$(CFLAGS) \$(CPPFLAGS) -c -o \$@ \"${c_src}\" -MMD -MF \"${d_inc}\" -MT \$@"
71 for exe in "${executables[@]}"; do
72 echo "\$(${exe}): \$(${exe}_OBJ)"
73 echo $'\t'"\$(CC) \$(LDFLAGS) -o \$(${exe}) \$(${exe}_OBJ) \$(LIBS)"
83 local mesg="$1"; shift
84 printf "fatal: ${mesg}\n" "$@"
89 local mesg="$1"; shift
90 printf "configure: ${mesg}\n" "$@"
98 --prefix=PREFIX change the install prefix [/usr/local]
99 --bindir=BINDIR target of executables [PREFIX/bin]
100 --datadir=DATADIR target of additional data [PREFIX/share]
101 --mandir=MANDIR target of manpages [DATADIR/man]
102 --man1dir=MAN1DIR manual section 1 [MANDIR/man1]
103 Environment variables:
110 while [ $# -ge 1 ]; do
112 --prefix=*) cf_prefix="${1#--prefix=}" ;;
113 --bindir=*) cf_bindir="${1#--bindir=}" ;;
114 --datadir=*) cf_datadir="${1#--datadir=}" ;;
115 --mandir=*) cf_mandir="${1#--mandir=}" ;;
116 --man1dir=*) cf_man1dir="${1#--man1dir=}" ;;
119 echo "Unknown parameter: $1"
128 # Some library functions
131 if which $1 >/dev/null 2>&1
137 # so we don't have to repeat the >/dev/null all the time
139 # strip parameters (ie, 'need_cmd $CC' with CC="gcc -m32" should work)
146 # Well we can expect those to exist, no?
152 # Let's figure out where we are...
157 cf_dir="$(readlink -f "${progname}")"
158 # or should we use the hopefully more reliable basename command?
159 cf_dir="${cf_dir%/*}"
161 if [[ $cf_dir == $cf_wd ]]; then
162 echo "Please run this script in a different directory \
163 to not overwrite the git working tree."
167 # execute a command inside $cf_dir
169 # do it in a subshell so we don't change directory ourselves
170 ( cd "${cf_dir}" && "$@" ) || false
177 has_cmd "${CC}" || CC=clang
178 has_cmd "${CC}" || CC=gcc
179 has_cmd "${CC}" || CC=cc
180 has_cmd "${CC}" || CC=tcc
181 has_cmd "${CC}" || die "No compiler found"
183 # We might add support for different compilers with a different CLI
186 if [[ $CC != clang && $CC != gcc && $CC != g++ ]]; then
187 cf_ccver="$(${CC} -v 2>&1)"
188 (( $? )) && die "Failed to retrieve compiler version info"
189 if (echo "${cf_ccver}" | grep -q '\<clang\|gcc\>'); then
190 msg "found compatible compiler"
192 die "don't know how to use this compiler..."
196 # Git information - that is, if git is available
199 # And provided we're in a git repo:
200 if [[ -d "${cf_dir}/.git" ]]; then
202 msg "reading git info"
203 cf_gitinfo_text="$(indir git describe --always)"
209 has_cmd valgrind && cf_valgrind=1
212 # default host specific values:
214 host="$(uname -s | tr A-Z a-z)"
217 cf_prefix="${cf_prefix:-/usr/local}"
218 cf_bindir="${cf_bindir:-${cf_prefix}/bin}"
219 cf_datadir="${cf_datadir:-${cf_prefix}/share}"
220 cf_mandir="${cf_mandir:-${cf_datadir}/man}"
221 cf_man1dir="${cf_man1dir:-${cf_mandir}/man1}"
225 cf_prefix="${cf_prefix:-}"
226 cf_bindir="${cf_bindir:-}"
227 cf_datadir="${cf_datadir:-}"
228 cf_mandir="${cf_mandir:-}"
229 cf_man1dir="${cf_man1dir:-}"
234 # for the default-supported compilers:
235 cf_cflags_gcc=(-Wall -Wextra -Werror -Wstrict-aliasing -Wno-attributes)
239 # compiler specific flags:
240 [[ $CC != g++ ]] && cf_cflags_gcc+=(-Wmissing-prototypes -Wstrict-prototypes)
241 [[ $CC = clang ]] && \
245 -Wno-format-nonliteral
246 -Wno-disabled-macro-expansion
249 -Wno-unknown-warning-option
252 if [[ $CC != tcc ]]; then
253 cf_cflags_gcc+=(-pedantic-errors)
255 cf_cflags_gcc+=(-Wno-pointer-sign -fno-common)
260 if (( cf_gitinfo )); then
261 cf_cflags_gcc+=(-DGMQCC_GITINFO="\"${cf_gitinfo_text}\"")
264 if (( ! cf_valgrind )); then
265 cf_cflags_gcc+=(-DNVALGRIND)
269 # Put the cflags/ldflags/libs we use into cf_cflags/ldflags/libs
271 case "${cf_cctype}" in
273 cf_cflags=("${cf_cflags_gcc[@]}")
274 cf_ldflags=("${cf_ldflags_gcc[@]}")
275 cf_libs=("${cf_libs_gcc[@]}")
278 die "compiler type '%s' not handled here!" "${cf_cctype}"
282 # Now generate our output file
284 echo "Generating Makefile"
287 # First: cflags and directories
292 CFLAGS = ${CFLAGS} ${cf_cflags[@]}
293 LDFLAGS = ${LDFLAGS} ${cf_ldflags[@]}
294 LIBS = ${LIBS} ${cf_libs[@]}
299 PREFIX = ${cf_prefix}
300 BINDIR = ${cf_bindir}
301 DATADIR = ${cf_datadir}
302 MANDIR = ${cf_mandir}
303 MAN1DIR = ${cf_man1dir}
307 # now all object variables
311 # the all rule to include all executables
314 # Now the Makefile.in
315 echo "# Makefile.in contents:"
320 # all the targets and how to build them
323 # include dependency files too
324 echo "-include *.o.d"
325 ) > "${cf_wd}/Makefile"