From 9919b75ec1ecf203b54d3d057e8332d2ea60245c Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Sat, 9 Oct 2021 15:42:14 +0800 Subject: [PATCH] build: add CONFIG_APP_REPRODUCIBLE_BUILD menuconfig option to produce reproducible binaries --- .gitlab/ci/host-test.yml | 17 ++++++++++++ .gitlab/ci/rules.yml | 2 ++ CMakeLists.txt | 8 +++++- Kconfig | 7 +++++ components/app_update/esp_app_desc.c | 2 +- .../bootloader_support/src/bootloader_init.c | 2 ++ tools/ci/executable-list.txt | 1 + tools/ci/test_reproducible_build.sh | 26 +++++++++++++++++++ 8 files changed, 63 insertions(+), 2 deletions(-) create mode 100755 tools/ci/test_reproducible_build.sh diff --git a/.gitlab/ci/host-test.yml b/.gitlab/ci/host-test.yml index 87d8c2c12b..f840160d86 100644 --- a/.gitlab/ci/host-test.yml +++ b/.gitlab/ci/host-test.yml @@ -64,6 +64,23 @@ test_ldgen_on_host: variables: LC_ALL: C.UTF-8 +test_reproducible_build: + extends: .host_test_template + script: + - ./tools/ci/test_reproducible_build.sh + artifacts: + when: on_failure + paths: + - "**/sdkconfig" + - "**/build*/*.bin" + - "**/build*/*.elf" + - "**/build*/*.map" + - "**/build*/flasher_args.json" + - "**/build*/*.bin" + - "**/build*/bootloader/*.bin" + - "**/build*/partition_table/*.bin" + expire_in: 1 week + .host_fuzzer_test_template: extends: - .host_test_template diff --git a/.gitlab/ci/rules.yml b/.gitlab/ci/rules.yml index 47f6b138cc..95da115cda 100644 --- a/.gitlab/ci/rules.yml +++ b/.gitlab/ci/rules.yml @@ -131,6 +131,8 @@ - "tools/detect_python.sh" - "tools/detect_python.fish" + - "tools/ci/test_reproducible_build.sh" + .patterns-windows: &patterns-windows - "tools/windows/**/*" diff --git a/CMakeLists.txt b/CMakeLists.txt index 4be17e206d..c39d22a1ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,7 +147,13 @@ endif() if(NOT ${CMAKE_C_COMPILER_VERSION} VERSION_LESS 8.0.0) if(CONFIG_COMPILER_HIDE_PATHS_MACROS) list(APPEND compile_options "-fmacro-prefix-map=${CMAKE_SOURCE_DIR}=.") - list(APPEND compile_options "-fmacro-prefix-map=${IDF_PATH}=IDF") + list(APPEND compile_options "-fmacro-prefix-map=${IDF_PATH}=/IDF") + endif() + + if(CONFIG_APP_REPRODUCIBLE_BUILD) + list(APPEND compile_options "-fdebug-prefix-map=${IDF_PATH}=/IDF") + list(APPEND compile_options "-fdebug-prefix-map=${PROJECT_DIR}=/IDF_PROJECT") + list(APPEND compile_options "-fdebug-prefix-map=${BUILD_DIR}=/IDF_BUILD") endif() endif() diff --git a/Kconfig b/Kconfig index 928d274106..92e94cfa4a 100644 --- a/Kconfig +++ b/Kconfig @@ -201,6 +201,13 @@ mainmenu "Espressif IoT Development Framework Configuration" config APP_BUILD_USE_FLASH_SECTIONS bool # Whether to place code/data into memory-mapped flash sections + config APP_REPRODUCIBLE_BUILD + bool "Enable reproducible build" + default n + select COMPILER_HIDE_PATHS_MACROS + help + If enabled, all date, time, and path information would be eliminated. + endmenu # Build type source "$COMPONENT_KCONFIGS_PROJBUILD_SOURCE_FILE" diff --git a/components/app_update/esp_app_desc.c b/components/app_update/esp_app_desc.c index e0fdfd6418..ae3325b1c3 100644 --- a/components/app_update/esp_app_desc.c +++ b/components/app_update/esp_app_desc.c @@ -32,7 +32,7 @@ const __attribute__((section(".rodata_desc"))) esp_app_desc_t esp_app_desc = { .secure_version = 0, #endif -#ifdef CONFIG_APP_COMPILE_TIME_DATE +#if defined(CONFIG_APP_COMPILE_TIME_DATE) && !defined(CONFIG_APP_REPRODUCIBLE_BUILD) .time = __TIME__, .date = __DATE__, #else diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index 1d73f5dc26..41538bce85 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -91,5 +91,7 @@ void bootloader_enable_random(void) void bootloader_print_banner(void) { ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER); +#ifndef CONFIG_APP_REPRODUCIBLE_BUILD ESP_LOGI(TAG, "compile time " __TIME__); +#endif } diff --git a/tools/ci/executable-list.txt b/tools/ci/executable-list.txt index c7bec63629..f85404e5be 100644 --- a/tools/ci/executable-list.txt +++ b/tools/ci/executable-list.txt @@ -67,6 +67,7 @@ tools/ci/test_build_system.sh tools/ci/test_build_system_cmake.sh tools/ci/test_check_kconfigs.py tools/ci/test_configure_ci_environment.sh +tools/ci/test_reproducible_build.sh tools/cmake/convert_to_cmake.py tools/docker/entrypoint.sh tools/docker/hooks/build diff --git a/tools/ci/test_reproducible_build.sh b/tools/ci/test_reproducible_build.sh new file mode 100755 index 0000000000..6cd6c66bd2 --- /dev/null +++ b/tools/ci/test_reproducible_build.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -euo + +for path in \ + "examples/get-started/hello_world" \ + "examples/bluetooth/nimble/blecent"; do + cd "${IDF_PATH}/${path}" + + echo "CONFIG_APP_REPRODUCIBLE_BUILD=y" >>sdkconfig.defaults + rm -f sdkconfig + + idf.py -B build_first fullclean build + idf.py -B build_second fullclean build + + for item in \ + "partition_table/partition-table.bin" \ + "bootloader/bootloader.bin" \ + "bootloader/bootloader.elf" \ + "bootloader/bootloader.map" \ + "*.bin" \ + "*.elf" \ + "*.map"; do + diff -s build_first/${item} build_second/${item} # use glob, don't use double quotes + done +done