1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
This file presents
* a list of platforms CLISP is known to run on,
* special hints for some platforms,
* hints for porting to new platforms.
List of platforms
==================
* GNU and Unix platforms
* macOS
* Windows (both native Windows and Cygwin)
Special hints for some platforms
================================
* On Nokia N800 (Arm) running Linux:
If you get a crash during loading of the first few lisp file (first GC),
add "-DNO_GENERATIONAL_GC" to CFLAGS.
If your modules do not work (clisp.h does not define "object" type),
install GNU sed.
* On ppc and ppc64 running Linux:
If you get a crash during loading of the first few lisp file (first GC),
add "-DNO_GENERATIONAL_GC" to CFLAGS.
Porting to new platforms
========================
The C compiler
--------------
Choose a reliable C compiler. GNU gcc is a good bet. Generally, start the
port with the least optimization settings regarding the compiler (-O0 in
the CFLAGS) and the safest optimization settings regarding the CLISP source
(configure with --enable-portability).
Address space layout
--------------------
Generally (except on 32-bit machines when configured with --enable-portability)
CLISP tries to use memory mapping facilities (mmap on Unix, VirtualAlloc on
Windows) in order to
- simplify memory management (a large block of memory is more efficient
to manage that a set of randomly distributed memory pages),
cf. macro SPVW_BLOCKS vs. SPVW_PAGES,
- support generational garbage collection,
cf. macro GENERATIONAL_GC,
- speed up type recognition by putting type tags into the pointers,
cf. macro TYPECODES vs. HEAPCODES.
Such memory mapping requires knowledge about the address space layout.
The configuration determines some parameters about the address space layout,
such as:
checking for the code address range... 0x00000000
checking for the malloc address range... 0x01000000
checking for the shared library address range... 0xB6000000
checking for the stack address range... 0xBE000000
If you need a deeper understanding of the address space layout, the following
tools print a memory map (i.e. the virtual memory areas) of a running process:
* The '-mm' option: Run
$ ./lisp.run -mm
This option works on many, but not all platforms.
* OS dependent tools: Run an executable, look up its process ID (through "ps"),
then:
- On Linux:
$ cat /proc/$pid/maps
$ pmap $pid
- On Mac OS X:
$ vmmap -interleaved $pid
- On FreeBSD:
$ cat /proc/$pid/map
$ procstat -v $pid
- On NetBSD:
$ cat /proc/$pid/map
- On OpenBSD:
# procmap -p $pid
- On AIX:
$ procmap -S $pid
- On Solaris:
$ pmap $pid
The stack address range is printed by these tools, but CLISP does not make
assumptions about it.
Verifying that all supported configurations work
------------------------------------------------
There are a number of configurations of the memory management (different
object representation, different GC algorithms, old_gc vs. multithread_gc,
etc.). It is useful to verify that all such supported configurations work
and which configuration cannot be supported on the particular platform,
so that
- you get an overview of which features don't work in any configuration
(you can then disable this feature in lispbibl.d),
- you can be sure that there are no hidden bugs lurking,
- later regressions become apparent quickly.
To do so:
1) Get at least one configuration to at least build lisp.run without
compilation errors (--enable-portability is your best bet for this).
Then get an understanding of address space layout (see above).
2) Add to lispbibl.d platform dependent sections:
- A section that defines MAPPABLE_ADDRESS_RANGE_START and
MAPPABLE_ADDRESS_RANGE_END.
- A section that defines the parameters for SINGLEMAP_MEMORY:
SINGLEMAP_ADDRESS_BASE, SINGLEMAP_TYPE_MASK, SINGLEMAP_oint_type_shift.
- A section that defines the parameters for ONE_FREE_BIT_HEAPCODES:
garcol_bit_o.
- A section that defines the parameters for TYPECODES_WITH_TRIVIALMAP.
- A section that defines the parameters for TYPECODES_WITH_MALLOC.
3) Build the whole set of variants.
This is done through one of the commands
make -k -f Makefile.devel multibuild-porting32-gcc
make -k -f Makefile.devel multibuild-porting32-cc
make -k -f Makefile.devel multibuild-porting64-gcc
make -k -f Makefile.devel multibuild-porting64-cc
Pick the one that matches your platform bitness (32-bit or 64-bit
platform) and your compiler (GCC or compatible, e.g. clang, versus
vendor cc).
Before doing this, you need to set an environment variable
MULTIBUILD_32_OPTIONS (for the 32-bit target) or MULTIBUILD_64_OPTIONS
(for the 64-bit target), that contain configuration options, typically
--prefix, --with-libsigsegv-prefix, --with-libffcall-prefix options.
4) Depending on the results, define *_WORKS macros in lispbibl.d:
- SINGLEMAP_WORKS, depending on the result of
build-porting*-spvw_pure_blocks
- HEAPCODES1BIT_WITH_TRIVIALMAP_WORKS, depending on the result of
build-porting*-one_free_bit_heapcodes-trivialmap
- HEAPCODES1BIT_WITH_MALLOC_WORKS, depending on the result of
build-porting*-one_free_bit_heapcodes-malloc
- KERNELVOID32_HEAPCODES_WORKS, depending on the result of
build-porting32-*-kernelvoid32_heapcodes
- GENERIC64C_HEAPCODES_WORKS, depending on the result of
build-porting64-*-generic64_heapcodes
- TYPECODES_WITH_TRIVIALMAP_WORKS, depending on the result of
build-porting*-typecodes-spvw_mixed_blocks-trivialmap
- TYPECODES_WITH_MALLOC_WORKS, depending on the result of
build-porting64-gcc-typecodes-spvw_pure_pages
build-porting64-gcc-typecodes-spvw_mixed_pages
build-porting64-gcc-typecodes-spvw_mixed_blocks-malloc
5) Redo step 3.
Inspect all the build-porting*/cbcstep3.log and determine which failures
were justified and which were bugs that you can fix.
If you could fix bugs, repeat this step.
6) Add to Makefile.devel a target multibuild-<platform> that contains all
configuration targets that should succeed.
7) Run "make -k -f Makefile.devel multibuild-<platform>" and verify that
build-porting*/cbcstep3.log succeeded.
Enabling optimizations that work
--------------------------------
After you have performed "Verifying that all supported configurations work"
(see above):
1) In makemake.in add a section with platform dependent configuration flags.
You can start with the flags that get enabled when ${enable_portability}
is 'yes'.
2) Remove at many de-optimization flags from this section as you can.
Then run
$ rm -rf build-porting*
$ make -k -f Makefile.devel multibuild-<platform>
If not all these builds succeeded (look at build-porting*/cbcstep3.log
again), re-enable some de-optimization flags and repeat this step.
Quick porting
-------------
If you don't want to go through the (lengthy) process described in the sections
above, you can alternatively make some educated guess about which configuration
will likely work out. Here are tips for this approach.
On 64-bit platforms, if you cannot identify a pattern for the address space
layout, add -DGENERIC64_HEAPCODES -falign-functions=8 to the CFLAGS.
If you get an error message concerning mapped memory, you should add
-DNO_SINGLEMAP to the CFLAGS and recompile. Doing so introduces a tiny speed
penalty. If you still get an error message concerning mapped memory, you
should add -DNO_TRIVIALMAP to the CFLAGS and recompile.
Other troubleshooting
---------------------
Some options or optimizations are enabled through macros, conditionally
defined in lispbibl.d. You can check which macros get defined in lispbibl.d
by looking into lispbibl.h, assuming you are using gcc. For example:
make lispbibl.h
grep TYPECODES lispbibl.h
If you get an error message mentioning "handle_fault", then generational GC
is not working. Add -DNO_GENERATIONAL_GC to the CFLAGS and recompile.
If you get an error message during the loading of the first 10 Lisp files,
during the construction of the first .mem file, check the choice of
setjmp/longjmp functions in lispbibl.d.
If interpreted.mem was successfully generated, but lisp.run dumps core when
loading .fas files, you should add -DSAFETY=3 to the CFLAGS and recompile.
Find out which is the least SAFETY level that produces a working lisp.run and
lispinit.mem, and tell me about it.
|