gollvm: add support for crosscompiling
Add support for compiling gollvm for other arch by specifying GOLLVM_DRIVER_DIR to a prebuilt gollvm with two targets, and specify target, toolchain and sysroot in GOLLVM_EXTRA_GOCFLAGS.
Example usage:
RISCV=$HOME/toolchain
SOURCE=$HOME/llvm-project/llvm
TRIPLE=riscv64-unknown-linux-gnu
# host
cmake -G Ninja -S $SOURCE -B build-x86 \
-DCMAKE_INSTALL_PREFIX=install-x86 \
-DCMAKE_BUILD_TYPE=Debug \
-DLLVM_USE_LINKER=bfd \
-DGOLLVM_DEFAULT_LINKER=bfd \
-DLLVM_TARGET_ARCH="X86-64,RISCV64" \
-DLLVM_TARGETS_TO_BUILD="X86;RISCV"
# crosscompile
cmake -G Ninja -S $SOURCE -B build-riscv \
-DCMAKE_INSTALL_PREFIX=$INSTALL \
-DCMAKE_BUILD_TYPE=Debug \
-DLLVM_USE_LINKER=bfd \
-DGOLLVM_DEFAULT_LINKER=bfd \
-DCMAKE_CROSSCOMPILING=True \
-DLLVM_TARGET_ARCH=RISCV64 \
-DLLVM_DEFAULT_TARGET_TRIPLE=$TRIPLE \
-DLLVM_TARGETS_TO_BUILD=RISCV \
-DCMAKE_C_COMPILER=$RISCV/bin/$TRIPLE-gcc \
-DCMAKE_CXX_COMPILER=$RISCV/bin/$TRIPLE-g++ \
-DLLVM_TABLEGEN=$PWD/build-x86/bin/llvm-tblgen \
-DGOLLVM_DRIVER_DIR=$PWD/build-x86/bin \
-DGOLLVM_EXTRA_GOCFLAGS="--target=$TRIPLE \
--gcc-toolchain=$RISCV/ \
--sysroot=$RISCV/sysroot" \
-DGOLLVM_USE_SPLIT_STACK=OFF \
-DCMAKE_C_FLAGS=-latomic \
-DCMAKE_CXX_FLAGS=-latomic
# build gollvm crosscompiler
ninja -C build-x86 llvm-goc llvm-goc-token llvm-godumpspec
# cross compile gollvm, go tools and install
ninja -C build-riscv install-gollvm
Change-Id: Ie4997771fd21437f65d857b7aaae267b7a394f23
Reviewed-on: https://go-review.googlesource.com/c/gollvm/+/425199
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 40a9618..2561f8b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,13 +39,28 @@
set(gollvm_binroot "${CMAKE_CURRENT_BINARY_DIR}")
+# Set MPN path according to the target processor
+string(REGEX REPLACE "-" " " lht_components ${LLVM_DEFAULT_TARGET_TRIPLE})
+separate_arguments(lht_components)
+list(GET lht_components 0 llarch)
+
+if( ${llarch} STREQUAL "x86_64" )
+ set(MPN_PATH "x86_64 generic")
+elseif( ${llarch} STREQUAL "aarch64" )
+ set(MPN_PATH "arm64 generic")
+elseif( ${llarch} STREQUAL "riscv64" )
+ set(MPN_PATH "riscv generic")
+else()
+ message(SEND_ERROR "Arch ${llarch} not yet supported")
+endif()
+
externalproject_add(libgmp
URL https://gmplib.org/download/gmp/gmp-6.2.0.tar.bz2 https://mirrors.kernel.org/gnu/gmp/gmp-6.2.0.tar.bz2
URL_MD5 c24161e0dd44cae78cd5f67193492a21
DOWNLOAD_DIR ${CMAKE_CURRENT_BINARY_DIR}/external-downloads
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/external/gmp-build
SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/external/gmp
- CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=${EXTINSTALLDIR} ${EXTCPPFLAGS} ${EXTLDFLAGS} ${EXTCC}
+ CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=${EXTINSTALLDIR} ${EXTCPPFLAGS} ${EXTLDFLAGS} ${EXTCC} --build=${LLVM_HOST_TRIPLE} --host=${LLVM_DEFAULT_TARGET_TRIPLE} MPN_PATH=${MPN_PATH}
BUILD_COMMAND make -j${PROCESSOR_COUNT} install
LOG_CONFIGURE 1
LOG_BUILD 1
@@ -59,7 +74,7 @@
DOWNLOAD_DIR ${CMAKE_CURRENT_BINARY_DIR}/external-downloads
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/external/mpfr
SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/external/mpfr
- CONFIGURE_COMMAND <SOURCE_DIR>/configure --with-gmp=${CMAKE_CURRENT_BINARY_DIR}/external/gmp --prefix=${EXTINSTALLDIR} ${EXTCPPFLAGS} ${EXTLDFLAGS} ${EXTCC}
+ CONFIGURE_COMMAND <SOURCE_DIR>/configure --with-gmp=${CMAKE_CURRENT_BINARY_DIR}/external/gmp --prefix=${EXTINSTALLDIR} ${EXTCPPFLAGS} ${EXTLDFLAGS} ${EXTCC} -build=${LLVM_HOST_TRIPLE} --host=${LLVM_DEFAULT_TARGET_TRIPLE}
BUILD_COMMAND make -j${PROCESSOR_COUNT} install
LOG_CONFIGURE 1
LOG_BUILD 1
@@ -74,7 +89,7 @@
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/external/mpc
SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/external/mpc
PREFIX ${EXTINSTALLDIR}
- CONFIGURE_COMMAND <SOURCE_DIR>/configure --with-gmp=${CMAKE_CURRENT_BINARY_DIR}/external/gmp --with-mpfr=${CMAKE_CURRENT_BINARY_DIR}/external/mpfr --prefix=${EXTINSTALLDIR} ${EXTCPPFLAGS} ${EXTLDFLAGS} ${EXTCC}
+ CONFIGURE_COMMAND <SOURCE_DIR>/configure --with-gmp=${CMAKE_CURRENT_BINARY_DIR}/external/gmp --with-mpfr=${CMAKE_CURRENT_BINARY_DIR}/external/mpfr --prefix=${EXTINSTALLDIR} ${EXTCPPFLAGS} ${EXTLDFLAGS} ${EXTCC} -build=${LLVM_HOST_TRIPLE} --host=${LLVM_DEFAULT_TARGET_TRIPLE}
BUILD_COMMAND make -j${PROCESSOR_COUNT} install
LOG_CONFIGURE 1
LOG_BUILD 1
diff --git a/cmake/modules/AutoGenGo.cmake b/cmake/modules/AutoGenGo.cmake
index 644075a..a0a3af6 100644
--- a/cmake/modules/AutoGenGo.cmake
+++ b/cmake/modules/AutoGenGo.cmake
@@ -375,7 +375,11 @@
CMAKE_PARSE_ARGUMENTS(ARG "EXPORT" "" "" ${ARGN})
# Construct default driver path
- set(driverpath "${GOLLVM_INSTALL_DIR}/bin/llvm-goc")
+ if (GOLLVM_DRIVER_DIR)
+ set(driverpath "${GOLLVM_DRIVER_DIR}/bin/llvm-goc")
+ else()
+ set(driverpath "${GOLLVM_INSTALL_DIR}/bin/llvm-goc")
+ endif()
file(REMOVE ${outfile})
file(WRITE ${outfile} "package ${package}\n\n")
diff --git a/cmake/modules/GoPackage.cmake b/cmake/modules/GoPackage.cmake
index 7e9e065..0d26a16 100644
--- a/cmake/modules/GoPackage.cmake
+++ b/cmake/modules/GoPackage.cmake
@@ -80,9 +80,14 @@
endif()
# Command to build *.gox.tmp
+ set(objcopycommand "objcopy")
+ if (GOLLVM_DRIVER_DIR)
+ set(objcopycommand "${LLVM_DEFAULT_TARGET_TRIPLE}-objcopy")
+ endif()
+
add_custom_command(
OUTPUT "${package_goxtmp}"
- COMMAND objcopy -j .go_export "${package_ofile}" "${package_goxtmp}"
+ COMMAND "${objcopycommand}" -j .go_export "${package_ofile}" "${package_goxtmp}"
DEPENDS ${package_ofile} ${package_picofile}
COMMENT "Building Go exports file for package '${pkgpath}'"
VERBATIM)
diff --git a/driver/GollvmOptions.td b/driver/GollvmOptions.td
index 3c60287..b2b627f 100644
--- a/driver/GollvmOptions.td
+++ b/driver/GollvmOptions.td
@@ -506,7 +506,8 @@
"frontend by not running any LLVM passes at all">;
def gcc_toolchain_EQ : Joined<["--"], "gcc-toolchain=">, Flags<[DriverOption]>,
- HelpText<"Use the gcc toolchain at the given directory">;
+ HelpText<"Use the gcc toolchain at the given directory, the directory typically contains "
+ "‘lib{,32,64}/gcc{,-cross}/$triple’ and ‘include’">;
def enable_gc_EQ : Joined<["-"], "enable-gc=">,
HelpText<"Enable stack map generation">;
diff --git a/driver/LinuxToolChain.cpp b/driver/LinuxToolChain.cpp
index 2a2fb10..bebad8c 100644
--- a/driver/LinuxToolChain.cpp
+++ b/driver/LinuxToolChain.cpp
@@ -34,9 +34,10 @@
static llvm::StringRef getOSLibDir(const llvm::Triple &triple)
{
- // multilib is not supported on major aarch64/arm64 linux distributions
+ // multilib is not supported on major aarch64/arm64 and riscv64 linux distributions
// subject to change when more scenarios to be taken into account
- if (triple.getArch() == llvm::Triple::aarch64)
+ if (triple.getArch() == llvm::Triple::aarch64 ||
+ triple.getArch() == llvm::Triple::riscv64)
return "lib";
// x86 uses the lib32 variant, unlike other archs.
if (triple.getArch() == llvm::Triple::x86)
@@ -67,8 +68,11 @@
pathlist &fpaths = filePaths();
addIfPathExists(fpaths, gccDetector_.getLibPath());
std::string osLibDir = getOSLibDir(targetTriple).str();
- if (!driver.sysRoot().empty())
+ if (!driver.sysRoot().empty()) {
+ addIfPathExists(fpaths, llvm::Twine(driver.sysRoot() + "/usr/"
+ + osLibDir).str());
osLibDir = driver.sysRoot() + "/" + osLibDir;
+ }
addIfPathExists(fpaths, llvm::Twine(gccDetector_.getParentLibPath() +
"/../" + ftrip).str());
addIfPathExists(fpaths, llvm::Twine(osLibDir).str());
@@ -136,6 +140,10 @@
break;
}
}
+ if (auto *Arg = args.getLastArg(gollvm::options::OPT_sysroot_EQ)) {
+ std::string Sysroot = Arg->getValue();
+ return Sysroot + "/" + LibDir + "/" + Loader;
+ }
return "/" + LibDir + "/" + Loader;
}
diff --git a/gotools/CMakeLists.txt b/gotools/CMakeLists.txt
index cf70562..e8023f4 100644
--- a/gotools/CMakeLists.txt
+++ b/gotools/CMakeLists.txt
@@ -22,8 +22,12 @@
endif()
# Driver for compiling *.go files.
-get_target_property(driverdir llvm-goc RUNTIME_OUTPUT_DIRECTORY)
-set(gollvm_driver "${driverdir}/llvm-goc")
+if (GOLLVM_DRIVER_DIR)
+ set(gollvm_driver "${GOLLVM_DRIVER_DIR}/llvm-goc")
+else()
+ get_target_property(driverdir llvm-goc RUNTIME_OUTPUT_DIRECTORY)
+ set(gollvm_driver "${driverdir}/llvm-goc")
+endif()
set(gocompiler ${gollvm_driver})
set(cmd_srcroot "${GOLLVM_SOURCE_DIR}/gofrontend/libgo/go/cmd")
diff --git a/libgo/CMakeLists.txt b/libgo/CMakeLists.txt
index b0cf30d..8625699 100644
--- a/libgo/CMakeLists.txt
+++ b/libgo/CMakeLists.txt
@@ -72,8 +72,12 @@
#......................................................................
# Driver for compiling *.go files.
-get_target_property(driverdir llvm-goc RUNTIME_OUTPUT_DIRECTORY)
-set(gollvm_driver "${driverdir}/llvm-goc")
+if (GOLLVM_DRIVER_DIR)
+ set(gollvm_driver "${GOLLVM_DRIVER_DIR}/llvm-goc")
+else()
+ get_target_property(driverdir llvm-goc RUNTIME_OUTPUT_DIRECTORY)
+ set(gollvm_driver "${driverdir}/llvm-goc")
+endif()
set(gocompiler ${gollvm_driver})
# Pick up any extra Go compiler flags specified via
@@ -272,8 +276,12 @@
set(gensysinfotmp "${libgo_binroot}/gen-sysinfo.go.tmp")
set(gensysinfomacrotmp "${libgo_binroot}/sysinfo.macros.txt")
set(gensysinfoobject "${libgo_binroot}/sysinfo.o")
-get_target_property(godumpspecdir llvm-godumpspec RUNTIME_OUTPUT_DIRECTORY)
-set(godumpspecexec "${godumpspecdir}/llvm-godumpspec")
+if (GOLLVM_DRIVER_DIR)
+ set(godumpspecexec "${GOLLVM_DRIVER_DIR}/llvm-godumpspec")
+else()
+ get_target_property(godumpspecdir llvm-godumpspec RUNTIME_OUTPUT_DIRECTORY)
+ set(godumpspecexec "${godumpspecdir}/llvm-godumpspec")
+endif()
set(sysinfoc "${libgo_srcroot}/sysinfo.c")
set(sysinfoflags ${basedefines})
list(APPEND sysinfoflags "-I${libgo_binroot}" "-I${libgo_binroot}/runtime")