Prechádzať zdrojové kódy

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.
Yuri D'Elia 2 rokov pred
rodič
commit
8a00179528
2 zmenil súbory, kde vykonal 69 pridanie a 35 odobranie
  1. 3 35
      CMakeLists.txt
  2. 66 0
      cmake/ReproducibleBuild.cmake

+ 3 - 35
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
     "<auto>"
@@ -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}")

+ 66 - 0
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()