Skip to content

Commit

Permalink
improve cross-compile instructions and makefile support (#849)
Browse files Browse the repository at this point in the history
Add a `--cross` argument to `configure` to indicate that the generated
makefile's `make` should be like `make kernel`, and a pb-based
bootstrap should rerun `configure` to build for the host machine
instead of the specified target machine.

Also, add support for `DESTDIR` as a more conventional alternative to
the `--temproot` configure flag. While we're at it, recognize
`CFLAGS_FOR_BUILD` for building `bin/zuo`.

As part of the change to `configure`, having `CC_FOR_BUILD` set does
not by itself disable the use of pb for creating or updating boot
files. Depending on how boot files are obtained, `--force` now may be
needed when using `CC_FOR_BUILD` as part of a cross compile that
doesn't use `--cross`.
  • Loading branch information
mflatt authored Jul 17, 2024
1 parent f1ad314 commit 1524f80
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 44 deletions.
65 changes: 53 additions & 12 deletions BUILDING
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ The makefile supports several targets:
manual pages. If the `--installprefix` used with "configure" is
writable by the current user, then `sudo` is not necessary.

To install to a staging directory instead of the final installation
path, use the `--temproot=<dir>` argument to the "configure" script
or supply `DESTDIR=<dir>` as an argument to after `make install`.

* `sudo make uninstall`

Uninstalls the executables, boot files, example files, and manual
Expand Down Expand Up @@ -485,16 +489,6 @@ the Cygwin values are incompatible with the Microsoft C Runtime
Library.


WINDOWS VIA CROSS-COMPILER

To cross-compile the main Chez Scheme executable for Windows using
MinGW, specify suitable build tools to configure, perhaps using
--toolprefix= like this:

./configure -m=ta6nt --toolprefix=x86_64-w64-mingw32- CC_FOR_BUILD=cc
make kernel


EMSCRIPTEN

To target WebAssembly via Emscripten and `emcc`, use the
Expand Down Expand Up @@ -545,9 +539,56 @@ Finally, configure the Emscripten build to use "demo.boot":
make


CROSS-COMPILING SCHEME PROGRAMS
CROSS COMPILING

To compile Chez Scheme for a target platform that is different than
the host platform, supply the `--cross` flag to the "configure" script
while also specifying the target machine type, compiler settings to
build for the target platform, and `CC_FOR_BUILD=<compiler>` to
provide a <compiler> suitable for building `bin/zuo`.

For example, to cross compile for Windows with a typical MinGW
installation, use `--toolprefix=x86_64-w64-mingw32-` to specify tools
that compile and link via MinGW:

./configure --cross -m=ta6nt --toolprefix=x86_64-w64-mingw32- CC_FOR_BUILD=cc
make

The configure arguments that are needed to cross compile will vary
with the host and target machines. On a platform where ta6osx is the
native machine type, for example, cross compiling for tarm64osx may be
as simple as specifying an `-arch` flag for the C compiler:

./configure --cross -m=tarm64osx CFLAGS="-arch arm64" CC_FOR_BUILD=cc
make

When additional configuration is needed for a *host* build (that is,
when just `./configure --pb` would not be enough to build for the host
platform), then more steps are needed. In that case, first build for
the host platform, configuring as needed. Use the result to create
boot files for the target using `make bootquick XM=<target machine>`
(see also the WAYS TO GET BOOT FILES section above). Finally, use both
`--cross` and `--force` to configure for the target platform.

./configure -m=ta6osx # configure for host
make # build for host
make bootquick XM=tarm64osx # use host to build target boot files
./configure --cross --force -m=tarm64osx CFLAGS="-arch arm64" CC_FOR_BUILD=cc
make # build for target

After `make` to build, use `make install` to gather cross-compiled
components. Typically, `--temproot=<dir>` should be supplied as a
configure argument along with `--cross`, in which case the
installation is placed in a <dir> to be moved to the target platform.
Alternatively, a destination directory be selected at the installation
step via `DESTDIR`:

make install DESTDIR=/tmp/staging


CROSS COMPILING SCHEME PROGRAMS

Using
After a non-cross build to work on the host platform, using

make bootquick XM=<machine type>

Expand Down
18 changes: 14 additions & 4 deletions build.zuo
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@
,(lambda (token)
(check-not-kernel-only)
((dynamic-require (at-source "makefiles/install.zuo") 'install)
at-dir))]
at-dir
(hash 'DESTDIR (hash-ref config 'DESTDIR ""))))]

[:target uninstall ()
,(lambda (token)
Expand Down Expand Up @@ -501,14 +502,23 @@
(alert (~a "checking boot files for " m " against pb"))
(define pb-dir (at-dir ".." "pb"))
(mkdir-p pb-dir)
(define config (map (lambda (s) (string-trim (string-trim s "\r")))
(string-split (file->string (at-dir "Mf-config")) "\n")))
(define cross? #t)
(define Mf-config
(cond
[(string=? (hash-ref config 'crossCompile "no") "yes")
(shell/wait (build-raw-path (at-source ".") "configure")
"--nomakefile"
"--pb")
(build-path pb-dir "Mf-config")]
[else (at-dir "Mf-config")]))
(define old-config (map (lambda (s) (string-trim (string-trim s "\r")))
(string-split (file->string Mf-config) "\n")))
(define m-line (~a "m=" m))
(define mboot-line (~a "mboot=" mboot))
(define new-config (cons "m=pb"
(filter (lambda (s) (not (or (string=? s m-line)
(string=? s mboot-line))))
config)))
old-config)))
(display-to-file (string-join new-config "\n") (build-path pb-dir "Mf-config")
:truncate)
(build (command-target->target (find-target "bootquick"
Expand Down
38 changes: 30 additions & 8 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,12 @@ enableFrompb=yes
pbendian=l
emscripten=no
empetite=no
crossCompile=no
moreBootFiles=
preloadBootFiles=
alwaysUseBootFile=
skipSubmoduleUpdate=
skipImmediateMakefile=
zuoExternal=

CONFIG_UNAME=`uname`
Expand Down Expand Up @@ -309,6 +311,9 @@ while [ $# != 0 ] ; do
--as-is)
skipSubmoduleUpdate=yes
;;
--nomakefile)
skipImmediateMakefile=yes
;;
--installprefix=*)
installprefix=`echo $1 | sed -e 's/^--installprefix=//'`
;;
Expand Down Expand Up @@ -406,6 +411,9 @@ while [ $# != 0 ] ; do
--empetite)
empetite=yes
;;
--cross)
crossCompile=yes
;;
--start=*)
alwaysUseBootFile=`echo $1 | sed -e 's/^--start=//'`
;;
Expand All @@ -428,6 +436,9 @@ while [ $# != 0 ] ; do
CC_FOR_BUILD=*)
CC_FOR_BUILD=`echo $1 | sed -e 's/^CC_FOR_BUILD=//'`
;;
CFLAGS_FOR_BUILD=*)
CFLAGS_FOR_BUILD=`echo $1 | sed -e 's/^CFLAGS_FOR_BUILD=//'`
;;
LD=*)
LD=`echo $1 | sed -e 's/^LD=//'`
;;
Expand Down Expand Up @@ -656,6 +667,7 @@ if [ "$help" = "yes" ]; then
echo " --pb specify pb (portable bytecode) version"
echo " --pbarch specify pb with inferred word and endianness"
echo " --emscripten build via emscripten (\"em\" tool prefix)"
echo " --cross build host to bootstrap target"
echo " --disable-x11 disable X11 support"
echo " --disable-curses disable [n]curses support"
echo " --disable-iconv disable iconv support"
Expand Down Expand Up @@ -689,12 +701,14 @@ if [ "$help" = "yes" ]; then
echo " --workarea=<pathname> build directory ($w)"
echo " --force disable use of pb to (re)build boot files"
echo " --as-is skip Git submodule update"
echo " --nomakefile create build-directory files only"
echo " CC=<C compiler> C compiler"
echo " CPPFLAGS=<C preprocessor flags> C preprocessor flags"
echo " CPPFLAGS+=<C preprocessor flags> add C preprocessor flags"
echo " CFLAGS=<C compiler flags> C compiler flags"
echo " CFLAGS+=<C compiler flags> add C compiler flags"
echo " CC_FOR_BUILD=<C compiler> C compiler and flags for build machine"
echo " CFLAGS_FOR_BUILD=<C compiler> additional C flags for build machine"
echo " LD=<linker> linker"
echo " LDFLAGS=<linker flags> additional linker flags"
echo " LDFLAGS+=<linker flags> add additional linker flags"
Expand Down Expand Up @@ -832,8 +846,6 @@ CFLAGS="${CFLAGS}${CFLAGS_ADD}"

if [ "$CC_FOR_BUILD" = "" ] ; then
CC_FOR_BUILD="${CC} ${CFLAGS}"
else
enableFrompb=no
fi

# Add automatic thread compilation flags, unless suppressed by --disable-auto-flags
Expand Down Expand Up @@ -1124,15 +1136,23 @@ case "$srcdir" in
;;
esac

# Makefile to build and launch Zuo
sed -e 's/$(w)/'$w'/g'\
"$srcdir"/makefiles/Makefile.in > Makefile
if [ "$skipImmediateMakefile" = "" ] ; then
# Makefile to build and launch Zuo
if [ "$crossCompile" = "yes" ] ; then
makefile_in=Makefile-cross.in
else
makefile_in=Makefile.in
fi
sed -e 's/$(w)/'$w'/g' "$srcdir"/makefiles/"$makefile_in" > Makefile
fi

mkdir -p $w

# Stub Zuo script to lanch the real one, using "Makefile"
# to locate the workarea:
cp "$srcdir"/makefiles/buildmain.zuo main.zuo
if [ "$skipImmediateMakefile" = "" ] ; then
# Stub Zuo script to lanch the real one, using "Makefile"
# to locate the workarea:
cp "$srcdir"/makefiles/buildmain.zuo main.zuo
fi

# Some idea, but in the workarea, so it refers to "workarea.zuo" here:
cp "$srcdir"/makefiles/workmain.zuo $w/main.zuo
Expand All @@ -1146,6 +1166,7 @@ m=$m
defaultm=$defaultm
flagsm=$flagsm
mboot=$mboot
crossCompile=$crossCompile
buildKernelOnly=$buildKernelOnly
enableFrompb=$enableFrompb
mdinclude=$mdinclude
Expand All @@ -1159,6 +1180,7 @@ exeSuffix=$exeSuffix
zlibConfigureEnv=$zlibConfigureEnv
zlibConfigureFlags=
CC_FOR_BUILD=$CC_FOR_BUILD
CFLAGS_FOR_BUILD=$CFLAGS_FOR_BUILD
CC=$CC
CPPFLAGS=$CPPFLAGS
CFLAGS=$CFLAGS
Expand Down
30 changes: 30 additions & 0 deletions makefiles/Makefile-cross.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# The `configure` script adjusts the next line:
workarea=$(w)

include $(workarea)/Mf-config

# This is a simplified variant of the makefile that is
# for cross compilation, where `kernel` is the only
# build option and `build` is mapped to `kernel`

.PHONY: build
build: $(ZUO_DEP)
+ $(ZUO) $(workarea) kernel MAKE="$(MAKE)"

.PHONY: kernel
kernel: $(ZUO_DEP)
+ $(ZUO) $(workarea) kernel MAKE="$(MAKE)"

.PHONY: install
install: $(ZUO_DEP)
$(ZUO) $(workarea) install MAKE="$(MAKE)" DESTDIR="$(DESTDIR)"

.PHONY: clean
clean: $(ZUO_DEP)
+ $(ZUO) $(workarea) clean MAKE="$(MAKE)"
$(RM_ZUO)

# Using `+` here means that $(ZUO) gets built even if `-n`/`--dry-run` is provided to `make`
$(ZUO_TARGET): $(srcdir)/zuo/zuo.c
+ mkdir -p bin
+ $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) -DZUO_LIB_PATH='"'"$(upsrcdir)/zuo/lib"'"' -o $(ZUO) $(srcdir)/zuo/zuo.c
21 changes: 19 additions & 2 deletions makefiles/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ kernel: $(ZUO_DEP)

.PHONY: install
install: $(ZUO_DEP)
$(ZUO) $(workarea) install MAKE="$(MAKE)"
$(ZUO) $(workarea) install MAKE="$(MAKE)" DESTDIR="$(DESTDIR)"

.PHONY: uninstall
uninstall: $(ZUO_DEP)
Expand Down Expand Up @@ -103,6 +103,23 @@ bootpbchunk: $(ZUO_DEP)
%.bootpbchunk: $(ZUO_DEP)
+ $(ZUO) $(workarea) bootpbchunk $* $(ARGS) MAKE="$(MAKE)"

# Supply XM=<machine> to compile for <machine> with configure
# arguments in ARGS
cross: $(ZUO_DEP)
+ $(ZUO) $(workarea) MAKE="$(MAKE)" -- cross "$(XM)" $(ARGS)

# `<machine>.cross` as alias for `cross XM=<machine>`
%.cross: $(ZUO_DEP)
+ $(ZUO) $(workarea) MAKE="$(MAKE)" -- cross $* $(ARGS)

# Supply XM=<machine> to install cross-compiled for <machine>
cross-install: $(ZUO_DEP)
+ $(ZUO) $(workarea) MAKE="$(MAKE)" DESTDIR="$(DESTDIR)" -- cross-install "$(XM)"

# `<machine>.install` as alias for `cross-install XM=<machine>`
%.install: $(ZUO_DEP)
+ $(ZUO) $(workarea) MAKE="$(MAKE)" DESTDIR="$(DESTDIR)" -- cross-install $*

.PHONY: docs
docs: build $(ZUO_DEP)
+ $(ZUO) $(workarea) docs MAKE="$(MAKE)"
Expand Down Expand Up @@ -147,4 +164,4 @@ clean: $(ZUO_DEP)
# Using `+` here means that $(ZUO) gets built even if `-n`/`--dry-run` is provided to `make`
$(ZUO_TARGET): $(srcdir)/zuo/zuo.c
+ mkdir -p bin
+ $(CC_FOR_BUILD) -DZUO_LIB_PATH='"'"$(upsrcdir)/zuo/lib"'"' -o $(ZUO) $(srcdir)/zuo/zuo.c
+ $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) -DZUO_LIB_PATH='"'"$(upsrcdir)/zuo/lib"'"' -o $(ZUO) $(srcdir)/zuo/zuo.c
Loading

0 comments on commit 1524f80

Please sign in to comment.