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