]> granicus.if.org Git - esp-idf/blob - tools/cmake/idf_functions.cmake
cmake: use built-in file function to create dummy main
[esp-idf] / tools / cmake / idf_functions.cmake
1 # Some IDF-specific functions and functions
2
3 include(crosstool_version_check)
4
5 #
6 # Set some variables used by rest of the build
7 #
8 # Note at the time this macro is expanded, the config is not yet
9 # loaded and the toolchain and project are not yet set
10 #
11 macro(idf_set_global_variables)
12     # Note that CONFIG_xxx is not available when this function is called
13
14     set_default(EXTRA_COMPONENT_DIRS "")
15
16     # Commmon components, required by every component in the build
17     #
18     set_default(COMPONENT_REQUIRES_COMMON "cxx esp32 newlib freertos heap log soc")
19
20     # PROJECT_PATH has the path to the IDF project (top-level cmake directory)
21     #
22     # (cmake calls this CMAKE_SOURCE_DIR, keeping old name for compatibility.)
23     set(PROJECT_PATH "${CMAKE_SOURCE_DIR}")
24
25     if(MAIN_SRCS)
26         message(WARNING "main is now a component, use of MAIN_SRCS is deprecated")
27         set_default(COMPONENT_DIRS "${PROJECT_PATH}/components ${EXTRA_COMPONENT_DIRS} \
28                                     ${IDF_PATH}/components")
29     else()
30         set_default(COMPONENT_DIRS "${PROJECT_PATH}/components ${EXTRA_COMPONENT_DIRS} \
31                                     ${IDF_PATH}/components ${PROJECT_PATH}/main")
32     endif()
33
34     spaces2list(COMPONENT_DIRS)
35
36     spaces2list(COMPONENTS)
37
38     # Tell cmake to drop executables in the top-level build dir
39     set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}")
40
41     # path to idf.py tool
42     set(IDFTOOL ${PYTHON} "${IDF_PATH}/tools/idf.py")
43 endmacro()
44
45 # Add all the IDF global compiler & preprocessor options
46 # (applied to all components). Some are config-dependent
47 #
48 # If you only want to set options for a particular component,
49 # don't call or edit this function. TODO DESCRIBE WHAT TO DO INSTEAD
50 #
51 function(idf_set_global_compiler_options)
52     add_definitions(-DESP_PLATFORM)
53     add_definitions(-DHAVE_CONFIG_H)
54
55     if(CONFIG_OPTIMIZATION_LEVEL_RELEASE)
56         add_compile_options(-Os)
57     else()
58         add_compile_options(-Og)
59     endif()
60
61     add_c_compile_options(-std=gnu99)
62
63     add_cxx_compile_options(-std=gnu++11 -fno-rtti)
64
65     if(CONFIG_CXX_EXCEPTIONS)
66         add_cxx_compile_options(-fexceptions)
67     else()
68         add_cxx_compile_options(-fno-exceptions)
69     endif()
70
71     # Default compiler configuration
72     add_compile_options(-ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib)
73
74     # Default warnings configuration
75     add_compile_options(
76         -Wall
77         -Werror=all
78         -Wno-error=unused-function
79         -Wno-error=unused-but-set-variable
80         -Wno-error=unused-variable
81         -Wno-error=deprecated-declarations
82         -Wextra
83         -Wno-unused-parameter
84         -Wno-sign-compare)
85     add_c_compile_options(
86         -Wno-old-style-declaration
87         )
88
89     # Stack protection
90     if(NOT BOOTLOADER_BUILD)
91         if(CONFIG_STACK_CHECK_NORM)
92             add_compile_options(-fstack-protector)
93         elseif(CONFIG_STACK_CHECK_STRONG)
94             add_compile_options(-fstack-protector-strong)
95         elseif(CONFIG_STACK_CHECK_ALL)
96             add_compile_options(-fstack-protector-all)
97         endif()
98     endif()
99
100     if(CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED)
101         add_definitions(-DNDEBUG)
102     endif()
103
104     # Always generate debug symbols (even in Release mode, these don't
105     # go into the final binary so have no impact on size)
106     add_compile_options(-ggdb)
107
108     # Enable ccache if it's on the path
109     if(NOT CCACHE_DISABLE)
110         find_program(CCACHE_FOUND ccache)
111         if(CCACHE_FOUND)
112             message(STATUS "ccache will be used for faster builds")
113             set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
114         endif()
115     endif()
116
117 endfunction()
118
119
120 # Verify the IDF environment is configured correctly (environment, toolchain, etc)
121 function(idf_verify_environment)
122
123     if(NOT CMAKE_PROJECT_NAME)
124         message(FATAL_ERROR "Internal error, IDF project.cmake should have set this variable already")
125     endif()
126
127     # Check toolchain is configured properly in cmake
128     if(NOT ( ${CMAKE_SYSTEM_NAME} STREQUAL "Generic" AND ${CMAKE_C_COMPILER} MATCHES xtensa))
129         message(FATAL_ERROR "Internal error, toolchain has not been set correctly by project "
130             "(or an invalid CMakeCache.txt file has been generated somehow)")
131     endif()
132
133     #
134     # Warn if the toolchain version doesn't match
135     #
136     # TODO: make these platform-specific for diff toolchains
137     gcc_version_check("5.2.0")
138     crosstool_version_check("1.22.0-80-g6c4433a")
139
140 endfunction()
141
142 # idf_add_executable
143 #
144 # Calls add_executable to add the final project executable
145 # Adds .map & .bin file targets
146 # Sets up flash-related targets
147 function(idf_add_executable)
148     set(exe_target ${PROJECT_NAME}.elf)
149
150     if(MAIN_SRCS)
151         spaces2list(MAIN_SRCS)
152         add_executable(${exe_target} ${MAIN_SRCS})
153     else()
154         # Create a dummy file to work around CMake requirement of having a source
155         # file while adding an executable
156         add_executable(${exe_target} "${CMAKE_CURRENT_BINARY_DIR}/dummy_main_src.c")
157         file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy_main_src.c)
158
159         add_custom_target(dummy_main_src DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dummy_main_src.c)
160
161         add_dependencies(${exe_target} dummy_main_src)
162     endif()
163
164     add_map_file(${exe_target})
165 endfunction()
166
167
168 # add_map_file
169 #
170 # Set linker args for 'exe_target' to generate a linker Map file
171 function(add_map_file exe_target)
172     get_filename_component(basename ${exe_target} NAME_WE)
173     set(mapfile "${basename}.map")
174     target_link_libraries(${exe_target} "-Wl,--gc-sections -Wl,--cref -Wl,--Map=${mapfile} -Wl,--start-group")
175     set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY
176         ADDITIONAL_MAKE_CLEAN_FILES
177         "${CMAKE_CURRENT_BINARY_DIR}/${mapfile}")
178
179     # add size targets, depend on map file, run idf_size.py
180     add_custom_target(size
181         DEPENDS ${exe_target}
182         COMMAND ${PYTHON} ${IDF_PATH}/tools/idf_size.py ${mapfile}
183         )
184     add_custom_target(size-files
185         DEPENDS ${exe_target}
186         COMMAND ${PYTHON} ${IDF_PATH}/tools/idf_size.py --files ${mapfile}
187         )
188     add_custom_target(size-components
189         DEPENDS ${exe_target}
190         COMMAND ${PYTHON} ${IDF_PATH}/tools/idf_size.py --archives ${mapfile}
191         )
192
193 endfunction()
194
195 # component_compile_options
196 #
197 # Wrapper around target_compile_options that passes the component name
198 function(component_compile_options)
199     target_compile_options(${COMPONENT_NAME} PRIVATE ${ARGV})
200 endfunction()
201
202 # component_compile_definitions
203 #
204 # Wrapper around target_compile_definitions that passes the component name
205 function(component_compile_definitions)
206     target_compile_definitions(${COMPONENT_NAME} PRIVATE ${ARGV})
207 endfunction()
208
209 # idf_get_git_revision
210 #
211 # Set global IDF_VER to the git revision of ESP-IDF.
212 #
213 # Running git_describe() here automatically triggers rebuilds
214 # if the ESP-IDF git version changes
215 function(idf_get_git_revision)
216     git_describe(IDF_VER "${IDF_PATH}")
217     add_definitions(-DIDF_VER=\"${IDF_VER}\")
218     git_submodule_check("${IDF_PATH}")
219     set(IDF_VER ${IDF_VER} PARENT_SCOPE)
220 endfunction()