Also I try to set CMAKE_CXX_KNOWN_FEATURES
You most probably forgot to clear your build tree. Variables in toolchain file are not "refreshed" when you re-run cmake. You have to remove the build files compleatly and reconfigure cmake when making modifications to the toolchain file. It should work. Note that CMAKE_*_KNOWN_FEATURES
is a list of features, o use list(APPEND CMAKE_CXX_COMPILE_FEATURES ...)
.
For reference for feature readers and because cmake uses a lot of global variables, I want to post what is working with sdcc
compiler for C language. For C because it's simpler, it's exactly the same for C++ it's similar with CXX*
variables. What is the meaning of variables can be deduced from their names.
cat > toolchain-sdcc.cmake <<EOF
find_program(CMAKE_C_COMPILER NAMES sdcc)
set(CMAKE_CROSSCOMPILING TRUE)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(CMAKE_C_STANDARD_DEFAULT "11") # this is the default C standard the compiler uses without any option
set(CMAKE_C90_STANDARD_COMPILE_OPTION "--std-c89")
set(CMAKE_C90_EXTENSION_COMPILE_OPTION "--std-sdcc89")
set(CMAKE_C99_STANDARD_COMPILE_OPTION "--std-c99")
set(CMAKE_C99_EXTENSION_COMPILE_OPTION "--std-sdcc99")
set(CMAKE_C11_STANDARD_COMPILE_OPTION "--std-c11")
set(CMAKE_C11_EXTENSION_COMPILE_OPTION "--std-sdcc11")
list(APPEND CMAKE_C_COMPILE_FEATURES
c_std_90
c_std_99
c_std_11
c_function_prototypes
c_restrict
c_static_assert
c_variadic_macros
)
EOF
cat > CMakeLists.txt <<EOF
cmake_minimum_required(VERSION 3.11)
set(CMAKE_TOOLCHAIN_FILE sdcc.cmake)
project(a LANGUAGES C)
file(WRITE a.c "int main() {}")
add_executable(a a.c)
target_compile_features(a PUBLIC
c_std_90
c_std_99
c_std_11
c_function_prototypes
c_restrict
c_static_assert
c_variadic_macros
)
EOF
after that cmake finds the compile features and the project can build.
There is also CMakeDetermineCompileFeatures.cmake
that defines cmake_determine_compile_features
that is run auto-magically from project()
call. Then if the macro cmake_record_c_compile_features
is defined by your toolchain, then that macro is used to determine C language compile features. So you can:
cat > toolchain-sdcc.cmake <<EOF
# ...
# remove list(APPEND CMAKE_C_COMPILE_FEATURES, not needed anymore
# this macro will be called from `project()`
macro(cmake_record_c_compile_features)
list(APPEND CMAKE_C90_COMPILE_FEATURES c_std_90 c_function_prototypes)
list(APPEND CMAKE_C99_COMPILE_FEATURES c_std_99 c_restrict c_variadic_macros)
list(APPEND CMAKE_C11_COMPILE_FEATURES c_std_11 c_static_assert)
set(_result 0) # expected by cmake_determine_compile_features
endmacro()
EOF
After that you will see that well known Detecting C compile features
message that are generated by CMakeDetermineCompileFeatures.cmake
when it calls cmake_record_c_compile_features
macro:
$ cmake -S . -B _build
...
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done
...
Last but not least, you can define CMAKE_C*_STANDARD__HAS_FULL_SUPPORT
macros and use Compiler/CMakeCommonCompilerMacros module that internally defines the cmake_determine_compile_features
macro, and it checks if CMAKE_C*_STANDARD__HAS_FULL_SUPPORT
is defines, if it is, it enables all features for that standard of the language:
cat > toolchain-sdcc.cmake <<EOF
# ...
set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON)
set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON)
set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON)
# will define cmake_record_c_compile_features macro
# that will inspect CMAKE_C*_STANDARD__HAS_FULL_SUPPORT variables
include(Compiler/CMakeCommonCompilerMacros)
EOF
But the real proper place would be to create Compilers/SDCC-C.cmake
in a CMAKE_MODULE_PATH
paths and put include(Compiler/CMakeCommonCompilerMacros)
there, like for example MSVC-CXX.cmake does.
Detecting CXX [-std=c++17] compiler features failed to compile with the following output:
or something similar. – S.M.