summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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()