666 lines
20 KiB
CMake
666 lines
20 KiB
CMake
include(CheckCCompilerFlag)
|
|
|
|
########################################################
|
|
# Table of contents
|
|
########################################################
|
|
# 1. Zephyr-aware extensions
|
|
# 1.1. zephyr_*
|
|
# 1.2. zephyr_library_*
|
|
# 1.3. generate_inc_*
|
|
# 2. Kconfig-aware extensions
|
|
# 2.1 *_if_kconfig
|
|
# 2.2 Misc
|
|
# 3. CMake-generic extensions
|
|
# 3.1. *_ifdef
|
|
# 3.2. *_ifndef
|
|
# 3.3. *_option compiler compatibility checks
|
|
# 3.4. Debugging CMake
|
|
|
|
########################################################
|
|
# 1. Zephyr-aware extensions
|
|
########################################################
|
|
# 1.1. zephyr_*
|
|
#
|
|
# The following methods are for modifying the CMake library[0] called
|
|
# "zephyr". zephyr is a catchall CMake library for source files that
|
|
# can be built purely with the include paths, defines, and other
|
|
# compiler flags that all zephyr source files use.
|
|
# [0] https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html
|
|
#
|
|
# Example usage:
|
|
# zephyr_sources(
|
|
# random_esp32.c
|
|
# utils.c
|
|
# )
|
|
#
|
|
# Is short for:
|
|
# target_sources(zephyr PRIVATE
|
|
# ${CMAKE_CURRENT_SOURCE_DIR}/random_esp32.c
|
|
# ${CMAKE_CURRENT_SOURCE_DIR}/utils.c
|
|
# )
|
|
|
|
# https://cmake.org/cmake/help/latest/command/target_sources.html
|
|
function(zephyr_sources)
|
|
foreach(arg ${ARGV})
|
|
if(IS_ABSOLUTE ${arg})
|
|
set(path ${arg})
|
|
else()
|
|
set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
|
|
endif()
|
|
|
|
if(IS_DIRECTORY ${path})
|
|
message(FATAL_ERROR "zephyr_sources() was called on a directory")
|
|
endif()
|
|
|
|
target_sources(zephyr PRIVATE ${path})
|
|
endforeach()
|
|
endfunction()
|
|
|
|
# https://cmake.org/cmake/help/latest/command/target_include_directories.html
|
|
function(zephyr_include_directories)
|
|
foreach(arg ${ARGV})
|
|
if(IS_ABSOLUTE ${arg})
|
|
set(path ${arg})
|
|
else()
|
|
set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
|
|
endif()
|
|
target_include_directories(zephyr_interface INTERFACE ${path})
|
|
endforeach()
|
|
endfunction()
|
|
|
|
# https://cmake.org/cmake/help/latest/command/target_include_directories.html
|
|
function(zephyr_system_include_directories)
|
|
foreach(arg ${ARGV})
|
|
if(IS_ABSOLUTE ${arg})
|
|
set(path ${arg})
|
|
else()
|
|
set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
|
|
endif()
|
|
target_include_directories(zephyr_interface SYSTEM INTERFACE ${path})
|
|
endforeach()
|
|
endfunction()
|
|
|
|
# https://cmake.org/cmake/help/latest/command/target_compile_definitions.html
|
|
function(zephyr_compile_definitions)
|
|
target_compile_definitions(zephyr_interface INTERFACE ${ARGV})
|
|
endfunction()
|
|
|
|
# https://cmake.org/cmake/help/latest/command/target_compile_options.html
|
|
function(zephyr_compile_options)
|
|
target_compile_options(zephyr_interface INTERFACE ${ARGV})
|
|
endfunction()
|
|
|
|
# https://cmake.org/cmake/help/latest/command/target_link_libraries.html
|
|
function(zephyr_link_libraries)
|
|
target_link_libraries(zephyr_interface INTERFACE ${ARGV})
|
|
endfunction()
|
|
|
|
# See this file section 3.1. target_cc_option
|
|
function(zephyr_cc_option)
|
|
foreach(arg ${ARGV})
|
|
target_cc_option(zephyr_interface INTERFACE ${arg})
|
|
endforeach()
|
|
endfunction()
|
|
|
|
function(zephyr_cc_option_fallback option1 option2)
|
|
target_cc_option_fallback(zephyr_interface INTERFACE ${option1} ${option2})
|
|
endfunction()
|
|
|
|
function(zephyr_ld_options)
|
|
target_ld_options(zephyr_interface INTERFACE ${ARGV})
|
|
endfunction()
|
|
|
|
# Getter functions for extracting build information from
|
|
# zephyr_interface. Returning lists, and strings is supported, as is
|
|
# requesting specific categories of build information (defines,
|
|
# includes, options).
|
|
#
|
|
# The naming convention follows:
|
|
# zephyr_get_${build_information}${format}(x)
|
|
# Where
|
|
# the argument 'x' is written with the result
|
|
# and
|
|
# ${build_information} can be one of
|
|
# - include_directories # -I directories
|
|
# - system_include_directories # -isystem directories
|
|
# - compile_definitions # -D'efines
|
|
# - compile_options # misc. compiler flags
|
|
# and
|
|
# ${format} can be
|
|
# the empty string '', signifying that it should be returned as a list
|
|
# _as_string signifying that it should be returned as a string
|
|
#
|
|
# e.g.
|
|
# zephyr_get_include_directories(x)
|
|
# writes "-Isome_dir;-Isome/other/dir" to x
|
|
|
|
# Utility macro used by the below macros.
|
|
macro(get_property_and_add_prefix result target property prefix)
|
|
get_property(target_property TARGET ${target} PROPERTY ${property})
|
|
foreach(x ${target_property})
|
|
list(APPEND ${result} ${prefix}${x})
|
|
endforeach()
|
|
endmacro()
|
|
|
|
macro(zephyr_get_include_directories i)
|
|
get_property_and_add_prefix(${i} zephyr_interface INTERFACE_INCLUDE_DIRECTORIES -I)
|
|
endmacro()
|
|
|
|
macro(zephyr_get_system_include_directories i)
|
|
get_property_and_add_prefix(${i} zephyr_interface INTERFACE_SYSTEM_INCLUDE_DIRECTORIES -isystem)
|
|
endmacro()
|
|
|
|
macro(zephyr_get_compile_definitions i)
|
|
get_property_and_add_prefix(${i} zephyr_interface INTERFACE_COMPILE_DEFINITIONS -D)
|
|
endmacro()
|
|
|
|
macro(zephyr_get_compile_options i)
|
|
get_property(${i} TARGET zephyr_interface PROPERTY INTERFACE_COMPILE_OPTIONS)
|
|
endmacro()
|
|
|
|
macro(zephyr_get_include_directories_as_string i)
|
|
zephyr_get_include_directories(${i})
|
|
|
|
string(REPLACE ";" " " ${i} ${${i}})
|
|
string(REPLACE "-I" " -I" ${i} ${${i}})
|
|
endmacro()
|
|
|
|
macro(zephyr_get_system_include_directories_as_string i)
|
|
get_property_and_add_prefix(${i} zephyr_interface INTERFACE_SYSTEM_INCLUDE_DIRECTORIES -isystem)
|
|
|
|
string(REPLACE ";" " " ${i} ${${i}})
|
|
string(REPLACE "-isystem" " -isystem" ${i} ${${i}})
|
|
endmacro()
|
|
|
|
macro(zephyr_get_compile_definitions_as_string i)
|
|
get_property_and_add_prefix(${i} zephyr_interface INTERFACE_COMPILE_DEFINITIONS -D)
|
|
|
|
string(REPLACE ";" " " ${i} ${${i}})
|
|
string(REPLACE "-D" " -D" ${i} ${${i}})
|
|
endmacro()
|
|
|
|
macro(zephyr_get_compile_options_as_string i)
|
|
zephyr_get_compile_options(j)
|
|
|
|
foreach(__opt__ ${j})
|
|
if(__opt__ MATCHES "<COMPILE_LANGUAGE:")
|
|
# TODO: Support COMPILE_LANGUAGE generator expressions
|
|
continue()
|
|
endif()
|
|
set(${i} "${${i}} ${__opt__}")
|
|
endforeach()
|
|
endmacro()
|
|
|
|
# 1.3 generate_inc_*
|
|
|
|
# These functions are useful if there is a need to generate a file
|
|
# that can be included into the application at build time. The file
|
|
# can also be compressed automatically when embedding it.
|
|
#
|
|
# See tests/application_development/gen_inc_file for an example of
|
|
# usage.
|
|
function(generate_inc_file
|
|
source_file # The source file to be converted to hex
|
|
generated_file # The generated file
|
|
)
|
|
add_custom_command(
|
|
OUTPUT ${generated_file}
|
|
COMMAND
|
|
${PYTHON_EXECUTABLE}
|
|
$ENV{ZEPHYR_BASE}/scripts/file2hex.py
|
|
${ARGN} # Extra arguments are passed to file2hex.py
|
|
--file ${source_file}
|
|
> ${generated_file} # Does pipe redirection work on Windows?
|
|
DEPENDS ${source_file}
|
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
)
|
|
endfunction()
|
|
|
|
function(generate_inc_file_for_target
|
|
target # The cmake target that depends on the generated file
|
|
source_file # The source file to be converted to hex
|
|
generated_file # The generated file
|
|
# Any additional arguments are passed on to file2hex.py
|
|
)
|
|
generate_inc_file(${source_file} ${generated_file} ${ARGN})
|
|
|
|
# Ensure 'generated_file' is generated before 'target' by creating a
|
|
# 'custom_target' for it and setting up a dependency between the two
|
|
# targets
|
|
|
|
# But first create a unique name for the custom target
|
|
# Replace / with _ (driver/serial => driver_serial) and . with _
|
|
set(generated_target_name ${generated_file})
|
|
|
|
string(REPLACE "/" "_" generated_target_name ${generated_target_name})
|
|
string(REPLACE "." "_" generated_target_name ${generated_target_name})
|
|
|
|
add_custom_target(${generated_target_name} DEPENDS ${generated_file})
|
|
add_dependencies(${target} ${generated_target_name})
|
|
endfunction()
|
|
|
|
# 2.1 zephyr_library_*
|
|
#
|
|
# Zephyr libraries use CMake's library concept and a set of
|
|
# assumptions about how zephyr code is organized to cut down on
|
|
# boilerplate code.
|
|
#
|
|
# A Zephyr library can be constructed by the function zephyr_library
|
|
# or zephyr_library_named. The constructors create a CMake library
|
|
# with a name accessible through the variable ZEPHYR_CURRENT_LIBRARY.
|
|
#
|
|
# The variable ZEPHYR_CURRENT_LIBRARY should seldomly be needed since
|
|
# the zephyr libraries have methods that modify the libraries. These
|
|
# methods have the signature: zephyr_library_<target-function>
|
|
#
|
|
# The methods are wrappers around the CMake target_* functions. See
|
|
# https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html for
|
|
# documentation on the underlying target_* functions.
|
|
#
|
|
# The methods modify the CMake target_* API to reduce boilerplate;
|
|
# PRIVATE is assumed
|
|
# The target is assumed to be ZEPHYR_CURRENT_LIBRARY
|
|
|
|
# Constructor with a directory-inferred name
|
|
macro(zephyr_library)
|
|
zephyr_library_get_current_dir_lib_name(lib_name)
|
|
zephyr_library_named(${lib_name})
|
|
endmacro()
|
|
|
|
# Determines what the current directory's lib name would be and writes
|
|
# it to the argument "lib_name"
|
|
macro(zephyr_library_get_current_dir_lib_name lib_name)
|
|
# Remove the prefix (/home/sebo/zephyr/driver/serial/CMakeLists.txt => driver/serial/CMakeLists.txt)
|
|
file(RELATIVE_PATH name $ENV{ZEPHYR_BASE} ${CMAKE_CURRENT_LIST_FILE})
|
|
|
|
# Remove the filename (driver/serial/CMakeLists.txt => driver/serial)
|
|
get_filename_component(name ${name} DIRECTORY)
|
|
|
|
# Replace / with __ (driver/serial => driver__serial)
|
|
string(REGEX REPLACE "/" "__" name ${name})
|
|
|
|
set(${lib_name} ${name})
|
|
endmacro()
|
|
|
|
# Constructor with an explicitly given name.
|
|
macro(zephyr_library_named name)
|
|
# This is a macro because we need add_library() to be executed
|
|
# within the scope of the caller.
|
|
set(ZEPHYR_CURRENT_LIBRARY ${name})
|
|
add_library(${name} STATIC "")
|
|
|
|
zephyr_append_cmake_library(${name})
|
|
|
|
target_link_libraries(${name} zephyr_interface)
|
|
endmacro()
|
|
|
|
|
|
function(zephyr_link_interface interface)
|
|
target_link_libraries(interface INTERFACE zephyr_interface)
|
|
endfunction()
|
|
|
|
#
|
|
# zephyr_library versions of normal CMake target_<func> functions
|
|
#
|
|
function(zephyr_library_sources source)
|
|
target_sources(${ZEPHYR_CURRENT_LIBRARY} PRIVATE ${source} ${ARGN})
|
|
endfunction()
|
|
|
|
function(zephyr_library_include_directories)
|
|
target_include_directories(${ZEPHYR_CURRENT_LIBRARY} PRIVATE ${ARGN})
|
|
endfunction()
|
|
|
|
function(zephyr_library_link_libraries item)
|
|
target_link_libraries(${ZEPHYR_CURRENT_LIBRARY} ${item} ${ARGN})
|
|
endfunction()
|
|
|
|
function(zephyr_library_compile_definitions item)
|
|
target_compile_definitions(${ZEPHYR_CURRENT_LIBRARY} PRIVATE ${item} ${ARGN})
|
|
endfunction()
|
|
|
|
function(zephyr_library_compile_options item)
|
|
target_compile_options(${ZEPHYR_CURRENT_LIBRARY} PRIVATE ${item} ${ARGN})
|
|
endfunction()
|
|
|
|
function(zephyr_library_cc_option)
|
|
foreach(arg ${ARGV})
|
|
target_cc_option(${ZEPHYR_CURRENT_LIBRARY} PRIVATE ${arg})
|
|
endforeach()
|
|
endfunction()
|
|
|
|
# Add the existing CMake library 'library' to the global list of
|
|
# Zephyr CMake libraries. This is done automatically by the
|
|
# constructor but must called explicitly on CMake libraries that do
|
|
# not use a zephyr library constructor, but have source files that
|
|
# need to be included in the build.
|
|
function(zephyr_append_cmake_library library)
|
|
set_property(GLOBAL APPEND PROPERTY ZEPHYR_LIBS ${library})
|
|
endfunction()
|
|
|
|
########################################################
|
|
# 2. Kconfig-aware extensions
|
|
########################################################
|
|
#
|
|
# Kconfig is a configuration language developed for the Linux
|
|
# kernel. The below functions integrate CMake with Kconfig.
|
|
#
|
|
# 2.1 *_if_kconfig
|
|
#
|
|
# Functions for conditionally including directories and source files
|
|
# that have matching KConfig values.
|
|
#
|
|
# zephyr_library_sources_if_kconfig(fft.c)
|
|
# is the same as
|
|
# zephyr_library_sources_ifdef(CONFIG_FFT fft.c)
|
|
#
|
|
# add_subdirectory_if_kconfig(serial)
|
|
# is the same as
|
|
# add_subdirectory_ifdef(CONFIG_SERIAL serial)
|
|
function(add_subdirectory_if_kconfig dir)
|
|
string(TOUPPER config_${dir} UPPER_CASE_CONFIG)
|
|
add_subdirectory_ifdef(${UPPER_CASE_CONFIG} ${dir})
|
|
endfunction()
|
|
|
|
function(target_sources_if_kconfig target scope item)
|
|
get_filename_component(item_basename ${item} NAME_WE)
|
|
string(TOUPPER CONFIG_${item_basename} UPPER_CASE_CONFIG)
|
|
target_sources_ifdef(${UPPER_CASE_CONFIG} ${target} ${scope} ${item})
|
|
endfunction()
|
|
|
|
function(zephyr_library_sources_if_kconfig item)
|
|
get_filename_component(item_basename ${item} NAME_WE)
|
|
string(TOUPPER CONFIG_${item_basename} UPPER_CASE_CONFIG)
|
|
zephyr_library_sources_ifdef(${UPPER_CASE_CONFIG} ${item})
|
|
endfunction()
|
|
|
|
function(zephyr_sources_if_kconfig item)
|
|
get_filename_component(item_basename ${item} NAME_WE)
|
|
string(TOUPPER CONFIG_${item_basename} UPPER_CASE_CONFIG)
|
|
zephyr_sources_ifdef(${UPPER_CASE_CONFIG} ${item})
|
|
endfunction()
|
|
|
|
# 2.2 Misc
|
|
#
|
|
# Parse a KConfig formatted file (typically named *.config) and
|
|
# introduce all the CONF_ variables into the CMake namespace
|
|
function(import_kconfig config_file)
|
|
# Parse the lines prefixed with CONFIG_ in ${config_file}
|
|
file(
|
|
STRINGS
|
|
${config_file}
|
|
DOT_CONFIG_LIST
|
|
REGEX "^CONFIG_"
|
|
)
|
|
|
|
foreach (CONFIG ${DOT_CONFIG_LIST})
|
|
# CONFIG looks like: CONFIG_NET_BUF=y
|
|
|
|
# Match the first part, the variable name
|
|
string(REGEX MATCH "[^=]+" CONF_VARIABLE_NAME ${CONFIG})
|
|
|
|
# Match the second part, variable value
|
|
string(REGEX MATCH "=(.+$)" CONF_VARIABLE_VALUE ${CONFIG})
|
|
# The variable name match we just did included the '=' symbol. To just get the
|
|
# part on the RHS we use match group 1
|
|
set(CONF_VARIABLE_VALUE ${CMAKE_MATCH_1})
|
|
|
|
if("${CONF_VARIABLE_VALUE}" MATCHES "^\"(.*)\"$") # Is surrounded by quotes
|
|
set(CONF_VARIABLE_VALUE ${CMAKE_MATCH_1})
|
|
endif()
|
|
|
|
set("${CONF_VARIABLE_NAME}" "${CONF_VARIABLE_VALUE}" PARENT_SCOPE)
|
|
endforeach()
|
|
endfunction()
|
|
|
|
########################################################
|
|
# 3. CMake-generic extensions
|
|
########################################################
|
|
#
|
|
# These functions extend the CMake API in a way that is not particular
|
|
# to Zephyr. Primarily they work around limitations in the CMake
|
|
# language to allow cleaner build scripts.
|
|
|
|
# 3.1. *_ifdef
|
|
#
|
|
# Functions for conditionally executing CMake functions with oneliners
|
|
# e.g.
|
|
#
|
|
# if(CONFIG_FFT)
|
|
# zephyr_library_source(
|
|
# fft_32.c
|
|
# fft_utils.c
|
|
# )
|
|
# endif()
|
|
#
|
|
# Becomes
|
|
#
|
|
# zephyr_source_ifdef(
|
|
# CONFIG_FFT
|
|
# fft_32.c
|
|
# fft_utils.c
|
|
# )
|
|
#
|
|
# More Generally
|
|
# "<function-name>_ifdef(CONDITION args)"
|
|
# Becomes
|
|
# """
|
|
# if(CONDITION)
|
|
# <function-name>(args)
|
|
# endif()
|
|
# """
|
|
#
|
|
# ifdef functions are added on an as-need basis. See
|
|
# https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html for
|
|
# a list of available functions.
|
|
function(add_subdirectory_ifdef feature_toggle dir)
|
|
if(${${feature_toggle}})
|
|
add_subdirectory(${dir})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(target_sources_ifdef feature_toggle target scope item)
|
|
if(${${feature_toggle}})
|
|
target_sources(${target} ${scope} ${item} ${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(target_compile_definitions_ifdef feature_toggle target scope item)
|
|
if(${${feature_toggle}})
|
|
target_compile_definitions(${target} ${scope} ${item} ${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(target_include_directories_ifdef feature_toggle target scope item)
|
|
if(${${feature_toggle}})
|
|
target_include_directories(${target} ${scope} ${item} ${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(target_link_libraries_ifdef feature_toggle target item)
|
|
if(${${feature_toggle}})
|
|
target_link_libraries(${target} ${item} ${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(add_compile_option_ifdef feature_toggle option)
|
|
if(${${feature_toggle}})
|
|
add_compile_options(${option})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(target_compile_option_ifdef feature_toggle target scope option)
|
|
if(${feature_toggle})
|
|
target_compile_options(${target} ${scope} ${option})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(target_cc_option_ifdef feature_toggle target scope option)
|
|
if(${feature_toggle})
|
|
target_cc_option(${target} ${scope} ${option})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(zephyr_library_sources_ifdef feature_toggle source)
|
|
if(${${feature_toggle}})
|
|
zephyr_library_sources(${source} ${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(zephyr_sources_ifdef feature_toggle)
|
|
if(${${feature_toggle}})
|
|
zephyr_sources(${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(zephyr_sources_ifndef feature_toggle)
|
|
if(NOT ${feature_toggle})
|
|
zephyr_sources(${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(zephyr_cc_option_ifdef feature_toggle)
|
|
if(${${feature_toggle}})
|
|
zephyr_cc_option(${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(zephyr_link_libraries_ifdef feature_toggle)
|
|
if(${${feature_toggle}})
|
|
zephyr_link_libraries(${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(zephyr_compile_options_ifdef feature_toggle)
|
|
if(${${feature_toggle}})
|
|
zephyr_compile_options(${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(zephyr_compile_definitions_ifdef feature_toggle)
|
|
if(${${feature_toggle}})
|
|
zephyr_compile_definitions(${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(zephyr_include_directories_ifdef feature_toggle)
|
|
if(${${feature_toggle}})
|
|
zephyr_include_directories(${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(zephyr_library_compile_definitions_ifdef feature_toggle item)
|
|
if(${${feature_toggle}})
|
|
zephyr_library_compile_definitions(${item} ${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(zephyr_library_compile_options_ifdef feature_toggle item)
|
|
if(${${feature_toggle}})
|
|
zephyr_library_compile_options(${item} ${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(zephyr_link_interface_ifdef feature_toggle interface)
|
|
if(${${feature_toggle}})
|
|
target_link_libraries(${interface} INTERFACE zephyr_interface)
|
|
endif()
|
|
endfunction()
|
|
|
|
function(zephyr_library_link_libraries_ifdef feature_toggle item)
|
|
if(${${feature_toggle}})
|
|
zephyr_library_link_libraries(${item})
|
|
endif()
|
|
endfunction()
|
|
|
|
|
|
# 3.2. *_ifndef
|
|
# See 3.1 *_ifdef
|
|
function(set_ifndef variable value)
|
|
if(NOT ${variable})
|
|
set(${variable} ${value} PARENT_SCOPE)
|
|
endif()
|
|
endfunction()
|
|
|
|
function(target_cc_option_ifndef feature_toggle target scope option)
|
|
if(NOT ${feature_toggle})
|
|
target_cc_option(${target} ${scope} ${option})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(zephyr_cc_option_ifndef feature_toggle)
|
|
if(NOT ${feature_toggle})
|
|
zephyr_cc_option(${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(zephyr_compile_options_ifndef feature_toggle)
|
|
if(NOT ${feature_toggle})
|
|
zephyr_compile_options(${ARGN})
|
|
endif()
|
|
endfunction()
|
|
|
|
# 3.2. *_option Compiler-compatibility checks
|
|
#
|
|
# Utility functions for silently omitting compiler flags when the
|
|
# compiler lacks support. *_cc_option was ported from KBuild, see
|
|
# cc-option in
|
|
# https://www.kernel.org/doc/Documentation/kbuild/makefiles.txt
|
|
#
|
|
function(target_cc_option target scope option)
|
|
string(MAKE_C_IDENTIFIER check${option} check)
|
|
check_c_compiler_flag(${option} ${check})
|
|
target_compile_option_ifdef(${check} ${target} ${scope} ${option})
|
|
endfunction()
|
|
|
|
# Support an optional second option for when the first option is
|
|
# not supported.
|
|
function(target_cc_option_fallback target scope option1 option2)
|
|
string(MAKE_C_IDENTIFIER check${option1} check)
|
|
check_c_compiler_flag(${option1} ${check})
|
|
if(${check})
|
|
target_compile_options(${target} ${scope} ${option1})
|
|
else()
|
|
target_compile_options(${target} ${scope} ${option2})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(target_ld_options target scope)
|
|
foreach(option ${ARGN})
|
|
string(MAKE_C_IDENTIFIER check${option} check)
|
|
check_c_compiler_flag(${option} ${check})
|
|
target_link_libraries_ifdef(${check} ${target} ${scope} ${option})
|
|
endforeach()
|
|
endfunction()
|
|
|
|
# 3.4. Debugging CMake
|
|
|
|
# Usage:
|
|
# print(BOARD)
|
|
#
|
|
# will print: "BOARD: nrf52_pca10040"
|
|
function(print arg)
|
|
message(STATUS "${arg}: ${${arg}}")
|
|
endfunction()
|
|
|
|
# Usage:
|
|
# assert(ZEPHYR_GCC_VARIANT "ZEPHYR_GCC_VARIANT not set.")
|
|
#
|
|
# will cause a FATAL_ERROR and print an error message if the first
|
|
# expression is false
|
|
macro(assert test comment)
|
|
if(NOT ${test})
|
|
message(FATAL_ERROR "Assertion failed: ${comment}")
|
|
endif()
|
|
endmacro()
|
|
|
|
# Usage:
|
|
# assert_exists(CMAKE_READELF)
|
|
#
|
|
# will cause a FATAL_ERROR if there is no file or directory behind the
|
|
# variable
|
|
macro(assert_exists var)
|
|
if(NOT EXISTS ${${var}})
|
|
message(FATAL_ERROR "No such file or directory: ${var}: '${${var}}'")
|
|
endif()
|
|
endmacro()
|