xref: /haiku/configure (revision 31f27c4d39887e0ef393db27279b8c154ccb1e4b)
1#!/bin/sh
2#
3# configure [ <options> ]
4
5# usage
6#
7# Prints usage.
8#
9usage()
10{
11	cat << EOF
12
13Usage: $0 <options>
14options:
15  --help                      Prints out this help.
16  --update                    Re-runs last configure invocation [must be given
17                              as first option!]
18  --bootstrap <haikuporter> <HaikuPorts cross repo> <HaikuPorts repo>
19                              Prepare for a bootstrap build. No pre-built
20                              packages will be used, instead they will be built
21                              from the sources (in several phases).
22                              <haikuporter> is the path to the haikuporter tool
23                              suitable for the host platform.
24                              <HaikuPorts cross repo> is the path to a checked
25                              out HaikuPorts cross-compilation repository.
26                              <HaikuPorts repo> is the path to a checked out
27                              HaikuPorts repository.
28  --build-cross-tools <arch>
29                              Assume cross compilation.
30                              Toolchain will be compiled and placed in the
31                              output directory under "cross-tools". The
32                              HAIKU_* tools variables will be set accordingly.
33                              <arch> specifies the target architecture, either
34                              "x86_gcc2", "x86", "x86_64", "ppc", "m68k",
35                              "arm", "arm64", "riscv64", "sparc"
36                              This option and --cross-tools-prefix can be
37                              specified multiple times. The first cross tools
38                              specify the primary tools, the subsequent ones the
39                              secondary tools (for "hybrid" images).
40  --cross-tools-prefix <prefix>
41                              Assume cross compilation. <prefix> should be a
42                              path to the directory where the cross
43                              compilation tools are located, plus the platform
44                              prefix, e.g. "/path/to/tools/i586-pc-haiku-".
45                              This overrides the HAIKU_* tool variables.
46  --cross-tools-source <buildtools dir>
47                              Toolchain sources for cross compilation.
48                              <buildtools dir> defines the location of the
49                              buildtools sources.
50  --distro-compatibility <level>
51                              The distribution's level of compatibility with
52                              the official Haiku distribution. The generated
53                              files will contain the respective trademarks
54                              accordingly.
55                              official -- the official Haiku distribution.
56                              compatible -- a Haiku Compatible (tm) distro.
57                              default -- any other distro (default value).
58  --host-only                 Configure for building tools for the build host
59                              only. Haiku cannot be built when configured like
60                              this.
61  --include-sources           Includes the source code of projects that require
62                              either an offer of source code or a copy of the
63                              patched sources. This is preferable when
64                              distributing on physical mediums.
65  --include-3rdparty          Include 3rdparty/ in the build system.
66  -j<n>                       Only relevant for --build-cross-tools. Is passed
67                              on to the make building the build tools.
68  --no-downloads              Do not download anything. Useful when trying to
69                              bootstrap and build Haiku from source only.
70  --target-arch <arch>        Haiku only: Specify the target architecture to
71                              build for. Must be one of the architectures of the
72                              host system. The installed build tools for that
73                              architecture will be used.
74                              This option can be specified multiple times. The
75                              first occurrence specifies the primary
76                              architecture of the Haiku to build, subsequent
77                              ones the secondary architectures.
78  --use-clang <arch>          Build with host Clang instead of GCC cross
79                              compiler, targeting <arch>
80  --use-gcc-pipe              Build with GCC option -pipe. Speeds up the build
81                              process, but uses more memory.
82  --use-gcc-graphite          Build with GCC Graphite engine for loop
83                              optimizations. (Only for GCC 4+.)
84  --use-32bit                 Use -m32 flag on 64bit host gcc compiler.
85  --no-full-xattr             Do not use Linux/*BSD/Darwin's native extended file
86                              attributes as Haiku attributes. If they are still
87                              available, they will be used to store hashes for
88                              the attribute emulation layer.
89  --no-xattr                  Do not use Linux/*BSD/Darwin's native extended file
90                              attributes for Haiku extended attributes at all,
91                              even if they are available.
92  --with-gdb <gdb sources dir>
93                              specify the path to a GDB source dir, to build
94                              GDB for each arch we build the cross-tools for.
95  --use-stack-protector       Build with stack protection enabled
96  --efi-signing-key           Private keyfile to sign any EFI bootloaders
97
98environment variables:
99  CC                          The host compiler. Defaults to "gcc".
100  HAIKU_AR_<arch>             The static library archiver for <arch>.
101                              Defaults to "ar".
102  HAIKU_CC_<arch>             The compiler for <arch>. Defaults to "gcc".
103  HAIKU_LD_<arch>             The <arch> linker. Defaults to "ld".
104  HAIKU_OBJCOPY_<arch>        The <arch> objcopy to be used. Defaults to
105                              "objcopy".
106  HAIKU_RANLIB_<arch>         The static library indexer for <arch>. Defaults
107                              to "ranlib".
108  HAIKU_STRIP_<arch>          The <arch> strip command. Defaults to "strip".
109  HAIKU_NASM                  The nasm assembler (x86 and x86_64 only).
110  HAIKU_CPPFLAGS_<arch>       The preprocessor flags for target architecture
111                              <arch>. Defaults to "".
112  HAIKU_CCFLAGS_<arch>        The C flags for target architecture <arch>.
113                              Defaults to "".
114  HAIKU_CXXFLAGS_<arch>       The C++ flags for target architecture <arch>.
115                              Defaults to "".
116  HAIKU_LINKFLAGS_<arch>      The flags passed to the compiler when linking for
117                              target architecture <arch>. Defaults to "".
118  HAIKU_LDFLAGS_<arch>        The linker flags for target architecture <arch>.
119                              Defaults to "".
120  HAIKU_ARFLAGS_<arch>        The flags passed to HAIKU_AR for target
121                              architecture <arch> for archiving. Defaults to
122                              "cru".
123  HAIKU_UNARFLAGS_<arch>      The flags passed to HAIKU_AR for target
124                              architecture <arch> for unarchiving. Defaults to
125                              "x".
126
127Non-default output directories:
128  By default all objects, build configuration, and other related files are
129  stored in /path/to/haiku_source/generated.  To store objects in a non-default
130  location, run "../../relative/path/to/haiku_source/configure <options>" from
131  within your non-default location.  "jam [ options ] targets" can then be run
132  directly inside your non-default location.  Another option is to invoke "jam
133  [ options ] targets" from within haiku_source.  This can be accomplished by
134  either "export HAIKU_OUTPUT_DIR=your non-default location" before invoking
135  jam or by creating a symlink of haiku_source/generated pointing to your
136  non-default location and running jam.
137
138
139EOF
140}
141
142# assertparam
143#
144# Checks whether at least one parameter is left.
145#
146assertparam()
147{
148	if [ $2 -lt 2 ]; then
149		echo $0: \`$1\': Parameter expected.
150		exit 1
151	fi
152}
153
154# assertparams
155#
156# Checks whether at least a certain number of parameters is left.
157#
158assertparams()
159{
160	if [ $3 -le $2 ]; then
161		echo $0: \`$1\': Not enough parameters.
162		exit 1
163	fi
164}
165
166# absolute_path
167#
168# returns the absolute path of a given path.
169#
170absolute_path()
171{
172	if [ "x$1" != "x${1#/}" ]; then
173		echo "$1"
174	else
175		echo "`pwd`/$1"
176	fi
177}
178
179# check_dir_exists
180#
181# check if a directory exists or not
182#
183check_dir_exists()
184{
185	if [ -d "$1" ]; then
186		return 0
187	else
188		return 1
189	fi
190}
191
192# check_file_exists
193#
194# check if a file exists or not
195#
196check_file_exists()
197{
198	if [ -f "$1" ]; then
199		return 0
200	else
201		return 1
202	fi
203}
204
205# real_path
206#
207# returns the realpath of a symbolic link.
208#
209real_path()
210{
211	perl -MCwd=realpath -e'print realpath($ARGV[0]), "\n"' "$1"
212}
213
214# relative_to
215#
216# returns $1 relative to $2
217#
218relative_to()
219{
220	perl -e 'use File::Spec; print File::Spec->abs2rel(@ARGV) . "\n"' \
221		"$1" "$2"
222}
223
224# valid_toolchain
225#
226# check if a toolchain is valid
227#
228valid_toolchain()
229{
230	TRIPLET="$1"
231	BASE="$2"
232	SOURCE="$3"
233	if [ ! -d "$BASE" ]; then
234		return 1
235	fi
236	if [ -f "$BASE/bin/$TRIPLET-gcc" ]; then
237		[ "$BASE/bin/$TRIPLET-gcc" -nt "$SOURCE/legacy/gcc/configure" ] && \
238			[ "$BASE/bin/$TRIPLET-gcc" -nt "$SOURCE/gcc/gcc/configure" ]
239		return $?
240	fi
241	return 1
242}
243
244# is_legacy_gcc
245#
246# Determines if the specified GCC version is a "legacy" (i.e. GCC < 4) one.
247#
248is_legacy_gcc()
249{
250	if [ `echo $1 | cut -d'.' -f1` -lt 4 ]; then
251		echo 1
252	else
253		echo 0
254	fi
255}
256
257# standard_gcc_settings
258#
259# Sets the variables for a GCC platform.
260#
261standard_gcc_settings()
262{
263	local gcc="$1"
264
265	if which greadlink > /dev/null 2>&1; then
266		readlink="greadlink -e"
267	elif which realpath > /dev/null 2>&1; then
268		readlink=realpath
269	elif readlink -e / > /dev/null 2>&1; then
270		readlink="readlink -e"
271	else
272		readlink=real_path
273	fi
274
275	# PLATFORM_LINKLIBS
276	local gcclib=`$gcc -print-libgcc-file-name`
277	local gccdir=`dirname ${gcclib}`
278
279	local gccRawVersion=`$gcc -dumpversion`
280	local gccMachine=`$gcc -dumpmachine`
281
282	# determine architecture from machine triple
283	case $gccMachine in
284		arm-*)		targetCpu=arm;;
285		aarch64-*)	targetCpu=arm64;;
286		i?86-*)		targetCpu=x86;;
287		m68k-*)		targetCpu=m68k;;
288		powerpc-*)	targetCpu=ppc;;
289		riscv64-*)	targetCpu=riscv64;;
290		sparc64-*)	targetCpu=sparc;;
291		x86_64-*)	targetCpu=x86_64;;
292		*)
293			echo "Unsupported gcc target machine: $gccMachine" >&2
294			exit 1
295			;;
296	esac
297
298	local targetArch=$targetCpu
299
300	case $gccRawVersion in
301		2.9*)
302			# check for correct (most up-to-date) legacy compiler and complain
303			# if an older one is installed
304			if [ $gccRawVersion != $haikuRequiredLegacyGCCVersion ]; then
305				echo "GCC version $haikuRequiredLegacyGCCVersion is required!";
306				echo "Please download it from www.haiku-os.org...";
307				exit 1;
308			fi
309
310			targetArch=x86_gcc2
311			;;
312	esac
313
314	local bootLibgcc
315	local bootLibSupCxx
316	local bootCxxHeaders
317	case $gccMachine in
318		x86_64-*)
319			# Boot loader is 32-bit, need the 32-bit libs and c++ config
320			bootLibgcc=`$gcc -m32 -print-file-name=libgcc.a`
321			bootLibSupCxx=`$gcc -m32 -print-file-name=libsupc++.a`
322
323			local headersBase=$gccdir/../../../..
324			local headers=$headersBase/$gccMachine/include/c++/$gccRawVersion
325			if [ ! -d $headers ]; then
326				headers=$headersBase/include/c++/$gccRawVersion
327			fi
328			bootCxxHeaders="$headers/$gccMachine/32"
329			;;
330	esac
331
332	# determine whether graphite loop optimization should/can be used
333	local useGraphite=`get_variable HAIKU_USE_GCC_GRAPHITE_$targetCpu`
334	if [ -z "$useGraphite" ]; then
335		useGraphite=$useGccGraphiteDefault
336	fi
337
338	if [ "$useGraphite" != 0 ]; then
339		UNUSED=`echo "int main() {}" | $gcc -xc -c -floop-block - 2>&1`
340		if [ $? != 0 ]; then
341			echo "GCC Graphite loop optimizations cannot be used on $targetArch"
342			useGraphite=0
343		fi
344	fi
345
346	set_variable HAIKU_CPU_$targetArch $targetCpu
347
348	get_build_tool_path CC_$targetArch "$gcc"
349	set_variable HAIKU_CC_IS_LEGACY_GCC_$targetArch \
350		`is_legacy_gcc $gccRawVersion`
351	set_variable HAIKU_CC_IS_CLANG_$targetArch $useClang
352	set_variable HAIKU_GCC_RAW_VERSION_$targetArch $gccRawVersion
353	set_variable HAIKU_GCC_MACHINE_$targetArch $gccMachine
354	set_variable HAIKU_GCC_LIB_DIR_$targetArch $gccdir
355	set_variable HAIKU_BOOT_CXX_HEADERS_DIR_$targetArch "$bootCxxHeaders"
356	set_variable HAIKU_BOOT_LIBSUPCXX_$targetArch "$bootLibSupCxx"
357	set_variable HAIKU_BOOT_LIBGCC_$targetArch $bootLibgcc
358	set_variable HAIKU_USE_GCC_GRAPHITE_$targetArch $useGraphite
359
360	standard_gcc_settings_targetArch=$targetArch
361}
362
363# set_variable
364#
365# Set the value of a variable.
366#
367set_variable()
368{
369	eval "$1=\"$2\""
370}
371
372# get_variable
373#
374# Echo the value of a variable.
375#
376get_variable()
377{
378	eval "echo \${$1}"
379}
380
381# set_default_value
382#
383# Set the value for a variable, if no value is set yet.
384#
385set_default_value()
386{
387	eval "$1=\${$1-$2}"
388}
389
390# get_build_tool_path
391#
392# Gets a usable absolute path of a build tool.
393#
394get_build_tool_path()
395{
396	local var="HAIKU_$1"
397	local varval="`get_variable $var`"
398	local cmd="$2"
399
400	if [ ! -z "$varval" ]; then
401		# this variable is already set (probably by user) so grab its contents
402		cmd=$varval
403	fi
404
405	local path=${cmd%% *}
406
407	if [ -f "$path" ]; then
408		# get absolute path from relative path
409		local oldPwd="`pwd`"
410		cd "`dirname "$path"`"
411		path="`pwd`/`basename "$path"`"
412		cd $oldPwd
413	else
414		which "$path" > /dev/null 2>&1 || {
415			echo "Build tool \"$path\" not found (maybe specify it in $var?)" >&2
416			exit 1
417		}
418	fi
419
420	if test "${cmd#* }" != "$cmd"; then
421		# $cmd contains arguments, so preserve them (and only them)
422		cmd=${cmd#* }
423	else
424		# $cmd does not contain arguments, so unset it
425		cmd=
426	fi
427	eval "$var=\"$path $cmd\""
428}
429
430# check_native_xattrs
431#
432# Checks the host platform's support for extended attributes.
433# 0: no support, 1: only enough for xattr-ref, 2: full support
434#
435check_native_xattrs()
436{
437	local xattr_set=
438	local xattr_set_args=
439	local xattr_get=
440	local xattr_get_args=
441	case $HOST_PLATFORM in
442		haiku_host)
443			xattr_set="addattr"; xattr_set_args="\$NAME \"\$VALUE\""
444			xattr_get="catattr"; xattr_get_args="\$NAME"
445			;;
446		darwin)
447			xattr_set="xattr"; xattr_set_args="-w \$NAME \"\$VALUE\""
448			xattr_get="xattr"; xattr_get_args="-p \$NAME"
449			;;
450		freebsd)
451			xattr_set="setextattr"; xattr_set_args="user \$NAME \"\$VALUE\""
452			xattr_get="getextattr"; xattr_get_args="user \$NAME"
453			;;
454		linux)
455			xattr_set="setfattr"; xattr_set_args="-n user.\$NAME -v \"\$VALUE\""
456			xattr_get="getfattr"; xattr_get_args="-n user.\$NAME"
457			;;
458		*)
459			return 0
460			;;
461	esac
462	if ! type $xattr_set >/dev/null 2>&1; then
463		echo "$0: could not find $xattr_set, assuming host has no extended attributes"
464		return 0
465	elif ! type $xattr_get >/dev/null 2>&1; then
466		echo "$0: could not find $xattr_get, assuming host has no extended attributes"
467		return 0
468	fi
469
470	mkdir -p "$outputDir"
471	echo "xattr test file" >"$outputDir/xattrtest"
472	local i=0
473	# on round 0, we test if we can set 3 attrs of 1K each (enough for xattr-ref)
474	# on round 1, we test if we can set 3 attrs of 45K each (enough for full xattr)
475	while [ $i -lt 2 ]; do
476		local j=0
477		while [ $j -lt 3 ]; do
478			NAME=attr$j
479			VALUE=`printf '%*s' $((1024 + $i * 45056)) "" | tr ' ' x`
480			if [ `echo -n $VALUE | wc -c` -lt $((1024 + $i * 45056)) ]; then
481				echo "$0: warning: could not generate test data for extended attributes"
482				rm "$outputDir/xattrtest"
483				return $i
484			elif ! $xattr_set `eval echo \"$xattr_set_args\"` \
485					"$outputDir/xattrtest" >/dev/null 2>&1 ; then
486				rm "$outputDir/xattrtest"
487				return $i
488			fi
489			j=$((j+1))
490		done
491		i=$((i+1))
492	done
493	rm "$outputDir/xattrtest"
494	return 2
495}
496
497is_in_list()
498{
499	local element
500	for element in $2; do
501		if [ "$1" = "$element" ]; then
502			return 0
503		fi
504	done
505	return 1
506}
507
508# check for --help or -h and show usage immediately
509if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
510	usage; exit 0;
511fi
512
513# get cwd and the source directory
514currentDir=`pwd`
515cd `dirname "$0"`
516sourceDir=`pwd`
517cd "$currentDir"
518
519# determine output directory
520if [ "$currentDir" = "$sourceDir" ]; then
521	outputDir=$currentDir/generated
522else
523	outputDir=$currentDir
524fi
525buildOutputDir="$outputDir/build"
526HAIKU_BUILD_ATTRIBUTES_DIR="$outputDir/attributes"
527buildConfigFile="$buildOutputDir/BuildConfig"
528
529# check for update request
530if [ "$1" = "--update" ]; then
531	if ! [ -e "$buildConfigFile" ]; then
532		echo $0 --update: \'$buildConfigFile\' not found - updating not possible.
533		exit 1
534	fi
535	# get last configure invocation and flags from BuildConfig and call ourselves with it
536	lastPwd=`grep "#d " "$buildConfigFile" | cut -c 4-`
537	lastConfig=`grep "#c " "$buildConfigFile" | cut -c 4-`
538	lastEnv=`grep "#e " "$buildConfigFile" | cut -c 4-`
539	lastArgs=`grep "#a " "$buildConfigFile" | cut -c 4-`
540	if [ -z "$lastConfig" ]; then
541		echo "$0 --update: The previous configure invocation was not properly" \
542			"encoded into '$buildConfigFile' - updating not possible."
543		exit 1
544	fi
545	cd "$lastPwd"
546	if [ -n "$lastEnv" ]; then
547		export $lastEnv
548	fi
549	$lastConfig $lastArgs
550	exit $?
551fi
552
553# backup the passed arguments
554configureArgs="$@"
555configurePath=$0
556
557# backup relevant environs
558configureEnvirons=
559for var in `env`; do
560	case "$var" in
561		CC\=*|HAIKU*\=*|JAMSHELL\=*)
562			configureEnvirons="$configureEnvirons $var"
563			;;
564	esac
565done
566
567# ensure umask is not too restrictive
568if [ `umask` -gt 22 ]; then
569	echo Your umask is too restrictive "(should be <= 0022;" is actually `umask`")"
570	echo
571	echo Additionally, if the source tree was cloned with a too-restrictive umask,
572	echo you will need to run \"git checkout\" again to fix this.
573	exit 1
574fi
575
576# internal default parameter values
577#
578platform=`uname`
579platformMachine=`uname  -m`
580targetArchs=
581buildCrossTools=
582buildCrossToolsScript="$sourceDir/build/scripts/build_cross_tools"
583buildCrossToolsJobs=
584useClang=0
585useGccGraphiteDefault=0
586unknownArchIndex=1
587haikuTargetArchs=
588gdbSources=
589
590if [ -z "$CC" ]; then
591	CC=gcc
592fi
593
594# detect the build platform
595case "${platform}" in
596	Darwin)  HOST_PLATFORM=darwin ;;
597	FreeBSD) HOST_PLATFORM=freebsd
598	         if [ "$HAIKU_HOST_USE_32BIT" = 1 ] ; then
599	         	echo Unsupported platform: FreeBSD ${platformMachine}
600	         	exit 1
601	         fi ;;
602	Haiku)   HOST_PLATFORM=haiku_host ;;
603	Linux)   HOST_PLATFORM=linux ;;
604	OpenBSD) HOST_PLATFORM=openbsd ;;
605	*)       echo Unsupported platform: ${platform}
606	         exit 1 ;;
607esac
608
609case $HOST_PLATFORM in
610	darwin|freebsd|openbsd) statCmd='stat -f' ;;
611	*)                      statCmd='stat -c' ;;
612esac
613
614# ensure git checkout was not done with a restrictive umask
615if [ `$statCmd '%a' "$sourceDir/data/system/boot/SetupEnvironment"` -lt 644 ]; then
616	echo "The source tree was cloned with a umask > 0022. It seems you"
617	echo have already corrected your umask, but not re-checked-out the
618	echo source tree. Try running:
619	echo "	git checkout --force"
620	echo to fix this problem.
621	exit 1
622fi
623
624# exported (BuildSetup) default parameter values
625#
626HOST_GCC_RAW_VERSION=`$CC -dumpversion`
627HOST_CC_IS_LEGACY_GCC=`is_legacy_gcc $HOST_GCC_RAW_VERSION`
628HOST_GCC_MACHINE=`$CC -dumpmachine`
629HAIKU_INCLUDE_SOURCES=0
630HAIKU_INCLUDE_3RDPARTY=0
631HAIKU_DISTRO_COMPATIBILITY=default
632TARGET_PLATFORM=haiku
633HAIKU_USE_GCC_PIPE=0
634HAIKU_HOST_USE_32BIT=0
635HAIKU_HOST_USE_XATTR=
636HAIKU_HOST_USE_XATTR_REF=
637HAIKU_HOST_BUILD_ONLY=0
638HOST_EXTENDED_REGEX_SED="sed -r"
639HOST_GCC_LD=`$CC -print-prog-name=ld`
640HOST_GCC_OBJCOPY=`$CC -print-prog-name=objcopy`
641HOST_SHA256=
642HOST_HAIKU_PORTER=
643HAIKU_PORTS=
644HAIKU_PORTS_CROSS=
645HAIKU_IS_BOOTSTRAP=0
646HAIKU_NO_DOWNLOADS=0
647
648HAIKU_PACKAGING_ARCHS=
649
650set_default_value HAIKU_NASM		nasm
651
652if sha256sum < /dev/null > /dev/null 2>&1; then
653	HOST_SHA256=sha256sum
654elif sha256 < /dev/null > /dev/null 2>&1; then
655	HOST_SHA256="sha256 -q"
656elif shasum < /dev/null > /dev/null 2>&1; then
657	HOST_SHA256="shasum -a 256"
658else
659	echo "Error: Neither sha256sum nor sha256 seem to be available!" >&2
660	exit 1
661fi
662
663haikuRequiredLegacyGCCVersion="2.95.3-haiku-2017_07_20"
664export haikuRequiredLegacyGCCVersion
665	# version of legacy gcc required to build haiku
666supportedTargetArchs="
667	arm
668	arm64
669	m68k
670	ppc
671	riscv64
672	sparc
673	x86
674	x86_64
675	x86_gcc2
676	"
677
678# parse parameters
679#
680while [ $# -gt 0 ] ; do
681	case "$1" in
682		--bootstrap)
683			assertparams "$1" 3 $#
684			HOST_HAIKU_PORTER="`absolute_path $2`"
685			HAIKU_PORTS_CROSS="`absolute_path $3`"
686			HAIKU_PORTS="`absolute_path $4`"
687			HAIKU_IS_BOOTSTRAP=1
688			HAIKU_NO_DOWNLOADS=1
689			check_file_exists "$HOST_HAIKU_PORTER" || (
690				echo "Invalid path to haikuporter: $HOST_HAIKU_PORTER" >&2
691				exit 1
692			)
693			check_dir_exists "$HAIKU_PORTS" || (
694				echo "Non-existent directory $HAIKU_PORTS" >&2
695				exit 1
696			)
697			check_dir_exists "$HAIKU_PORTS_CROSS" || (
698				echo "Non-existent directory $HAIKU_PORTS_CROSS" >&2
699				exit 1
700			)
701			shift 4
702			;;
703		--cross-tools-source)
704			assertparam "$1" $#
705			buildCrossTools=$2
706			shift 2
707			;;
708		--build-cross-tools)
709			assertparam "$1" $#
710			targetArch=$2
711			shift 2
712			case "$targetArch" in
713				x86_gcc2)	targetMachine=i586-pc-haiku;;
714				x86)		targetMachine=i586-pc-haiku;;
715				x86_64)		targetMachine=x86_64-unknown-haiku;;
716				ppc)		targetMachine=powerpc-apple-haiku;;
717				m68k)		targetMachine=m68k-unknown-haiku;;
718				arm)		targetMachine=arm-unknown-haiku;;
719				arm64)		targetMachine=aarch64-unknown-haiku;;
720				riscv64)	targetMachine=riscv64-unknown-haiku;;
721				sparc)		targetMachine=sparc64-unknown-haiku;;
722				*)
723					echo "Unsupported target architecture: $targetArch" >&2
724					exit 1
725					;;
726			esac
727			set_variable buildCrossToolsMachine_$targetArch $targetMachine
728			targetArchs="$targetArchs $targetArch"
729			;;
730		--cross-tools-prefix)
731			assertparam "$1" $#
732			targetArch=unknown${unknownArchIndex}
733			set_variable crossToolsPrefix_$targetArch "$2"
734			targetArchs="$targetArchs $targetArch"
735			unknownArchIndex=$(($unknownArchIndex + 1))
736			shift 2
737			;;
738		--distro-compatibility)
739			assertparam "$1" $#
740			HAIKU_DISTRO_COMPATIBILITY=$2
741			case "$HAIKU_DISTRO_COMPATIBILITY" in
742				official)	;;
743				compatible)	;;
744				default)	;;
745				*)			echo "Invalid distro compatibility" \
746								"level: $HAIKU_DISTRO_COMPATIBILITY"
747							exit 1;;
748			esac
749			shift 2
750			;;
751		--host-only)	HAIKU_HOST_BUILD_ONLY=1; shift 1;;
752		--include-sources)	HAIKU_INCLUDE_SOURCES=1; shift 1;;
753		--include-3rdparty)	HAIKU_INCLUDE_3RDPARTY=1; shift 1;;
754        -j*)				buildCrossToolsJobs="$1"; shift 1;;
755		--no-downloads)	HAIKU_NO_DOWNLOADS=1; shift 1;;
756		--target-arch)
757			assertparam "$1" $#
758			targetArch=$2
759			shift 2
760			if [ ! "$platform" = Haiku ]; then
761				echo "--target-arch can only be specified on Haiku." >&2
762				exit 1
763			fi
764			is_in_list "$targetArch" "$supportedTargetArchs" || (
765				echo "Unsupported target architecture: \"$targetArch\"" >&2
766				exit 1
767			)
768			haikuTargetArchs="$haikuTargetArchs $targetArch"
769			;;
770		--use-clang)
771			assertparam "$1" $#
772			targetArch=$2
773			useClang=1
774			case "$targetArch" in
775				x86)		targetMachine=i586-pc-haiku;;
776				x86_64)		targetMachine=x86_64-unknown-haiku;;
777				ppc)		targetMachine=powerpc-apple-haiku;;
778				arm)		targetMachine=arm-unknown-haiku;;
779				arm64)		targetMachine=aarch64-unknown-haiku;;
780				riscv64)	targetMachine=riscv64-unknown-haiku;;
781				sparc)		targetMachine=sparc64-unknown-haiku;;
782				*)
783					echo "Unsupported target architecture: $2" >&2
784					exit 1
785					;;
786			esac
787			get_build_tool_path clang clang
788			if [ -z `get_variable "crossToolsPrefix_$targetArch"` ] \
789					&& [ -z `get_variable buildCrossToolsMachine_$targetArch` ]; then
790				set_variable crossToolsPrefix_$targetArch llvm-
791			fi
792			clangVersion=`$HAIKU_clang -v 2>&1 | head -1 | cut -d " " -f3`
793			if [ `echo $clangVersion | cut -d'.' -f1` -lt 7 ]; then
794				echo "Haiku requires Clang 7 or better to build, but you have $clangVersion."
795				echo "Please install a newer version."
796				exit 1
797			fi
798			targetArchs="$targetArchs $targetArch"
799			shift 2
800			;;
801		--use-gcc-pipe)	HAIKU_USE_GCC_PIPE=1; shift 1;;
802		--use-gcc-graphite)	useGccGraphiteDefault=1; shift 1;;
803		--use-32bit)	HAIKU_HOST_USE_32BIT=1; shift 1;;
804		--no-full-xattr)HAIKU_HOST_USE_XATTR=0; shift 1;;
805		--no-xattr)		HAIKU_HOST_USE_XATTR_REF=0; shift 1;;
806		--with-gdb)	gdbSources=$2; shift 2;;
807		--use-stack-protector)	HAIKU_USE_STACK_PROTECTOR=1; shift 1;;
808		--efi-signing-key)
809			assertparam "$1" $#
810			HAIKU_EFI_SIGNING_KEY="$2"
811			shift 2
812			;;
813		*)				echo Invalid argument: \`$1\'; exit 1;;
814	esac
815done
816
817# check for case-sensitive filesystem
818mkdir haikuCaseTest 2>/dev/null
819mkdir haikucasetest 2>/dev/null
820caseInsensitive=$?
821rmdir haikuCaseTest haikucasetest 2>/dev/null
822if [ $caseInsensitive != 0 ]; then
823	echo "You need a case-sensitive file-system to build Haiku."
824	if [ $HOST_PLATFORM = "darwin" ]; then
825		echo "You can create a case-sensitive disk image using Disk Utility."
826	fi
827	exit 1
828fi
829
830# check xattr support
831if [ -z $HAIKU_HOST_USE_XATTR_REF ]; then
832	check_native_xattrs
833	attrSupport=$?
834	if [ $attrSupport = 2 ] && [ -z $HAIKU_HOST_USE_XATTR ]; then
835		HAIKU_HOST_USE_XATTR=1
836	elif [ $attrSupport = 1 ]; then
837		HAIKU_HOST_USE_XATTR_REF=1
838	fi
839fi
840if [ -z $HAIKU_HOST_USE_XATTR ]; then HAIKU_HOST_USE_XATTR=0; fi
841if [ -z $HAIKU_HOST_USE_XATTR_REF ]; then HAIKU_HOST_USE_XATTR_REF=0; fi
842
843# determine how to invoke sed with extended regexp support for non-GNU sed
844if [ $HOST_PLATFORM = "darwin" ]; then
845	HOST_EXTENDED_REGEX_SED="sed -E"
846fi
847
848# pick a JAMSHELL
849if [ "$JAMSHELL" = "" ]; then
850	if check_file_exists /bin/dash; then
851		JAMSHELL=/bin/dash
852	else
853		JAMSHELL=/bin/sh
854	fi
855fi
856if ! $JAMSHELL -c true; then
857	echo "$JAMSHELL does not work! Please specify a working JAMSHELL."
858	exit 1
859fi
860
861# locate python
862if python3 --version < /dev/null > /dev/null 2>&1; then
863	HOST_PYTHON="python3"
864elif python --version < /dev/null > /dev/null 2>&1; then
865	HOST_PYTHON="python"
866else
867	echo "a python interpreter is required"
868	exit 1
869fi
870
871# check if nasm can actually output ELF files
872# (the stock version in OSX can't)
873# XXX: should probably only test for x86* arch
874if [ "$("$HAIKU_NASM" -hf | grep -c elf'[36][24] ')" -ne "2" ]; then
875	echo "$HAIKU_NASM cannot generate ELF files. Please install a working version."
876	if [ $HOST_PLATFORM = "darwin" ]; then
877		echo "You can install it from Mac Ports."
878		echo "Mac Ports is available at: http://www.macports.org/"
879	fi
880	exit 1
881fi
882
883# create output directory
884mkdir -p "$buildOutputDir" || exit 1
885
886if [ "$HAIKU_HOST_BUILD_ONLY" = 1 ]; then
887	invalidCommand=$sourceDir/build/scripts/host_build_only
888	HAIKU_AR=$invalidCommand
889	HAIKU_CC=$invalidCommand
890	HAIKU_LD=$invalidCommand
891	HAIKU_OBJCOPY=$invalidCommand
892	HAIKU_RANLIB=$invalidCommand
893	HAIKU_ELFEDIT=$invalidCommand
894	HAIKU_NASM=$invalidCommand
895	HAIKU_STRIP=$invalidCommand
896else
897	# On Haiku determine target architectures and tools automatically.
898	if [ -z "$targetArchs" ]; then
899		if [ $HOST_PLATFORM != haiku_host ]; then
900			echo "Please specify the build tools to use or build (via" \
901				"--cross-tools-prefix or --build-cross-tools) or specify a" \
902				"host-only build (--host-only)." >&2
903			echo "For more info, invoke $0 --help"
904			exit 1
905		fi
906
907		# determine primary architecture
908		targetArch=`package list -i /system/packages/haiku-*.hpkg \
909			| sed '/^\s*architecture:/!d; s,^\s*architecture:\s*,,'`
910		is_in_list "$targetArch" "$supportedTargetArchs" || (
911			echo "Unsupported target architecture: \"$targetArch\"" >&2
912			exit 1
913		)
914		targetArchs=$targetArch
915
916		set_default_value HAIKU_AR_$targetArch			ar
917		set_default_value HAIKU_CC_$targetArch			gcc
918		set_default_value HAIKU_LD_$targetArch			ld
919		set_default_value HAIKU_OBJCOPY_$targetArch		objcopy
920		set_default_value HAIKU_RANLIB_$targetArch		ranlib
921		set_default_value HAIKU_ELFEDIT_$targetArch		elfedit
922		set_default_value HAIKU_STRIP_$targetArch		strip
923
924		# determine secondary architectures
925		for targetArch in $supportedTargetArchs; do
926			if [ -e /system/packages/haiku_$targetArch-*.hpkg ]; then
927				targetArchs="$targetArchs $targetArch"
928				set_default_value HAIKU_AR_$targetArch		ar-$targetArch
929				set_default_value HAIKU_CC_$targetArch		gcc-$targetArch
930				set_default_value HAIKU_LD_$targetArch		ld-$targetArch
931				set_default_value HAIKU_OBJCOPY_$targetArch	objcopy-$targetArch
932				set_default_value HAIKU_RANLIB_$targetArch	ranlib-$targetArch
933				set_default_value HAIKU_ELFEDIT_$targetArch	elfedit-$targetArch
934				set_default_value HAIKU_STRIP_$targetArch	strip-$targetArch
935			fi
936		done
937
938		# The target architectures might have been specified explicitly.
939		if [ -n "$haikuTargetArchs" ]; then
940			for targetArch in $haikuTargetArchs; do
941				is_in_list "$targetArch" "$targetArchs" || (
942					echo "Unsupported target architecture: \"$targetArch\"." \
943						"Only native architectures of the host platform can" \
944						"be specified." >&2
945					exit 1
946				)
947			done
948			targetArchs="$haikuTargetArchs"
949		fi
950	fi
951
952	if [ "$targetArchs" = " x86_gcc2" ]; then
953		echo "Building a GCC2-only Haiku is no longer supported."
954		echo "Please configure the secondary architecture."
955		exit 1
956	fi
957
958	isPrimaryArch=1
959	for targetArch in $targetArchs; do
960		# Note: targetArch is "unknown<n>" at this point if a cross-tools
961		# prefix was specified. The standard_gcc_settings call below will get
962		# the actual architecture.
963
964		if test "${HAIKU_PACKAGING_ARCHS#*$targetArch\b}" != "$HAIKU_PACKAGING_ARCHS"; then
965			# somehow we wound up with a duplicate arch; skip this one
966			continue
967		fi
968
969		crossToolsPrefix=`get_variable crossToolsPrefix_$targetArch`
970
971		# build cross tools from sources
972		if [ -n "$buildCrossTools" -a -z "$crossToolsPrefix" ]; then
973			crossToolsDir="$outputDir/cross-tools-$targetArch"
974			targetMachine=`get_variable buildCrossToolsMachine_$targetArch`
975			script="$buildCrossToolsScript"
976			scriptArgs=
977			if [ $targetArch != x86_gcc2 ]; then
978				script="${script}_gcc4"
979				scriptArgs="$targetMachine"
980				set_default_value HAIKU_USE_GCC_GRAPHITE_$targetArch	\
981					$useGccGraphiteDefault
982			fi
983			secondaryArch=
984			if [ -z "$isPrimaryArch" ]; then
985				secondaryArch=$targetArch
986			fi
987
988			case $HOST_PLATFORM in
989				freebsd|openbsd)	MAKE=gmake;;
990				*)					MAKE=make;;
991			esac
992
993			if ! valid_toolchain "${targetMachine}" "${crossToolsDir}" "${buildCrossTools}"; then
994				MAKE=$MAKE \
995				SECONDARY_ARCH=$secondaryArch \
996				HAIKU_USE_GCC_GRAPHITE=`get_variable \
997					HAIKU_USE_GCC_GRAPHITE_$targetArch` \
998				HAIKU_USE_GCC_PIPE=$HAIKU_USE_GCC_PIPE \
999				HAIKU_USE_GDB="$gdbSources" \
1000				"$script" $scriptArgs "$sourceDir" "$buildCrossTools" \
1001					"$crossToolsDir" $buildCrossToolsJobs || exit 1
1002			else
1003				echo "$targetArch crosstools already exist in $crossToolsDir; skipping build"
1004			fi
1005			crossToolsPrefix="$crossToolsDir/bin/${targetMachine}-"
1006		fi
1007
1008		# prepare gcc settings and get the actual target architecture
1009		if [ $useClang = 1 ]; then
1010			gcc="$HAIKU_clang -target ${targetMachine}"
1011			if [ ! -z "${crossToolsPrefix}" ]; then
1012				gcc="$gcc -B ${crossToolsPrefix}"
1013			fi
1014
1015			# Clang's compiler intrinsics are not compatible with GCC's or even
1016			# across versions of Clang, so we must collect them for use in the build.
1017			mkdir -p "$outputDir/clang_headers" || exit 1
1018			clangHeadersDir=`$gcc -print-resource-dir`/include/
1019			case $targetArch in
1020				x86*) cp $clangHeadersDir/*intrin* $clangHeadersDir/mm3* "$outputDir/clang_headers" || exit 1 ;;
1021				ppc*) cp $clangHeadersDir/*altivec* "$outputDir/clang_headers" || exit 1 ;;
1022				arm*) cp $clangHeadersDir/*arm* "$outputDir/clang_headers" || exit 1 ;;
1023			esac
1024		elif [ -z "${crossToolsPrefix}" ]; then
1025			gcc=`get_variable HAIKU_CC_$targetArch`
1026		else
1027			gcc="${crossToolsPrefix}gcc"
1028		fi
1029		standard_gcc_settings "$gcc"
1030		targetArch=$standard_gcc_settings_targetArch
1031
1032		# set default values for flags
1033		set_default_value HAIKU_CPPFLAGS_$targetArch	""
1034		set_default_value HAIKU_CCFLAGS_$targetArch		""
1035		set_default_value HAIKU_CXXFLAGS_$targetArch	""
1036		set_default_value HAIKU_LINKFLAGS_$targetArch	""
1037		set_default_value HAIKU_LDFLAGS_$targetArch		""
1038		set_default_value HAIKU_ARFLAGS_$targetArch		cru
1039		set_default_value HAIKU_UNARFLAGS_$targetArch	x
1040
1041		# Override the cross tools variables, if the tools were built or a
1042		# prefix was specified.
1043		if [ $useClang = 1 ]; then
1044			get_build_tool_path LD_$targetArch ld.lld
1045			get_build_tool_path ELFEDIT_$targetArch elfedit
1046		elif [ -n "$crossToolsPrefix" ]; then
1047			get_build_tool_path LD_$targetArch ${crossToolsPrefix}ld
1048			if [ `get_variable HAIKU_CC_IS_LEGACY_GCC_$targetArch` -eq 0 ]; then
1049				get_build_tool_path ELFEDIT_$targetArch ${crossToolsPrefix}elfedit
1050			fi
1051		fi
1052		if [ -n "$crossToolsPrefix" ]; then
1053			get_build_tool_path AR_$targetArch ${crossToolsPrefix}ar
1054			get_build_tool_path OBJCOPY_$targetArch ${crossToolsPrefix}objcopy
1055			get_build_tool_path RANLIB_$targetArch ${crossToolsPrefix}ranlib
1056			get_build_tool_path STRIP_$targetArch ${crossToolsPrefix}strip
1057		fi
1058
1059		# check whether the Haiku compiler really targets Haiku
1060		targetMachine=`get_variable HAIKU_GCC_MACHINE_$targetArch`
1061		case "$targetMachine" in
1062			*-*-haiku)	;;
1063			*)
1064				echo The compiler specified as Haiku target compiler is not a \
1065				valid Haiku cross-compiler. Please see ReadMe.cross-compile. >&2
1066				echo compiler: $HAIKU_CC
1067				echo compiler is configured for target: $targetMachine
1068				exit 1 ;;
1069		esac
1070
1071		HAIKU_PACKAGING_ARCHS="$HAIKU_PACKAGING_ARCHS $targetArch"
1072		isPrimaryArch=
1073	done
1074fi
1075
1076# Generate BuildConfig
1077cat << EOF > "$buildConfigFile"
1078# -- WARNING --
1079# This file was AUTOMATICALLY GENERATED by configure, and will be completely
1080# overwritten the next time configure is run.
1081#
1082#d ${currentDir}
1083#c ${configurePath}
1084#e ${configureEnvirons}
1085#a ${configureArgs}
1086
1087HOST_PLATFORM				?= "${HOST_PLATFORM}" ;
1088TARGET_PLATFORM 			?= "${TARGET_PLATFORM}" ;
1089HAIKU_PACKAGING_ARCHS		?= ${HAIKU_PACKAGING_ARCHS} ;
1090
1091HAIKU_NO_DOWNLOADS			?= "${HAIKU_NO_DOWNLOADS}" ;
1092HAIKU_INCLUDE_SOURCES		?= "${HAIKU_INCLUDE_SOURCES}" ;
1093HAIKU_INCLUDE_3RDPARTY		?= "${HAIKU_INCLUDE_3RDPARTY}" ;
1094HAIKU_DISTRO_COMPATIBILITY	?= "${HAIKU_DISTRO_COMPATIBILITY}" ;
1095
1096HAIKU_USE_GCC_PIPE			?= "${HAIKU_USE_GCC_PIPE}" ;
1097HAIKU_HOST_USE_32BIT		?= "${HAIKU_HOST_USE_32BIT}" ;
1098HAIKU_HOST_USE_XATTR		?= "${HAIKU_HOST_USE_XATTR}" ;
1099HAIKU_HOST_USE_XATTR_REF	?= "${HAIKU_HOST_USE_XATTR_REF}" ;
1100HAIKU_HOST_BUILD_ONLY		?= "${HAIKU_HOST_BUILD_ONLY}" ;
1101
1102JAMSHELL					?= ${JAMSHELL} -e -c ;
1103
1104HOST_CC						?= ${CC} ;
1105HOST_CC_IS_LEGACY_GCC		?= ${HOST_CC_IS_LEGACY_GCC} ;
1106HOST_GCC_MACHINE			?= ${HOST_GCC_MACHINE} ;
1107HOST_LD						?= ${HOST_GCC_LD} ;
1108HOST_OBJCOPY				?= ${HOST_GCC_OBJCOPY} ;
1109HOST_EXTENDED_REGEX_SED		?= ${HOST_EXTENDED_REGEX_SED} ;
1110HOST_SHA256					?= ${HOST_SHA256} ;
1111HOST_PYTHON					?= ${HOST_PYTHON} ;
1112HAIKU_NASM					?= ${HAIKU_NASM} ;
1113
1114HAIKU_BUILD_ATTRIBUTES_DIR	?= "${HAIKU_BUILD_ATTRIBUTES_DIR}" ;
1115
1116HOST_HAIKU_PORTER			?= ${HOST_HAIKU_PORTER} ;
1117HAIKU_PORTS					?= ${HAIKU_PORTS} ;
1118HAIKU_PORTS_CROSS			?= ${HAIKU_PORTS_CROSS} ;
1119HAIKU_IS_BOOTSTRAP			?= ${HAIKU_IS_BOOTSTRAP} ;
1120
1121HAIKU_BOOT_EFI_PRIVATE_KEYFILE	?= ${HAIKU_EFI_SIGNING_KEY} ;
1122EOF
1123
1124for targetArch in $HAIKU_PACKAGING_ARCHS; do
1125	variables="
1126		HAIKU_CC					HAIKU_CC
1127		HAIKU_CC_IS_LEGACY_GCC		HAIKU_CC_IS_LEGACY_GCC
1128		HAIKU_CC_IS_CLANG			HAIKU_CC_IS_CLANG
1129		HAIKU_USE_GCC_GRAPHITE		HAIKU_USE_GCC_GRAPHITE
1130		HAIKU_CPU					HAIKU_CPU
1131		HAIKU_GCC_MACHINE			HAIKU_GCC_MACHINE
1132		HAIKU_GCC_LIB_DIR			HAIKU_GCC_LIB_DIR
1133		HAIKU_BOOT_LIBGCC			HAIKU_BOOT_LIBGCC
1134		HAIKU_BOOT_LIBSUPC++		HAIKU_BOOT_LIBSUPCXX
1135		HAIKU_AR					HAIKU_AR
1136		HAIKU_LD					HAIKU_LD
1137		HAIKU_OBJCOPY				HAIKU_OBJCOPY
1138		HAIKU_RANLIB				HAIKU_RANLIB
1139		HAIKU_ELFEDIT				HAIKU_ELFEDIT
1140		HAIKU_STRIP					HAIKU_STRIP
1141		HAIKU_CPPFLAGS				HAIKU_CPPFLAGS
1142		HAIKU_CCFLAGS				HAIKU_CCFLAGS
1143		HAIKU_C++FLAGS				HAIKU_CXXFLAGS
1144		HAIKU_LINKFLAGS				HAIKU_LINKFLAGS
1145		HAIKU_LDFLAGS				HAIKU_LDFLAGS
1146		HAIKU_ARFLAGS				HAIKU_ARFLAGS
1147		HAIKU_UNARFLAGS				HAIKU_UNARFLAGS
1148		"
1149	set -- $variables
1150	while [ $# -ge 2 ]; do
1151		value=`get_variable ${2}_$targetArch`
1152		echo "${1}_${targetArch} ?= $value ;" >> "$buildConfigFile"
1153		shift 2
1154	done
1155
1156	# For variables that may have long values, distribute them over multiple
1157	# lines so that jam doesn't hit the maximum line length.
1158	variables="
1159		HAIKU_BOOT_C++_HEADERS_DIR	HAIKU_BOOT_CXX_HEADERS_DIR
1160		"
1161	set -- $variables
1162	while [ $# -ge 2 ]; do
1163		echo "${1}_${targetArch} ?= " >> "$buildConfigFile"
1164		get_variable ${2}_$targetArch | xargs -n 1 echo "   " \
1165			>> "$buildConfigFile"
1166		echo "    ;" >> "$buildConfigFile"
1167		shift 2
1168	done
1169done
1170
1171
1172# Generate a Jamfile in the output directory.
1173
1174cat << EOF > $outputDir/Jamfile
1175# -- WARNING --
1176# This file was AUTOMATICALLY GENERATED by configure, and will be completely
1177# overwritten the next time configure is run.
1178
1179HAIKU_TOP			= $(relative_to "${sourceDir}" "${outputDir}") ;
1180HAIKU_OUTPUT_DIR	= . ;
1181
1182include [ FDirName \$(HAIKU_TOP) Jamfile ] ;
1183
1184EOF
1185
1186echo "Configured successfully!"
1187