I'm attempting to build a library for Linux using CMake and Clang on Windows 10. Because this library needs to be compatible with a specific version of the Unreal Engine, I'm using the recommended cross-compilation toolchain for Unreal Engine 4.26, which is labelled v17_clang-10.0.1-centos7.
I've not made a toolchain file yet, but have been experimenting with CMake options on the command line to find a setup that works. My current configuration is:
CCenvironment variable points tov17_clang-10.0.1-centos7\x86_64-unknown-linux-gnu\bin\clang.exeCXXenvironment variable points tov17_clang-10.0.1-centos7\x86_64-unknown-linux-gnu\bin\clang++.exe-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY: According to this answer, this must be set toSTATIC_LIBRARYor the compiler checks will fail (and did when I first ran them) when they try to link.-DCMAKE_C_COMPILER_TARGET=x86_64-unknown-linux-gnuand-DCMAKE_CXX_COMPILER_TARGET=x86_64-unknown-linux-gnuare set to match the Clang distribution I'm using.- For good measure,
-DCMAKE_SYSTEM_NAME=linuxand-DCMAKE_SYSTEM_PROCESSOR=x86_64are also set.
This configuration is generated correctly (I'm using Ninja as the generator), but when building it appears that the target is still Windows and not Linux. I get lots of errors like the following:
[14/106] Building CXX object core/thirdParty/cppfs-1.2.0/cppfs-1.2.0/source/cppfs/CMakeFiles/cppfs.dir/source/Diff.cpp.obj
FAILED: core/thirdParty/cppfs-1.2.0/cppfs-1.2.0/source/cppfs/CMakeFiles/cppfs.dir/source/Diff.cpp.obj
C:\UnrealToolchains\v17_clang-10.0.1-centos7\x86_64-unknown-linux-gnu\bin\clang++.exe -DCLIENT_VERSION_MAJOR=-1
-DCLIENT_VERSION_MINOR=-1 -DCLIENT_VERSION_PATCH=-1 -DCPPFS_STATIC_DEFINE -DFACEIT_CORELIB_BUILD_PRODUCER
-DHAVE_OPENSSL -DSERVER_VERSION_MAJOR=-1 -DSERVER_VERSION_MINOR=-1 -DSERVER_VERSION_PATCH=-1 -DSYSTEM_WINDOWS
-Icore/thirdParty/cppfs-1.2.0/cppfs-1.2.0/source/include
-I../core/thirdParty/cppfs-1.2.0/cppfs-1.2.0/source/cppfs/3rdparty
-I../core/thirdParty/cppfs-1.2.0/cppfs-1.2.0/source/cppfs/include
-Icore/thirdParty/cppfs-1.2.0/cppfs-1.2.0/source/cppfs/include -g -Xclang -gcodeview -O0 -D_DEBUG -D_DLL -D_MT
-Xclang --dependent-lib=msvcrtd -Wall -Wextra -pedantic -Werror -Wl,--fatal-warnings -fPIC -Wno-unused-parameter
-std=gnu++14 -MD -MT core/thirdParty/cppfs-1.2.0/cppfs-1.2.0/source/cppfs/CMakeFiles/cppfs.dir/source/Diff.cpp.obj
-MF core\thirdParty\cppfs-1.2.0\cppfs-1.2.0\source\cppfs\CMakeFiles\cppfs.dir\source\Diff.cpp.obj.d
-o core/thirdParty/cppfs-1.2.0/cppfs-1.2.0/source/cppfs/CMakeFiles/cppfs.dir/source/Diff.cpp.obj
-c ../core/thirdParty/cppfs-1.2.0/cppfs-1.2.0/source/cppfs/source/Diff.cpp
clang++: error: -Wl,--fatal-warnings: 'linker' input unused [-Werror,-Wunused-command-line-argument]
clang++: error: unsupported option '-fPIC' for target 'x86_64-pc-windows-msvc'
It seems that the target is x86_64-pc-windows-msvc, and PLATFORM_WINDOWS is defined, so my input settings have been ignored. What am I missing here? Do I need an actual toolchain file after all?
EDIT: After recommendations in the comments, I have created a toolchain file which looks like this:
if("$ENV{LINUX_MULTIARCH_ROOT}" STREQUAL "")
message(FATAL_ERROR "Provide the path to the Clang toolchain in the LINUX_MULTIARCH_ROOT environment variable.")
endif()
# Clang target triple
set(TARGET_TRIPLE x86_64-unknown-linux-gnu)
# Clean path separators
file(TO_CMAKE_PATH $ENV{LINUX_MULTIARCH_ROOT}/${TARGET_TRIPLE} TOOLCHAIN_ROOT)
list(APPEND CMAKE_PROGRAM_PATH ${TOOLCHAIN_ROOT}/bin)
set(CMAKE_CROSSCOMPILING TRUE)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR x86_64)
# specify the cross compiler
set(CMAKE_C_COMPILER_TARGET ${TARGET_TRIPLE})
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER_TARGET ${TARGET_TRIPLE})
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_ASM_COMPILER_TARGET ${TARGET_TRIPLE})
set(CMAKE_ASM_COMPILER clang)
# C/C++ toolchain
set(CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN ${TOOLCHAIN_ROOT})
set(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN ${TOOLCHAIN_ROOT})
# This must be set or compiler checks fail when linking
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_ROOT})
set(CMAKE_SYSROOT ${TOOLCHAIN_ROOT})
After starting from a clean environment it seems the target is now detected correctly, but instead I get a configuring error saying Could NOT find Threads (missing: Threads_FOUND). I'm assuming this is because the Threads package is not being found in the toolchain, although I can verify that the libraries are present in Windows explorer.
Another edit: I'm beginning to wonder whether the package cannot be found because CMake is attempting to look for a package description file rather than the libraries themselves? Is there a way I can fix that for this particular case of cross-compilation?