cmake-rs icon indicating copy to clipboard operation
cmake-rs copied to clipboard

Improve cross-compiling support

Open spl opened this issue 6 years ago • 6 comments
trafficstars

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:

  1. Use a CMAKE_TOOLCHAIN_FILE (#10) as suggested by the CMake CrossCompiling wiki page
  2. Set the CMAKE_SYSTEM_NAME and CMAKE_SYSTEM_PROCESSOR in the build.rs for 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:

  1. Leave cmake-rs mostly untouched and continue to add special cases for various targets.

  2. Create a sort of condition matrix to support combinations in a regular way. For example, you might start with host == target and host != target and branch within those into different supported targets.

  3. 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 of trust
  • iOS support (e.g. grpc-sys)

Anyway, these are just some initial thoughts on the matter. Feedback would be appreciated!

spl avatar May 21 '19 13:05 spl

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!

alexcrichton avatar May 22 '19 13:05 alexcrichton

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.

benesch avatar Sep 26 '19 05:09 benesch

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!

benesch avatar Sep 26 '19 05:09 benesch

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

Boscop avatar Dec 29 '20 00:12 Boscop

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.

roblabla avatar Jun 04 '21 10:06 roblabla

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.

messense avatar Jul 26 '22 12:07 messense