]> granicus.if.org Git - esp-idf/commitdiff
cmake: Add partition table, and .bin file targets
authorAngus Gratton <angus@espressif.com>
Fri, 19 Jan 2018 04:47:49 +0000 (15:47 +1100)
committerAngus Gratton <gus@projectgus.com>
Sun, 29 Apr 2018 23:59:20 +0000 (09:59 +1000)
components/bootloader/subproject/CMakeLists.txt
components/esptool_py/project_include.cmake [new file with mode: 0644]
components/partition_table/CMakeLists.txt
examples/get-started/hello_world/CMakeLists.txt
tools/cmake/components.cmake
tools/cmake/idf_functions.cmake
tools/cmake/project.cmake
tools/cmake/utilities.cmake

index ab7b5aaa6e74f4886676de8fb49f6934430e3de2..1931392d53ef0e6e05f26996811392f4d334767b 100644 (file)
@@ -1,24 +1,21 @@
 cmake_minimum_required(VERSION 3.5)
 set(CMAKE_TOOLCHAIN_FILE $ENV{IDF_PATH}/toolchain.cmake)
-project(idf_bootloader ASM C CXX)
 
-set(COMPONENTS bootloader esptool_py esp32 soc bootloader_support log spi_flash micro-ecc soc)
+if(NOT SDKCONFIG)
+  message(FATAL_ERROR "Bootloader subproject expects the SDKCONFIG variable to be passed in by the parent build process.")
+endif()
 
+project(bootloader ASM C CXX)
+
+set(COMPONENTS bootloader esptool_py esp32 soc bootloader_support log spi_flash micro-ecc soc)
 set(BOOTLOADER_BUILD 1)
 set(IS_BOOTLOADER_BUILD 1)  # deprecated, use BOOTLOADER_BUILD
 add_definitions(-DBOOTLOADER_BUILD=1)
 
-if(NOT SDKCONFIG)
-  message(FATAL_ERROR "Bootloader subproject expects the SDKCONFIG variable to be passed in by the app build process.")
-endif()
-
-include($ENV{IDF_PATH}/tools/cmake/project.cmake)
-
-add_executable(bootloader.elf
-  main/bootloader_start.c
+set(MAIN_SRCS main/bootloader_start.c
   main/flash_qio_mode.c)
 
-target_link_libraries(bootloader.elf ${COMPONENT_LIBRARIES})
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 
 target_link_libraries(bootloader.elf "-L ${CMAKE_CURRENT_SOURCE_DIR}/main")
 target_link_libraries(bootloader.elf "-T esp32.bootloader.ld")
diff --git a/components/esptool_py/project_include.cmake b/components/esptool_py/project_include.cmake
new file mode 100644 (file)
index 0000000..52fc289
--- /dev/null
@@ -0,0 +1,48 @@
+# Set some global esptool.py variables
+set(ESPTOOLPY "${PYTHON}" "${CMAKE_CURRENT_LIST_DIR}/esptool/esptool.py" --chip esp32)
+set(ESPSECUREPY "${PYTHON}" "${CMAKE_CURRENT_LIST_DIR}/esptool/espsecure.py")
+
+set(ESPPORT $ENV{ESPPORT})
+if(NOT ESPPORT)
+  set(ESPPORT ${CONFIG_ESPTOOLPY_PORT})
+endif()
+
+set(ESPBAUD $ENV{ESPPORT})
+if(NOT ESPBAUD)
+  set(ESPPORT ${CONFIG_ESPTOOLPY_PORT})
+endif()
+
+set(ESPFLASHMODE ${CONFIG_ESPTOOLPY_FLASHMODE})
+set(ESPFLASHFREQ ${CONFIG_ESPTOOLPY_FLASHFREQ})
+set(ESPFLASHSIZE ${CONFIG_ESPTOOLPY_FLASHSIZE})
+
+set(ESPTOOLPY_SERIAL "${ESPTOOLPY}" --port "${ESPPORT}" --baud ${ESPBAUD})
+
+if(CONFIG_ESPTOOLPY_FLASHSIZE_DETECT)
+  set(flashsize_arg detect)
+else()
+  set(flashsize_arg ${ESPFLASHSIZE})
+endif()
+
+set(ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS --flash_mode ${ESPFLASHMODE} --flash_freq ${ESPFLASHFREQ} --flash_size ${ESPFLASHSIZE})
+
+set(ESPTOOLPY_WRITE_FLASH_OPTIONS --flash_mode ${ESPFLASHMODE} --flash_freq ${ESPFLASHFREQ} --flash_size ${flashsize_Arg})
+
+set(ESPTOOLPY_WRITE_FLASH ${ESPTOOLPY_SERIAL} write_flash ${ESPTOOLPY_WRITE_FLASH_OPTIONS})
+
+#
+# Add 'binary' target - generates with elf2image
+#
+add_custom_command(OUTPUT "${PROJECT_NAME}.bin"
+  COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS} -o "${PROJECT_NAME}.bin" "${PROJECT_NAME}.elf"
+  DEPENDS ${PROJECT_NAME}.elf
+  VERBATIM
+  )
+add_custom_target(binary ALL DEPENDS "${PROJECT_NAME}.bin")
+
+#
+# Add 'flash' target - not all build systems can run this directly
+#
+add_custom_target(flash DEPENDS binary partition_table bootloader_subproject)
+# TODO: this target should call "idftool" not esptool directly, so it can
+# override things (port, baud, etc) at runtime not configure time
index b8a17b13a297ab0a29337295fc3949d1a5e02f44..f394088066efaa06f1f4ba86734804c4ab86ae01 100644 (file)
@@ -20,27 +20,34 @@ else()
   set(final_partition_target "build_partition_table")
 endif()
 
-add_custom_target(build_partition_table ALL
-  "${PYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.py" -q
-  ${partition_csv} ${unsigned_partition_bin}
-  BYPRODUCTS ${unsigned_partition_bin}
-  DEPENDS ${partition_csv} "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.py"
-  VERBATIM)
+if(CONFIG_PARTITION_TABLE_MD5)
+    set(md5_opt --disable-md5sum)
+endif()
+
+if(CONFIG_ESPTOOLPY_FLASHSIZE)
+    set(flashsize_opt --flash-size ${CONFIG_ESPTOOLPY_FLASHSIZE})
+endif()
+
+add_custom_command(OUTPUT "${unsigned_partition_bin}"
+    COMMAND "${PYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.py" -q ${md5_opt} ${flashsize_opt}
+    ${partition_csv} ${unsigned_partition_bin}
+    DEPENDS ${partition_csv} "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.py"
+    VERBATIM)
 
 # Add signing steps
 if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
   get_filename_component(secure_boot_signing_key "${CONFIG_SECURE_BOOT_SIGNING_KEY}" ABSOLUTE BASE_DIR "${PROJECT_PATH}")
 
-  add_custom_target(signpartition_table ALL
-    "${PYTHON}" "${ESPSECUREPY}" sign_data --keyfile "${secure_boot_signing_key}" -o "${final_partition_bin}" "${unsigned_partition_bin}"
-    BYPRODUCTS "${final_partition_bin}"
+  add_custom_command(OUTPUT "${final_partition_bin}"
+    COMMAND "${PYTHON}" "${ESPSECUREPY}" sign_data --keyfile "${secure_boot_signing_key}" -o "${final_partition_bin}" "${unsigned_partition_bin}"
     DEPENDS "${unsigned_partition_bin}"
     VERBATIM)
 
 endif()
 
-# Use global properties ESPTOOL_WRITE_FLASH_ARGS & FLASH_DEPENDS to pass this info to the esptool component for flashing
-set_property(GLOBAL APPEND_STRING PROPERTY ESPTOOL_WRITE_FLASH_ARGS "${final_partition_bin} ${partition_table_offset} ")
-set_property(GLOBAL APPEND PROPERTY FLASH_DEPENDS "${final_partition_target}")
+add_custom_target(partition_table ALL DEPENDS "${final_partition_bin}")
+
+# Use global properties ESPTOOL_WRITE_FLASH_ARGS to pass this info to build hte list of esptool write arguments for flashing
+set_property(GLOBAL APPEND_STRING PROPERTY ESPTOOL_WRITE_FLASH_ARGS "${partition_table_offset} ${final_partition_bin} ")
 
 register_config_only_component()
index 4e66c5efdb0dc17eb906a4ae86d3485fff878ccb..4ae205fa256527dad34fa2d69c7d3438e59edbb4 100644 (file)
@@ -1,12 +1,10 @@
-# The following four lines of boilerplate have to be in your project's CMakeLists
+# The following five lines of boilerplate have to be in your project's CMakeLists
 # in this exact order for cmake to work correctly
 cmake_minimum_required(VERSION 3.5)
 set(CMAKE_TOOLCHAIN_FILE $ENV{IDF_PATH}/toolchain.cmake)
-project(idf_project ASM C CXX)
 
-include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(hello-world ASM C CXX)
 
-add_executable(hello_world.elf
-  main/hello_world_main.c)
+set(MAIN_SRCS main/hello_world_main.c)
 
-target_link_libraries(hello_world.elf ${COMPONENT_LIBRARIES})
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
index 9930a44eb71aef517901c67b88e0dc8e650193e4..8e2b857756475fad10947f6d77cf46899ccf149d 100644 (file)
@@ -76,6 +76,15 @@ function(register_component)
     endforeach()
   endif()
 
+  # add public includes from other components when building this component
+  if(COMPONENT_SRCS OR embed_binaries)
+    add_library(${component} STATIC ${COMPONENT_SRCS})
+    set(include_type PUBLIC)
+  else()
+    add_library(${component} INTERFACE) # header-only component
+    set(include_type INTERFACE)
+  endif()
+
   # binaries to embed directly in library
   spaces2list(COMPONENT_EMBED_FILES)
   spaces2list(COMPONENT_EMBED_TXTFILES)
@@ -88,20 +97,13 @@ function(register_component)
     target_add_binary_data("${component}" "${embed_data}" "${embed_type}")
   endforeach()
 
-  # add public includes from other components when building this component
-  if(COMPONENT_SRCS OR embed_binaries)
-    add_library(${component} STATIC ${COMPONENT_SRCS} ${embed_binaries})
-    set(include_type PUBLIC)
-  else()
-    add_library(${component} INTERFACE) # header-only component
-    set(include_type INTERFACE)
-  endif(COMPONENT_SRCS OR embed_binaries)
-
+  # add public includes
   foreach(include_dir ${COMPONENT_ADD_INCLUDEDIRS})
     get_filename_component(include_dir ${include_dir} ABSOLUTE BASE_DIR ${component_dir})
     target_include_directories(${component} ${include_type} ${include_dir})
   endforeach()
 
+  # add private includes
   foreach(include_dir ${COMPONENT_PRIV_INCLUDEDIRS})
     if (${include_type} STREQUAL INTERFACE)
       message(FATAL_ERROR "Component ${component} can't have no source files and COMPONENT_PRIV_INCLUDEDIRS set.")
@@ -123,10 +125,10 @@ function(components_finish_registration)
   # each component should see the include directories of each other
   #
   # (we can't do this until all components are registered, because if(TARGET ...) won't work
-  foreach(a ${COMPONENTS})
+  foreach(a ${COMPONENTS} ${CMAKE_PROJECT_NAME}.elf)
     if (TARGET ${a})
       get_target_property(a_type ${a} TYPE)
-      if (${a_type} STREQUAL STATIC_LIBRARY)
+      if (${a_type} STREQUAL STATIC_LIBRARY OR ${a_type} STREQUAL EXECUTABLE)
         foreach(b ${COMPONENTS})
           if (TARGET ${b} AND NOT ${a} STREQUAL ${b})
             # Add all public compile options from b in a
@@ -138,15 +140,14 @@ function(components_finish_registration)
               $<TARGET_PROPERTY:${b},INTERFACE_COMPILE_OPTIONS>)
           endif()
         endforeach(b)
-      endif(${a_type} STREQUAL STATIC_LIBRARY)
+      endif(${a_type} STREQUAL STATIC_LIBRARY OR ${a_type} STREQUAL EXECUTABLE)
 
-      set(COMPONENT_LIBRARIES "${COMPONENT_LIBRARIES};${a}")
+      if (${a_type} MATCHES .+_LIBRARY)
+        set(COMPONENT_LIBRARIES "${COMPONENT_LIBRARIES};${a}")
+      endif()
     endif()
   endforeach()
 
-  # set COMPONENT_LIBRARIES in top-level scope
-  set(COMPONENT_LIBRARIES "${COMPONENT_LIBRARIES}" PARENT_SCOPE)
-
   # Embedded binary & text files
   spaces2list(COMPONENT_EMBED_FILES)
   foreach(embed_src ${COMPONENT_EMBED_FILES})
@@ -157,4 +158,6 @@ function(components_finish_registration)
     target_add_binary_data(${component} "${embed_src}" TEXT)
   endforeach()
 
+  target_link_libraries(${CMAKE_PROJECT_NAME}.elf ${COMPONENT_LIBRARIES})
+
 endfunction(components_finish_registration)
index a9100b7db77e06604f77ecac55216ac3706662bc..d7f9bb2354d32601dfebe2743f303cd84583ca8e 100644 (file)
@@ -3,6 +3,7 @@
 include(crosstool_version_check)
 
 macro(idf_set_global_variables)
+  # Note that CONFIG_xxx is not available when this function is called
 
   set_default(EXTRA_COMPONENT_DIRS "")
 
@@ -18,6 +19,9 @@ macro(idf_set_global_variables)
 
   spaces2list(COMPONENTS)
 
+  # Tell cmake to drop executables in the top-level build dir
+  set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}")
+
 endmacro()
 
 # Add all the IDF global compiler & preprocessor options
@@ -76,27 +80,18 @@ function(idf_set_global_compiler_options)
 
 endfunction(idf_set_global_compiler_options)
 
-# Override add_executable to add IDF-specific
-# linker flags & map file to all built executables
-function(add_executable target)
-  get_filename_component(basename ${target} NAME_WE)
-  set(mapfile "${basename}.map")
-
-  _add_executable(${ARGV})
-
-  target_link_libraries(${target} "-Wl,--gc-sections -Wl,--cref -Wl,--Map=${mapfile} -Wl,--start-group")
-
-  set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/${mapfile}")
-endfunction(add_executable)
-
 
 # Verify the IDF environment is configured correctly (environment, toolchain, etc)
 function(idf_verify_environment)
 
+  if(NOT CMAKE_PROJECT_NAME)
+    message(FATAL_ERROR "Project top-level CMakeLists.txt file must call project() before including project.cmake")
+  endif()
+
   # Check toolchain is configured properly in cmake
   if(NOT ( ${CMAKE_SYSTEM_NAME} STREQUAL "Generic" AND ${CMAKE_C_COMPILER} MATCHES xtensa))
-    message(FATAL_ERROR "The parent project CMakeLists.txt file needs to set CMAKE_TOOLCHAIN_FILE "
-      "before including this file. "
+    message(FATAL_ERROR "Project top-level CMakeLists.txt file needs to set CMAKE_TOOLCHAIN_FILE "
+      "before including project.cmake.\n"
       "Update CMakeLists.txt to match the template project and delete CMakeCache.txt before "
       "re-running cmake.")
   endif()
@@ -108,3 +103,28 @@ function(idf_verify_environment)
   crosstool_version_check("1.22.0-80-g6c4433a")
 
 endfunction()
+
+# idf_add_executable
+#
+# Calls add_executable to add the final project executable
+# Adds .map & .bin file targets
+# Sets up flash-related targets
+function(idf_add_executable)
+  set(exe_target ${PROJECT_NAME}.elf)
+
+  spaces2list(${MAIN_SRCS})
+  add_executable(${exe_target} "${MAIN_SRCS}")
+
+  add_map_file(${exe_target})
+endfunction(idf_add_executable)
+
+
+# add_map_file
+#
+# Set linker args for 'exe_target' to generate a linker Map file
+function(add_map_file exe_target)
+  get_filename_component(basename ${exe_target} NAME_WE)
+  set(mapfile "${basename}.map")
+  target_link_libraries(${exe_target} "-Wl,--gc-sections -Wl,--cref -Wl,--Map=${mapfile} -Wl,--start-group")
+  set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/${mapfile}")
+endfunction(add_map_file)
index f45d7166d214e2567978a0ef9b94710e95cbc598..a37d6fd0c511308dd8b94cadbd3996752c3dae57 100644 (file)
@@ -50,17 +50,31 @@ add_definitions(-DIDF_VER=\"${GIT_REVISION}\")
 git_submodule_check("${IDF_PATH}")
 
 
+# Include any top-level project_include.cmake files from components
+foreach(component ${COMPONENT_PATHS})
+  include_if_exists("${component}/project_include.cmake")
+endforeach()
+
 #
-# Add components to the build
+# Add each component to the build as a library
 #
 foreach(component ${COMPONENT_PATHS})
   get_filename_component(component_name ${component} NAME)
   add_subdirectory(${component} ${component_name})
 endforeach()
 
+#
+# Add the app executable to the build (has name of PROJECT.elf)
+#
+idf_add_executable()
+
+#
+# Finish component registration (add cross-dependencies, make
+# executable dependent on all components.)
+#
 components_finish_registration()
 
-# Load the targets for the bootloader subproject
+# Define the external target to build the bootloader subproject
 if(NOT BOOTLOADER_BUILD)
   include(bootloader_subproject)
 endif()
index f7ffcabb0bc7111a5235241e8beb72554044eb21..045b884973414709ab51e8d66230ce9583e83ca5 100644 (file)
@@ -102,7 +102,7 @@ endfunction()
 # to a binary object as part of the build
 function(target_add_binary_data target embed_file embed_type)
 
-  get_filename_component(embed_file "${embed_file}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+  get_filename_component(embed_file "${embed_file}" ABSOLUTE)
 
   get_filename_component(name "${embed_file}" NAME)
   set(embed_srcfile "${CMAKE_BINARY_DIR}/${name}.c")
@@ -121,3 +121,8 @@ function(target_add_binary_data target embed_file embed_type)
   target_sources("${target}" PRIVATE "${embed_srcfile}")
 endfunction()
 
+macro(include_if_exists path)
+  if(EXISTS "${path}")
+    include("${path}")
+  endif()
+endmacro(include_if_exists)