Porting to a New Target Platform¶
Warning
This is a work in progress, as we work through doing a new port.
Naming Your Target¶
A target name typically consists of the CPU type and the OS name, separated by a hyphen. Due to using the hyphen as a separator, the CPU type and OS name should not include a hyphen.
Example target names are:
arm-linux
ppc-darwin
x86-win32
x86_64-linux
CPU types are typically:
#"arm"
#"ppc"
#"x86"
#"x86_64"
OS names are typically:
#"linux"
#"darwin"
#"freebsd"
#"win32"
Warning
Some existing targets are poorly named. We may attempt to
rename #"win32"
to #"windows"
in the future.
Warning
We do not yet have a strategy in place for targets which are not for a particular CPU and OS type. Examples of these would be emscripten, the JVM, and Google’s Native Client.
New Registry¶
The registry is how we map library names to the actual project files that should be built to provide that library. This lets us provide per-platform implementations of libraries as required.
The registry can be found within sources/registry
.
The easiest way to do this is to copy an existing directory and modify it as needed. If you are doing a port to a Unix-like platform, this should be pretty straightforward to copy from one of the Linux definitions.
System Library¶
New LID and definitions¶
You will need to create a new .lid
file to point to the per-platform
files for the new target. You will also need a *-operating-system.dylan
file to provide a couple of definitions.
There are plenty of examples of this within sources/system
for the
currently supported target platforms.
Magic Numbers¶
The system library requires some magic numbers for accessing struct members defined within the standard C library.
To do this, compile sources/system/dump-magic-numbers.c
for your target
platform and execute it on the target. This will generate a Dylan file that
you can add to the system library.
C Back-End¶
If the new processor type is a 64 bit processor, you will want to update the C back-end appropriately:
Edit
sources/dfmc/c-back-end/c-back-end.dylan
Update the definition of
back-end-word-size
You will also need to do a couple of edits to the C run-time:
Edit
sources/lib/run-time/run-time.*
, looking for usages of__x86_64__
Warning
We should improve this code within the C run-time.
Additionally, there are some mappings involving OPEN_DYLAN_TARGET_PLATFORM
in sources/lib/run-time/Makefile.in
that will need to be updated.
LLVM Back-End¶
The per-platform configurations for the LLVM back-end can be found
within sources/dfmc/llvm-back-end/llvm-targets.dylan
.
When adding a new CPU type, add a new abstract back-end for the CPU with the appropriate data layout and word size.
When adding a new OS type, add a new abstract back-end for the OS.
After that, you can create the new target back-end that inherits from the appropriate CPU and OS specific abstract back-ends. You may need to override the data layout if a different ABI is required.
Warning
Someone should document how to correctly determine the appropriate data layout to use.
Be sure to invoke register-back-end
correctly with your new back-end
class.
Additionally, as with the C back-end, there are some mappings involving
OPEN_DYLAN_TARGET_PLATFORM
in sources/lib/run-time/Makefile.in
that will need to be updated.
This isn’t completely written yet.
Build Scripts¶
Build scripts are partially documented within Jam-based Build System.
The existing build scripts can be found within sources/jamfiles
.
You will want to copy an existing one and make whatever changes are
required. When targeting a Unix-like platform, much of the logic is
already shared within sources/jamfiles/posix-build.jam
.
You should also add your new build script to sources/jamfiles/Makefile.in
so that it gets installed.
Autoconf¶
The configure.ac
script handles detecting a target platform and
setting some appropriate variables within the build system. There
is a large block that deals with checking the $host
(set up
by AC_CANONICAL_TARGET
) and configuring things appropriately.
After updating configure.ac
, be sure to re-run autogen.sh
to create an updated configure
script before re-running
configure
.
Performing a Cross-Build¶
In the examples below, we will use arm-linux
as the example.
Preparing the Garbage Collector¶
Currently, most ports of Open Dylan will probably be using the Boehm garbage collector rather than MPS. An easy way to get the required files is to install the Boehm GC on the target platform and then copy the include and library files back to the build machine being used to perform cross-compilation.
If you intend to start with MPS, you will need to ensure that the MPS has been ported to the target platform first. This is an undertaking that is outside the scope of this document.
Building the Run-Time¶
You can cross-compile the run-time by going to sources/lib/run-time
and running make install
, however, you will need to pass some special
flags to make
:
CC
This should point to your cross-compiler, along with any special compilation flags that are required, such as the include paths for the garbage collector, or target CPU flags.
OPEN_DYLAN_TARGET_PLATFORM
This should be the name of the target platform for which you are cross-compiling.
OPEN_DYLAN_USER_INSTALL
This points to the path to the installation of Open Dylan which you will be using to perform cross-compilation.
An example command line might look like:
make CC="arm-linux-gnueabihf-gcc -I/path/to/gc/include" \
OPEN_DYLAN_TARGET_PLATFORM=arm-linux \
OPEN_DYLAN_USER_INSTALL=/opt/opendylan-current \
clean install
Creating a Custom Build Script¶
When cross-compiling, it is best to set up a custom Jam build
script which can be passed to the dylan-compiler
. This will
allow you to customize important parts of the build configuration.
An example custom script might look like:
CC = /opt/arm-linux/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-gcc ;
GC_CFLAGS = -I/opt/arm-linux/gc/include -DGC_USE_BOEHM -DGC_THREADS ;
GC_LFLAGS = -L/opt/arm-linux/gc/lib -lgc ;
include $(SYSTEM_BUILD_SCRIPTS)/arm-linux-build.jam ;
This just overrides the default values for some variables and then
includes the system-provided build script for arm-linux
.
Cross-Building a Test Application¶
Assuming that you’ve cross-compiled and installed a copy of the run-time into the version of Open Dylan that you’re using for cross-compilation, this is an easy step:
OPEN_DYLAN_TARGET_PLATFORM=arm-linux \
dylan-compiler -build-script path/to/custom-build.jam \
-build hello-world
This should create a build of the hello-world
application
in the _build
directory. This directory can be copied to the
target machine and executed. Hopefully it runs correctly. If not,
now is the time to start debugging.
Cross-Building the Dylan Compiler¶
This is no different from building the hello-world
application
except that now you are building dylan-compiler
:
OPEN_DYLAN_TARGET_PLATFORM=arm-linux \
dylan-compiler -build-script path/to/custom-build.jam \
-build dylan-compiler
Building without a Cross-Compiler¶
When you don’t have an actual cross-compiler when porting to a new platform, the recommended solution is to use a shared file system and custom compiler scripts.
Set up a file system that is shared between the build host and the target host.
On the build host, create a script for running the C compiler via ssh on the target host.
Use this custom script to build the run-time library.
Set up a custom build script as described above and use it to compile a test application and the Dylan compiler.