summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Vorlicek <janvorli@microsoft.com>2018-06-02 10:23:10 +0200
committerGitHub <noreply@github.com>2018-06-02 10:23:10 +0200
commite7ad6110bfc1b888aceba9e0abbcbaae475517a8 (patch)
tree0c1415dd51b748a77b4beca3d75775d4f8e8515e
parentfd895f1c74712edd9dbee4cf265e7a4d39f55f4c (diff)
downloadcoreclr-e7ad6110bfc1b888aceba9e0abbcbaae475517a8.tar.gz
coreclr-e7ad6110bfc1b888aceba9e0abbcbaae475517a8.tar.bz2
coreclr-e7ad6110bfc1b888aceba9e0abbcbaae475517a8.zip
Enable Alpine cross build for arm and arm64 (#18234)
* Enable Alpine cross build for arm and arm64 This change enables cross build and rootfs creation for Alpine Linux ARM / ARM64 targets. Besides that, I've cleaned up the toolchain.cmake and got rid of the explicit specification of GCC version specific include and lib folders for all targets except of Tizen. Clang is able to figure that out on its own the same way as it does when doing regular non-cross builds, but it needed one more option for that. I've also fixed a bug in the `add_compile_param` macro that caused ignoring of parameters in cases where another parameter that was a substring of the one being added was already present. So for example if an option `-L${CMAKE_SYSROOT}/usr/lib/gcc` was already added, attempt to add option `-L${CMAKE_SYSROOT}/usr/lib` would do nothing. * Fix to make it work with cmake 2.8 too The older cmake that is still in use on Ubuntu 14.04 doesn't have support for specifying sysroot and target via cmake variables. So I've replaced those by explicit setting of the compiler / linker options instead.
-rw-r--r--Documentation/building/cross-building.md28
-rwxr-xr-xcross/build-rootfs.sh50
-rw-r--r--cross/toolchain.cmake59
-rw-r--r--cross/tryrun.cmake26
4 files changed, 117 insertions, 46 deletions
diff --git a/Documentation/building/cross-building.md b/Documentation/building/cross-building.md
index 5a4060c910..d0047f90af 100644
--- a/Documentation/building/cross-building.md
+++ b/Documentation/building/cross-building.md
@@ -16,13 +16,13 @@ Build using "-arm" as the architecture. For example:
C:\coreclr> build.cmd -arm -debug
-Cross Compilation for ARM on Linux
-==================================
+Cross Compilation for ARM, ARM64 or x86 on Linux
+================================================
Through cross compilation, on Linux it is possible to build CoreCLR for arm or arm64.
-Requirements
-------------
+Requirements for targetting Debian based distros
+------------------------------------------------
You need a Debian based host and the following packages needs to be installed:
@@ -37,14 +37,30 @@ and conversely for arm64:
ben@ubuntu ~/git/coreclr/ $ sudo apt-get install binutils-aarch64-linux-gnu
+Requirements for targetting ARM or ARM64 Alpine Linux
+-----------------------------------------------------
+
+You can use any Linux distro as a host. The qemu, qemu-user-static and binfmt-support packages need to be installed (the names may be different for some distros).
+
+In addition, to cross compile CoreCLR, the binutils for Alpine need to be built from the https://github.com/richfelker/musl-cross-make repo, since they are not available as packages.
+
+To build them, use the following steps:
+* Clone the repo
+* Create a new config.mak file in the root directory of the repo and add the following lines into it:
+ * `TARGET = armv6-alpine-linux-musleabihf` for ARM or `TARGET = aarch64-alpine-linux-musl` for ARM64
+ * `OUTPUT = /usr`
+ * `BINUTILS_CONFIG=--enable-gold=yes`
+* Run `make` with current directory set to the root of the repo
+* Run `sudo make install`
+
Generating the rootfs
---------------------
The `cross\build-rootfs.sh` script can be used to download the files needed for cross compilation. It will generate an rootfs as this is what CoreCLR targets.
Usage: ./cross/build-rootfs.sh [BuildArch] [LinuxCodeName] [lldbx.y] [--skipunmount]
BuildArch can be: arm(default), armel, arm64, x86
- LinuxCodeName - optional, Code name for Linux, can be: trusty(default), vivid, wily, xenial. If BuildArch is armel, LinuxCodeName is jessie(default) or tizen.
- lldbx.y - optional, LLDB version, can be: lldb3.6(default), lldb3.8
+ LinuxCodeName - optional, Code name for Linux, can be: trusty(default), vivid, wily, xenial or alpine. If BuildArch is armel, LinuxCodeName is jessie(default) or tizen.
+ lldbx.y - optional, LLDB version, can be: lldb3.6(default), lldb3.8. This is ignored when building rootfs for Alpine Linux.
The `build-rootfs.sh` script must be run as root as it has to make some symlinks to the system, it will by default generate the rootfs in `cross\rootfs\<BuildArch>` however this can be changed by setting the `ROOTFS_DIR` environment variable.
diff --git a/cross/build-rootfs.sh b/cross/build-rootfs.sh
index 1f42c75578..ec6af484fa 100755
--- a/cross/build-rootfs.sh
+++ b/cross/build-rootfs.sh
@@ -4,8 +4,8 @@ usage()
{
echo "Usage: $0 [BuildArch] [LinuxCodeName] [lldbx.y] [--skipunmount]"
echo "BuildArch can be: arm(default), armel, arm64, x86"
- echo "LinuxCodeName - optional, Code name for Linux, can be: trusty(default), vivid, wily, xenial, zesty. If BuildArch is armel, LinuxCodeName is jessie(default) or tizen."
- echo "lldbx.y - optional, LLDB version, can be: lldb3.6(default), lldb3.8, lldb3.9, lldb4.0, no-lldb"
+ echo "LinuxCodeName - optional, Code name for Linux, can be: trusty(default), vivid, wily, xenial, zesty, alpine. If BuildArch is armel, LinuxCodeName is jessie(default) or tizen."
+ echo "lldbx.y - optional, LLDB version, can be: lldb3.6(default), lldb3.8, lldb3.9, lldb4.0, no-lldb. Ignored for alpine"
echo "--skipunmount - optional, will skip the unmount of rootfs folder."
exit 1
}
@@ -22,14 +22,24 @@ __SkipUnmount=0
# base development support
__UbuntuPackages="build-essential"
+__AlpinePackages="alpine-base"
+__AlpinePackages+=" build-base"
+__AlpinePackages+=" linux-headers"
+__AlpinePackages+=" lldb-dev"
+__AlpinePackages+=" llvm-dev"
+
# symlinks fixer
__UbuntuPackages+=" symlinks"
# CoreCLR and CoreFX dependencies
-__UbuntuPackages+=" gettext"
-__UbuntuPackages+=" libunwind8-dev"
-__UbuntuPackages+=" liblttng-ust-dev"
__UbuntuPackages+=" libicu-dev"
+__UbuntuPackages+=" liblttng-ust-dev"
+__UbuntuPackages+=" libunwind8-dev"
+
+__AlpinePackages+=" gettext-dev"
+__AlpinePackages+=" icu-dev"
+__AlpinePackages+=" libunwind-dev"
+__AlpinePackages+=" lttng-ust-dev"
# CoreFX dependencies
__UbuntuPackages+=" libcurl4-openssl-dev"
@@ -37,6 +47,11 @@ __UbuntuPackages+=" libkrb5-dev"
__UbuntuPackages+=" libssl-dev"
__UbuntuPackages+=" zlib1g-dev"
+__AlpinePackages+=" curl-dev"
+__AlpinePackages+=" krb5-dev"
+__AlpinePackages+=" openssl-dev"
+__AlpinePackages+=" zlib-dev"
+
__UnprocessedBuildArgs=
for i in "$@" ; do
lowerI="$(echo $i | awk '{print tolower($0)}')"
@@ -48,10 +63,14 @@ for i in "$@" ; do
arm)
__BuildArch=arm
__UbuntuArch=armhf
+ __AlpineArch=armhf
+ __QEMUArch=arm
;;
arm64)
__BuildArch=arm64
__UbuntuArch=arm64
+ __AlpineArch=aarch64
+ __QEMUArch=aarch64
;;
armel)
__BuildArch=armel
@@ -113,6 +132,10 @@ for i in "$@" ; do
__UbuntuRepo=
__Tizen=tizen
;;
+ alpine)
+ __LinuxCodeName=alpine
+ __UbuntuRepo=
+ ;;
--skipunmount)
__SkipUnmount=1
;;
@@ -140,7 +163,22 @@ if [ -d "$__RootfsDir" ]; then
rm -rf $__RootfsDir
fi
-if [[ -n $__LinuxCodeName ]]; then
+if [[ "$__LinuxCodeName" == "alpine" ]]; then
+ __ApkToolsVersion=2.9.1
+ __AlpineVersion=3.7
+ __ApkToolsDir=$(mktemp -d)
+ wget https://github.com/alpinelinux/apk-tools/releases/download/v$__ApkToolsVersion/apk-tools-$__ApkToolsVersion-x86_64-linux.tar.gz -P $__ApkToolsDir
+ tar -xf $__ApkToolsDir/apk-tools-$__ApkToolsVersion-x86_64-linux.tar.gz -C $__ApkToolsDir
+ mkdir -p $__RootfsDir/usr/bin
+ cp -v /usr/bin/qemu-$__QEMUArch-static $__RootfsDir/usr/bin
+ $__ApkToolsDir/apk-tools-$__ApkToolsVersion/apk \
+ -X http://dl-cdn.alpinelinux.org/alpine/v$__AlpineVersion/main \
+ -X http://dl-cdn.alpinelinux.org/alpine/v$__AlpineVersion/community \
+ -X http://dl-cdn.alpinelinux.org/alpine/edge/testing \
+ -U --allow-untrusted --root $__RootfsDir --arch $__AlpineArch --initdb \
+ add $__AlpinePackages
+ rm -r $__ApkToolsDir
+elif [[ -n $__LinuxCodeName ]]; then
qemu-debootstrap --arch $__UbuntuArch $__LinuxCodeName $__RootfsDir $__UbuntuRepo
cp $__CrossDir/$__BuildArch/sources.list.$__LinuxCodeName $__RootfsDir/etc/apt/sources.list
chroot $__RootfsDir apt-get update
diff --git a/cross/toolchain.cmake b/cross/toolchain.cmake
index ea8d6cabf8..071d411241 100644
--- a/cross/toolchain.cmake
+++ b/cross/toolchain.cmake
@@ -1,4 +1,5 @@
set(CROSS_ROOTFS $ENV{ROOTFS_DIR})
+
set(TARGET_ARCH_NAME $ENV{TARGET_BUILD_ARCH})
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
@@ -11,13 +12,21 @@ if(TARGET_ARCH_NAME STREQUAL "armel")
endif()
elseif(TARGET_ARCH_NAME STREQUAL "arm")
set(CMAKE_SYSTEM_PROCESSOR armv7l)
- set(TOOLCHAIN "arm-linux-gnueabihf")
+ if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/armv6-alpine-linux-musleabihf)
+ set(TOOLCHAIN "armv6-alpine-linux-musleabihf")
+ else()
+ set(TOOLCHAIN "arm-linux-gnueabihf")
+ endif()
elseif(TARGET_ARCH_NAME STREQUAL "arm64")
set(CMAKE_SYSTEM_PROCESSOR aarch64)
- set(TOOLCHAIN "aarch64-linux-gnu")
+ if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/aarch64-alpine-linux-musl)
+ set(TOOLCHAIN "aarch64-alpine-linux-musl")
+ else()
+ set(TOOLCHAIN "aarch64-linux-gnu")
+ endif()
elseif(TARGET_ARCH_NAME STREQUAL "x86")
set(CMAKE_SYSTEM_PROCESSOR i686)
- set(TOOLCHAIN "i386-linux-gnu")
+ set(TOOLCHAIN "i686-linux-gnu")
else()
message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only armel, arm, arm64 and x86 are supported!")
endif()
@@ -27,12 +36,7 @@ if(TARGET_ARCH_NAME STREQUAL "armel")
if(DEFINED TIZEN_TOOLCHAIN)
include_directories(SYSTEM ${CROSS_ROOTFS}/usr/lib/gcc/${TIZEN_TOOLCHAIN}/include/c++/)
include_directories(SYSTEM ${CROSS_ROOTFS}/usr/lib/gcc/${TIZEN_TOOLCHAIN}/include/c++/armv7l-tizen-linux-gnueabi)
- else() # TODO: this setting assumes debian armel rootfs
- include_directories(SYSTEM ${CROSS_ROOTFS}/usr/include/c++/4.9)
- include_directories(SYSTEM ${CROSS_ROOTFS}/usr/include/${TOOLCHAIN}/c++/4.9)
endif()
-elseif(TARGET_ARCH_NAME STREQUAL "arm64")
- include_directories(SYSTEM ${CROSS_ROOTFS}/usr/include)
endif()
# add_compile_param - adds only new options without duplicates.
@@ -43,7 +47,7 @@ macro(add_compile_param)
message(FATAL_ERROR "Wrong using add_compile_param! Two or three parameters must be given! See add_compile_param description.")
endif()
foreach(OPTION ${ARGV1})
- if(NOT ${ARGV0} MATCHES "${OPTION}")
+ if(NOT ${ARGV0} MATCHES "${OPTION}($| )")
set(${ARGV0} "${${ARGV0}} ${OPTION}")
if(${ARGC} EQUAL "3") # CACHE FORCE mode
set(${ARGV0} "${${ARGV0}}" CACHE STRING "${ARGV2}" FORCE)
@@ -54,52 +58,47 @@ endmacro()
# Specify link flags
add_compile_param(CROSS_LINK_FLAGS "--sysroot=${CROSS_ROOTFS}")
+add_compile_param(CROSS_LINK_FLAGS "--gcc-toolchain=${CROSS_ROOTFS}/usr")
+add_compile_param(CROSS_LINK_FLAGS "--target=${TOOLCHAIN}")
add_compile_param(CROSS_LINK_FLAGS "-fuse-ld=gold")
+
if(TARGET_ARCH_NAME STREQUAL "armel")
- add_compile_param(CROSS_LINK_FLAGS "-target ${TOOLCHAIN}")
if(DEFINED TIZEN_TOOLCHAIN) # For Tizen only
add_compile_param(CROSS_LINK_FLAGS "-B${CROSS_ROOTFS}/usr/lib/gcc/${TIZEN_TOOLCHAIN}")
add_compile_param(CROSS_LINK_FLAGS "-L${CROSS_ROOTFS}/lib")
add_compile_param(CROSS_LINK_FLAGS "-L${CROSS_ROOTFS}/usr/lib")
add_compile_param(CROSS_LINK_FLAGS "-L${CROSS_ROOTFS}/usr/lib/gcc/${TIZEN_TOOLCHAIN}")
- else()
- add_compile_param(CROSS_LINK_FLAGS "-B${CROSS_ROOTFS}/usr/lib/gcc/${TOOLCHAIN}/4.9")
- add_compile_param(CROSS_LINK_FLAGS "-L${CROSS_ROOTFS}/usr/lib/${TOOLCHAIN}")
- add_compile_param(CROSS_LINK_FLAGS "-L${CROSS_ROOTFS}/lib/${TOOLCHAIN}")
- add_compile_param(CROSS_LINK_FLAGS "-L${CROSS_ROOTFS}/usr/lib/gcc/${TOOLCHAIN}/4.9")
endif()
-elseif(TARGET_ARCH_NAME MATCHES "^(arm|arm64)$")
- add_compile_param(CROSS_LINK_FLAGS "-target ${TOOLCHAIN}")
- add_compile_param(CROSS_LINK_FLAGS "-B${CROSS_ROOTFS}/usr/lib/gcc/${TOOLCHAIN}")
- add_compile_param(CROSS_LINK_FLAGS "-L${CROSS_ROOTFS}/lib/${TOOLCHAIN}")
-else() # x86 case
- add_compile_param(CROSS_LINK_FLAGS "-B${CROSS_ROOTFS}/usr/lib/gcc/i686-linux-gnu")
- add_compile_param(CROSS_LINK_FLAGS "-L${CROSS_ROOTFS}/lib/${TOOLCHAIN}")
- add_compile_param(CROSS_LINK_FLAGS "-L${CROSS_ROOTFS}/usr/lib/${TOOLCHAIN}")
+elseif(TARGET_ARCH_NAME STREQUAL "x86")
add_compile_param(CROSS_LINK_FLAGS "-m32")
endif()
+
add_compile_param(CMAKE_EXE_LINKER_FLAGS "${CROSS_LINK_FLAGS}" "TOOLCHAIN_EXE_LINKER_FLAGS")
add_compile_param(CMAKE_SHARED_LINKER_FLAGS "${CROSS_LINK_FLAGS}" "TOOLCHAIN_EXE_LINKER_FLAGS")
add_compile_param(CMAKE_MODULE_LINKER_FLAGS "${CROSS_LINK_FLAGS}" "TOOLCHAIN_EXE_LINKER_FLAGS")
# Specify compile options
-add_compile_options(--sysroot=${CROSS_ROOTFS})
+add_compile_options("--sysroot=${CROSS_ROOTFS}")
+add_compile_options("--target=${TOOLCHAIN}")
+add_compile_options("--gcc-toolchain=${CROSS_ROOTFS}/usr")
+
+if(TARGET_ARCH_NAME MATCHES "^(arm|armel|arm64)$")
+ set(CMAKE_C_COMPILER_TARGET ${TOOLCHAIN})
+ set(CMAKE_CXX_COMPILER_TARGET ${TOOLCHAIN})
+ set(CMAKE_ASM_COMPILER_TARGET ${TOOLCHAIN})
+endif()
+
if(TARGET_ARCH_NAME MATCHES "^(arm|armel)$")
add_compile_options(-mthumb)
add_compile_options(-mfpu=vfpv3)
if(TARGET_ARCH_NAME STREQUAL "armel")
- add_compile_options(-target armv7-linux-gnueabi)
add_compile_options(-mfloat-abi=softfp)
if(DEFINED TIZEN_TOOLCHAIN)
add_compile_options(-Wno-deprecated-declarations) # compile-time option
add_compile_options(-D__extern_always_inline=inline) # compile-time option
endif()
- else() # arm case
- add_compile_options(-target armv7-linux-gnueabihf)
endif()
-elseif(TARGET_ARCH_NAME STREQUAL "arm64")
- add_compile_options(-target ${TOOLCHAIN})
-else() # x86 case
+elseif(TARGET_ARCH_NAME STREQUAL "x86")
add_compile_options(-m32)
add_compile_options(-Wno-error=unused-command-line-argument)
endif()
diff --git a/cross/tryrun.cmake b/cross/tryrun.cmake
index 16eb2e11a8..d0bd77dc97 100644
--- a/cross/tryrun.cmake
+++ b/cross/tryrun.cmake
@@ -1,9 +1,18 @@
+set(CROSS_ROOTFS $ENV{ROOTFS_DIR})
set(TARGET_ARCH_NAME $ENV{TARGET_BUILD_ARCH})
macro(set_cache_value)
set(${ARGV0} ${ARGV1} CACHE STRING "Result from TRY_RUN" FORCE)
endmacro()
+if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/armv6-alpine-linux-musleabihf OR
+ EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/aarch64-alpine-linux-musl)
+
+ SET(ALPINE_LINUX 1)
+else()
+ SET(ALPINE_LINUX 0)
+endif()
+
if(TARGET_ARCH_NAME MATCHES "^(armel|arm|arm64|x86)$")
set_cache_value(FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL_EXITCODE 1)
set_cache_value(GETPWUID_R_SETS_ERRNO_EXITCODE 0)
@@ -33,13 +42,22 @@ if(TARGET_ARCH_NAME MATCHES "^(armel|arm|arm64|x86)$")
set_cache_value(PTHREAD_CREATE_MODIFIES_ERRNO_EXITCODE 1)
set_cache_value(REALPATH_SUPPORTS_NONEXISTENT_FILES_EXITCODE 1)
set_cache_value(SEM_INIT_MODIFIES_ERRNO_EXITCODE 1)
- set_cache_value(SSCANF_CANNOT_HANDLE_MISSING_EXPONENT_EXITCODE 1)
- set_cache_value(SSCANF_SUPPORT_ll_EXITCODE 0)
- set_cache_value(UNGETC_NOT_RETURN_EOF_EXITCODE 0)
+
+
+ if(ALPINE_LINUX)
+ set_cache_value(SSCANF_CANNOT_HANDLE_MISSING_EXPONENT_EXITCODE 0)
+ set_cache_value(SSCANF_SUPPORT_ll_EXITCODE 1)
+ set_cache_value(UNGETC_NOT_RETURN_EOF_EXITCODE 1)
+ else()
+ set_cache_value(SSCANF_CANNOT_HANDLE_MISSING_EXPONENT_EXITCODE 1)
+ set_cache_value(SSCANF_SUPPORT_ll_EXITCODE 0)
+ set_cache_value(UNGETC_NOT_RETURN_EOF_EXITCODE 0)
+ endif()
+
else()
message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only armel, arm, arm64 and x86 are supported!")
endif()
if(TARGET_ARCH_NAME STREQUAL "x86")
- set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES 0)
+ set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES_EXITCODE 0)
endif()