Clean on Mac OS X
This page is a work-in-progress for building Clean on recent Mac OS X systems. There is an official build for Clean on Mac, but it's 32-bit PowerPC-based; a shame since the newest Macs are 64-bit Intel-based.
Another useful page for building Clean on recent Unices is the Clean2.2 on 64bit Xubuntu page.
This guide assumes basic knowledge of Terminal.app and the basics of UNIX. I am writing this during my fall 2010 Functional Programming course, using a MacBook Pro 2009 model running Mac OS X 10.6.4. You need to have XCode Tools installed before you begin. Please report back in the Discussion above what your results are.
Building the GNU assembler
Because XCode Tools contains an ancient version of the GNU assembler, we will start by building one ourselves. However, because `gas` does not seem to be able to write to 64-bit mach-o objectfiles at time of writing, we will build a version of gas that builds 64-bit ELF files, and we will convert them to Mach-O 64-bit (improvements to this process are very welcome). To start, download GNU binutils to your Downloads directory using your browser (or in your terminal if you have 'wget' or similar installed), then:
~$ mkdir /tmp/gas ~$ cd /tmp/gas /tmp/gas$ mv ~/Downloads/binutils-2.20.1.tar.gz . /tmp/gas$ tar -xzf binutils-2.20.1.tar.gz /tmp/gas$ cd binutils-2.20.1/bfd /tmp/gas/binutils-2.20.1/bfd$ ./configure --prefix="$HOME" --target="x86_64-apple-elf" [...] config.status: executing default commands /tmp/gas/binutils-2.20.1/bfd$ make [...] touch stamp-lib /tmp/gas/binutils-2.20.1/bfd$ cd ../opcodes /tmp/gas/binutils-2.20.1/opcodes$ ./configure --prefix="$HOME" --target="x86_64-apple-elf" [...] config.status: creating po/Makefile /tmp/gas/binutils-2.20.1/opcodes$ make libopcodes.la [...] /tmp/gas/binutils-2.20.1/opcodes$ cd ../libiberty /tmp/gas/binutils-2.20.1/libiberty$ ./configure --prefix="$HOME" [...] /tmp/gas/binutils-2.20.1/libiberty$ make libiberty.a [...] else true; fi /tmp/gas/binutils-2.20.1/libiberty$ cd ../gas /tmp/gas/binutils-2.20.1/gas$ ./configure --prefix="$HOME" --target="x86_64-apple-elf" [...] config.status: executing default commands /tmp/gas/binutils-2.20.1/gas$ make [...] /tmp/gas/binutils-2.20.1/gas$ make install [...] /tmp/gas/binutils-2.20.1/gas$ ~/bin/x86_64-apple-elf-as --version [...] This assembler was configured for a target of `x86_64-apple-elf'. /tmp/gas/binutils-2.20.1/gas$ cd /tmp /tmp$
We are ready to assemble to ELF. Now, to be able to assemble to Mach-O, our native format, we need objconv, a tool by Agner Fog. Download objconv.zip to your Downloads folder, then:
/tmp$ mkdir objconv && cd objconv /tmp/objconv$ mv ~/Downloads/objconv.zip . /tmp/objconv$ unzip objconv.zip Archive: objconv.zip inflating: objconv.exe inflating: objconv-instructions.pdf extracting: source.zip extracting: extras.zip /tmp/objconv$ unzip source.zip Archive: source.zip [...] inflating: build.sh /tmp/objconv$ g++ -o objconv -O2 *.cpp [...] /tmp/objconv$ file objconv objconv: Mach-O 64 bit executable x86_64 /tmp/objconv$ cp objconv ~/bin/ /tmp/objconv$ cd /tmp /tmp$
If you want, you can clean up your binutils and objconv build dirs, or it will happen automatically at next boot.
/tmp$ rm -rf gas /tmp$ rm -rf objconv
Now we can finally assemble Intel gas x86-64 assembly files to 64-bit Mach-O files!
Downloading sources
Because a part of Clean is written in Clean, we need to take a 'bootstrap' package to build. This package contains some 'precompiled' Clean source (no machine-dependent object code, however). You can get it from the Download page (direct link).
Of course, the way of downloading and the place to download is up to you. I use wget and download to $HOME/clean.
~$ mkdir clean ~$ cd clean ~/clean$ wget http://clean.cs.ru.nl/download/Clean22/linux/Clean2.2_boot.tar.gz [...] 2010-09-05 14:10:41 (429 KB/s) - '`Clean2.2_boot.tar.gz'' opgeslagen [5651786/5651786]
And unpack it...
~/clean$ tar -xzf Clean2.2_boot.tar.gz
Download some of my patches, which will hopefully be merged (after which this guide will be updated):
~/clean$ wget http://files.dazjorz.com/clean/clean_mac_runtimesystem.patch ~/clean$ wget http://files.dazjorz.com/clean/clean_mac_codegenerator.patch ~/clean$ wget http://files.dazjorz.com/clean/clean_mac_stdenvinclusion.patch ~/clean$ wget http://files.dazjorz.com/clean/clean_mac_clm.patch ~/clean$ md5sum *.patch 7905de9c52f77ba3d68f424ab75871fe clean_mac_clm.patch 4bc56357ef14e1016a2955a987535350 clean_mac_codegenerator.patch d0c7a14afcfc02566c81e027e1a0c329 clean_mac_runtimesystem.patch e8bf18f68d336ddf879c5c8e11eaec56 clean_mac_stdenvinclusion.patch
Building the RuntimeSystem
Because the standard Makefile assumes we are using Linux, we will build the RuntimeSystem ourselves.
~/clean$ patch -p0 <clean_mac_runtimesystem.patch patching file clean/src/RuntimeSystem/Makefile.macosx patching file clean/src/RuntimeSystem/Makefileprofile.macosx patching file clean/src/RuntimeSystem/afileIO3.asm patching file clean/src/RuntimeSystem/afileIO3.s patching file clean/src/RuntimeSystem/areals.s patching file clean/src/RuntimeSystem/scon.c patching file clean/src/RuntimeSystem/ufileIO2.c ~/clean$ cd clean/src/RuntimeSystem ~/clean/clean/src/RuntimeSystem$ make -f Makefile.macosx [...] ~/clean/clean/src/RuntimeSystem$ file _startup.a astartup.o _startup.a: current ar archive astartup.o: Mach-O 64-bit object ~/clean/clean/src/RuntimeSystem$ make -f Makefile.macosx proper [...] ~/clean/clean/src/RuntimeSystem$ cd ../../.. ~/clean$
Building the Code Generator
The Clean Code Generator turns intermediate Clean files (.abc) into objectfiles (.o) or assembly files (.s).
~/clean$ patch -p0 <clean_mac_codegenerator.patch patching file clean/src/CodeGenerator/Makefile.macosx patching file clean/src/CodeGenerator/cg.c patching file clean/src/CodeGenerator/cgaas.c patching file clean/src/CodeGenerator/cgawas.c patching file clean/src/CodeGenerator/cginput.c patching file clean/src/CodeGenerator/cgport.h ~/clean$ cd clean/src/CodeGenerator ~/clean/clean/src/CodeGenerator$ make -f Makefile.macosx [...] gcc o/cg.o o/cginput.o o/cgcode.o o/cginstructions.o o/cgstack.o o/cgcalc.o o/cglin.o o/cgopt.o o/cgaas.o o/cgawas.o -arch x86_64 -framework Carbon -o cg ~/clean/clean/src/CodeGenerator$ make -f Makefile.macosx proper rm o/cg.o o/cginput.o o/cgcode.o o/cginstructions.o o/cgstack.o o/cgcalc.o o/cglin.o o/cgopt.o o/cgaas.o o/cgawas.o ~/clean/clean/src/CodeGenerator$ file cg cg: Mach-O 64-bit executable x86_64
~/clean/clean/src/CodeGenerator$ cd .. ~/clean/clean/src$ make ../exe/cg cp CodeGenerator/cg ../exe/cg ~/clean/clean/src$ cd ../.. ~/clean$
Compiling patch_bin, clm and clms
We need to install patch_bin correctly first, before compiling clms. Clm will be built automatically while building patch_bin.
~/clean$ patch -p0 <clean_mac_clm.patch patching file clean/src/tools/clm/Makefile.macosx patching file clean/src/tools/clm/clm.c ~/clean$ cd clean/src/tools/clm ~/clean/clean/src/tools/clm$ make -f Makefile.macosx [...] ~/clean/clean/src/tools/clm$ file patch_bin clm patch_bin: Mach-O 64-bit executable clm: Mach-O 64-bit executable ~/clean/clean/src/tools/clm$ make -f Makefile.macosx clms [...] ~/clean/clean/src/tools/clm$ file clms clms: Mach-O 64-bit executable ~/clean/clean/src/tools/clm$ cd ../.. ~/clean/clean/src$ make ../bin/patch_bin cp tools/clm/patch_bin ../bin/patch_bin ~/clean/clean/src$ make ../bin/clm cp tools/clm/clm ../bin/clm [...] ~/clean/clean/src$ cd ../.. ~/clean$
Compiling the standard libraries
The current Clean bootstrap packages are for 32-bits systems. They contain ABC files that will only work for x86 builds, and not for the 64-bits builds we are doing. Therefore, we will need a 64 bit installation of Clean to generate the .abc files we need. The next Clean release will have a 64-bit boot package, so this won't be necessary anymore.
In this section, we will assume a 64 bit Linux installation. You can use the binary package on Download Clean to install this. Run this on a Linux machine: a Mac won't work!
Maybe someone will make a package with all the .abc files inside it, if the next Clean release takes too long...
Preparing the environment
Make sure the `clm` (from the binary package) on your Linux machine creates working Clean executables.
Unpack the bootstrap package. We will first remove all .abc files in it, then replace them with 64-bit .abc files.
linux:~$ mkdir boot; cd boot; wget http://clean.cs.ru.nl/download/Clean22/linux/Clean2.2_boot.tar.gz [...] linux:~/boot$ md5sum Clean2.2_boot.tar.gz 860fb509a5127dee616cbf2a689277b1 Clean2.2_boot.tar.gz linux:~/boot$ tar -xzf Clean2.2_boot.tar.gz linux:~/boot$ cd boot/clean linux:~/boot/boot/clean$ cd clean/stdenv linux:~/boot/boot/clean/clean/stdenv$ rm Clean\ System\ Files/*.abc
Building the ABC files
linux:~/boot/boot/clean/clean/stdenv$ make stdenv clm -P . -ABC StdBool Compiling StdBool clm -P . -ABC StdChar Compiling StdChar [....] clm -P . -ABC StdGeneric Compiling StdGeneric make: *** No rule to make target `Clean System Files/_system.abc', needed by `stdenv'. Stop.
TODO: I need to find a fix for the above problem.
The standard environment objectfile we have just compiled is useless. It will only work on 64-bits Linux systems. However, in the process of creating this file, the build process created the intermediary Clean .abc files that we needed for our compilation. You should transfer these files back to your Mac so you can continue the build. For example, with scp after using "stitch" to build the 64 bit .abc files:
~/clean$ cd clean/stdenv ~/clean/clean/stdenv$ rm Clean\ System\ Files/*.abc ~/clean/clean/stdenv$ scp "stitch:boot/boot/clean/clean/stdenv/Clean\ System\ Files/*.abc" Clean\ System\ Files
Now that the .abc files are in place, we can continue the build:
~/clean/clean/stdenv$ make stdenv [...]
Compiling the linker
We are going to need the .abc files from Linux again, so log into it. Because the build references 'clms', which seems to be the same as 'clm' except for optimalization (?), we need to make sure 'clms' is in our PATH as an alias to clm. The steps below may be different for you.
linux:~$ cd `dirname $(which clm)` linux:~/clean/bin$ ln -s clm clms linux:~/clean/bin$ clms Usage: clm [options] module_name [-o application_name] path options: -I path -IL library -P paths [...] linux:~/clean/bin$ cd linux:~$
Now that you have a working clm, continue the build.
linux:~$ cd boot/boot/clean/clean/src linux:~/boot/boot/clean/clean/src$ make tools/elf_linker/linker cd tools/elf_linker; \ ../clm/clms -nr -nt -h 20m -s 2m -I ia32 -I ../../libraries/ArgEnvUnix -I ../../compiler/main/Unix -I ../../../stdenv linker -o linker; \ cp linker ../../../exe/linker; \ ../../../bin/clm -nr -nt -h 20m -s 2m -I ia32 -I ../../libraries/ArgEnvUnix -I ../../compiler/main/Unix linker -o linker Compiling linker Warning [StdFile.abc,63,accFiles;34]: no inline code for this rule Warning [StdFile.abc,63,stdio;33]: no inline code for this rule Warning [linker,_match0]: function may fail Compiling elf_linker [...] Generating code for elf_relocations Generating code for elf_linker2 Linking linker linux:~/boot/boot/clean/clean/src$
This linker is also useless, but the .abc files aren't! Copy the .abc files in "linux:~/boot/boot/clean/clean/src/tools/elf_linker/Clean System Files" to your Mac to continue. For example:
~/clean$ cd src/tools/elf_linker ~/clean/src/tools/elf_linker$ scp "stitch:boot/boot/clean/clean/src/tools/elf_linker/Clean\ System\ Files/*.abc" Clean\ System\ Files ~/clean/src/tools/elf_linker$ cd ../.. ~/clean/src$ make tools/elf_linker/linker [...]
The rest of this process is TODO
Compiling cocl
TODO
Compiling htoclean
TODO
Installing and wrapping up
TODO