We know how to compile an Autotools project using cosmocc
but how do you compile a CMake project with cosmocc
?
Here's an example project:
main.c
#include <stdio.h>
int main() {
puts("Hello world!");
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.29)
project(hello-world LANGUAGES C)
add_executable(hello-world main.c)
You can almost just do CC=cosmocc cmake ...
and call it day. Almost. But not quite! 😉 There are some other CMake settings you need to set to get things to work well with cosmocc
.
First, you'll need to add a CMAKE_USER_MAKE_RULES_OVERRIDE
file to define the object suffix as .o
instead of .obj
. cosmocc
currently doesn't work if the object extension is not .o
. 🤷♀️
cosmocc-override.cmake
set(CMAKE_ASM_OUTPUT_EXTENSION .o)
set(CMAKE_C_OUTPUT_EXTENSION .o)
set(CMAKE_CXX_OUTPUT_EXTENSION .o)
Why can't we just specify -DCMAKE_C_OUTPUT_EXTENSION=".o"
on the command line? It needs to be defined after the Generic
configuration is loaded so it doesn't get reset to the default .obj
. CMAKE_USER_MAKE_RULES_OVERRIDE
is the recommended way to do it. https://gitlab.kitware.com/cmake/cmake/-/issues/18713
ASM="cosmocc" \
CC="cosmocc" \
CXX="cosmoc++" \
cmake \
-DCMAKE_SYSTEM_NAME="Generic" \
-UCMAKE_SYSTEM_PROCESSOR \
-DCMAKE_USER_MAKE_RULES_OVERRIDE="$PWD/cosmocc-override.cmake" \
-DCMAKE_AR="$(command -v cosmoar)" \
-UCMAKE_RANLIB \
-B build
-- The C compiler identification is GNU 12.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /somewhere/cosmocc/bin/cosmocc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done (2.9s)
-- Generating done (0.0s)
-- Build files have been written to: /somewhere/hello-world/build
Do I have to specify CMAKE_SYSTEM_NAME
and CMAKE_SYSTEM_PROCESSOR
? Yes. They configure some CMake magic internally and configure what your CMakeLists.txt
thinks it's compilation target is.
Why not CMAKE_SYSTEM_NAME="Linux"
? So that if(LINUX)
and other Linux-specific stuff in CMakeLists.txt
doesn't activate for unknown-unknown-cosmo
.
Why not CMAKE_SYSTEM_PROCESSOR="unknown"
? unset
is what means unknown-unknown-cosmo
to CMake. CMake internals use if(CMAKE_SYSTEM_PROCESSOR)
, not if(CMAKE_SYSTEM_PROCESSOR STREQUAL unknown)
.
Why does CMAKE_AR
need to be an absolute path? Unfixed issue. https://gitlab.kitware.com/cmake/cmake/-/issues/18087
Why does CMAKE_RANLIB
need to be unset? CMake gates using ranlib
behind if(CMAKE_RANLIB)
so it must be unset
not just an empty string. cosmocc
doesn't bundle a cosmoar
.
Why can't we do AR="cosmoar"
like CC
and CXX
? Unfixed issue. https://gitlab.kitware.com/cmake/cmake/-/issues/18712
Now that the project is configured with all the compiler settings and other magic✨ we can run the build step:
cmake --build build
[ 50%] Building C object CMakeFiles/hello-world.dir/main.c.o
[100%] Linking C executable hello-world
[100%] Built target hello-world
You just made a magic✨ binary! 🥳
On Windows you need to rename it or symlink it to have an .exe
or .com
suffix to execute it.
./build/hello-world
Hello world!