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 and toolchains #171

Merged
merged 11 commits into from
Dec 28, 2022
Merged

Conversation

abeimler
Copy link
Contributor

@abeimler abeimler commented Nov 4, 2022

Hello,
I try to add some toolchain file (for mingw) and emscripten.
The compiler detection seems to work, but I can't fully build the test projects.

To enable Cross-compiling you need to set the cross-compiler via (environment variable) CC and CXX, then call this cmake-macro:

enable_cross_compiler()

(before run_vcpkg())

There are also some TODOs and problem...

  1. Detect Compiler and set Toolchain
    (I tried to detect the compiler with detect_compiler(), but it didn't work, so I fallback to $ENV{CXX})
  2. Override Toolchain and set chainload toolchain for vcpkg
    (when running run_vcpkg())
  3. Conan Support ??? @aminya
  4. Test on Windows done by CI
  5. Emscripten support (experimental)
  6. Cleanup code and run linter

Right now, I have some problems building the test Project(s), seems like vcpkg didn't like the 3rd-party libs and throws an error:

CMake Error at scripts/cmake/vcpkg_execute_required_process.cmake:96 (message):
    Command failed: /root/cmake/cmake-3.24.2-linux-x86_64/bin/cmake /root/vcpkg/buildtrees/eigen3/src/3.4.0-bd1201c15a.clean -DBUILD_TESTING=OFF -DEIGEN_BUILD_PKGCONFIG=ON -DCMAKE_MAKE_PROGRAM=/root/ninja/ninja -DCMAKE_SYSTEM_NAME=Linux -DBUILD_SHARED_LIBS=OFF -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/root/vcpkg/scripts/toolchains/linux.cmake -DVCPKG_TARGET_TRIPLET=x64-linux -DVCPKG_SET_CHARSET_FLAG=ON -DVCPKG_PLATFORM_TOOLSET=external -DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=ON -DCMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=ON -DCMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY=ON -DCMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP=TRUE -DCMAKE_VERBOSE_MAKEFILE=ON -DVCPKG_APPLOCAL_DEPS=OFF -DCMAKE_TOOLCHAIN_FILE=/root/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION=ON -DVCPKG_CXX_FLAGS= -DVCPKG_CXX_FLAGS_RELEASE= -DVCPKG_CXX_FLAGS_DEBUG= -DVCPKG_C_FLAGS= -DVCPKG_C_FLAGS_RELEASE= -DVCPKG_C_FLAGS_DEBUG= -DVCPKG_CRT_LINKAGE=dynamic -DVCPKG_LINKER_FLAGS= -DVCPKG_LINKER_FLAGS_RELEASE= -DVCPKG_LINKER_FLAGS_DEBUG= -DVCPKG_TARGET_ARCHITECTURE=x64 -DCMAKE_INSTALL_LIBDIR:STRING=lib -DCMAKE_INSTALL_BINDIR:STRING=bin -D_VCPKG_ROOT_DIR=/root/vcpkg -D_VCPKG_INSTALLED_DIR=/home/project_options/test/build/vcpkg_installed -DVCPKG_MANIFEST_INSTALL=OFF -DCMAKEPACKAGE_INSTALL_DIR=/root/vcpkg/packages/eigen3_x64-linux/debug/share/eigen3 -DPKGCONFIG_INSTALL_DIR=/root/vcpkg/packages/eigen3_x64-linux/debug/lib/pkgconfig -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/root/vcpkg/packages/eigen3_x64-linux/debug
    Working Directory: /root/vcpkg/buildtrees/eigen3/x64-linux-dbg
    Error code: 1
    See logs for more information:
      /root/vcpkg/buildtrees/eigen3/config-x64-linux-dbg-out.log
      /root/vcpkg/buildtrees/eigen3/config-x64-linux-dbg-err.log

Call Stack (most recent call first):
  /home/project_options/test/build/vcpkg_installed/x64-linux/share/vcpkg-cmake/vcpkg_cmake_configure.cmake:426 (vcpkg_execute_required_process)
  buildtrees/versioning_/versions/eigen3/0475ed327bda734cad0acd35978cde9379bc8619/portfile.cmake:12 (vcpkg_cmake_configure)
  scripts/ports.cmake:147 (include)


error: building eigen3:x64-linux failed with: BUILD_FAILED
error: Please ensure you're using the latest port files with `git pull` and `vcpkg update`.
Then check for known issues at:
    https://github.com/microsoft/vcpkg/issues?q=is%3Aissue+is%3Aopen+in%3Atitle+eigen3
You can submit a new issue at:
    https://github.com/microsoft/vcpkg/issues/new?template=report-package-build-failure.md&title=[eigen3]+Build+error
Include '[eigen3] Build error' in your bug report title, the following version information in your bug description, and attach any relevant failure logs from above.
    vcpkg-tool version: 2022-10-17-3247920fbdd47d08f36cbd480addd9890d3c2435
    vcpkg-scripts version: a4013afe6 2022-11-03 (24 hours ago)


Please use the prefilled template from /home/project_options/test/build/vcpkg_installed/vcpkg/issue_body.md when reporting your issue.
-- Running vcpkg install - failed

Notes:
I'm using mostly docker for my Testing with setup-cpp and ubuntu-images.
Added test_minimal more for experimenting, would be nice to have only test for cross-compiling and everything.

I also run the test-project, on my native (Linux) machine and had some problem building it =|

Environment:
OS: Linux 64-Bit (Arch Linux)
Compiler: gcc 12

@aminya aminya added the enhancement New feature or request label Nov 4, 2022
@@ -23,6 +23,37 @@ tasks:
CWD:
sh: git rev-parse --show-toplevel

test_docker:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add these to the CI in .github/workflows/CI.yml

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm ... I mostly use this for development and testing on my machine.
I will try to add some github actions

docker/build.sh Outdated
@@ -0,0 +1,7 @@
#!/bin/bash
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to have these bash script files? The point of Taskfile is to collect these in a cross-platform file.

@@ -108,7 +108,24 @@ macro(run_vcpkg)
list(APPEND VCPKG_FEATURE_FLAGS "versions")
set(CMAKE_TOOLCHAIN_FILE
${_vcpkg_args_VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake
CACHE STRING "vcpkg toolchain file")
CACHE STRING "vcpkg toolchain file" FORCE)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be forced?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In enable_cross_compiler() I'm already setting a toolchain (as default), so if you are not using vcpkg, this should be the default, otherwise vcpkg overrides it and sets VCPKG_CHAINLOAD_TOOLCHAIN_FILE in addition.

but this case need also more testing

@aminya
Copy link
Owner

aminya commented Nov 15, 2022

The compiler detection seems to work, but I can't fully build the test projects.
To enable Cross-compiling you need to set the cross-compiler via (environment variable) CC and CXX,

The compiler detection also uses CC/CXX environment variables. It calls enable_language function in an isolated Cmake process so that CMake resolves the CC/CXX language (usually based on the environment variables).

@aminya
Copy link
Owner

aminya commented Nov 15, 2022

Right now, I have some problems building the test Project(s), seems like vcpkg didn't like the 3rd-party libs and throws an error:

I also run the test-project, on my native (Linux) machine and had some problem building it =|

The Mingw vcpkg code is continuously tested in the CI. So the error is related to the new code or something in the environment

@@ -0,0 +1,133 @@
cmake_minimum_required(VERSION 3.16...3.21)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this helps you test the code easier, it is fine. We can merge and remove test_minimal whenever the development is over.

@@ -102,7 +118,11 @@ macro(configure_mingw_vcpkg_after)
include("${ProjectOptions_SRC_DIR}/Utilities.cmake")
detect_architecture(_arch)
string(TOLOWER "${_arch}" _arch)
set(Z_VCPKG_TARGET_TRIPLET_ARCH ${_arch})
if(CROSSCOMPILING AND TARGET_ARCHITECTURE)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this condition work? From my experience of working with CMake's confusing datatypes, an explicit "${variable}" STREQL "" works better for making sure that the condition is correct.

@abeimler
Copy link
Contributor Author

abeimler commented Nov 20, 2022

You can now set the cross-compiler (with -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc and -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++) or with -DDEFAULT_TRIPLET=wasm32-emscripten

DEFAULT_TRIPLET

  • x64-mingw-dynamic
  • x64-mingw-static
  • x86-mingw-dynamic
  • x86-mingw-static
  • wasm32-emscripten

similar to vcpkg community triplet
sets CMAKE_C_COMPILER/CMAKE_CXX_COMPILER variables, e.g. x64-mingw-dynamic => x86_64-w64-mingw32-gcc

Example

# 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()
cmake . -B ./build -DCMAKE_BUILD_TYPE:STRING=Release -G 'Ninja' -DENABLE_CROSS_COMPILING:BOOL=ON -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++
cmake . -B ./build -DCMAKE_BUILD_TYPE:STRING=Release -G 'Ninja' -DENABLE_CROSS_COMPILING:BOOL=ON -DDEFAULT_TRIPLET=x64-mingw-dynamic
cmake . -B ./build -DCMAKE_BUILD_TYPE:STRING=Release -G 'Ninja' -DENABLE_CROSS_COMPILING:BOOL=ON -DDEFAULT_TRIPLET=wasm32-emscripten

Notes

  • For emscripten you have to use the DEFAULT_TRIPLET, otherwise Emscripten.cmake throws an error and can't detect the compiler (version). (-DCMAKE_C_COMPILER=emcc -DCMAKE_CXX_COMPILER=em++ didn't work)
  • for mingw you need to have mingw-w64 and powershell (for vcpkg) installed.
  • for emscripten you need to have emsdk installed (and setup)

* fix path in toolchain
@abeimler
Copy link
Contributor Author

the minimal example seems to compile with mingw, but not the test/-example.

@abeimler
Copy link
Contributor Author

abeimler commented Dec 10, 2022

Further TODOs

Future Ideas

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

Usage

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 this additional arguments:

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

See Taskfile and docker examples

Notes

  • this features 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 setup Community triplets easier
  • Best way to experiment with cross-compiling is by using docker and in a close environment

@abeimler abeimler changed the title WIP: Feature/toolchains Cross-compiling and toolchains Dec 10, 2022
@abeimler abeimler marked this pull request as ready for review December 10, 2022 12:11
@abeimler abeimler requested a review from aminya December 22, 2022 22:02
Copy link
Owner

@aminya aminya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will merge this for now. Let's open an issue for the TODOs you mentioned.

@aminya aminya merged commit b5d5a70 into aminya:main Dec 28, 2022
@aminya aminya mentioned this pull request Dec 28, 2022
9 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants