├── .gitignore ├── CMakeLists.txt ├── README.md ├── aarch64-linux-gnu.cmake ├── aarch64-windows-gnu.cmake ├── cmake ├── Platform │ ├── UEFI.cmake │ └── WASI.cmake ├── zig-ar ├── zig-ar.cmd ├── zig-c++ ├── zig-c++.cmd ├── zig-cc ├── zig-cc.cmd ├── zig-ranlib ├── zig-ranlib.cmd ├── zig-rc ├── zig-rc.cmd └── zig-toolchain.cmake ├── riscv64-freestanding-none.cmake ├── src ├── myexe.cpp ├── mylib.cpp └── mylib.h ├── wasm32-emscripten-musl.cmake ├── wasm32-wasi-musl.cmake ├── x86-windows-gnu.cmake ├── x86_64-linux-gnu.cmake ├── x86_64-linux-musl.cmake ├── x86_64-uefi-gnu.cmake ├── x86_64-windows-gnu.cmake ├── x86_64-windows-msvc.cmake └── zig-targets.json /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | bin2 3 | compile_commands.json 4 | .clangd 5 | temp.* 6 | .vs 7 | .cache 8 | build*/ 9 | .idea/ 10 | cmake-build*/ 11 | CMakeLists.txt.user 12 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.22) 2 | 3 | project(cmake-zig) 4 | 5 | add_library(mylib-static STATIC src/mylib.cpp) 6 | add_library(mylib-shared SHARED src/mylib.cpp) 7 | 8 | add_executable(myexe src/myexe.cpp) 9 | target_link_libraries(myexe PRIVATE mylib-static) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zig-cross 2 | 3 | Example of using [zig](https://ziglang.org) as a CMake Toolchain for cross compiling. 4 | 5 | Reference: https://zig.news/kristoff/cross-compile-a-c-c-project-with-zig-3599 6 | 7 | ## Building 8 | 9 | - [Install zig](https://ziglang.org/learn/getting-started/#installing-zig) in your PATH (`choco install zig` on Windows) 10 | - `cmake -B build-aarch64 -G Ninja --toolchain aarch64-linux-gnu.cmake` 11 | - `cmake --build build-arch64` 12 | 13 | You can create toolchains for other triples as well, just create a file named `aarch64-windows-gnu.cmake` with the following contents to build for Windows on ARM64: 14 | 15 | ```cmake 16 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/zig-toolchain.cmake) 17 | ``` 18 | 19 | ## clangd 20 | 21 | To get [clangd](https://clangd.llvm.org/) to work you need to first enable generation of `compile_commands.json`: 22 | 23 | ```sh 24 | cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 25 | ``` 26 | 27 | Additionally you need to pass pass the following arguments to `clangd`: 28 | 29 | ```json 30 | "clangd.arguments": [ 31 | "--log=verbose", 32 | "--query-driver=**/zig-cc.cmd,**/zig-cc,**/zig-c++.cmd,**/zig-c++", 33 | ] 34 | ``` 35 | 36 | Without these arguments `clangd` will not query the driver (`zig c++`) and the include paths will not be resolved correctly. 37 | -------------------------------------------------------------------------------- /aarch64-linux-gnu.cmake: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/zig-toolchain.cmake) -------------------------------------------------------------------------------- /aarch64-windows-gnu.cmake: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/zig-toolchain.cmake) -------------------------------------------------------------------------------- /cmake/Platform/UEFI.cmake: -------------------------------------------------------------------------------- 1 | # References: 2 | # - https://gitlab.kitware.com/cmake/cmake/-/merge_requests/6630 3 | # - https://gitlab.kitware.com/cmake/cmake/-/issues/16538 4 | # - https://kubasejdak.com/how-to-cross-compile-for-embedded-with-cmake-like-a-champ 5 | 6 | include(Platform/Generic) 7 | 8 | set(CMAKE_EXECUTABLE_SUFFIX ".efi") 9 | set(CMAKE_SHARED_LIBRARY_SUFFIX ".efi") 10 | set(CMAKE_SHARED_LIBRARY_PREFIX "") 11 | 12 | # UEFI APIs might expect 16-bit wchar_t 13 | add_compile_options(-fshort-wchar) 14 | -------------------------------------------------------------------------------- /cmake/Platform/WASI.cmake: -------------------------------------------------------------------------------- 1 | set(WASI 1) -------------------------------------------------------------------------------- /cmake/zig-ar: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | zig ar "$@" 3 | -------------------------------------------------------------------------------- /cmake/zig-ar.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | zig ar %* -------------------------------------------------------------------------------- /cmake/zig-c++: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | zig c++ "$@" 3 | -------------------------------------------------------------------------------- /cmake/zig-c++.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | zig c++ %* -------------------------------------------------------------------------------- /cmake/zig-cc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | zig cc "$@" 3 | -------------------------------------------------------------------------------- /cmake/zig-cc.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | zig cc %* -------------------------------------------------------------------------------- /cmake/zig-ranlib: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | zig ranlib "$@" 3 | -------------------------------------------------------------------------------- /cmake/zig-ranlib.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | zig ranlib %* -------------------------------------------------------------------------------- /cmake/zig-rc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | zig rc "$@" 3 | -------------------------------------------------------------------------------- /cmake/zig-rc.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | zig rc %* -------------------------------------------------------------------------------- /cmake/zig-toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard() 2 | 3 | if(CMAKE_GENERATOR MATCHES "Visual Studio") 4 | message(FATAL_ERROR "Visual Studio generator not supported, use: cmake -G Ninja") 5 | endif() 6 | 7 | if(NOT DEFINED ZIG_TARGET) 8 | get_filename_component(PARENT_LIST_DIR "${CMAKE_PARENT_LIST_FILE}" DIRECTORY) 9 | string(FIND "${CMAKE_CURRENT_LIST_DIR}" "${PARENT_LIST_DIR}" POS) 10 | if(POS EQUAL 0) 11 | get_filename_component(ZIG_TARGET "${CMAKE_PARENT_LIST_FILE}" NAME_WLE) 12 | endif() 13 | endif() 14 | 15 | if(NOT ZIG_TARGET MATCHES "^([a-zZ-Z0-9_]+)-([a-zZ-Z0-9_]+)-([a-zZ-Z0-9_.]+)$") 16 | message(FATAL_ERROR "Expected ZIG_TARGET=--") 17 | endif() 18 | 19 | set(ZIG_ARCH ${CMAKE_MATCH_1}) 20 | set(ZIG_OS ${CMAKE_MATCH_2}) 21 | set(ZIG_ABI ${CMAKE_MATCH_3}) 22 | 23 | if(ZIG_OS STREQUAL "linux") 24 | set(CMAKE_SYSTEM_NAME "Linux") 25 | elseif(ZIG_OS STREQUAL "windows") 26 | set(CMAKE_SYSTEM_NAME "Windows") 27 | elseif(ZIG_OS STREQUAL "macos") 28 | set(CMAKE_SYSTEM_NAME "Darwin") 29 | elseif(ZIG_OS STREQUAL "freestanding") 30 | set(CMAKE_SYSTEM_NAME "Generic") 31 | elseif(ZIG_OS STREQUAL "uefi") 32 | set(CMAKE_SYSTEM_NAME "UEFI") 33 | # Fix compiler detection (lld-link: error: : undefined symbol: EfiMain) 34 | set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) 35 | elseif(ZIG_OS STREQUAL "wasi") 36 | set(CMAKE_SYSTEM_NAME "WASI") 37 | elseif(ZIG_OS STREQUAL "emscripten") 38 | set(CMAKE_SYSTEM_NAME "Emscripten") 39 | else() 40 | # NOTE: If this happens, add a new case with one of the following system names: 41 | # https://cmake.org/cmake/help/latest/variable/CMAKE_SYSTEM_NAME.html#system-names-known-to-cmake 42 | message(FATAL_ERROR "Unknown OS: ${ZIG_OS}") 43 | endif() 44 | 45 | set(CMAKE_SYSTEM_VERSION 1) 46 | set(CMAKE_SYSTEM_PROCESSOR ${ZIG_ARCH}) 47 | 48 | if(CMAKE_HOST_WIN32) 49 | set(SCRIPT_SUFFIX ".cmd") 50 | else() 51 | set(SCRIPT_SUFFIX "") 52 | endif() 53 | 54 | # Work around a bug in clangd where 'c++' is reordered on the command line 55 | set(CMAKE_C_COMPILER "${CMAKE_CURRENT_LIST_DIR}/zig-cc${SCRIPT_SUFFIX}" -target ${ZIG_TARGET}) 56 | set(CMAKE_CXX_COMPILER "${CMAKE_CURRENT_LIST_DIR}/zig-c++${SCRIPT_SUFFIX}" -target ${ZIG_TARGET}) 57 | 58 | # This is working (thanks to Simon for finding this trick) 59 | set(CMAKE_AR "${CMAKE_CURRENT_LIST_DIR}/zig-ar${SCRIPT_SUFFIX}") 60 | set(CMAKE_RANLIB "${CMAKE_CURRENT_LIST_DIR}/zig-ranlib${SCRIPT_SUFFIX}") 61 | set(CMAKE_RC_COMPILER "${CMAKE_CURRENT_LIST_DIR}/zig-rc${SCRIPT_SUFFIX}") 62 | 63 | # Add custom UEFI platform to module path 64 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") 65 | -------------------------------------------------------------------------------- /riscv64-freestanding-none.cmake: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/zig-toolchain.cmake) -------------------------------------------------------------------------------- /src/myexe.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "mylib.h" 4 | 5 | int main() 6 | { 7 | puts(mylib()); 8 | } -------------------------------------------------------------------------------- /src/mylib.cpp: -------------------------------------------------------------------------------- 1 | #include "mylib.h" 2 | 3 | const char* mylib() 4 | { 5 | return "hello from mylib"; 6 | } -------------------------------------------------------------------------------- /src/mylib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN32 4 | #define MYLIB_EXPORT __declspec(dllexport) 5 | #else 6 | #define MYLIB_EXPORT 7 | #endif // _WIN32 8 | 9 | 10 | extern "C" MYLIB_EXPORT const char* mylib(); -------------------------------------------------------------------------------- /wasm32-emscripten-musl.cmake: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/zig-toolchain.cmake) -------------------------------------------------------------------------------- /wasm32-wasi-musl.cmake: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/zig-toolchain.cmake) -------------------------------------------------------------------------------- /x86-windows-gnu.cmake: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/zig-toolchain.cmake) -------------------------------------------------------------------------------- /x86_64-linux-gnu.cmake: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/zig-toolchain.cmake) -------------------------------------------------------------------------------- /x86_64-linux-musl.cmake: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/zig-toolchain.cmake) -------------------------------------------------------------------------------- /x86_64-uefi-gnu.cmake: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/zig-toolchain.cmake) -------------------------------------------------------------------------------- /x86_64-windows-gnu.cmake: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/zig-toolchain.cmake) -------------------------------------------------------------------------------- /x86_64-windows-msvc.cmake: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_LIST_DIR}/cmake/zig-toolchain.cmake) --------------------------------------------------------------------------------