Skip to content

Cross-compiling #180

Open
Open
@aminya

Description

@aminya

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

Activity

glennvl

glennvl commented on Dec 28, 2022

@glennvl

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

abeimler commented on Dec 30, 2022

@abeimler
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

glennvl commented on Jan 8, 2023

@glennvl

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

glennvl commented on Jan 8, 2023

@glennvl

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

aminya commented on Jan 9, 2023

@aminya
OwnerAuthor

@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

abeimler commented on Jan 9, 2023

@abeimler
Contributor

@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

aminya commented on Jan 17, 2023

@aminya
OwnerAuthor

clang-tidy complains about unused compiler arguments

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

aminya

aminya commented on Jan 19, 2023

@aminya
OwnerAuthor

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

Project579 commented on May 9, 2023

@Project579
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.

linked a pull request that will close this issuefix: cross arm C build #193on Aug 22, 2023
linked a pull request that will close this issueFix: Docker task (Taskfiles) #187on Aug 22, 2023
linked a pull request that will close this issueinstall mingw with setup-cpp #233on Aug 22, 2023
kassane

kassane commented on Oct 11, 2023

@kassane

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
Cross-compiling · Issue #180 · aminya/project_options