CMake: Clang-based cross-compile for Linux uses wrong target platform

Viewed 573

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:

  • CC environment variable points to v17_clang-10.0.1-centos7\x86_64-unknown-linux-gnu\bin\clang.exe
  • CXX environment variable points to v17_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 to STATIC_LIBRARY or 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-gnu and -DCMAKE_CXX_COMPILER_TARGET=x86_64-unknown-linux-gnu are set to match the Clang distribution I'm using.
  • For good measure, -DCMAKE_SYSTEM_NAME=linux and -DCMAKE_SYSTEM_PROCESSOR=x86_64 are 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?

0 Answers
Related