From 8a001795286d374df24b439ad5fd4f74c91ad8cb Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 10 Oct 2022 14:19:03 +0200 Subject: [PATCH] cmake: Improved reproducibility rules Rewrite cmake rules for reproducibility and move them inside a separate module. The new rules are cleaner and can operate on multi-directory projects transparently. --- CMakeLists.txt | 38 ++------------------ cmake/ReproducibleBuild.cmake | 66 +++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 35 deletions(-) create mode 100644 cmake/ReproducibleBuild.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index d526860d3..06d1c3211 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.19) include(cmake/Utilities.cmake) include(cmake/GetGitRevisionDescription.cmake) +include(cmake/ReproducibleBuild.cmake) set(PROJECT_VERSION_SUFFIX "" @@ -236,39 +237,8 @@ list(TRANSFORM AVR_SOURCES PREPEND ${PRUSA_BOARDS_DIR}/cores/prusa_einsy_rambo/) # Target configuration # if(CMAKE_CROSSCOMPILING) - # Reproducible build support - function(set_reproducible_sources source_list prefix) - foreach(file IN LISTS ${source_list}) - get_filename_component(base ${file} NAME) - set(target "${prefix}${base}") - set_property( - SOURCE ${file} - APPEND - PROPERTY COMPILE_OPTIONS "-frandom-seed=${target}.o" - ) - endforeach() - endfunction() - - function(set_reproducible_target target) - set_target_properties(${target} PROPERTIES STATIC_LIBRARY_OPTIONS "-D") - endfunction() - - set_reproducible_sources(AVR_SOURCES "core/") - - add_link_options(-fdebug-prefix-map=${CMAKE_SOURCE_DIR}=) - add_link_options(-fdebug-prefix-map=${CMAKE_BINARY_DIR}=) - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "8") - add_compile_options(-ffile-prefix-map=${CMAKE_SOURCE_DIR}=) - endif() - # TODO: get date from the last git commit to set as epoch - set(ENV{SOURCE_DATE_EPOCH} 0) - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "8") - string(TIMESTAMP SOURCE_DATE_EPOCH "%Y-%m-%d") - add_compile_definitions(SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH}") - string(TIMESTAMP SOURCE_TIME_EPOCH "%H:%M:%S") - add_compile_definitions(SOURCE_TIME_EPOCH="${SOURCE_TIME_EPOCH}") - endif() + set_source_epoch(0) # default optimization flags set(CMAKE_CXX_FLAGS_DEBUG "-Og -g") @@ -318,6 +288,7 @@ set_target_properties(ALL_MULTILANG PROPERTIES EXCLUDE_FROM_ALL FALSE) function(add_base_binary variant_name) add_executable(${variant_name} ${FW_SOURCES} ${FW_HEADERS} ${VARIANT_CFG_DST}) set_target_properties(${variant_name} PROPERTIES EXCLUDE_FROM_ALL TRUE) + set_reproducible_target(${variant_name}) target_include_directories( ${variant_name} @@ -361,9 +332,6 @@ function(add_base_binary variant_name) endfunction() function(fw_add_variant variant_name) - # Set FW_SOURCES to be reproducible in this variant as it's set in a separate project - set_reproducible_sources(FW_SOURCES "Firmware/") - set(variant_header "variants/${variant_name}.h") string(REPLACE "1_75mm_" "" variant_name "${variant_name}") string(REPLACE "-E3Dv6full" "" variant_name "${variant_name}") diff --git a/cmake/ReproducibleBuild.cmake b/cmake/ReproducibleBuild.cmake new file mode 100644 index 000000000..bdc799513 --- /dev/null +++ b/cmake/ReproducibleBuild.cmake @@ -0,0 +1,66 @@ +# +# Functions and utilities for build reproducibility +# + +# Set a target to be reproducible +function(set_reproducible_target target) + # properties for static libraries + set_target_properties(${target} PROPERTIES STATIC_LIBRARY_OPTIONS "-D") + + # properties on executables + target_link_options(${target} PRIVATE -fdebug-prefix-map=${CMAKE_SOURCE_DIR}=) + target_link_options(${target} PRIVATE -fdebug-prefix-map=${CMAKE_BINARY_DIR}=) + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "8") + target_compile_options(${target} PRIVATE -ffile-prefix-map=${CMAKE_SOURCE_DIR}=) + endif() + + # properties on sources + get_target_property(sources ${target} SOURCES) + get_target_property(source_dir ${target} SOURCE_DIR) + foreach(file IN LISTS sources) + cmake_path(ABSOLUTE_PATH file BASE_DIRECTORY ${source_dir}) + cmake_path(RELATIVE_PATH file BASE_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE rpath) + set_property( + SOURCE ${file} + DIRECTORY ${source_dir} + APPEND + PROPERTY COMPILE_OPTIONS "-frandom-seed=${rpath}" + ) + endforeach() +endfunction() + +# Get the list of targets for all directories +function(get_all_targets _result _dir) + get_property( + _subdirs + DIRECTORY "${_dir}" + PROPERTY SUBDIRECTORIES + ) + foreach(_subdir IN LISTS _subdirs) + get_all_targets(${_result} "${_subdir}") + endforeach() + get_directory_property(_sub_targets DIRECTORY "${_dir}" BUILDSYSTEM_TARGETS) + set(${_result} + ${${_result}} ${_sub_targets} + PARENT_SCOPE + ) +endfunction() + +# Make every target reproducible +function(set_all_targets_reproducible) + get_all_targets(targets ${CMAKE_SOURCE_DIR}) + foreach(target IN LISTS targets) + set_reproducible_target(${target}) + endforeach() +endfunction() + +# Set source epoch +function(set_source_epoch epoch) + set(ENV{SOURCE_DATE_EPOCH} ${epoch}) + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "8") + string(TIMESTAMP SOURCE_DATE_EPOCH "%Y-%m-%d") + add_compile_definitions(SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH}") + string(TIMESTAMP SOURCE_TIME_EPOCH "%H:%M:%S") + add_compile_definitions(SOURCE_TIME_EPOCH="${SOURCE_TIME_EPOCH}") + endif() +endfunction()