cmake-rs
cmake-rs copied to clipboard
Improve cross-compiling support
I ran into a cross-compiling issue where cmake used the host's CMAKE_SYSTEM_PROCESSOR instead of the target's and incorrectly evaluated a condition in the CMakeLists.txt that led to some unsupported compiler flags being used.
After thinking for a bit about how to deal with this issue in general, I can see a couple of solutions:
- Use a
CMAKE_TOOLCHAIN_FILE(#10) as suggested by the CMake CrossCompiling wiki page - Set the
CMAKE_SYSTEM_NAMEandCMAKE_SYSTEM_PROCESSORin thebuild.rsfor each target triplet that I need
The first seems too involved if I only need the second, but the second seems like it should be something not specific to my crate since it only depends directly on the $TARGET.
(Also, let me add as a warning that I am by no means very knowledgeable about CMake, so there may be other reasonable ways to do this.)
I see that there is some support for cross-compiling to certain targets in cmake-rs already (e.g. a9f74a4bf488c132876c9976c98b44cdc1a0603c, #35, #45), but it seems to be done on a case-by-case basis. Plus, there appears to be a large amount of target-specific logic
So, this has led me to wonder if the cmake-rs cross-compiling/target-specific story could be improved and extended to support more targets in a relatively clean way. I'm posting this issue basically to see if there's interest and to discuss ideas. Here are some thoughts on different approaches:
-
Leave
cmake-rsmostly untouched and continue to add special cases for various targets. -
Create a sort of condition matrix to support combinations in a regular way. For example, you might start with
host == targetandhost != targetand branch within those into different supported targets. -
Remove all or most of the target-specific logic and put it into
CMAKE_TOOLCHAIN_FILEs, one for each of the different cases supported.
I suppose the latter two options have in common a mapping from Rust target triples to (at least) CMAKE_SYSTEM_NAME/CMAKE_SYSTEM_PROCESSOR pairs, though the Rust one may be more explicit. (I'm certainly not the first person to think of this: https://github.com/rust-lang/rust/issues/50220#issuecomment-433133136)
There are a few other improvements (at least, I think they are) that might also be considered (now or in some distant future):
- Use
$CARGO_CFG_TARGET_OS,$CARGO_CFG_TARGET_ARCH, etc. instead of$TARGET - CI with
cross, perhaps in the style oftrust - iOS support (e.g.
grpc-sys)
Anyway, these are just some initial thoughts on the matter. Feedback would be appreciated!
I'm not really personally familiar enough with cmake to know how best to approach this, but I'm all for improving the cross-compile story!
Ugh, I just got bitten by this. Thanks for filing such a thorough issue about the problem space, @spl! I'd like to voice my support for doing something simple. A basic translation from target triple to (CMAKE_SYSTEM_NAME, CMAKE_SYSTEM_PROCESSOR) would go a long way, I think.
Or, in the short term, an escape hatch of reading CMAKE_SYSTEM_NAME and CMAKE_SYSTEM_PROCESSOR from the environment could at least ease the pain of this!
Any update on this? :)
I'm getting this build error when cross compiling for macos because one of my deps's build.rs script uses this cmake crate:
error: failed to run custom build command for `ffts v0.1.0 (ssh://[email protected]/Boscop/ffts-rs#ef6850c8)`
Caused by:
process didn't exit successfully: `/home/me/projects/myproject/target/release/build/ffts-a7bc83ba5c7e316e/build-script-build` (exit code: 101)
--- stdout
running: "cmake" "/home/me/.cargo/git/checkouts/ffts-rs-90217fe977f2ad3e/ef6850c/ffts" "-DCMAKE_INSTALL_PREFIX=/home/me/projects/myproject/target/x86_64-apple-darwin/release/build/ffts-709feedc794cf523/out" "-DCMAKE_C_FLAGS= -ffunction-sections -fdata-sections -fPIC --target=x86_64-apple-darwin" "-DCMAKE_C_COMPILER=/home/me/3rdparty/osxcross/target/bin/o64-clang" "-DCMAKE_CXX_FLAGS= -ffunction-sections -fdata-sections -fPIC --target=x86_64-apple-darwin" "-DCMAKE_CXX_COMPILER=/home/me/3rdparty/osxcross/target/bin/o64-clang++" "-DCMAKE_ASM_FLAGS= -ffunction-sections -fdata-sections -fPIC --target=x86_64-apple-darwin" "-DCMAKE_ASM_COMPILER=/home/me/3rdparty/osxcross/target/bin/o64-clang" "-DCMAKE_BUILD_TYPE=Release"
-- The C compiler identification is Clang 10.0.1
-- The ASM compiler identification is Clang
-- Found assembler: /home/me/3rdparty/osxcross/target/bin/o64-clang
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - failed
-- Check for working C compiler: /home/me/3rdparty/osxcross/target/bin/o64-clang
-- Check for working C compiler: /home/me/3rdparty/osxcross/target/bin/o64-clang - broken
-- Configuring incomplete, errors occurred!
See also "/home/me/projects/myproject/target/x86_64-apple-darwin/release/build/ffts-709feedc794cf523/out/build/CMakeFiles/CMakeOutput.log".
See also "/home/me/projects/myproject/target/x86_64-apple-darwin/release/build/ffts-709feedc794cf523/out/build/CMakeFiles/CMakeError.log".
--- stderr
CMake Error at /usr/share/cmake-3.18/Modules/CMakeTestCCompiler.cmake:66 (message):
The C compiler
"/home/me/3rdparty/osxcross/target/bin/o64-clang"
is not able to compile a simple test program.
It fails with the following output:
Change Dir: /home/me/projects/myproject/target/x86_64-apple-darwin/release/build/ffts-709feedc794cf523/out/build/CMakeFiles/CMakeTmp
Run Build Command(s):/usr/bin/make cmTC_d5773/fast && /usr/bin/make -f CMakeFiles/cmTC_d5773.dir/build.make CMakeFiles/cmTC_d5773.dir/build
make[1]: Entering directory '/home/me/projects/myproject/target/x86_64-apple-darwin/release/build/ffts-709feedc794cf523/out/build/CMakeFiles/CMakeTmp'
Building C object CMakeFiles/cmTC_d5773.dir/testCCompiler.c.o
/home/me/3rdparty/osxcross/target/bin/o64-clang -ffunction-sections -fdata-sections -fPIC --target=x86_64-apple-darwin -o CMakeFiles/cmTC_d5773.dir/testCCompiler.c.o -c /home/me/projects/myproject/target/x86_64-apple-darwin/release/build/ffts-709feedc794cf523/out/build/CMakeFiles/CMakeTmp/testCCompiler.c
Linking C executable cmTC_d5773
/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_d5773.dir/link.txt --verbose=1
/home/me/3rdparty/osxcross/target/bin/o64-clang -ffunction-sections -fdata-sections -fPIC --target=x86_64-apple-darwin -rdynamic CMakeFiles/cmTC_d5773.dir/testCCompiler.c.o -o cmTC_d5773
/usr/bin/ld: unrecognized option '-dynamic'
/usr/bin/ld: use the --help option for usage information
clang-10: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [CMakeFiles/cmTC_d5773.dir/build.make:106: cmTC_d5773] Error 1
make[1]: Leaving directory '/home/me/projects/myproject/target/x86_64-apple-darwin/release/build/ffts-709feedc794cf523/out/build/CMakeFiles/CMakeTmp'
make: *** [Makefile:140: cmTC_d5773/fast] Error 2
CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
CMakeLists.txt:3 (project)
thread 'main' panicked at '
command did not execute successfully, got: exit code: 1
build script failed, must exit now', /home/me/.cargo/registry/src/github.com-1ecc6299db9ec823/cmake-0.1.44/src/lib.rs:885:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
error: build failed
Btw, this is the build.rs script:
fn main() {
let dst = cmake::Config::new("ffts").profile("Release").build();
println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
let target_windows = std::env::var("CARGO_CFG_WINDOWS").is_ok();
println!("cargo:rustc-link-lib=static={}", if target_windows { "ffts_static" } else { "ffts" });
}
Is there anything I can do to make this work? :)
I followed these instructions, so I'm building with
PATH="$(pwd)/osxcross/target/bin:$PATH" \
CC=o64-clang \
CXX=o64-clang++ \
cargo build --target x86_64-apple-darwin
I'm also getting bit by this a bit. I'm trying to cross-compile BoringSSL from Linux to Windows-MSVC. I have a working toolchain locally, so it should all be fine. But cmake currently blows up in the visual_studio_generator function, since cc's find_vs_studio simply returns an error unconditionally when trying to locate VS on non-windows build host.
I think the ideal solution here is to honor the CMAKE_GENERATOR environment variable, which can be used to select the CMAKE_GENERATOR. I think, if self.generator is unset, defaulting to the CMAKE_GENERATOR before trying to locate the Visual Studio Generator ought to do the trick.
The rest of the issues I can work around using the CMAKE_TOOLCHAIN_FILE.
I've opened #158 that adds CMAKE_SYSTEM_NAME and CMAKE_SYSTEM_PROCESSOR based CARGO_CFG_TARGET_OS and CARGO_CFG_TARGET_ARCH, it's tested with cross for supported targets.