Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross-compiling #180

Open
6 of 9 tasks
aminya opened this issue Dec 28, 2022 · 10 comments · Fixed by #188, #193, #196, #187 or #233
Open
6 of 9 tasks

Cross-compiling #180

aminya opened this issue Dec 28, 2022 · 10 comments · Fixed by #188, #193, #196, #187 or #233

Comments

@aminya
Copy link
Owner

aminya commented Dec 28, 2022

Future Ideas

  • add more specific project_options for emscripten
  • add cross-compiler for ARM
  • Maybe Android (toolchain)

Usage

The best you can do is add this to your cmake file:

# opt-in cross-compiling
option(ENABLE_CROSS_COMPILING "Detect cross compiler and setup toolchain" OFF)
if(ENABLE_CROSS_COMPILING)
  enable_cross_compiler()
endif()
run_vcpkg() # run_vcpkg AFTER enable_cross_compiler, when using vcpkg

and run cmake with these additional arguments:

-DENABLE_CROSS_COMPILING:BOOL=ON -DDEFAULT_TRIPLET=x64-mingw-dynamic

See Taskfile and docker examples

Notes

  • This feature isn't a magic switch to enable cross-compiling
    • vcpkg Community triplets are not guaranteed to succeed.
    • emscripten can be more of a specific use case and you may need to add some flags
  • The toolchain files are more of a basic setup and examples
  • enable_cross_compiler() and run_vcpkg() can help you set up Community triplets easier
  • Best way to experiment with cross-compiling is by using docker and in a closed environment

Originally posted by @abeimler in #171 (comment)

Upvote & Fund

  • I am using Polar.sh so you can upvote and help fund this issue. The funding is received once the issue is completed & confirmed by you.

  • Thank you in advance for helping prioritize & fund our backlog.

Fund with Polar
@glennvl
Copy link

glennvl commented Dec 28, 2022

I am attempting to use project_options v0.26.3 for an embedded project. The idea is to write everything from scratch in C++, but as a first step I'm attempting to get the build system and tooling setup, for which I'm using the devkit demo code which is written in C. I am using vscode on windows with ubuntu in wsl (after I get everything to work I want to use docker).

What I noticed so far (when cross compiling for the target board) is:

  • clang-tidy complains about unused compiler arguments
[build] warning: argument unused during compilation: '-mcpu=cortex-m4' [clang-diagnostic-unused-command-line-argument]
[build] warning: argument unused during compilation: '-mfloat-abi=hard' [clang-diagnostic-unused-command-line-argument]
[build] warning: argument unused during compilation: '-mfpu=fpv4-sp-d16' [clang-diagnostic-unused-command-line-argument]
[build] warning: argument unused during compilation: '-mthumb' [clang-diagnostic-unused-command-line-argument]
  • When passing --extra-arg=--target=arm-none-eabi-gcc to clang-tidy, those warnings disappear, but it then fails to find standard library headers. Adding -p=${CMAKE_BINARY_DIR}/compile_commands.json does not make a difference.
[build] /projects/STM32F303-DISCOVERY/src/Demo/Inc/usbd_conf.h:26:10: error: 'stdio.h' file not found [clang-diagnostic-error]
[build] #include <stdio.h>
  • cppcheck is missing preprocessor definitions. This became visible because CMSIS checks if the used compiler is supported. Manually adding -D__GNUC__ to CPPCHECK_OPTIONS fixes this specific sympton, but I assume there's some rootcause that should be resolved.
[build] /projects/STM32F303-DISCOVERY/src/Drivers/CMSIS/Include/cmsis_compiler.h:261:0: warning: #error Unknown compiler. [preprocessorErrorDirective]
[build]   #error Unknown compiler.
[build] ^
  • Compilation is unreliable, cppcheck sometimes crashes, compilation fails most of the time, sometimes it succeeds. I haven't looked into this further, but it may be normal since 1000+ warnings are produced from the demo code and the memory available for WSL is limited.

@abeimler
Copy link
Contributor

What I noticed so far (when cross compiling for the target board) is:

  • clang-tidy complains about unused compiler arguments
[build] warning: argument unused during compilation: '-mcpu=cortex-m4' [clang-diagnostic-unused-command-line-argument]
[build] warning: argument unused during compilation: '-mfloat-abi=hard' [clang-diagnostic-unused-command-line-argument]
[build] warning: argument unused during compilation: '-mfpu=fpv4-sp-d16' [clang-diagnostic-unused-command-line-argument]
[build] warning: argument unused during compilation: '-mthumb' [clang-diagnostic-unused-command-line-argument]

Maybe related to #96 ? @aminya

@glennvl
Copy link

glennvl commented Jan 8, 2023

To follow up on the clang-tidy issue. Adding -p ${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json works when using the latest cmake version 3.25.1. It is then not needed to add --extra-arg=--target=arm-none-eabi-gcc.

@glennvl
Copy link

glennvl commented Jan 8, 2023

As for cppcheck, I haven't figured it out yet. When I manually run cppcheck using the following script

#!/bin/sh

cppcheck -D__GNUC__ \
         --project=build/arm-cortex-m4-gcc-debug/compile_commands.json \
         --platform=cmake/arm-cortex-m4-platform.xml \
         --cppcheck-build-dir=build/arm-cortex-m4-gcc-debug/cppcheck \
         --enable=style,performance,warning,portability \
         --inline-suppr \
         --suppress=cppcheckError \
         --suppress=internalAstError \
         --suppress=unmatchedSuppression \
         --suppress=passedByValue \
         --suppress=syntaxError \
         --inconclusive \
         --std=c11 \
         --template=gcc \
         --verbose

Everything appears to be working fine.

cppcheck_output.txt

But when I run it from within cmake with the same parameters, all sorts of weirdness (including regular crashes) happens...

cmake_output.txt

@aminya
Copy link
Owner Author

aminya commented Jan 9, 2023

@abeimler Could you add some docs about Toolchains to the Readme?

I'd like to tag a new release, but we should add some basic docs for the new features.

@abeimler
Copy link
Contributor

abeimler commented Jan 9, 2023

@abeimler Could you add some docs about Toolchains to the Readme?

I'd like to tag a new release, but we should add some basic docs for the new features.

Well, writing docs is not my most vital skill ^^
The best I can do is give some examples and Dockerfiles ...

  1. Add those to your CMakeLists.txt:
# opt-in cross-compiling
option(ENABLE_CROSS_COMPILING "Detect cross compiler and setup toolchain" OFF)
if(ENABLE_CROSS_COMPILING)
  enable_cross_compiler()
endif()
run_vcpkg() # run_vcpkg AFTER enable_cross_compiler, when using vcpkg
  1. use -DENABLE_CROSS_COMPILING:BOOL=ON for enabling cross-compiling and set the target with -DDEFAULT_TRIPLET=x64-mingw-dynamic (using DEFAULT_TRIPLET is the easiest way and should be recommended).

The option for DEFAULT_TRIPLET are the simlary to vcpkg VCPKG_DEFAULT_TRIPLET

  • x64-mingw-dynamic
  • x64-mingw-static
  • x86-mingw-dynamic
  • x86-mingw-static
  • wasm32-emscripten
  • arm-linux
  • arm64-linux

Alternatively, you can set the (cross)compiler directly with: -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ or set the environment variable for CC and CXX.


For arm-linux/arm64-linux, you must set the compiler:

For (bare-metal) you don't need/can't(?) set arm-linux/arm64-linux (for vcpkg):

Example:

  • -DENABLE_CROSS_COMPILING:BOOL=ON -DCMAKE_C_COMPILER=gcc-aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=gcc-aarch64-linux-gnu-g++ -DDEFAULT_TRIPLET=arm64-linux
  • -DENABLE_CROSS_COMPILING:BOOL=ON -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc -DCMAKE_CXX_COMPILER=arm-linux-gnueabi-g++ -DDEFAULT_TRIPLET=arm-linux -DCROSS_ROOT=/usr/gcc-arm-linux-gnueabihf
  • -DENABLE_CROSS_COMPILING:BOOL=ON -DCMAKE_C_COMPILER=arm-none-eabi-gcc -DCMAKE_CXX_COMPILER=arm-none-eabi-g++
  • -DENABLE_CROSS_COMPILING:BOOL=ON -DCMAKE_C_COMPILER=arm-none-eabi-gcc -DCMAKE_CXX_COMPILER=arm-none-eabi-g++ -DTARGET_ARCHITECTURE:STRING=arm -DCROSS_ROOT:STRING="/usr/arm-none-eabi-gcc" -DCROSS_TRIPLET:STRING=arm-none-eabi-gcc

Notes

  • Of course, you need to set up the cross-compiler and environment on your own hint hint setup-cpp, for later ... install mingw-w64, emscripten step-by-step.
  • This feature isn't a magic switch to enable cross-compiling for everything, it's more of a base-line
  • The toolchain files (provided by project_options) are more of a basic setup and example (you may need to use your own cmake toolchains, depending on your environment) ... see VCPKG_CHAINLOAD_TOOLCHAIN_FILE for vcpkg
  • enable_cross_compiler() and run_vcpkg() can help you set up Community triplets for vcpkg easier
  • try to auto-detect the following cross-compilers, when setting DEFAULT_TRIPLET
  • otherwise when you are setting the C/CXX compiler (-DCMAKE_C_COMPILER=gcc-aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=gcc-aarch64-linux-gnu-g++), I try to auto-detect the DEFAULT_TRIPLET
  • if you have problem finding (system) libraries, maybe the SYSROOT for the cross-compiler is wrong, you can set the SYSROOT with -DCROSS_ROOT=/usr/gcc-arm-linux-gnueabihf

(@aminya Hope this can help you to write a proper section)

@aminya
Copy link
Owner Author

aminya commented Jan 17, 2023

clang-tidy complains about unused compiler arguments

Related to this discussion
https://discourse.cmake.org/t/using-clang-tidy-with-cross-compilation/5435

@aminya
Copy link
Owner Author

aminya commented Jan 19, 2023

Another remaining issue for Cross-compiling is that its options are using global CMake options instead of the function arguments. We should be using function arguments

@Project579
Copy link
Contributor

It would also be nice if clang based tools (clang-tidy and iwyu) actually worked when cross compiling, I have some ideas on how to make them work but they require refactoring in lot's of places, I may post a draft PR in the future with my current progress.

@kassane
Copy link

kassane commented Oct 11, 2023

Is it intended to add support for clang/llvm-libcxx for cross-compilation?

Currently the zig toolchain allows portability to the LLVM toolchain. Integration with CMake is a bit problematic due to the space between the zig cc or zig c++ command.

The main difference between zig and conventional toolchain is that for C++ it restricts to using libcxx by default. However, it is possible to use another ABI.

e.g.:
https://github.com/uber/hermetic_cc_toolchain - zig cc on bazel

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment