From b49a657448be0baa98dda854af3e6c3398bd8036 Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Wed, 27 Nov 2019 19:01:40 +0800 Subject: [PATCH] build: Add CONFIG_APP_PROJECT_VER to set the project version from Kconfig --- components/app_update/CMakeLists.txt | 7 ++ components/app_update/Kconfig.projbuild | 14 ++++ components/app_update/component.mk | 82 +++++++++---------- docs/en/api-guides/build-system-legacy.rst | 3 +- docs/en/api-guides/build-system.rst | 3 +- docs/en/api-reference/system/system.rst | 2 +- examples/system/ota/README.md | 9 +- tools/ci/test_build_system.sh | 16 ++++ tools/ci/test_build_system_cmake.sh | 19 ++++- tools/cmake/project.cmake | 1 - .../GetGitRevisionDescription.cmake.in | 29 ++++--- 11 files changed, 123 insertions(+), 62 deletions(-) diff --git a/components/app_update/CMakeLists.txt b/components/app_update/CMakeLists.txt index 9fa866e59..fbf57688e 100644 --- a/components/app_update/CMakeLists.txt +++ b/components/app_update/CMakeLists.txt @@ -7,11 +7,18 @@ idf_component_register(SRCS "esp_ota_ops.c" # linker will ignore this structure as it has no other files depending on it. target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_app_desc") +if(CONFIG_APP_PROJECT_VER_FROM_CONFIG) + # Ignore current PROJECT_VER (which was set in __project_get_revision()). + # Gets the version from the CONFIG_APP_PROJECT_VER. + idf_build_set_property(PROJECT_VER "${CONFIG_APP_PROJECT_VER}") +endif() + # cut PROJECT_VER and PROJECT_NAME to required 32 characters. idf_build_get_property(project_ver PROJECT_VER) idf_build_get_property(project_name PROJECT_NAME) string(SUBSTRING "${project_ver}" 0 31 PROJECT_VER_CUT) string(SUBSTRING "${project_name}" 0 31 PROJECT_NAME_CUT) +message(STATUS "App \"${PROJECT_NAME_CUT}\" version: ${PROJECT_VER_CUT}") set_source_files_properties( SOURCE "esp_app_desc.c" diff --git a/components/app_update/Kconfig.projbuild b/components/app_update/Kconfig.projbuild index 2c77c8ae2..4c0e9c345 100644 --- a/components/app_update/Kconfig.projbuild +++ b/components/app_update/Kconfig.projbuild @@ -22,4 +22,18 @@ menu "Application manager" The PROJECT_NAME variable from the build system will not affect the firmware image. This value will not be contained in the esp_app_desc structure. + config APP_PROJECT_VER_FROM_CONFIG + bool "Get the project version from Kconfig" + default n + help + If this is enabled, then config item APP_PROJECT_VER will be used for the variable PROJECT_VER. + Other ways to set PROJECT_VER will be ignored. + + config APP_PROJECT_VER + string "Project version" + default "1" + depends on APP_PROJECT_VER_FROM_CONFIG + help + Project version + endmenu # "Application manager" diff --git a/components/app_update/component.mk b/components/app_update/component.mk index 3914d42fd..23470d575 100644 --- a/components/app_update/component.mk +++ b/components/app_update/component.mk @@ -8,49 +8,49 @@ COMPONENT_ADD_LDFLAGS += -u esp_app_desc ifndef IS_BOOTLOADER_BUILD -GET_PROJECT_VER ?= -ifeq ("${PROJECT_VER}", "") -ifeq ("$(wildcard ${PROJECT_PATH}/version.txt)","") + # If ``CONFIG_APP_PROJECT_VER_FROM_CONFIG`` option is set, the value of ``CONFIG_APP_PROJECT_VER`` will be used + # Else, if ``PROJECT_VER`` variable set in project Makefile file, its value will be used. + # Else, if the ``$PROJECT_PATH/version.txt`` exists, its contents will be used as ``PROJECT_VER``. + # Else, if the project is located inside a Git repository, the output of git describe will be used. + # Otherwise, ``PROJECT_VER`` will be "1". + ifdef CONFIG_APP_PROJECT_VER_FROM_CONFIG + PROJECT_VER:= $(CONFIG_APP_PROJECT_VER) + else + ifneq ("${PROJECT_VER}", "") + PROJECT_VER:= $(PROJECT_VER) + else + ifneq ("$(wildcard ${PROJECT_PATH}/version.txt)","") + PROJECT_VER := $(shell cat ${PROJECT_PATH}/version.txt) + else + GIT_PROJECT_VER := $(shell cd ${PROJECT_PATH} && git describe --always --tags --dirty 2> /dev/null) + ifeq ("${GIT_PROJECT_VER}", "") + PROJECT_VER := "1" + $(info Project is not inside a git repository, or git repository has no commits) + $(info will not use 'git describe' to determine PROJECT_VER.) + else + PROJECT_VER:= $(GIT_PROJECT_VER) + endif # a git repository + endif # version.txt + endif # PROJECT_VER + endif # CONFIG_APP_PROJECT_VER_FROM_CONFIG -GET_PROJECT_VER := $(shell cd ${PROJECT_PATH} && git describe --always --tags --dirty 2> /dev/null) -ifeq ("${GET_PROJECT_VER}", "") -GET_PROJECT_VER := "1" -$(info Project is not inside a git repository, will not use 'git describe' to determine PROJECT_VER.) -endif + # cut PROJECT_VER and PROJECT_NAME to required 32 characters. + PROJECT_VER_CUT := $(shell echo "$(PROJECT_VER)" | cut -c 1-31) + PROJECT_NAME_CUT := $(shell echo "$(PROJECT_NAME)" | cut -c 1-31) -else -# read from version.txt -GET_PROJECT_VER := $(shell cat ${PROJECT_PATH}/version.txt) -endif -endif -# If ``PROJECT_VER`` variable set in project Makefile file, its value will be used. -# Else, if the ``$PROJECT_PATH/version.txt`` exists, its contents will be used as ``PROJECT_VER``. -# Else, if the project is located inside a Git repository, the output of git describe will be used. -# Otherwise, ``PROJECT_VER`` will be "1". + $(info App "$(PROJECT_NAME_CUT)" version: $(PROJECT_VER_CUT)) -ifeq ("${PROJECT_VER}", "") -PROJECT_VER:= $(GET_PROJECT_VER) -else -PROJECT_VER:= $(PROJECT_VER) -endif + NEW_DEFINES:= "$(PROJECT_VER_CUT) $(PROJECT_NAME_CUT) $(IDF_VER)" + ifeq ("$(wildcard ${TMP_DEFINES})","") + OLD_DEFINES:= "" + else + OLD_DEFINES:= "$(shell cat $(TMP_DEFINES))" + endif -# cut PROJECT_VER and PROJECT_NAME to required 32 characters. -PROJECT_VER_CUT := $(shell echo "$(PROJECT_VER)" | cut -c 1-31) -PROJECT_NAME_CUT := $(shell echo "$(PROJECT_NAME)" | cut -c 1-31) + # If NEW_DEFINES (PROJECT_VER, PROJECT_NAME) were changed then rebuild only esp_app_desc. + ifneq (${NEW_DEFINES}, ${OLD_DEFINES}) + $(shell echo $(NEW_DEFINES) > $(TMP_DEFINES); rm -f esp_app_desc.o;) + endif -$(info App "$(PROJECT_NAME_CUT)" version: $(PROJECT_VER_CUT)) - -NEW_DEFINES:= "$(PROJECT_VER_CUT) $(PROJECT_NAME_CUT) $(IDF_VER)" -ifeq ("$(wildcard ${TMP_DEFINES})","") -OLD_DEFINES:= "" -else -OLD_DEFINES:= "$(shell cat $(TMP_DEFINES))" -endif - -# If NEW_DEFINES (PROJECT_VER, PROJECT_NAME) were changed then rebuild only esp_app_desc. -ifneq (${NEW_DEFINES}, ${OLD_DEFINES}) -$(shell echo $(NEW_DEFINES) > $(TMP_DEFINES); rm -f esp_app_desc.o;) -endif - -esp_app_desc.o: CPPFLAGS += -D PROJECT_VER=\""$(PROJECT_VER_CUT)"\" -D PROJECT_NAME=\""$(PROJECT_NAME_CUT)"\" -endif + esp_app_desc.o: CPPFLAGS += -D PROJECT_VER=\""$(PROJECT_VER_CUT)"\" -D PROJECT_NAME=\""$(PROJECT_NAME_CUT)"\" +endif # IS_BOOTLOADER_BUILD diff --git a/docs/en/api-guides/build-system-legacy.rst b/docs/en/api-guides/build-system-legacy.rst index 19c1ad3ee..b1ab9eb14 100644 --- a/docs/en/api-guides/build-system-legacy.rst +++ b/docs/en/api-guides/build-system-legacy.rst @@ -193,7 +193,8 @@ The following variables are set at the project level, but exported for use in th - ``IDF_VERSION_MAJOR``, ``IDF_VERSION_MINOR``, ``IDF_VERSION_PATCH``: Components of ESP-IDF version, to be used in conditional expressions. Note that this information is less precise than that provided by ``IDF_VER`` variable. ``v4.0-dev-*``, ``v4.0-beta1``, ``v4.0-rc1`` and ``v4.0`` will all have the same values of ``ESP_IDF_VERSION_*`` variables, but different ``IDF_VER`` values. - ``PROJECT_VER``: Project version. - * If ``PROJECT_VER`` variable is set in project Makefile file, its value will be used. + * If :ref:`CONFIG_APP_PROJECT_VER_FROM_CONFIG` option is set, the value of :ref:`CONFIG_APP_PROJECT_VER` will be used. + * Else, if ``PROJECT_VER`` variable is set in project Makefile file, its value will be used. * Else, if the ``$PROJECT_PATH/version.txt`` exists, its contents will be used as ``PROJECT_VER``. * Else, if the project is located inside a Git repository, the output of git describe will be used. * Otherwise, ``PROJECT_VER`` will be "1". diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index de2a6479f..fbb71b317 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -368,7 +368,8 @@ from the component CMakeLists.txt: - ``IDF_TARGET``: Name of the target for which the project is being built. - ``PROJECT_VER``: Project version. - * If ``PROJECT_VER`` variable is set in project CMakeLists.txt file, its value will be used. + * If :ref:`CONFIG_APP_PROJECT_VER_FROM_CONFIG` option is set, the value of :ref:`CONFIG_APP_PROJECT_VER` will be used. + * Else, if ``PROJECT_VER`` variable is set in project CMakeLists.txt file, its value will be used. * Else, if the ``PROJECT_DIR/version.txt`` exists, its contents will be used as ``PROJECT_VER``. * Else, if the project is located inside a Git repository, the output of git describe will be used. * Otherwise, ``PROJECT_VER`` will be "1". diff --git a/docs/en/api-reference/system/system.rst b/docs/en/api-reference/system/system.rst index 47b036686..52888a5bc 100644 --- a/docs/en/api-reference/system/system.rst +++ b/docs/en/api-reference/system/system.rst @@ -155,7 +155,7 @@ To set version in your project manually you need to set ``PROJECT_VER`` variable (For legacy GNU Make build system: in application Makefile put ``PROJECT_VER = "0.1.0.1"`` before including ``project.mk``.) -If ``PROJECT_VER`` variable is not set in the project then it will be retrieved from either ``$(PROJECT_PATH)/version.txt`` file (if present) else using git command ``git describe``. If neither is available then ``PROJECT_VER`` will be set to "1". Application can make use of this by calling :cpp:func:`esp_ota_get_app_description` or :cpp:func:`esp_ota_get_partition_description` functions. +If :ref:`CONFIG_APP_PROJECT_VER_FROM_CONFIG` option is set, the value of :ref:`CONFIG_APP_PROJECT_VER` will be used. Otherwise if ``PROJECT_VER`` variable is not set in the project then it will be retrieved from either ``$(PROJECT_PATH)/version.txt`` file (if present) else using git command ``git describe``. If neither is available then ``PROJECT_VER`` will be set to "1". Application can make use of this by calling :cpp:func:`esp_ota_get_app_description` or :cpp:func:`esp_ota_get_partition_description` functions. diff --git a/examples/system/ota/README.md b/examples/system/ota/README.md index 0baf9d048..0215a9a9e 100644 --- a/examples/system/ota/README.md +++ b/examples/system/ota/README.md @@ -109,10 +109,11 @@ If GPIO is not pulled low then the operable of the app will be confirmed. For ``native_ota_example``, code has been added to demonstrate how to check the version of the application and prevent infinite firmware updates. Only the application with the new version can be downloaded. Version checking is performed after the very first firmware image package has been received, which contains data about the firmware version. The application version can be taken from three places: -1. If ``PROJECT_VER`` variable set in project Cmake/Makefile file, its value will be used. -2. Else, if the ``$PROJECT_PATH/version.txt`` exists, its contents will be used as ``PROJECT_VER``. -3. Else, if the project is located inside a Git repository, the output of ``git describe`` will be used. -4. Otherwise, ``PROJECT_VER`` will be "1". +1. If `CONFIG_APP_PROJECT_VER_FROM_CONFIG` option is set, the value of `CONFIG_APP_PROJECT_VER` will be used. +2. Else, if ``PROJECT_VER`` variable set in project Cmake/Makefile file, its value will be used. +3. Else, if the ``$PROJECT_PATH/version.txt`` exists, its contents will be used as ``PROJECT_VER``. +4. Else, if the project is located inside a Git repository, the output of ``git describe`` will be used. +5. Otherwise, ``PROJECT_VER`` will be "1". In ``native_ota_example``, ``$PROJECT_PATH/version.txt`` is used to define the version of app. Change the version in the file to compile the new firmware. diff --git a/tools/ci/test_build_system.sh b/tools/ci/test_build_system.sh index 7851bfcc7..ebe459dd5 100755 --- a/tools/ci/test_build_system.sh +++ b/tools/ci/test_build_system.sh @@ -265,6 +265,22 @@ function run_tests() version+=$(git describe --always --tags --dirty) grep "${version}" log.log || failure "Project version should have a hash commit" + print_status "Get the version of app from Kconfig option" + make clean > /dev/null + rm -f sdkconfig.defaults + rm -f sdkconfig + echo "project_version_from_txt" > ${TESTDIR}/template/version.txt + echo "CONFIG_APP_PROJECT_VER_FROM_CONFIG=y" >> sdkconfig.defaults + echo 'CONFIG_APP_PROJECT_VER="project_version_from_Kconfig"' >> sdkconfig.defaults + make defconfig > /dev/null + make >> log.log || failure "Failed to build" + version="App \"app-template\" version: " + version+="project_version_from_Kconfig" + grep "${version}" log.log || failure "Project version should be from Kconfig" + rm -f sdkconfig.defaults + rm -f sdkconfig + rm -f ${TESTDIR}/template/version.txt + print_status "Build fails if partitions don't fit in flash" sed -i.bak "s/CONFIG_ESPTOOLPY_FLASHSIZE.\+//" sdkconfig # remove all flashsize config echo "CONFIG_ESPTOOLPY_FLASHSIZE_1MB=y" >> sdkconfig # introduce undersize flash diff --git a/tools/ci/test_build_system_cmake.sh b/tools/ci/test_build_system_cmake.sh index f22446d75..71e549722 100755 --- a/tools/ci/test_build_system_cmake.sh +++ b/tools/ci/test_build_system_cmake.sh @@ -120,10 +120,25 @@ function run_tests() print_status "Get the version of app from git describe. Project is not inside IDF and do not have a tag only a hash commit." idf.py reconfigure >> log.log || failure "Failed to build" - version="Project version: " + version="App \"app-template\" version: " version+=$(git describe --always --tags --dirty) grep "${version}" log.log || failure "Project version should have a hash commit" + print_status "Get the version of app from Kconfig option" + idf.py clean > /dev/null + rm -f sdkconfig.defaults + rm -f sdkconfig + echo "project_version_from_txt" > ${TESTDIR}/template/version.txt + echo "CONFIG_APP_PROJECT_VER_FROM_CONFIG=y" >> sdkconfig.defaults + echo 'CONFIG_APP_PROJECT_VER="project_version_from_Kconfig"' >> sdkconfig.defaults + idf.py build >> log.log || failure "Failed to build" + version="App \"app-template\" version: " + version+="project_version_from_Kconfig" + grep "${version}" log.log || failure "Project version should be from Kconfig" + rm -f sdkconfig.defaults + rm -f sdkconfig + rm -f ${TESTDIR}/template/version.txt + print_status "Moving BUILD_DIR_BASE out of tree" clean_build_dir OUTOFTREE_BUILD=${TESTDIR}/alt_build @@ -555,7 +570,7 @@ endmenu\n" >> ${IDF_PATH}/Kconfig clean_build_dir git branch test_build_system git worktree add ../esp-idf-template-test test_build_system - diff <(idf.py reconfigure | grep "Project version") <(cd ../esp-idf-template-test && idf.py reconfigure | grep "Project version") \ + diff <(idf.py reconfigure | grep "App \"app-template\" version: ") <(cd ../esp-idf-template-test && idf.py reconfigure | grep "App \"app-template\" version: ") \ || failure "Version on worktree should have been properly resolved" git worktree remove ../esp-idf-template-test diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake index 78d7ae30e..a97382788 100644 --- a/tools/cmake/project.cmake +++ b/tools/cmake/project.cmake @@ -55,7 +55,6 @@ function(__project_get_revision var) endif() endif() endif() - message(STATUS "Project version: ${PROJECT_VER}") set(${var} "${PROJECT_VER}" PARENT_SCOPE) endfunction() diff --git a/tools/cmake/third_party/GetGitRevisionDescription.cmake.in b/tools/cmake/third_party/GetGitRevisionDescription.cmake.in index 0cf025b14..41cf7ed5f 100644 --- a/tools/cmake/third_party/GetGitRevisionDescription.cmake.in +++ b/tools/cmake/third_party/GetGitRevisionDescription.cmake.in @@ -18,23 +18,30 @@ set(HEAD_HASH) file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) +set(GIT_DIR "@GIT_DIR@") +# handle git-worktree +if(EXISTS "${GIT_DIR}/commondir") + file(READ "${GIT_DIR}/commondir" GIT_DIR_NEW LIMIT 1024) + string(STRIP "${GIT_DIR_NEW}" GIT_DIR_NEW) + if(NOT IS_ABSOLUTE "${GIT_DIR_NEW}") + get_filename_component(GIT_DIR_NEW ${GIT_DIR}/${GIT_DIR_NEW} ABSOLUTE) + endif() + if(EXISTS "${GIT_DIR_NEW}") + set(GIT_DIR "${GIT_DIR_NEW}") + endif() +endif() if(HEAD_CONTENTS MATCHES "ref") # named branch string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") - if(EXISTS "@GIT_DIR@/${HEAD_REF}") - configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) - else() - if(EXISTS "@GIT_DIR@/packed-refs") - configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) - file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) - if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") - set(HEAD_HASH "${CMAKE_MATCH_1}") - endif() - endif() + if(EXISTS "${GIT_DIR}/${HEAD_REF}") + configure_file("${GIT_DIR}/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) + elseif(EXISTS "${GIT_DIR}/logs/${HEAD_REF}") + configure_file("${GIT_DIR}/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) + set(HEAD_HASH "${HEAD_REF}") endif() else() # detached HEAD - configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) + configure_file("${GIT_DIR}/HEAD" "@GIT_DATA@/head-ref" COPYONLY) endif() if(NOT HEAD_HASH)