[OpenWrt-Devel] [PATCH] [RFC] toolchain: add OCaml compiler

Stefan Hellermann stefan at the2masters.de
Thu Sep 17 13:31:56 EDT 2015


While porting the Unison File Synchronizer to openwrt I added the
OCaml compiler to openwrt toolchain.
Cross-compiling OCaml seems to be only tested for windows mingw
targets. I had to add a patch to the OCaml configure scripts, to feed
it with a few bits of the target. I hope i did it right for all
targets.
Cross-compiling OCaml needs a bootstrap OCaml installed on the host,
so I actually added OCaml twice, one time in tools and one time in
toolchain.
I discovered a bug when trying to cross-compile on a 64 bit host for
a 32 bit target, the resulting binaries won't work on the target.
For this case I added a workaround in tools/ocaml to compile a
32 bit bootstrap OCaml on x86_64 hosts when building for 32 bit
targets. This workaround is tested for a x86_64 host when
compiling for ar71xx and x86_64 targets.
This workaround is probably buggy when switching from x86_64 to
ar71xx targets without make dirclean, as tools/ocaml is not
rebuild in this case.

Tested with Unison File Synchronizer on ar71xx and x86_64. Beware:
Stripping unison won't work!
Better solutions and comments are appreciated!

Signed-off-by: Stefan Hellermann <stefan at the2masters.de>
---
 toolchain/Config.in                            |  6 +++
 toolchain/Makefile                             |  3 +-
 toolchain/ocaml/Makefile                       | 55 +++++++++++++++++++++++++
 toolchain/ocaml/patches/001-crosscompile.patch | 57 ++++++++++++++++++++++++++
 tools/Makefile                                 |  1 +
 tools/ocaml/Makefile                           | 35 ++++++++++++++++
 6 files changed, 156 insertions(+), 1 deletion(-)
 create mode 100644 toolchain/ocaml/Makefile
 create mode 100644 toolchain/ocaml/patches/001-crosscompile.patch
 create mode 100644 tools/ocaml/Makefile

diff --git a/toolchain/Config.in b/toolchain/Config.in
index 474a14f..88bbe98 100644
--- a/toolchain/Config.in
+++ b/toolchain/Config.in
@@ -206,6 +206,12 @@ comment "Compiler"
 
 source "toolchain/gcc/Config.in"
 
+config OCAML
+	bool
+	prompt "Build OCaml Compiler" if TOOLCHAINOPTS
+	help
+	  Enable if you want to build the OCaml Compiler.
+
 comment "C Library"
 	depends on TOOLCHAINOPTS
 
diff --git a/toolchain/Makefile b/toolchain/Makefile
index cd5399e..92c6f82 100644
--- a/toolchain/Makefile
+++ b/toolchain/Makefile
@@ -28,7 +28,7 @@
 curdir:=toolchain
 
 # subdirectories to descend into
-$(curdir)/builddirs := $(if $(CONFIG_GDB),gdb) $(if $(CONFIG_INSIGHT),insight) $(if $(CONFIG_EXTERNAL_TOOLCHAIN),wrapper,kernel-headers binutils gcc/minimal gcc/initial gcc/final $(LIBC)/headers $(LIBC) fortify-headers)
+$(curdir)/builddirs := $(if $(CONFIG_GDB),gdb) $(if $(CONFIG_INSIGHT),insight) $(if $(CONFIG_OCAML),ocaml) $(if $(CONFIG_EXTERNAL_TOOLCHAIN),wrapper,kernel-headers binutils gcc/minimal gcc/initial gcc/final $(LIBC)/headers $(LIBC) fortify-headers)
 ifdef CONFIG_USE_UCLIBC
   $(curdir)/builddirs += $(LIBC)/utils
 endif
@@ -49,6 +49,7 @@ ifeq ($(CONFIG_EXTERNAL_TOOLCHAIN),)
   $(curdir)/$(LIBC)/utils/compile:=$(curdir)/gcc/final/install
   $(curdir)/$(LIBC)/prepare:=$(curdir)/$(LIBC)/headers/prepare
   $(curdir)/$(LIBC)/utils/prepare:=$(curdir)/$(LIBC)/headers/prepare
+  $(curdir)/ocaml/prepare:=$(curdir)/gcc/final/install
 endif
 
 ifndef DUMP_TARGET_DB
diff --git a/toolchain/ocaml/Makefile b/toolchain/ocaml/Makefile
new file mode 100644
index 0000000..dfb4135
--- /dev/null
+++ b/toolchain/ocaml/Makefile
@@ -0,0 +1,55 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ocaml
+PKG_VERSION:=4.02.3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://caml.inria.fr/pub/distrib/$(PKG_NAME)-$(word 1,$(subst ., ,$(PKG_VERSION))).$(word 2,$(subst ., ,$(PKG_VERSION)))/
+PKG_MD5SUM:=ef1a324608c97031cbd92a442d685ab7
+
+include $(INCLUDE_DIR)/toolchain-build.mk
+
+# custom configure script
+HOST_CONFIGURE_VARS =
+HOST_CONFIGURE_ARGS = \
+	-prefix $(TOOLCHAIN_DIR) \
+	-target-bindir $(TOOLCHAIN_DIR)/bin \
+	-target $(REAL_GNU_TARGET_NAME) \
+	-cc "$(TARGET_CC) $(TARGET_CFLAGS)" \
+	-as "$(TARGET_AS) $(TARGET_ASFLAGS)" \
+	-no-pthread -no-shared-libs \
+	-no-debugger -no-ocamldoc -no-graph -no-cfi
+
+ifneq ($(CONFIG_BIG_ENDIAN),)
+HOST_CONFIGURE_ARGS += -big-endian
+endif
+
+# OCaml applications for 32 bit targets need to be cross-compiled on a 32 bit host OCaml.
+# The following catches x86_64 hosts only. Tested on x86_64 for ar71xx and x86_64 targets.
+ifeq ($(HOST_ARCH)$(CONFIG_ARCH_64BIT),x86_64)
+HOST_CONFIGURE_ARGS += -host i386-linux
+else
+HOST_CONFIGURE_ARGS += -host $(GNU_HOST_NAME)
+endif
+
+define Host/Compile
+        $(MAKE) -C $(HOST_BUILD_DIR) world
+endef
+
+define Host/Install
+	$(call Host/Install/Default)
+	mv $(TOOLCHAIN_DIR)/bin/ocamlc $(TOOLCHAIN_DIR)/bin/$(TARGET_CROSS)ocamlc
+endef
+
+define Host/Clean
+	$(call Host/Clean/Default)
+	rm -f $(STAGING_DIR_HOST)/bin/$(TARGET_CROSS)ocamlc
+endef
+
+$(eval $(call HostBuild))
diff --git a/toolchain/ocaml/patches/001-crosscompile.patch b/toolchain/ocaml/patches/001-crosscompile.patch
new file mode 100644
index 0000000..a5eedca
--- /dev/null
+++ b/toolchain/ocaml/patches/001-crosscompile.patch
@@ -0,0 +1,57 @@
+--- ocaml-4.02.3/configure	2015-05-12 16:46:37.000000000 +0200
++++ ocaml-4.02.3_new/configure	2015-09-17 16:20:07.104000000 +0200
+@@ -47,6 +47,7 @@
+ no_naked_pointers=false
+ TOOLPREF=""
+ with_cfi=true
++big_endian=1
+ 
+ # Try to turn internationalization off, can cause config.guess to malfunction!
+ unset LANG
+@@ -154,6 +155,8 @@
+         no_naked_pointers=true;;
+     -no-cfi|--no-cfi)
+         with_cfi=false;;
++    -big-endian|--big-endian)
++        big_endian=0;;
+     *) if echo "$1" | grep -q -e '^--\?[a-zA-Z0-9-]\+='; then
+          err "configure expects arguments of the form '-prefix /foo/bar'," \
+              "not '-prefix=/foo/bar' (note the '=')."
+@@ -532,18 +535,14 @@
+ else
+   # For cross-compilation, runtest always fails: add special handling.
+   case "$target" in
+-    i686-*-mingw*) inf "OK, this is a regular 32 bit architecture."
+-                   echo "#undef ARCH_SIXTYFOUR" >> m.h
+-                   set 4 4 4 2 8
+-                   arch64=false;;
+-    x86_64-*-mingw*) inf "Wow! A 64 bit architecture!"
++    *64-*) inf "Wow! A 64 bit architecture!"
+                      echo "#define ARCH_SIXTYFOUR" >> m.h
+                      set 4 4 8 2 8
+                      arch64=true;;
+-    *) err "Since datatype sizes cannot be guessed when cross-compiling,\n" \
+-           "a hardcoded list is used but your architecture isn't known yet.\n" \
+-           "You need to determine the sizes yourself.\n" \
+-           "Please submit a bug report in order to expand the list." ;;
++    *) inf "OK, this is a regular 32 bit architecture."
++                   echo "#undef ARCH_SIXTYFOUR" >> m.h
++                   set 4 4 4 2 8
++                   arch64=false;;
+   esac
+ fi
+ 
+@@ -567,8 +566,11 @@
+ 
+ # Determine endianness
+ 
+-sh ./runtest endian.c
+-case $? in
++if ! $cross_compiler; then
++  sh ./runtest endian.c
++  big_endian=$?
++fi
++case $big_endian in
+   0) inf "This is a big-endian architecture."
+      echo "#define ARCH_BIG_ENDIAN" >> m.h;;
+   1) inf "This is a little-endian architecture."
diff --git a/tools/Makefile b/tools/Makefile
index 60041dd..ac2acd4 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -24,6 +24,7 @@ ifneq ($(CONFIG_PACKAGE_kmod-b43)$(CONFIG_PACKAGE_kmod-b43legacy)$(CONFIG_BRCMSM
 endif
 
 tools-$(BUILD_TOOLCHAIN) += gmp mpfr mpc libelf expat
+tools-$(CONFIG_OCAML) += ocaml
 tools-y += m4 libtool autoconf automake flex bison pkg-config sed mklibs
 tools-y += sstrip make-ext4fs e2fsprogs mtd-utils mkimage
 tools-y += firmware-utils patch-image patch quilt yaffs2 flock padjffs2
diff --git a/tools/ocaml/Makefile b/tools/ocaml/Makefile
new file mode 100644
index 0000000..4e0a595
--- /dev/null
+++ b/tools/ocaml/Makefile
@@ -0,0 +1,35 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ocaml
+PKG_VERSION:=4.02.3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://caml.inria.fr/pub/distrib/$(PKG_NAME)-$(word 1,$(subst ., ,$(PKG_VERSION))).$(word 2,$(subst ., ,$(PKG_VERSION)))/
+PKG_MD5SUM:=ef1a324608c97031cbd92a442d685ab7
+
+include $(INCLUDE_DIR)/host-build.mk
+
+# custom configure script
+HOST_CONFIGURE_VARS =
+HOST_CONFIGURE_ARGS = -prefix $(STAGING_DIR_HOST) \
+	-no-pthread -no-debugger -no-ocamldoc -no-graph -no-cfi
+
+# OCaml applications for 32 bit targets need to be cross-compiled on a 32 bit host OCaml.
+# The following catches x86_64 hosts only. Tested on x86_64 for ar71xx and x86_64 targets.
+ifeq ($(HOST_ARCH)$(CONFIG_ARCH_64BIT),x86_64)
+HOST_CONFIGURE_ARGS += \
+	-cc "gcc -m32" -as "as --32" -aspp "gcc -m32 -c" \
+	-host i386-linux -partialld "ld -r -melf_i386"
+endif
+
+define Host/Compile
+	$(MAKE) -C $(HOST_BUILD_DIR) world
+endef
+
+$(eval $(call HostBuild))
-- 
2.1.4
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list