Install package `libssl-dev`
Use Racket 8.5 for build
Fix license and update version
raco-exe-multitarget
is a wrapper around
raco-cross to easily
create Racket standalone binaries for multiple target platforms in one
invocation.
This tool is supposed to be run from the directory containing the top-level
info.rkt
file for your package.
Example:
todo-txt [main]$ raco exe-multitarget \
--targets x86_64-linux,x86_64-win32 \
--launcher-name-template "{launcher-name}-{version}-{target}" \
--version 1.2.3 \
file/todoreport.rkt
[Lots of output from different raco commands ...]
todo-txt [main]$ ls -1 build
todoreport-1.2.3-x86_64-linux
todoreport-1.2.3-x86_64-win32.exe
For each target, the execution roughly corresponds to:
raco cross --target target pkg remove <package-name>
raco cross --target target pkg install --deps search-auto
raco cross --target target exe --orig-exe --embed-dlls <launcher-path>
The first two steps are used to install all necessary dependencies in each
target's raco-cross
directory.
After executing these three steps for each target, raco exe-multitarget
removes, starting from the current directory, all .dep
and .zo
files in
compiled
directories. This is necessary since the package is installed as a
linked package, so raco cross
generates .dep
and .zo
files -- possibly
for a non-native target -- under the current directory. When using these files
in the native environment (outside raco cross
), this results in a fasl-read
exception. The removal of the .dep
and .zo
files avoids this error.
Note that the .dep
und .zo
files are only removed under the current
directory. If other dependencies had been installed as linked packages, their
directories may still contain .dep
and .zo
files for non-native targets,
leading to the fasl-read
error. A future enhancement of raco-exe-multitarget
may optionally remove .dep
and .zo
files in such other linked directories.
Tip: raco cross
, even for a single target, takes a while to install even a
minimal installation for this target. Therefore, if you haven't used raco cross
before and want to experiment with raco exe-multitarget
, run it first
with only one target to get an idea of the needed time. Fortunately, after the
initial setup for a target, the compilation for this target will be much faster.
The full command line syntax is described in the --help
output:
usage: raco exe-multitarget [ <option> ... ] <launcher-path> [<launcher-paths>] ...
`raco exe-multitarget` creates standalone binaries for different platforms.
<option> is one of
-t <targets>, --targets <targets>
comma-separated list of targets (default: native target)
-b <build-directory-template>, --build-directory-template <build-directory-template>
build directory template (default: "build"). See also the information on
template variables below.
-l <launcher-name-template>, --launcher-name-template <launcher-name-template>
launcher name template (default: "{launcher-name}-{version}-{target}" if
`--version` is specified, otherwise "{launcher-name}-target"). See also
the information on template variables below.
-V <version>, --version <version>
version string
-n <package-name>, --package-name <package-name>
package name (default: base name of current directory)
--gui
create binaries from `gracket` instead of `racket`
--help, -h
Show this help
--
Do not treat any remaining argument as a switch (at this level)
Multiple single-letter switches can be combined after
one `-`. For example, `-h-` is the same as `-h --`.
The options `--build-directory-template` and `--launcher-name-template`
can contain the following variables in curly brackets:
{launcher-name} This variable is derived from each launcher path on
the command line. The value is the base name minus the ".rkt" suffix.
For example, for a launcher path `/path/to/my-launcher.rkt`,
`{launcher-name}` is "my-launcher".
{target} `raco cross` target as specified with the `--targets` option.
Valid values are shown by `raco cross --browse`, for example
`x86_64-linux`. Currently only targets for the cs VM are allowed.
{nice-target} The same as `target`, but the suffix "win32" is changed
to "windows". This is intended to avoid confusion for end users from
the seeming contradiction of the name parts "x86_64" (64 bit) and
"win32" (32 bit).
{version} This template variable contains the version string as specified
with the `--version` option. Note: If no `--version` option is used,
`{version}` is invalid!
Example:
raco exe-multitarget \
--targets x86_64-linux,x86_64-win32 \
--build-directory-template "build-{target}" \
--launcher-name-template "{launcher-name}-{version}-{nice-target}" \
--version 1.2.3 \
file/todoreport.rkt
will generate the executable files
build-x86_64-linux/todoreport-1.2.3-x86_64-linux
build-x86_64-win32/todoreport-1.2.3-x86_64-windows.exe
Note that the build directory template uses "{target}" and the launcher
name template uses "{nice-target}".
launcher-paths
are the paths of the Racket files that should be compiled to
target executables.
Valid target names are those listed by raco cross --browse
.
Currently the option --vm
for raco cross
is hardcoded as "cs". Do we need
the bc VM? Add it later if necessary.
Version AUTO
to automatically determine version from info.rkt
or by other
means? However, this may not work reliably, so maybe it's better not to
support it.
When running raco exe-multitarget
with a non-native target as the last one,
the .dep
and .zo
files left by raco cross
are ones for the non-native
platform and a direct invocation (i.e. outside of raco cross) of the launcher
fails. Example:
$ racket file/todoreport.rkt --help
fasl-read: incompatible fasl-object machine-type 'ta6nt found in #<binary input port bytevector>
context...:
body of data
Possible ways to deal with this:
- Remove `.dep` and `.zo` files after running `raco exe-multitarget`. This
has the disadvantage that a launcher will run more slowly since it can't
use the compiled files anymore if the user had created them intentionally.
This is the currently implemented approach.
- Run `raco make <launcher-path>` for each launcher outside `raco cross`.
However, if no `.dep` and `.zo` files existed before, running `raco make`
kind of "freezes" certain settings. For example, if `errortrace` is
added after the dep/zo compilation, running the launcher will use old
compiled files and the change from/to `errortrace` doesn't have an effect.
This can be frustrating to debug.
For all these approaches, it's important to keep in mind that if the user
had run raco make
and then added more code, the compiled files may be
incomplete and it would be futile if we tried to keep track of which
compiled files existed before running raco exe-multitarget
, with the
thought of creating the same compiled files as existed previously. This is
too brittle. As a workaround, maybe add an option --make
(or different
name) to run raco make <launcher-path>
after all cross-compilations.
Relatedly, if the current project directory references linked packages as
dependencies, the dep
and zo
files there will also implicitly be
overwritten by raco cross
with possibly non-native binary files. Currently,
raco-exe-multitarget
doesn't deal with this problem.
For some scenarios raco dist
instead of raco exe
might be needed. Maybe
even combine the raco dist
result with AppImage creation under Linux?
I'm open to changing the name of the package. For example, if the tool can
eventually use raco dist
in addition to raco exe
, the "exe" in the name
may be misleading.
More, depending on feedback.