| # *DOCUMENTATION* |
| # |
| # Note that this is *NOT* the top-level CMakeLists.txt. That's in the |
| # application. See the Application Development Primer documentation |
| # for details. |
| # |
| # To see a list of typical targets execute "make usage" |
| # More info can be located in ./README.rst |
| # Comments in this file are targeted only to the developer, do not |
| # expect to learn how to build the kernel reading this file. |
| |
| if(NOT DEFINED ZEPHYR_BINARY_DIR) |
| message(FATAL_ERROR "A user error has occured. |
| cmake was invoked with '${CMAKE_CURRENT_LIST_DIR}' specified as the source directory, |
| but it must be invoked with an application source directory, |
| such as '${CMAKE_CURRENT_LIST_DIR}/samples/hello_world'. |
| Debug variables: |
| CMAKE_CACHEFILE_DIR: ${CMAKE_CACHEFILE_DIR} |
| ") |
| endif() |
| |
| project(Zephyr-Kernel VERSION ${PROJECT_VERSION}) |
| enable_language(C CXX ASM) |
| |
| # Verify that the toolchain can compile a dummy file, if it is not we |
| # won't be able to test for compatiblity with certain C flags. |
| check_c_compiler_flag("" toolchain_is_ok) |
| assert(toolchain_is_ok "The toolchain is unable to build a dummy C file. See CMakeError.log.") |
| |
| set(CMAKE_EXECUTABLE_SUFFIX .elf) |
| set(ZEPHYR_PREBUILT_EXECUTABLE zephyr_prebuilt) |
| |
| set(OFFSETS_H_TARGET offsets_h) |
| set(SYSCALL_MACROS_H_TARGET syscall_macros_h_target) |
| set(SYSCALL_LIST_H_TARGET syscall_list_h_target) |
| set(DRIVER_VALIDATION_H_TARGET driver_validation_h_target) |
| set(KOBJ_TYPES_H_TARGET kobj_types_h_target) |
| set(LINKER_SCRIPT_TARGET linker_script_target) |
| |
| |
| if(NOT PROPERTY_LINKER_SCRIPT_DEFINES) |
| set_property(GLOBAL PROPERTY PROPERTY_LINKER_SCRIPT_DEFINES -D__GCC_LINKER_CMD__) |
| endif() |
| |
| define_property(GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT BRIEF_DOCS " " FULL_DOCS " ") |
| set_property( GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT elf32-little${ARCH}) # BFD format |
| |
| # "zephyr_interface" is a source-less library that encapsulates all the global |
| # compiler options needed by all source files. All zephyr libraries, |
| # including the library named "zephyr" link with this library to |
| # obtain these flags. |
| # https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#interface-libraries |
| add_library(zephyr_interface INTERFACE) |
| |
| # "zephyr" is a catch-all CMake library for source files that can be |
| # built purely with the include paths, defines, and other compiler |
| # flags that come with zephyr_interface. |
| zephyr_library_named(zephyr) |
| |
| zephyr_include_directories( |
| kernel/include |
| ${ARCH_DIR}/${ARCH}/include |
| include |
| include/drivers |
| ${PROJECT_BINARY_DIR}/include/generated |
| ${USERINCLUDE} |
| ${STDINCLUDE} |
| ) |
| |
| # Don't add non-existing include directories, it creates noise and |
| # warnings in some tooling |
| foreach(optional_include_dir |
| ${SOC_DIR}/${ARCH}/${SOC_PATH} |
| ${SOC_DIR}/${ARCH}/${SOC_PATH}/include |
| ${SOC_DIR}/${ARCH}/${SOC_FAMILY}/include |
| ) |
| if(EXISTS ${optional_include_dir}) |
| zephyr_include_directories(${optional_include_dir}) |
| endif() |
| endforeach() |
| |
| zephyr_compile_definitions( |
| KERNEL |
| __ZEPHYR__=1 |
| ) |
| |
| # @Intent: Set compiler flags to enable buffer overflow checks in libc functions |
| # @config in CONFIG_NO_OPTIMIZATIONS optional : Optimizations may affect security |
| toolchain_cc_security_fortify() |
| |
| # @Intent: Set compiler flags to detect general stack overflows across all functions |
| if(CONFIG_STACK_CANARIES) |
| toolchain_cc_security_canaries() |
| endif() |
| |
| if(BUILD_VERSION) |
| zephyr_compile_definitions( |
| BUILD_VERSION=${BUILD_VERSION} |
| ) |
| endif() |
| |
| # We need to set an optimization level. |
| # Default to -Os |
| # unless CONFIG_NO_OPTIMIZATIONS is set, then it is -O0 |
| # or unless CONFIG_DEBUG is set, then it is -Og |
| # |
| # also, some toolchain's break with -Os, and some toolchain's break |
| # with -Og so allow them to override what flag to use |
| # |
| # Finally, the user can use Kconfig to add compiler options that will |
| # come after these options and override them |
| set_ifndef(OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG "-O0") |
| set_ifndef(OPTIMIZE_FOR_DEBUG_FLAG "-Og") |
| set_ifndef(OPTIMIZE_FOR_SIZE_FLAG "-Os") |
| set_ifndef(OPTIMIZE_FOR_SPEED_FLAG "-O2") |
| |
| if(CONFIG_NO_OPTIMIZATIONS) |
| set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG}) |
| elseif(CONFIG_DEBUG_OPTIMIZATIONS) |
| set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_DEBUG_FLAG}) |
| elseif(CONFIG_SPEED_OPTIMIZATIONS) |
| set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_SPEED_FLAG}) |
| elseif(CONFIG_SIZE_OPTIMIZATIONS) |
| set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_SIZE_FLAG}) # Default |
| else() |
| assert(0 "Unreachable code. Expected optimization level to have been chosen. See Kconfig.zephyr") |
| endif() |
| |
| # Dialects of C++, corresponding to the multiple published ISO standards. |
| # Which standard it implements can be selected using the -std= command-line option. |
| set_ifndef(DIALECT_STD_CPP98 "c++98") |
| set_ifndef(DIALECT_STD_CPP11 "c++11") |
| set_ifndef(DIALECT_STD_CPP14 "c++14") |
| set_ifndef(DIALECT_STD_CPP17 "c++17") |
| set_ifndef(DIALECT_STD_CPP2A "c++2a") |
| |
| if(CONFIG_STD_CPP98) |
| set(STD_CPP_DIALECT ${DIALECT_STD_CPP98}) |
| elseif(CONFIG_STD_CPP11) |
| set(STD_CPP_DIALECT ${DIALECT_STD_CPP11}) # Default |
| elseif(CONFIG_STD_CPP14) |
| set(STD_CPP_DIALECT ${DIALECT_STD_CPP14}) |
| elseif(CONFIG_STD_CPP17) |
| set(STD_CPP_DIALECT ${DIALECT_STD_CPP17}) |
| elseif(CONFIG_STD_CPP2A) |
| set(STD_CPP_DIALECT ${DIALECT_STD_CPP2A}) |
| else() |
| assert(0 "Unreachable code. Expected C++ standard to have been chosen. See Kconfig.zephyr.") |
| endif() |
| |
| zephyr_compile_options( |
| ${OPTIMIZATION_FLAG} # Usually -Os |
| -g # TODO: build configuration enough? |
| -Wall |
| -Wformat |
| -Wformat-security |
| -Wno-format-zero-length |
| -imacros ${AUTOCONF_H} |
| -ffreestanding |
| -Wno-main |
| -fno-common |
| ${NOSTDINC_F} |
| ${TOOLCHAIN_C_FLAGS} |
| ) |
| |
| zephyr_compile_options( |
| $<$<COMPILE_LANGUAGE:CXX>:-std=${STD_CPP_DIALECT}> |
| $<$<COMPILE_LANGUAGE:CXX>:-fcheck-new> |
| $<$<COMPILE_LANGUAGE:CXX>:-ffunction-sections> |
| $<$<COMPILE_LANGUAGE:CXX>:-fdata-sections> |
| |
| $<$<COMPILE_LANGUAGE:ASM>:-xassembler-with-cpp> |
| $<$<COMPILE_LANGUAGE:ASM>:-D_ASMLANGUAGE> |
| ) |
| |
| if(NOT CONFIG_RTTI) |
| zephyr_compile_options( |
| $<$<COMPILE_LANGUAGE:CXX>:-fno-rtti> |
| ) |
| endif() |
| |
| if(NOT CONFIG_EXCEPTIONS) |
| zephyr_compile_options( |
| $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions> |
| ) |
| endif() |
| |
| zephyr_ld_options( |
| ${TOOLCHAIN_LD_FLAGS} |
| ) |
| |
| if(NOT CONFIG_NATIVE_APPLICATION) |
| zephyr_ld_options( |
| -nostdlib |
| -static |
| -no-pie |
| ) |
| endif() |
| |
| if(CONFIG_LIB_CPLUSPLUS) |
| zephyr_ld_options( |
| -lstdc++ |
| ) |
| endif() |
| |
| # ========================================================================== |
| # |
| # cmake -DW=... settings |
| # |
| # W=1 - warnings that may be relevant and does not occur too often |
| # W=2 - warnings that occur quite often but may still be relevant |
| # W=3 - the more obscure warnings, can most likely be ignored |
| # ========================================================================== |
| if(W MATCHES "1") |
| zephyr_compile_options( |
| -Wextra |
| -Wunused |
| -Wno-unused-parameter |
| -Wmissing-declarations |
| -Wmissing-format-attribute |
| -Wold-style-definition |
| ) |
| zephyr_cc_option( |
| -Wmissing-prototypes |
| -Wmissing-include-dirs |
| -Wunused-but-set-variable |
| -Wno-missing-field-initializers |
| ) |
| endif() |
| |
| if(W MATCHES "2") |
| zephyr_compile_options( |
| -Waggregate-return |
| -Wcast-align |
| -Wdisabled-optimization |
| -Wnested-externs |
| -Wshadow |
| ) |
| zephyr_cc_option( |
| -Wlogical-op |
| -Wmissing-field-initializers |
| ) |
| endif() |
| |
| if(W MATCHES "3") |
| zephyr_compile_options( |
| -Wbad-function-cast |
| -Wcast-qual |
| -Wconversion |
| -Wpacked |
| -Wpadded |
| -Wpointer-arith |
| -Wredundant-decls |
| -Wswitch-default |
| ) |
| zephyr_cc_option( |
| -Wpacked-bitfield-compat |
| -Wvla |
| ) |
| endif() |
| |
| if(NOT CONFIG_STD_CPP98) # "register" keyword was deprecated since C++11. |
| zephyr_compile_options( |
| $<$<COMPILE_LANGUAGE:CXX>:-Wno-register> |
| ) |
| endif() |
| |
| # Allow the user to inject options when calling cmake, e.g. |
| # 'cmake -DEXTRA_CFLAGS="-Werror -Wno-deprecated-declarations" ..' |
| include(cmake/extra_flags.cmake) |
| |
| if(CONFIG_READABLE_ASM) |
| zephyr_cc_option(-fno-reorder-blocks) |
| zephyr_cc_option(-fno-ipa-cp-clone) |
| zephyr_cc_option(-fno-partial-inlining) |
| endif() |
| |
| zephyr_cc_option(-fno-asynchronous-unwind-tables) |
| zephyr_cc_option(-fno-pie) |
| zephyr_cc_option(-fno-pic) |
| zephyr_cc_option(-fno-strict-overflow) |
| zephyr_cc_option(-Wno-pointer-sign) |
| |
| if(CONFIG_OVERRIDE_FRAME_POINTER_DEFAULT) |
| if(CONFIG_OMIT_FRAME_POINTER) |
| zephyr_cc_option(-fomit-frame-pointer) |
| else() |
| zephyr_cc_option(-fno-omit-frame-pointer) |
| endif() |
| endif() |
| |
| separate_arguments(CONFIG_COMPILER_OPT_AS_LIST UNIX_COMMAND ${CONFIG_COMPILER_OPT}) |
| zephyr_compile_options(${CONFIG_COMPILER_OPT_AS_LIST}) |
| |
| # TODO: Include arch compiler options at this point. |
| |
| if(CMAKE_C_COMPILER_ID STREQUAL "Clang") |
| zephyr_cc_option( |
| #FIXME: need to fix all of those |
| -Wno-sometimes-uninitialized |
| -Wno-shift-overflow |
| -Wno-missing-braces |
| -Wno-self-assign |
| -Wno-address-of-packed-member |
| -Wno-unused-function |
| -Wno-initializer-overrides |
| -Wno-section |
| -Wno-unknown-warning-option |
| -Wno-unused-variable |
| -Wno-format-invalid-specifier |
| -Wno-gnu |
| # comparison of unsigned expression < 0 is always false |
| -Wno-tautological-compare |
| ) |
| else() # GCC assumed |
| zephyr_cc_option( |
| -Wno-unused-but-set-variable |
| -fno-reorder-functions |
| ) |
| |
| if(NOT ${ZEPHYR_TOOLCHAIN_VARIANT} STREQUAL "xcc") |
| zephyr_cc_option(-fno-defer-pop) |
| endif() |
| endif() |
| |
| zephyr_cc_option_ifdef(CONFIG_STACK_USAGE -fstack-usage) |
| |
| zephyr_system_include_directories(${NOSTDINC}) |
| |
| # Force an error when things like SYS_INIT(foo, ...) occur with a missing header. |
| zephyr_cc_option(-Werror=implicit-int) |
| |
| # Prohibit void pointer arithmetic. Illegal in C99 |
| zephyr_cc_option(-Wpointer-arith) |
| |
| # Prohibit date/time macros, which would make the build non-deterministic |
| # cc-option(-Werror=date-time) |
| |
| # TODO: Archiver arguments |
| # ar_option(D) |
| |
| # Declare MPU userspace dependencies before the linker scripts to make |
| # sure the order of dependencies are met |
| if(CONFIG_USERSPACE) |
| if(CONFIG_APP_SHARED_MEM) |
| set(APP_SMEM_DEP app_smem_linker) |
| endif() |
| if(CONFIG_ARM) |
| set(PRIV_STACK_DEP priv_stacks_prebuilt) |
| endif() |
| endif() |
| |
| set_ifndef(LINKERFLAGPREFIX -Wl) |
| |
| if(NOT CONFIG_NATIVE_APPLICATION) |
| zephyr_ld_options( |
| ${LINKERFLAGPREFIX},-X |
| ${LINKERFLAGPREFIX},-N |
| ) |
| endif() |
| |
| zephyr_ld_options( |
| ${LINKERFLAGPREFIX},--gc-sections |
| ${LINKERFLAGPREFIX},--build-id=none |
| ) |
| |
| if(NOT CONFIG_NATIVE_APPLICATION) |
| set(NOSTDINC_F -nostdinc) |
| endif() |
| |
| get_property(TOPT GLOBAL PROPERTY TOPT) |
| set_ifndef( TOPT -T) |
| |
| if(NOT CONFIG_NATIVE_APPLICATION) |
| # Funny thing is if this is set to =error, some architectures will |
| # skip this flag even though the compiler flag check passes |
| # (e.g. ARC and Xtensa). So warning should be the default for now. |
| # |
| # Skip this for native application as Zephyr only provides |
| # additions to the host toolchain linker script. The relocation |
| # sections (.rel*) requires us to override those provided |
| # by host toolchain. As we can't account for all possible |
| # combination of compiler and linker on all machines used |
| # for development, it is better to turn this off. |
| # |
| # CONFIG_LINKER_ORPHAN_SECTION_PLACE is to place the orphan sections |
| # without any warnings or errors, which is the default behavior. |
| # So there is no need to explicity set a linker flag. |
| if(CONFIG_LINKER_ORPHAN_SECTION_WARN) |
| zephyr_ld_options( |
| ${LINKERFLAGPREFIX},--orphan-handling=warn |
| ) |
| elseif(CONFIG_LINKER_ORPHAN_SECTION_ERROR) |
| zephyr_ld_options( |
| ${LINKERFLAGPREFIX},--orphan-handling=error |
| ) |
| endif() |
| endif() |
| |
| if(CONFIG_HAVE_CUSTOM_LINKER_SCRIPT) |
| set(LINKER_SCRIPT ${APPLICATION_SOURCE_DIR}/${CONFIG_CUSTOM_LINKER_SCRIPT}) |
| if(NOT EXISTS ${LINKER_SCRIPT}) |
| set(LINKER_SCRIPT ${CONFIG_CUSTOM_LINKER_SCRIPT}) |
| assert_exists(CONFIG_CUSTOM_LINKER_SCRIPT) |
| endif() |
| else() |
| # Try a board specific linker file |
| set(LINKER_SCRIPT ${BOARD_DIR}/linker.ld) |
| if(NOT EXISTS ${LINKER_SCRIPT}) |
| # If not available, try an SoC specific linker file |
| set(LINKER_SCRIPT ${SOC_DIR}/${ARCH}/${SOC_PATH}/linker.ld) |
| endif() |
| endif() |
| |
| if(NOT EXISTS ${LINKER_SCRIPT}) |
| message(FATAL_ERROR "Could not find linker script: '${LINKER_SCRIPT}'. Corrupted configuration?") |
| endif() |
| |
| # Custom section support in linker scripts requires that the application source |
| # directory is in the preprocessor search path, in order to find the custom |
| # linker script fragments. |
| if(CONFIG_CUSTOM_RODATA_LD OR CONFIG_CUSTOM_RWDATA_LD OR CONFIG_CUSTOM_SECTIONS_LD) |
| zephyr_include_directories(${APPLICATION_SOURCE_DIR}) |
| endif() |
| |
| configure_file(version.h.in ${PROJECT_BINARY_DIR}/include/generated/version.h) |
| |
| function(construct_add_custom_command_for_linker_pass linker_output_name output_variable) |
| set(extra_dependencies ${ARGN}) |
| set(linker_cmd_file_name ${linker_output_name}.cmd) |
| |
| if (${linker_output_name} MATCHES "^linker_pass_final$") |
| set(linker_pass_define -DLINKER_PASS2) |
| else() |
| set(linker_pass_define "") |
| endif() |
| |
| # Different generators deal with depfiles differently. |
| if(CMAKE_GENERATOR STREQUAL "Unix Makefiles") |
| # Note that the IMPLICIT_DEPENDS option is currently supported only |
| # for Makefile generators and will be ignored by other generators. |
| set(linker_script_dep IMPLICIT_DEPENDS C ${LINKER_SCRIPT}) |
| elseif(CMAKE_GENERATOR STREQUAL "Ninja") |
| # Using DEPFILE with other generators than Ninja is an error. |
| set(linker_script_dep DEPFILE ${PROJECT_BINARY_DIR}/${linker_cmd_file_name}.dep) |
| else() |
| # TODO: How would the linker script dependencies work for non-linker |
| # script generators. |
| message(STATUS "Warning; this generator is not well supported. The |
| Linker script may not be regenerated when it should.") |
| set(linker_script_dep "") |
| endif() |
| |
| zephyr_get_include_directories_for_lang(C current_includes) |
| get_filename_component(base_name ${CMAKE_CURRENT_BINARY_DIR} NAME) |
| get_property(current_defines GLOBAL PROPERTY PROPERTY_LINKER_SCRIPT_DEFINES) |
| |
| set(${output_variable} |
| OUTPUT ${linker_cmd_file_name} |
| DEPENDS |
| ${LINKER_SCRIPT} |
| ${extra_dependencies} |
| # NB: 'linker_script_dep' will use a keyword that ends 'DEPENDS' |
| ${linker_script_dep} |
| COMMAND ${CMAKE_C_COMPILER} |
| -x assembler-with-cpp |
| ${NOSTDINC_F} |
| ${NOSYSDEF_CFLAG} |
| -MD -MF ${linker_cmd_file_name}.dep -MT ${base_name}/${linker_cmd_file_name} |
| ${current_includes} |
| ${current_defines} |
| ${linker_pass_define} |
| -E ${LINKER_SCRIPT} |
| -P # Prevent generation of debug `#line' directives. |
| -o ${linker_cmd_file_name} |
| VERBATIM |
| WORKING_DIRECTORY ${PROJECT_BINARY_DIR} |
| |
| PARENT_SCOPE |
| ) |
| endfunction() |
| |
| # Error-out when the deprecated naming convention is found (until |
| # after 1.14.0 has been released) |
| foreach(path |
| ${BOARD_DIR}/dts.fixup |
| ${PROJECT_SOURCE_DIR}/soc/${ARCH}/${SOC_PATH}/dts.fixup |
| ${APPLICATION_SOURCE_DIR}/dts.fixup |
| ) |
| if(EXISTS ${path}) |
| message(FATAL_ERROR |
| "A deprecated filename has been detected. Porting is required." |
| "The file '${path}' exists, but it should be named dts_fixup.h instead." |
| "See https://github.com/zephyrproject-rtos/zephyr/pull/10352 for more details" |
| ) |
| endif() |
| endforeach() |
| |
| set_ifndef( DTS_BOARD_FIXUP_FILE ${BOARD_DIR}/dts_fixup.h) |
| set_ifndef( DTS_SOC_FIXUP_FILE ${SOC_DIR}/${ARCH}/${SOC_PATH}/dts_fixup.h) |
| set( DTS_APP_FIXUP_FILE ${APPLICATION_SOURCE_DIR}/dts_fixup.h) |
| |
| set_ifndef(DTS_CAT_OF_FIXUP_FILES ${ZEPHYR_BINARY_DIR}/include/generated/generated_dts_board_fixups.h) |
| |
| # Concatenate the fixups into a single header file for easy |
| # #include'ing |
| file(WRITE ${DTS_CAT_OF_FIXUP_FILES} "/* May only be included by generated_dts_board.h */\n\n") |
| foreach(fixup_file |
| ${DTS_BOARD_FIXUP_FILE} |
| ${DTS_SOC_FIXUP_FILE} |
| ${DTS_APP_FIXUP_FILE} |
| ${shield_dts_fixups} |
| ) |
| if(EXISTS ${fixup_file}) |
| file(READ ${fixup_file} contents) |
| file(APPEND ${DTS_CAT_OF_FIXUP_FILES} "${contents}") |
| endif() |
| endforeach() |
| |
| # Unfortunately, the order in which CMakeLists.txt code is processed |
| # matters so we need to be careful about how we order the processing |
| # of subdirectories. One example is "Compiler flags added late in the |
| # build are not exported to external build systems #5605"; when we |
| # integrate with an external build system we read out all compiler |
| # flags when the external project is created. So an external project |
| # defined in subsys or ext will not get global flags added by drivers/ |
| # or tests/ as the subdirectories are ordered now. |
| # |
| # Another example of when the order matters is the reading and writing |
| # of global properties such as ZEPHYR_LIBS or |
| # GENERATED_KERNEL_OBJECT_FILES. |
| # |
| # Arch is placed early because it defines important compiler flags |
| # that must be exported to external build systems defined in |
| # e.g. subsys/. |
| add_subdirectory(arch) |
| add_subdirectory(lib) |
| # We use include instead of add_subdirectory to avoid creating a new directory scope. |
| # This is because source file properties are directory scoped, including the GENERATED |
| # property which is set implicitly for custom command outputs |
| include(misc/generated/CMakeLists.txt) |
| |
| if(EXISTS ${SOC_DIR}/${ARCH}/CMakeLists.txt) |
| add_subdirectory(${SOC_DIR}/${ARCH} soc/${ARCH}) |
| else() |
| add_subdirectory(${SOC_DIR}/${ARCH}/${SOC_PATH} soc/${ARCH}/${SOC_PATH}) |
| endif() |
| |
| add_subdirectory(boards) |
| add_subdirectory(ext) |
| add_subdirectory(subsys) |
| add_subdirectory(drivers) |
| add_subdirectory(tests) |
| |
| # Add all zephyr modules subdirectories. |
| message("Including module(s): ${ZEPHYR_MODULES_NAME}") |
| set(index 0) |
| foreach(module_name ${ZEPHYR_MODULES_NAME}) |
| list(GET ZEPHYR_MODULES_DIR ${index} module_dir) |
| math(EXPR index "${index} + 1") |
| add_subdirectory(${module_dir} ${CMAKE_BINARY_DIR}/${module_name}) |
| endforeach() |
| |
| set(syscall_macros_h ${ZEPHYR_BINARY_DIR}/include/generated/syscall_macros.h) |
| |
| add_custom_target(${SYSCALL_MACROS_H_TARGET} DEPENDS ${syscall_macros_h}) |
| add_custom_command( OUTPUT ${syscall_macros_h} |
| COMMAND |
| ${PYTHON_EXECUTABLE} |
| ${ZEPHYR_BASE}/scripts/gen_syscall_header.py |
| > ${syscall_macros_h} |
| DEPENDS ${ZEPHYR_BASE}/scripts/gen_syscall_header.py |
| ) |
| |
| |
| set(syscall_list_h ${CMAKE_CURRENT_BINARY_DIR}/include/generated/syscall_list.h) |
| set(syscalls_json ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/syscalls.json) |
| |
| # The syscalls subdirs txt file is constructed by python containing a list of folders to use for |
| # dependency handling, including empty folders. |
| # Windows: The list is used to specify DIRECTORY list with CMAKE_CONFIGURE_DEPENDS attribute. |
| # Other OS: The list will update whenever a file is added/removed/modified and ensure a re-build. |
| set(syscalls_subdirs_txt ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/syscalls_subdirs.txt) |
| |
| # As syscalls_subdirs_txt is updated whenever a file is modified, this file can not be used for |
| # monitoring of added / removed folders. A trigger file is thus used for correct dependency |
| # handling. The trigger file will update when a folder is added / removed. |
| set(syscalls_subdirs_trigger ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/syscalls_subdirs.trigger) |
| |
| if(NOT (${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows)) |
| set(syscalls_links --create-links ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/syscalls_links) |
| endif() |
| |
| # When running CMake it must be ensured that all dependencies are correctly acquired. |
| execute_process( |
| COMMAND |
| ${PYTHON_EXECUTABLE} |
| ${ZEPHYR_BASE}/scripts/subfolder_list.py |
| --directory ${ZEPHYR_BASE}/include # Walk this directory |
| --out-file ${syscalls_subdirs_txt} # Write file with discovered folder |
| --trigger ${syscalls_subdirs_trigger} # Trigger file that is used for json generation |
| ${syscalls_links} # If defined, create symlinks for dependencies |
| ) |
| file(STRINGS ${syscalls_subdirs_txt} PARSE_SYSCALLS_PATHS_DEPENDS) |
| |
| if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) |
| # On windows only adding/removing files or folders will be reflected in depends. |
| # Hence adding a file requires CMake to re-run to add this file to the file list. |
| set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${PARSE_SYSCALLS_PATHS_DEPENDS}) |
| |
| # Also On Windows each header file must be monitored as file modifications are not reflected |
| # on directory level. |
| file(GLOB_RECURSE PARSE_SYSCALLS_HEADER_DEPENDS ${ZEPHYR_BASE}/include/*.h) |
| else() |
| # The syscall parsing depends on the folders in order to detect add/removed/modified files. |
| # When a folder is removed, CMake will try to find a target that creates that dependency. |
| # This command sets up the target for CMake to find. |
| # Without this code, CMake will fail with the following error: |
| # <folder> needed by '<target>', missing and no known rule to make it |
| # when a folder is removed. |
| add_custom_command(OUTPUT ${PARSE_SYSCALLS_PATHS_DEPENDS} |
| COMMAND ${CMAKE_COMMAND} -E echo "" |
| COMMENT "Preparing syscall dependency handling" |
| ) |
| |
| add_custom_command( |
| OUTPUT |
| ${syscalls_subdirs_trigger} |
| COMMAND |
| ${PYTHON_EXECUTABLE} |
| ${ZEPHYR_BASE}/scripts/subfolder_list.py |
| --directory ${ZEPHYR_BASE}/include # Walk this directory |
| --out-file ${syscalls_subdirs_txt} # Write file with discovered folder |
| --trigger ${syscalls_subdirs_trigger} # Trigger file that is used for json generation |
| ${syscalls_links} # If defined, create symlinks for dependencies |
| DEPENDS ${PARSE_SYSCALLS_PATHS_DEPENDS} |
| ) |
| |
| # Ensure subdir file always exists when specifying CMake dependency. |
| if(NOT EXISTS ${syscalls_subdirs_txt}) |
| file(WRITE ${syscalls_subdirs_txt} "") |
| endif() |
| |
| # On other OS'es, modifying a file is reflected on the folder timestamp and hence detected |
| # when using depend on directory level. |
| # Thus CMake only needs to re-run when sub-directories are added / removed, which is indicated |
| # using a trigger file. |
| set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${syscalls_subdirs_txt}) |
| endif() |
| |
| # SYSCALL_INCLUDE_DIRECTORY will include the directories that needs to be |
| # searched for syscall declarations if CONFIG_APPLICATION_DEFINED_SYSCALL is set |
| if(CONFIG_APPLICATION_DEFINED_SYSCALL) |
| set(SYSCALL_INCLUDE_DIRECTORY --include ${APPLICATION_SOURCE_DIR}) |
| endif() |
| |
| add_custom_command( |
| OUTPUT |
| ${syscalls_json} |
| COMMAND |
| ${PYTHON_EXECUTABLE} |
| ${ZEPHYR_BASE}/scripts/parse_syscalls.py |
| --include ${ZEPHYR_BASE}/include # Read files from this dir |
| ${SYSCALL_INCLUDE_DIRECTORY} |
| --json-file ${syscalls_json} # Write this file |
| DEPENDS ${syscalls_subdirs_trigger} ${PARSE_SYSCALLS_HEADER_DEPENDS} |
| ) |
| |
| add_custom_target(${SYSCALL_LIST_H_TARGET} DEPENDS ${syscall_list_h}) |
| add_custom_command(OUTPUT include/generated/syscall_dispatch.c ${syscall_list_h} |
| # Also, some files are written to include/generated/syscalls/ |
| COMMAND |
| ${PYTHON_EXECUTABLE} |
| ${ZEPHYR_BASE}/scripts/gen_syscalls.py |
| --json-file ${syscalls_json} # Read this file |
| --base-output include/generated/syscalls # Write to this dir |
| --syscall-dispatch include/generated/syscall_dispatch.c # Write this file |
| --syscall-list ${syscall_list_h} |
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| DEPENDS ${syscalls_json} |
| ) |
| |
| set(DRV_VALIDATION ${PROJECT_BINARY_DIR}/include/generated/driver-validation.h) |
| add_custom_command( |
| OUTPUT ${DRV_VALIDATION} |
| COMMAND |
| ${PYTHON_EXECUTABLE} |
| ${ZEPHYR_BASE}/scripts/gen_kobject_list.py |
| --validation-output ${DRV_VALIDATION} |
| $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose> |
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| ) |
| add_custom_target(${DRIVER_VALIDATION_H_TARGET} DEPENDS ${DRV_VALIDATION}) |
| |
| include($ENV{ZEPHYR_BASE}/cmake/kobj.cmake) |
| gen_kobj(KOBJ_INCLUDE_PATH) |
| |
| # Generate offsets.c.obj from offsets.c |
| # Generate offsets.h from offsets.c.obj |
| |
| set(OFFSETS_LIB offsets) |
| |
| set(OFFSETS_C_PATH ${ARCH_DIR}/${ARCH}/core/offsets/offsets.c) |
| set(OFFSETS_H_PATH ${PROJECT_BINARY_DIR}/include/generated/offsets.h) |
| |
| add_library( ${OFFSETS_LIB} OBJECT ${OFFSETS_C_PATH}) |
| target_link_libraries(${OFFSETS_LIB} zephyr_interface) |
| add_dependencies( ${OFFSETS_LIB} |
| ${SYSCALL_LIST_H_TARGET} |
| ${SYSCALL_MACROS_H_TARGET} |
| ${DRIVER_VALIDATION_H_TARGET} |
| ${KOBJ_TYPES_H_TARGET} |
| ) |
| |
| add_custom_command( |
| OUTPUT ${OFFSETS_H_PATH} |
| COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/gen_offset_header.py |
| -i $<TARGET_OBJECTS:${OFFSETS_LIB}> |
| -o ${OFFSETS_H_PATH} |
| DEPENDS ${OFFSETS_LIB} |
| ) |
| add_custom_target(${OFFSETS_H_TARGET} DEPENDS ${OFFSETS_H_PATH}) |
| |
| zephyr_include_directories(${TOOLCHAIN_INCLUDES}) |
| |
| zephyr_get_include_directories_for_lang(C ZEPHYR_INCLUDES) |
| |
| add_subdirectory(kernel) |
| |
| # Read list content |
| get_property(ZEPHYR_LIBS_PROPERTY GLOBAL PROPERTY ZEPHYR_LIBS) |
| |
| foreach(zephyr_lib ${ZEPHYR_LIBS_PROPERTY}) |
| # TODO: Could this become an INTERFACE property of zephyr_interface? |
| add_dependencies(${zephyr_lib} ${OFFSETS_H_TARGET}) |
| |
| # Verify that all (non-imported) libraries have source |
| # files. Libraries without source files are not supported because |
| # they are an indication that something has been misconfigured. |
| get_target_property(lib_imported ${zephyr_lib} IMPORTED) |
| get_target_property(lib_sources ${zephyr_lib} SOURCES) |
| if(lib_sources STREQUAL lib_sources-NOTFOUND |
| AND (NOT (${zephyr_lib} STREQUAL app)) |
| AND (NOT lib_imported) |
| ) |
| # app is not checked because it's sources are added to it after |
| # this CMakeLists.txt file has been processed |
| message(FATAL_ERROR "\ |
| The Zephyr library '${zephyr_lib}' was created without source files. \ |
| Empty (non-imported) libraries are not supported. \ |
| Either make sure that the library has the sources it should have, \ |
| or make sure it is not created when it has no source files.") |
| endif() |
| endforeach() |
| |
| get_property(OUTPUT_FORMAT GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT) |
| |
| if (CONFIG_CODE_DATA_RELOCATION) |
| set(CODE_RELOCATION_DEP code_relocation_source_lib) |
| endif() # CONFIG_CODE_DATA_RELOCATION |
| |
| construct_add_custom_command_for_linker_pass( |
| linker |
| custom_command |
| ${ALIGN_SIZING_DEP} |
| ${PRIV_STACK_DEP} |
| ${APP_SMEM_DEP} |
| ${CODE_RELOCATION_DEP} |
| ${OFFSETS_H_TARGET} |
| ) |
| add_custom_command( |
| ${custom_command} |
| ) |
| |
| add_custom_target( |
| ${LINKER_SCRIPT_TARGET} |
| DEPENDS |
| linker.cmd |
| ) |
| |
| # Give the '${LINKER_SCRIPT_TARGET}' target all of the include directories so |
| # that cmake can successfully find the linker_script's header |
| # dependencies. |
| zephyr_get_include_directories_for_lang(C |
| ZEPHYR_INCLUDE_DIRS |
| STRIP_PREFIX # Don't use a -I prefix |
| ) |
| set_property(TARGET |
| ${LINKER_SCRIPT_TARGET} |
| PROPERTY INCLUDE_DIRECTORIES |
| ${ZEPHYR_INCLUDE_DIRS} |
| ) |
| |
| set(zephyr_lnk |
| ${LINKERFLAGPREFIX},-Map=${PROJECT_BINARY_DIR}/${KERNEL_MAP_NAME} |
| -u_OffsetAbsSyms |
| -u_ConfigAbsSyms |
| ${LINKERFLAGPREFIX},--whole-archive |
| ${ZEPHYR_LIBS_PROPERTY} |
| ${LINKERFLAGPREFIX},--no-whole-archive |
| kernel |
| $<TARGET_OBJECTS:${OFFSETS_LIB}> |
| ${LIB_INCLUDE_DIR} |
| -L${PROJECT_BINARY_DIR} |
| ${TOOLCHAIN_LIBS} |
| ) |
| |
| if(CONFIG_GEN_ISR_TABLES) |
| if(CONFIG_GEN_SW_ISR_TABLE) |
| list(APPEND GEN_ISR_TABLE_EXTRA_ARG --sw-isr-table) |
| endif() |
| |
| if(CONFIG_GEN_IRQ_VECTOR_TABLE) |
| list(APPEND GEN_ISR_TABLE_EXTRA_ARG --vector-table) |
| endif() |
| |
| # isr_tables.c is generated from ${ZEPHYR_PREBUILT_EXECUTABLE} by |
| # gen_isr_tables.py |
| add_custom_command( |
| OUTPUT isr_tables.c |
| COMMAND ${CMAKE_OBJCOPY} |
| -I ${OUTPUT_FORMAT} |
| -O binary |
| --only-section=.intList |
| $<TARGET_FILE:${ZEPHYR_PREBUILT_EXECUTABLE}> |
| isrList.bin |
| COMMAND ${PYTHON_EXECUTABLE} |
| ${ZEPHYR_BASE}/arch/common/gen_isr_tables.py |
| --output-source isr_tables.c |
| --kernel $<TARGET_FILE:${ZEPHYR_PREBUILT_EXECUTABLE}> |
| --intlist isrList.bin |
| $<$<BOOL:${CONFIG_BIG_ENDIAN}>:--big-endian> |
| $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--debug> |
| ${GEN_ISR_TABLE_EXTRA_ARG} |
| DEPENDS ${ZEPHYR_PREBUILT_EXECUTABLE} |
| ) |
| set_property(GLOBAL APPEND PROPERTY GENERATED_KERNEL_SOURCE_FILES isr_tables.c) |
| endif() |
| |
| if(CONFIG_CODE_DATA_RELOCATION) |
| set(MEM_RELOCATAION_LD "${PROJECT_BINARY_DIR}/include/generated/linker_relocate.ld") |
| set(MEM_RELOCATAION_CODE "${PROJECT_BINARY_DIR}/code_relocation.c") |
| |
| add_custom_command( |
| OUTPUT ${MEM_RELOCATAION_CODE} ${MEM_RELOCATAION_LD} |
| COMMAND |
| ${PYTHON_EXECUTABLE} |
| ${ZEPHYR_BASE}/scripts/gen_relocate_app.py |
| $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose> |
| -d ${APPLICATION_BINARY_DIR} |
| -i '$<TARGET_PROPERTY:code_data_relocation_target,COMPILE_DEFINITIONS>' |
| -o ${MEM_RELOCATAION_LD} |
| -c ${MEM_RELOCATAION_CODE} |
| DEPENDS app kernel ${ZEPHYR_LIBS_PROPERTY} |
| ) |
| |
| add_library(code_relocation_source_lib STATIC ${MEM_RELOCATAION_CODE}) |
| target_link_libraries(code_relocation_source_lib zephyr_interface) |
| |
| endif() |
| |
| if(CONFIG_USERSPACE) |
| zephyr_get_compile_options_for_lang_as_string(C compiler_flags_priv) |
| string(REPLACE "-ftest-coverage" "" NO_COVERAGE_FLAGS "${compiler_flags_priv}") |
| string(REPLACE "-fprofile-arcs" "" NO_COVERAGE_FLAGS "${NO_COVERAGE_FLAGS}") |
| |
| get_property(include_dir_in_interface TARGET zephyr_interface |
| PROPERTY INTERFACE_INCLUDE_DIRECTORIES) |
| |
| get_property(sys_include_dir_in_interface TARGET zephyr_interface |
| PROPERTY INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) |
| |
| get_property(compile_definitions_interface TARGET zephyr_interface |
| PROPERTY INTERFACE_COMPILE_DEFINITIONS) |
| |
| set(complete_include_dirs ${include_dir_in_interface} ${sys_include_dir_in_interface}) |
| endif() |
| |
| |
| if(CONFIG_ARM AND CONFIG_USERSPACE) |
| set(GEN_PRIV_STACKS $ENV{ZEPHYR_BASE}/scripts/gen_priv_stacks.py) |
| set(PROCESS_PRIV_STACKS_GPERF $ENV{ZEPHYR_BASE}/scripts/process_gperf.py) |
| |
| set(PRIV_STACKS priv_stacks_hash.gperf) |
| set(PRIV_STACKS_OUTPUT_SRC_PRE priv_stacks_hash_preprocessed.c) |
| set(PRIV_STACKS_OUTPUT_SRC priv_stacks_hash.c) |
| set(PRIV_STACKS_OUTPUT_OBJ priv_stacks_hash.c.obj) |
| set(PRIV_STACKS_OUTPUT_OBJ_RENAMED priv_stacks_hash_renamed.o) |
| |
| # Essentially what we are doing here is extracting some information |
| # out of the nearly finished elf file, generating the source code |
| # for a hash table based on that information, and then compiling and |
| # linking the hash table back into a now even more nearly finished |
| # elf file. |
| |
| # Use the script GEN_PRIV_STACKS to scan the kernel binary's |
| # (${ZEPHYR_PREBUILT_EXECUTABLE}) DWARF information to produce a table of kernel |
| # objects (PRIV_STACKS) which we will then pass to gperf |
| add_custom_command( |
| OUTPUT ${PRIV_STACKS} |
| COMMAND |
| ${PYTHON_EXECUTABLE} |
| ${GEN_PRIV_STACKS} |
| --kernel $<TARGET_FILE:priv_stacks_prebuilt> |
| --output ${PRIV_STACKS} |
| $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose> |
| DEPENDS priv_stacks_prebuilt |
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| ) |
| add_custom_target(priv_stacks DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${PRIV_STACKS}) |
| |
| # Use gperf to generate C code (PRIV_STACKS_OUTPUT_SRC_PRE) which implements a |
| # perfect hashtable based on PRIV_STACKS |
| add_custom_command( |
| OUTPUT ${PRIV_STACKS_OUTPUT_SRC_PRE} |
| COMMAND |
| ${GPERF} -C |
| --output-file ${PRIV_STACKS_OUTPUT_SRC_PRE} |
| ${PRIV_STACKS} |
| DEPENDS priv_stacks ${PRIV_STACKS} |
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| ) |
| add_custom_target(priv_stacks_output_src_pre DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${PRIV_STACKS_OUTPUT_SRC_PRE}) |
| |
| # For our purposes the code/data generated by gperf is not optimal. |
| # |
| # The script PROCESS_GPERF creates a new c file OUTPUT_SRC based on |
| # OUTPUT_SRC_PRE to greatly reduce the amount of code/data generated |
| # since we know we are always working with pointer values |
| add_custom_command( |
| OUTPUT ${PRIV_STACKS_OUTPUT_SRC} |
| COMMAND |
| ${PYTHON_EXECUTABLE} |
| ${PROCESS_PRIV_STACKS_GPERF} |
| -i ${PRIV_STACKS_OUTPUT_SRC_PRE} |
| -o ${PRIV_STACKS_OUTPUT_SRC} |
| -p "struct _k_priv_stack_map" |
| $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose> |
| DEPENDS priv_stacks_output_src_pre ${PRIV_STACKS_OUTPUT_SRC_PRE} |
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| ) |
| add_custom_target(priv_stacks_output_src DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${PRIV_STACKS_OUTPUT_SRC}) |
| |
| set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${PRIV_STACKS_OUTPUT_SRC} |
| PROPERTIES COMPILE_DEFINITIONS "${compile_definitions_interface}") |
| |
| # always compile priv_stacks_hash.c at optimization -Os |
| set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${PRIV_STACKS_OUTPUT_SRC} |
| PROPERTIES COMPILE_FLAGS |
| "${NO_COVERAGE_FLAGS} -Os -fno-function-sections -fno-data-sections ") |
| |
| # We need precise control of where generated text/data ends up in the final |
| # kernel image. Disable function/data sections and use objcopy to move |
| # generated data into special section names |
| add_library(priv_stacks_output_lib STATIC |
| ${CMAKE_CURRENT_BINARY_DIR}/${PRIV_STACKS_OUTPUT_SRC} |
| ) |
| |
| # Turn off -ffunction-sections, etc. |
| # NB: Using a library instead of target_compile_options(priv_stacks_output_lib |
| # [...]) because a library's options have precedence |
| add_library(priv_stacks_output_lib_interface INTERFACE) |
| foreach(incl ${complete_include_dirs}) |
| target_include_directories(priv_stacks_output_lib_interface INTERFACE ${incl}) |
| endforeach() |
| |
| target_link_libraries(priv_stacks_output_lib priv_stacks_output_lib_interface) |
| |
| set(PRIV_STACKS_OUTPUT_OBJ_PATH ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/priv_stacks_output_lib.dir/${PRIV_STACKS_OUTPUT_OBJ}) |
| |
| add_custom_command( |
| OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PRIV_STACKS_OUTPUT_OBJ_RENAMED} |
| COMMAND |
| ${CMAKE_OBJCOPY} |
| --rename-section .bss=.priv_stacks.noinit |
| --rename-section .data=.priv_stacks.data |
| --rename-section .text=.priv_stacks.text |
| --rename-section .rodata=.priv_stacks.rodata |
| ${PRIV_STACKS_OUTPUT_OBJ_PATH} |
| ${PRIV_STACKS_OUTPUT_OBJ_RENAMED} |
| DEPENDS priv_stacks_output_lib |
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| ) |
| add_custom_target(priv_stacks_output_obj_renamed DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${PRIV_STACKS_OUTPUT_OBJ_RENAMED}) |
| |
| add_library(priv_stacks_output_obj_renamed_lib STATIC IMPORTED GLOBAL) |
| set_property( |
| TARGET priv_stacks_output_obj_renamed_lib |
| PROPERTY |
| IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${PRIV_STACKS_OUTPUT_OBJ_RENAMED} |
| ) |
| add_dependencies( |
| priv_stacks_output_obj_renamed_lib |
| priv_stacks_output_obj_renamed |
| ) |
| |
| set_property(GLOBAL APPEND PROPERTY GENERATED_KERNEL_OBJECT_FILES priv_stacks_output_obj_renamed_lib) |
| endif() |
| |
| if(CONFIG_USERSPACE) |
| set(GEN_KOBJ_LIST ${ZEPHYR_BASE}/scripts/gen_kobject_list.py) |
| set(PROCESS_GPERF ${ZEPHYR_BASE}/scripts/process_gperf.py) |
| |
| set(OBJ_LIST kobject_hash.gperf) |
| set(OUTPUT_SRC_PRE kobject_hash_preprocessed.c) |
| set(OUTPUT_SRC kobject_hash.c) |
| set(OUTPUT_OBJ kobject_hash.c.obj) |
| set(OUTPUT_OBJ_RENAMED kobject_hash_renamed.o) |
| |
| # Essentially what we are doing here is extracting some information |
| # out of the nearly finished elf file, generating the source code |
| # for a hash table based on that information, and then compiling and |
| # linking the hash table back into a now even more nearly finished |
| # elf file. |
| |
| # Use the script GEN_KOBJ_LIST to scan the kernel binary's |
| # (${ZEPHYR_PREBUILT_EXECUTABLE}) DWARF information to produce a table of kernel |
| # objects (OBJ_LIST) which we will then pass to gperf |
| add_custom_command( |
| OUTPUT ${OBJ_LIST} |
| COMMAND |
| ${PYTHON_EXECUTABLE} |
| ${GEN_KOBJ_LIST} |
| --kernel $<TARGET_FILE:${ZEPHYR_PREBUILT_EXECUTABLE}> |
| --gperf-output ${OBJ_LIST} |
| $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose> |
| DEPENDS ${ZEPHYR_PREBUILT_EXECUTABLE} |
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| ) |
| add_custom_target(obj_list DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${OBJ_LIST}) |
| |
| # Use gperf to generate C code (OUTPUT_SRC_PRE) which implements a |
| # perfect hashtable based on OBJ_LIST |
| add_custom_command( |
| OUTPUT ${OUTPUT_SRC_PRE} |
| COMMAND |
| ${GPERF} |
| --output-file ${OUTPUT_SRC_PRE} |
| ${OBJ_LIST} |
| DEPENDS obj_list ${OBJ_LIST} |
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| ) |
| add_custom_target(output_src_pre DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_SRC_PRE}) |
| |
| # For our purposes the code/data generated by gperf is not optimal. |
| # |
| # The script PROCESS_GPERF creates a new c file OUTPUT_SRC based on |
| # OUTPUT_SRC_PRE to greatly reduce the amount of code/data generated |
| # since we know we are always working with pointer values |
| add_custom_command( |
| OUTPUT ${OUTPUT_SRC} |
| COMMAND |
| ${PYTHON_EXECUTABLE} |
| ${PROCESS_GPERF} |
| -i ${OUTPUT_SRC_PRE} |
| -o ${OUTPUT_SRC} |
| -p "struct _k_object" |
| $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose> |
| DEPENDS output_src_pre ${OUTPUT_SRC_PRE} |
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| ) |
| add_custom_target(output_src DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_SRC}) |
| |
| # We need precise control of where generated text/data ends up in the final |
| # kernel image. Disable function/data sections and use objcopy to move |
| # generated data into special section names |
| add_library(output_lib STATIC |
| ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_SRC} |
| ) |
| |
| # always compile kobject_hash.c at optimization -Os |
| set_source_files_properties(${OUTPUT_SRC} PROPERTIES COMPILE_FLAGS |
| "${NO_COVERAGE_FLAGS} -Os -fno-function-sections -fno-data-sections") |
| |
| set_source_files_properties(${OUTPUT_SRC} |
| PROPERTIES COMPILE_DEFINITIONS "${compile_definitions_interface}") |
| |
| # Turn off -ffunction-sections, etc. |
| # NB: Using a library instead of target_compile_options(output_lib |
| # [...]) because a library's options have precedence |
| add_library(output_lib_interface INTERFACE) |
| |
| target_link_libraries(output_lib output_lib_interface) |
| |
| foreach(incl ${complete_include_dirs}) |
| target_include_directories(output_lib_interface INTERFACE ${incl}) |
| endforeach() |
| |
| |
| set(OUTPUT_OBJ_PATH ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/output_lib.dir/${OUTPUT_OBJ}) |
| |
| add_custom_command( |
| OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_OBJ_RENAMED} |
| COMMAND |
| ${CMAKE_OBJCOPY} |
| --rename-section .data=.kobject_data.data |
| --rename-section .text=.kobject_data.text |
| --rename-section .rodata=.kobject_data.rodata |
| ${OUTPUT_OBJ_PATH} |
| ${OUTPUT_OBJ_RENAMED} |
| DEPENDS output_lib |
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| ) |
| add_custom_target(output_obj_renamed DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_OBJ_RENAMED}) |
| |
| add_library(output_obj_renamed_lib STATIC IMPORTED GLOBAL) |
| set_property( |
| TARGET output_obj_renamed_lib |
| PROPERTY |
| IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_OBJ_RENAMED} |
| ) |
| add_dependencies( |
| output_obj_renamed_lib |
| output_obj_renamed |
| ) |
| |
| set_property(GLOBAL APPEND PROPERTY GENERATED_KERNEL_OBJECT_FILES output_obj_renamed_lib) |
| endif() |
| |
| # Read global variables into local variables |
| get_property(GKOF GLOBAL PROPERTY GENERATED_KERNEL_OBJECT_FILES) |
| get_property(GKSF GLOBAL PROPERTY GENERATED_KERNEL_SOURCE_FILES) |
| |
| |
| get_property(CSTD GLOBAL PROPERTY CSTD) |
| set_ifndef(CSTD c99) |
| |
| zephyr_compile_options( |
| $<$<COMPILE_LANGUAGE:C>:-std=${CSTD}> |
| ) |
| |
| configure_file( |
| $ENV{ZEPHYR_BASE}/include/arch/arc/v2/app_data_alignment.ld |
| ${PROJECT_BINARY_DIR}/include/generated/app_data_alignment.ld) |
| |
| configure_file( |
| $ENV{ZEPHYR_BASE}/include/arch/arm/cortex_m/scripts/app_smem.ld |
| ${PROJECT_BINARY_DIR}/include/generated/app_smem.ld) |
| |
| if(CONFIG_APP_SHARED_MEM AND CONFIG_USERSPACE) |
| set(APP_SMEM_LD "${PROJECT_BINARY_DIR}/include/generated/app_smem.ld") |
| set(OBJ_FILE_DIR "${PROJECT_BINARY_DIR}/../") |
| |
| add_custom_target( |
| ${APP_SMEM_DEP} |
| DEPENDS |
| ${APP_SMEM_LD} |
| ) |
| |
| if(CONFIG_NEWLIB_LIBC) |
| set(NEWLIB_PART -l libc.a z_newlib_partition) |
| endif() |
| add_custom_command( |
| OUTPUT ${APP_SMEM_LD} |
| COMMAND ${PYTHON_EXECUTABLE} |
| ${ZEPHYR_BASE}/scripts/gen_app_partitions.py |
| -d ${OBJ_FILE_DIR} |
| -o ${APP_SMEM_LD} |
| ${NEWLIB_PART} |
| $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose> |
| DEPENDS |
| kernel |
| ${ZEPHYR_LIBS_PROPERTY} |
| WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/ |
| COMMENT "Generating app_smem linker section" |
| ) |
| endif() |
| |
| if(CONFIG_USERSPACE AND CONFIG_ARM) |
| construct_add_custom_command_for_linker_pass( |
| linker_priv_stacks |
| custom_command |
| ${ALIGN_SIZING_DEP} |
| ${CODE_RELOCATION_DEP} |
| ${APP_SMEM_DEP} |
| ${APP_SMEM_LD} |
| ${OFFSETS_H_TARGET} |
| ) |
| add_custom_command( |
| ${custom_command} |
| ) |
| |
| add_custom_target( |
| linker_priv_stacks_script |
| DEPENDS |
| linker_priv_stacks.cmd |
| ) |
| |
| set_property(TARGET |
| linker_priv_stacks_script |
| PROPERTY INCLUDE_DIRECTORIES |
| ${ZEPHYR_INCLUDE_DIRS} |
| ) |
| |
| set(PRIV_STACK_LIB priv_stacks_output_obj_renamed_lib) |
| add_executable( priv_stacks_prebuilt misc/empty_file.c) |
| target_link_libraries(priv_stacks_prebuilt ${TOPT} ${PROJECT_BINARY_DIR}/linker_priv_stacks.cmd ${zephyr_lnk} ${CODE_RELOCATION_DEP}) |
| set_property(TARGET priv_stacks_prebuilt PROPERTY LINK_DEPENDS ${PROJECT_BINARY_DIR}/linker_priv_stacks.cmd) |
| add_dependencies( priv_stacks_prebuilt ${ALIGN_SIZING_DEP} linker_priv_stacks_script ${OFFSETS_LIB}) |
| endif() |
| |
| # FIXME: Is there any way to get rid of empty_file.c? |
| add_executable( ${ZEPHYR_PREBUILT_EXECUTABLE} misc/empty_file.c) |
| target_link_libraries(${ZEPHYR_PREBUILT_EXECUTABLE} ${TOPT} ${PROJECT_BINARY_DIR}/linker.cmd ${PRIV_STACK_LIB} ${zephyr_lnk} ${CODE_RELOCATION_DEP}) |
| set_property(TARGET ${ZEPHYR_PREBUILT_EXECUTABLE} PROPERTY LINK_DEPENDS ${PROJECT_BINARY_DIR}/linker.cmd) |
| add_dependencies( ${ZEPHYR_PREBUILT_EXECUTABLE} ${ALIGN_SIZING_DEP} ${PRIV_STACK_DEP} ${LINKER_SCRIPT_TARGET} ${OFFSETS_LIB}) |
| |
| |
| if(GKOF OR GKSF) |
| set(KERNEL_ELF kernel_elf) |
| set(logical_target_for_zephyr_elf ${KERNEL_ELF}) |
| |
| # The second linker pass uses the same source linker script of the |
| # first pass (LINKER_SCRIPT), but this time with a different output |
| # file and preprocessed with the define LINKER_PASS2. |
| construct_add_custom_command_for_linker_pass( |
| linker_pass_final |
| custom_command |
| ${ALIGN_SIZING_DEP} |
| ${PRIV_STACK_DEP} |
| ${CODE_RELOCATION_DEP} |
| ${ZEPHYR_PREBUILT_EXECUTABLE} |
| ${OFFSETS_H_TARGET} |
| ) |
| add_custom_command( |
| ${custom_command} |
| ) |
| |
| set(LINKER_PASS_FINAL_SCRIPT_TARGET linker_pass_final_script_target) |
| add_custom_target( |
| ${LINKER_PASS_FINAL_SCRIPT_TARGET} |
| DEPENDS |
| linker_pass_final.cmd |
| ) |
| set_property(TARGET |
| ${LINKER_PASS_FINAL_SCRIPT_TARGET} |
| PROPERTY INCLUDE_DIRECTORIES |
| ${ZEPHYR_INCLUDE_DIRS} |
| ) |
| |
| add_executable( ${KERNEL_ELF} misc/empty_file.c ${GKSF}) |
| target_link_libraries(${KERNEL_ELF} ${GKOF} ${TOPT} ${PROJECT_BINARY_DIR}/linker_pass_final.cmd ${zephyr_lnk} ${CODE_RELOCATION_DEP}) |
| set_property(TARGET ${KERNEL_ELF} PROPERTY LINK_DEPENDS ${PROJECT_BINARY_DIR}/linker_pass_final.cmd) |
| add_dependencies( ${KERNEL_ELF} ${ALIGN_SIZING_DEP} ${PRIV_STACK_DEP} ${LINKER_PASS_FINAL_SCRIPT_TARGET}) |
| else() |
| set(logical_target_for_zephyr_elf ${ZEPHYR_PREBUILT_EXECUTABLE}) |
| # Use the prebuilt elf as the final elf since we don't have a |
| # generation stage. |
| endif() |
| |
| # Export the variable to the application's scope to allow the |
| # application to know what the name of the final elf target is. |
| set(logical_target_for_zephyr_elf ${logical_target_for_zephyr_elf} PARENT_SCOPE) |
| |
| # To avoid having the same logical target name for the zephyr lib and |
| # the zephyr elf, we set the kernel_elf file name to zephyr.elf. |
| set_target_properties(${logical_target_for_zephyr_elf} PROPERTIES OUTPUT_NAME ${KERNEL_NAME}) |
| |
| set(post_build_commands "") |
| |
| list_append_ifdef(CONFIG_CHECK_LINK_MAP |
| post_build_commands |
| COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/check_link_map.py ${KERNEL_MAP_NAME} |
| ) |
| |
| if(NOT CONFIG_BUILD_NO_GAP_FILL) |
| # Use ';' as separator to get proper space in resulting command. |
| set(GAP_FILL "--gap-fill;0xff") |
| endif() |
| |
| list_append_ifdef( |
| CONFIG_BUILD_OUTPUT_HEX |
| post_build_commands |
| COMMAND ${CMAKE_OBJCOPY} -S -Oihex ${GAP_FILL} -R .comment -R COMMON -R .eh_frame ${KERNEL_ELF_NAME} ${KERNEL_HEX_NAME} |
| ) |
| |
| list_append_ifdef( |
| CONFIG_BUILD_OUTPUT_BIN |
| post_build_commands |
| COMMAND ${CMAKE_OBJCOPY} -S -Obinary ${GAP_FILL} -R .comment -R COMMON -R .eh_frame ${KERNEL_ELF_NAME} ${KERNEL_BIN_NAME} |
| ) |
| |
| list_append_ifdef( |
| CONFIG_BUILD_OUTPUT_S19 |
| post_build_commands |
| COMMAND ${CMAKE_OBJCOPY} ${GAP_FILL} --srec-len 1 --output-target=srec ${KERNEL_ELF_NAME} ${KERNEL_S19_NAME} |
| ) |
| |
| list_append_ifdef( |
| CONFIG_OUTPUT_DISASSEMBLY |
| post_build_commands |
| COMMAND ${CMAKE_OBJDUMP} -S ${KERNEL_ELF_NAME} > ${KERNEL_LST_NAME} |
| ) |
| |
| list_append_ifdef( |
| CONFIG_OUTPUT_STAT |
| post_build_commands |
| COMMAND ${CMAKE_READELF} -e ${KERNEL_ELF_NAME} > ${KERNEL_STAT_NAME} |
| ) |
| |
| list_append_ifdef( |
| CONFIG_BUILD_OUTPUT_STRIPPED |
| post_build_commands |
| COMMAND ${CMAKE_STRIP} --strip-all ${KERNEL_ELF_NAME} -o ${KERNEL_STRIP_NAME} |
| ) |
| |
| list_append_ifdef( |
| CONFIG_BUILD_OUTPUT_EXE |
| post_build_commands |
| COMMAND ${CMAKE_COMMAND} -E copy ${KERNEL_ELF_NAME} ${KERNEL_EXE_NAME} |
| ) |
| |
| get_property(extra_post_build_commands |
| GLOBAL PROPERTY |
| extra_post_build_commands |
| ) |
| |
| list(APPEND |
| post_build_commands |
| ${extra_post_build_commands} |
| ) |
| |
| add_custom_command( |
| TARGET ${logical_target_for_zephyr_elf} |
| POST_BUILD |
| ${post_build_commands} |
| COMMENT "Generating files from zephyr.elf for board: ${BOARD}" |
| # NB: COMMENT only works for some CMake-Generators |
| ) |
| |
| # To populate with hex files to merge, do the following: |
| # set_property(GLOBAL APPEND PROPERTY HEX_FILES_TO_MERGE ${my_local_list}) |
| # Note that the zephyr.hex file will not be included automatically. |
| get_property(HEX_FILES_TO_MERGE GLOBAL PROPERTY HEX_FILES_TO_MERGE) |
| if(HEX_FILES_TO_MERGE) |
| # Merge in out-of-tree hex files. |
| set(MERGED_HEX_NAME merged.hex) |
| |
| add_custom_command( |
| OUTPUT ${MERGED_HEX_NAME} |
| COMMAND |
| ${PYTHON_EXECUTABLE} |
| ${ZEPHYR_BASE}/scripts/mergehex.py |
| -o ${MERGED_HEX_NAME} |
| ${HEX_FILES_TO_MERGE} |
| DEPENDS ${HEX_FILES_TO_MERGE} ${logical_target_for_zephyr_elf} |
| ) |
| |
| add_custom_target(mergehex ALL DEPENDS ${MERGED_HEX_NAME}) |
| list(APPEND FLASH_DEPS mergehex) |
| endif() |
| |
| if(CONFIG_OUTPUT_PRINT_MEMORY_USAGE) |
| # Use --print-memory-usage with the first link. |
| # |
| # Don't use this option with the second link because seeing it twice |
| # could confuse users and using it on the second link would suppress |
| # it when the first link has a ram/flash-usage issue. |
| set(option ${LINKERFLAGPREFIX},--print-memory-usage) |
| string(MAKE_C_IDENTIFIER check${option} check) |
| |
| set(SAVED_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) |
| set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${option}") |
| zephyr_check_compiler_flag(C "" ${check}) |
| set(CMAKE_REQUIRED_FLAGS ${SAVED_CMAKE_REQUIRED_FLAGS}) |
| |
| target_link_libraries_ifdef(${check} ${ZEPHYR_PREBUILT_EXECUTABLE} ${option}) |
| endif() |
| |
| if(EMU_PLATFORM) |
| include(${ZEPHYR_BASE}/cmake/emu/${EMU_PLATFORM}.cmake) |
| else() |
| add_custom_target(run |
| COMMAND |
| ${CMAKE_COMMAND} -E echo |
| "===================================================" |
| "Emulation/Simulation not supported with this board." |
| "===================================================" |
| ) |
| endif() |
| |
| add_subdirectory(cmake/flash) |
| add_subdirectory(cmake/usage) |
| add_subdirectory(cmake/reports) |
| |
| if(CONFIG_ASSERT AND (NOT CONFIG_FORCE_NO_ASSERT)) |
| message(WARNING " |
| ------------------------------------------------------------ |
| --- WARNING: __ASSERT() statements are globally ENABLED --- |
| --- The kernel will run more slowly and use more memory --- |
| ------------------------------------------------------------" |
| ) |
| endif() |
| |
| if(CONFIG_BOARD_DEPRECATED) |
| message(WARNING " |
| WARNING: The board '${BOARD}' is deprecated and will be |
| removed in version ${CONFIG_BOARD_DEPRECATED}" |
| ) |
| endif() |
| |
| if(CONFIG_X86 AND CONFIG_USERSPACE AND NOT CONFIG_X86_NO_MELTDOWN) |
| message(WARNING " |
| WARNING: You have enabled CONFIG_USERSPACE on an x86-based target. |
| If your CPU is vulnerable to the Meltdown CPU bug, security of |
| supervisor-only memory pages is not guaranteed. This version of Zephyr |
| does not contain a fix for this issue." |
| ) |
| endif() |