xref: /freebsd/contrib/bmake/boot-strap (revision c60f6422ffae3ea85e7b10bad950ad27c463af18)
1:
2# NAME:
3#	boot-strap
4#
5# SYNOPSIS:
6#	boot-strap ["options"]
7#	boot-strap --prefix=/opt --install
8#	boot-strap --prefix=$HOME --install-host-target -DWITH_PROG_VERSION
9#	boot-strap ["options"] op=build
10#	boot-strap ["options"] op=install
11#
12# DESCRIPTION:
13#	This script is used to configure/build bmake it builds for
14#	each host-target in a different subdir to keep the src clean.
15#	There is no requirement for an existing make(1).
16#
17#	On successful completion if no '--install' flag is given,
18#	it echos a command to do installation.
19#
20#	The variable "op" defaults to 'all', and is affected by
21#	'--install' flag as above.
22#	Other values include:
23#
24#	configure
25#		Just run 'configure'
26#
27#	build
28#		If 'configure' has not been done, do it, then
29#		run the build script, and finally 'test'.
30#
31#	install
32#		If 'build' has not been done, do it, 'test' then
33#		install.
34#
35#	clean
36#		attempt to clean up
37#
38#	test
39#		run the unit-tests.  Done automatically after 'build'
40#		and before 'install'.
41#
42#	The above are leveraged by a trivial makefile for the benefit
43#	of those that have './configure; make; make install' baked
44#	into them.
45#
46#	Options:
47#
48#	-c "rc"
49#		Pick up settings from "rc".
50#		We look for '.bmake-boot-strap.rc' before processing
51#		options (unless SKIP_RC is set in environment).
52#
53#	--share "share_dir"
54#		Where to put man pages and mk files.
55#		If $prefix ends in $HOST_TARGET, and $prefix/../share
56#		exits, the default will be that rather than $prefix/share.
57#
58#	--mksrc "mksrc"
59#		Indicate where the mk files can be found.
60#		Default is $Mydir/mk
61#
62#	--install
63#		If build and test work, run bmake install.
64#		BINDIR=$prefix/bin
65#		SHAREDIR=$prefix/share
66#
67#	--install-host-target
68#		As for '--install' but BINDIR=$prefix/$HOST_TARGET/bin
69#		This is useful when $prefix/ is shared by multiple
70#		machines.
71#
72#	Flags relevant when installing:
73#
74#	-DWITHOUT_INSTALL_MK
75#		Skip installing mk files.
76#		By default they will be installed to $prefix/share/mk
77#
78#	-DWITH_PROG_VERSION
79#		Install 'bmake' as 'bmake-$MAKE_VERSION'
80#		A symlink will be made as 'bmake' unless
81#		-DWITHOUT_PROG_LINK is set.
82#
83#	Possibly useful configure_args:
84#
85#	--without-makefile
86#		do not generate 'makefile'.
87#
88#		'makefile' is used to enable the classic
89#		'./configure; make; make install' dance, but on
90#		systems with case insensitive filesystems it can lead
91#		to infinite recursion.
92#
93#		It is disabled by default on Darwin, and Cygwin.
94#
95#	--without-meta
96#		disable use of meta mode.
97#
98#		Even without filemon(9) meta mode is very useful
99#		both for debugging build and improving reliability of
100#		update builds.
101#
102#	--without-filemon
103#		disable use of filemon(9) which is currently only
104#		available for NetBSD and FreeBSD.
105#
106#	--with-filemon=ktrace
107#		on NetBSD or others with fktrace(2), use ktrace
108#		version of filemon.
109#
110#	--with-filemon="path/to/filemon.h"
111#		enables use of filemon(9) by meta mode.
112#
113#	--with-machine="machine"
114#		set "machine" to override that determined by
115#		machine.sh
116#
117#	--with-force-machine="machine"
118#		force "machine" even if uname(3) provides a value.
119#
120#	--with-machine_arch="machine_arch"
121#		set "machine_arch" to override that determined by
122#		machine.sh
123#
124#	--with-force_machine_arch="machine_arch"
125#		force "machine_arch" to override that determined by
126#		machine.sh
127#
128#	--with-default-sys-path="syspath"
129#		set an explicit default "syspath" which is where bmake
130#		will look for sys.mk and friends.
131#
132# AUTHOR:
133#	Simon J. Gerraty <sjg@crufty.net>
134
135# RCSid:
136#	$Id: boot-strap,v 1.62 2025/11/15 16:53:14 sjg Exp $
137#
138#	@(#) Copyright (c) 2001 Simon J. Gerraty
139#
140#	This file is provided in the hope that it will
141#	be of use.  There is absolutely NO WARRANTY.
142#	Permission to copy, redistribute or otherwise
143#	use this file is hereby granted provided that
144#	the above copyright notice and this notice are
145#	left intact.
146#
147#	Please send copies of changes and bug-fixes to:
148#	sjg@crufty.net
149#
150
151Mydir=`dirname $0`
152. "$Mydir/os.sh"
153case "$Mydir" in
154/*) ;;
155*) Mydir=`cd "$Mydir" && 'pwd'`;;
156esac
157
158Usage() {
159	[ "$1" ] && echo "ERROR: $@" >&2
160	echo "Usage:" >&2
161	echo "$0 [--<configure_arg> ...][<prefix>][--install]" >&2
162	exit 1
163}
164
165Error() {
166	echo "ERROR: $@" >&2
167	exit 1
168}
169
170source_rc() {
171	rc="$1"; shift
172	for d in ${*:-""}
173	do
174		r="${d:+$d/}$rc"
175		[ -f "$r" -a -s "$r" ] || continue
176		echo "NOTE: reading $r"
177		. "$r"
178		break
179	done
180}
181
182have() {
183	case `(type "$1") 2>&1` in
184	*" found") return 1;;
185	esac
186	return 0
187}
188
189Env() {
190	have env && env || set
191}
192
193cmd_args="$@"
194
195# clear some things from the environment that we care about
196# any variable starting with any of these prefixes will be unset
197for p in MAKE OBJ SB WITH
198do
199	unset ENV `Env | sed -n "/^$p/s,=.*,,p"`
200done
201
202# --install[-host-target] will set this
203INSTALL_PREFIX=
204# other things we pass to install step
205INSTALL_ARGS=
206CONFIGURE_ARGS=
207MAKESYSPATH=
208# pick a useful default prefix (for me at least ;-)
209for prefix in /opt/$HOST_TARGET "$HOME/$HOST_TARGET" /usr/pkg /usr/local ""
210do
211	[ -d "${prefix:-.}" ] || continue
212	case "$prefix" in
213	*/$HOST_TARGET)
214		p=`dirname $prefix`
215		if [ -d $p/share ]; then
216			INSTALL_BIN=$HOST_TARGET/bin
217			prefix=$p
218		fi
219		;;
220	esac
221        echo "NOTE: default prefix=$prefix ${INSTALL_BIN:+INSTALL_BIN=$INSTALL_BIN}"
222	break
223done
224srcdir=$Mydir
225mksrc=$Mydir/mk
226objdir=
227quiet=:
228
229${SKIP_RC:+:} source_rc .bmake-boot-strap.rc . "$Mydir/.." "$HOME"
230
231get_optarg() {
232	expr "x$1" : "x[^=]*=\\(.*\\)"
233}
234
235here=`'pwd'`
236if [ $here = $Mydir ]; then
237   # avoid pollution
238   OBJROOT=../
239fi
240
241op=all
242BMAKE=
243
244while :
245do
246	case "$1" in
247	--) shift; break;;
248        --help) sed -n -e "1d;/RCSid/,\$d" -e '/^#\.[a-z]/d' -e '/^#/s,^# *,,p' $0; exit 0;;
249	--prefix) prefix="$2"; shift;;
250	--prefix=*) prefix=`get_optarg "$1"`;;
251	--src=*) srcdir=`get_optarg "$1"`;;
252	--with-mksrc=*|--mksrc=*) mksrc=`get_optarg "$1"`;;
253	--share=*) share_dir=`get_optarg "$1"`;;
254	--share) share_dir="$2"; shift;;
255	--with-default-sys-path=*)
256	    CONFIGURE_ARGS="$1";;
257	--with-default-sys-path)
258	    CONFIGURE_ARGS="$1 $2";;
259	--install) INSTALL_PREFIX=${INSTALL_PREFIX:-$prefix};;
260	--install-host-target)
261                INSTALL_PREFIX=${INSTALL_PREFIX:-$prefix}
262                INSTALL_BIN=$HOST_TARGET/bin;;
263	--install-destdir=*) INSTALL_DESTDIR=`get_optarg "$1"`;;
264	--install-prefix=*) INSTALL_PREFIX=`get_optarg "$1"`;;
265	-DWITH*) INSTALL_ARGS="$INSTALL_ARGS $1";;
266	-s|--src) srcdir="$2"; shift;;
267	-m|--mksrc) mksrc="$2"; shift;;
268	-o|--objdir) objdir="$2"; shift;;
269	-q) quiet=;;
270	-c) source_rc "$2"; shift;;
271	--*) CONFIGURE_ARGS="$CONFIGURE_ARGS $1";;
272	*=*) eval "$1"; export `expr "x$1" : "x\\(.[^=]*\\)=.*"`;;
273	*) break;;
274	esac
275        shift
276done
277
278AddConfigure() {
279	case " $CONFIGURE_ARGS " in
280	*" $1"*) ;;
281	*) CONFIGURE_ARGS="$CONFIGURE_ARGS $1$2";;
282	esac
283}
284
285GetDir() {
286	match="$1"
287	shift
288	fmatch="$1"
289	shift
290	for dir in $*
291	do
292		[ -d "$dir" ] || continue
293		case "/$dir/" in
294		*$match*) ;;
295		*) continue;;
296		esac
297		case "$fmatch" in
298		.) ;;
299		*) [ -s $dir/$fmatch ] || continue;;
300		esac
301		case "$dir/" in
302		*./*) cd "$dir" && 'pwd';;
303		/*) echo $dir;;
304		*) cd "$dir" && 'pwd';;
305		esac
306		break
307	done
308}
309
310FindHereOrAbove() {
311    (
312	_t=-s
313	while :
314	do
315		case "$1" in
316		-C) cd "$2"; shift; shift;;
317		-?) _t=$1; shift;;
318		*) break;;
319		esac
320	done
321	case "$1" in
322	/*)	# we shouldn't be here
323		[ $_t "$1" ] && echo "$1"
324		return
325		;;
326	.../*) want=`echo "$1" | sed 's,^.../*,,'`;;
327	*) want="$1";;
328	esac
329	here=`'pwd'`
330	while :
331	do
332		if [ $_t "./$want" ]; then
333			echo "$here/$want"
334			return
335		fi
336		cd ..
337		here=`'pwd'`
338		case "$here" in
339		/) return;;
340		esac
341	done
342    )
343}
344
345# is $1 newer than $2 ...
346is_newer() {
347	case `'ls' -1td "$@" 2> /dev/null | head -1` in
348	$1) return 0;;
349	esac
350	return 1
351}
352
353# is $1 missing from $2 (or PATH) ?
354no_path() {
355	eval "__p=\$${2:-PATH}"
356	case ":$__p:" in *:"$1":*) return 1;; *) return 0;; esac
357}
358
359# if $1 exists and is not in path, append it
360add_path () {
361	case "$1" in
362	-?) t=$1; shift;;
363	*) t=-d;;
364	esac
365	case "$2,$1" in
366	MAKESYSPATH,.../*) ;;
367	*) [ $t ${1:-.} ] || return;;
368	esac
369	no_path $* && eval ${2:-PATH}="$__p${__p:+:}$1"
370}
371
372
373srcdir=`GetDir /bmake make-bootstrap.sh.in "$srcdir" "$2" "$Mydir" ./bmake* "$Mydir"/../bmake*`
374[ -d "${srcdir:-/dev/null}" ] || Usage
375case "$mksrc" in
376none|-) # we ignore this now
377	mksrc=$Mydir/mk
378	;;
379.../*)	# find here or above
380	mksrc=`FindHereOrAbove -C "$Mydir" -s "$mksrc/sys.mk"`
381	# that found a file
382	mksrc=`dirname $mksrc`
383	;;
384*)	# guess we want mksrc...
385	mksrc=`GetDir /mk sys.mk "$mksrc" "$3" ./mk* "$srcdir"/mk* "$srcdir"/../mk*`
386	[ -d "${mksrc:-/dev/null}" ] || Usage "Use '-m none' to build without mksrc"
387	;;
388esac
389
390# Ok, get to work...
391objdir="${objdir:-$OBJROOT$HOST_TARGET}"
392[ -d "$objdir" ] || mkdir -p "$objdir"
393[ -d "$objdir" ] || mkdir "$objdir"
394cd "$objdir" || exit 1
395# make it absolute
396objdir=`'pwd'`
397# save a copy of our env for debugging
398Env > env.out
399
400ShareDir() {
401	case "/$1" in
402	/) [ -d /share ] || return;;
403	*/$HOST_TARGET)
404		if [ -d "$1/../share" ]; then
405			echo `dirname "$1"`/share
406			return
407		fi
408		;;
409	esac
410	echo $1/share
411}
412
413# make it easy to force prefix to use $HOST_TARGET
414: looking at "$prefix"
415case "$prefix" in
416*/host?target) prefix=`echo "$prefix" | sed "s,host.target,${HOST_TARGET},"`;;
417esac
418
419share_dir="${share_dir:-`ShareDir $prefix`}"
420
421AddConfigure --prefix= "$prefix"
422case "$CONFIGURE_ARGS" in
423*--with-*-sys-path*) ;; # skip
424*) [ "$share_dir" ] && AddConfigure --with-default-sys-path= "$share_dir/mk";;
425esac
426if [ "$mksrc" ]; then
427        AddConfigure --with-mksrc= "$mksrc"
428        # not all cc's support this
429        CFLAGS_MF= CFLAGS_MD=
430        export CFLAGS_MF CFLAGS_MD
431fi
432
433# this makes it easy to run the bmake we just built
434# the :tA dance is needed because 'pwd' and even /bin/pwd
435# may not give the same result as realpath().
436Bmake() {
437    (
438	    cd $Mydir &&
439	    MAKESYSPATH=$mksrc SRCTOP=$Mydir OBJTOP=$objdir \
440	    MAKEOBJDIR='${.CURDIR:S,${SRCTOP:tA},${OBJTOP:tA},}' \
441	    ${BMAKE:-$objdir/bmake} -f $Mydir/Makefile "$@"
442    )
443}
444
445op_configure() {
446	$srcdir/configure $CONFIGURE_ARGS || exit 1
447}
448
449op_build() {
450	[ -s make-bootstrap.sh ] || op_configure
451	chmod 755 make-bootstrap.sh || exit 1
452	./make-bootstrap.sh || exit 1
453	case "$op" in
454	build) rm -f tested; op_test;;
455	esac
456}
457
458op_test() {
459	[ -x bmake ] || op_build
460	case "$op" in
461	test) ;;
462	*) is_newer bmake tested || return;;
463	esac
464	Bmake test TEST_MAKE=$objdir/bmake "$@" || exit 1
465	touch tested
466}
467
468op_clean() {
469	if [ -x bmake ]; then
470		ln bmake bmake$$
471		BMAKE=$objdir/bmake$$ Bmake clean
472		rm -f bmake$$
473	elif [ $objdir != $srcdir ]; then
474		rm -rf *
475	fi
476}
477
478op_install() {
479	op_test
480	case "$INSTALL_PREFIX,$INSTALL_BIN,$prefix" in
481	,$HOST_TARGET/bin,*/$HOST_TARGET)
482		INSTALL_PREFIX=`dirname $prefix`
483		;;
484	esac
485	INSTALL_PREFIX=${INSTALL_PREFIX:-$prefix}
486	Bmake install prefix=$INSTALL_PREFIX BINDIR=$INSTALL_PREFIX/${INSTALL_BIN:-bin} ${INSTALL_DESTDIR:+DESTDIR=$INSTALL_DESTDIR} $INSTALL_ARGS || exit 1
487}
488
489op_all() {
490	rm -f make-bootstrap.sh bmake *.o
491	if [ -n "$INSTALL_PREFIX" ]; then
492		op_install
493	else
494		op_test
495		MAKE_VERSION=`sed -n '/^_MAKE_VERSION/ { s,.*=  *,,;p; }' $srcdir/Makefile`
496		cat << EOM
497You can install by running:
498
499$0 $cmd_args op=install
500
501Use --install-prefix=/something to install somewhere other than $prefix
502Use --install-destdir=/somewhere to set DESTDIR during install
503Use --install-host-target to use INSTALL_BIN=$HOST_TARGET/bin
504Use -DWITH_PROG_VERSION to install as bmake-$MAKE_VERSION
505Use -DWITHOUT_PROG_LINK to suppress bmake -> bmake-$MAKE_VERSION symlink
506Use -DWITHOUT_INSTALL_MK to skip installing files to $prefix/share/mk
507EOM
508	fi
509	cat << EOM
510
511Note: bmake.cat1 contains ANSI escape sequences.
512You may need the -r or -R option to more/less to view it correctly.
513
514EOM
515}
516
517op_$op "$@"
518exit 0
519