[education/rkward] rkward/rbackend/rpackages: Use elaborate solution from ECM for detecting GNU tar, and coercing it to create reproducible archives.

Thomas Friedrichsmeier null at kde.org
Mon Mar 28 21:10:28 BST 2022


Git commit 834e8ebbb15ae97fd5b956fffd2cfbae4574daa7 by Thomas Friedrichsmeier.
Committed on 28/03/2022 at 20:08.
Pushed by tfry into branch 'master'.

Use elaborate solution from ECM for detecting GNU tar, and coercing it to create reproducible archives.

M  +46   -6    rkward/rbackend/rpackages/CMakeLists.txt
D  +-    --    rkward/rbackend/rpackages/rkward_0.7.3.tar.gz

https://invent.kde.org/education/rkward/commit/834e8ebbb15ae97fd5b956fffd2cfbae4574daa7

diff --git a/rkward/rbackend/rpackages/CMakeLists.txt b/rkward/rbackend/rpackages/CMakeLists.txt
index fd4921ba..3f9fc857 100644
--- a/rkward/rbackend/rpackages/CMakeLists.txt
+++ b/rkward/rbackend/rpackages/CMakeLists.txt
@@ -1,17 +1,57 @@
+# Ok, so this seems a bit ove the top, and I hope we'll find an easier solution one of those days:
+# During build, we package the support R package sources, so they can be installed in whatever R backend will be used at runtime.
+# However, that breaks reproducible builds, as timestamps and owner info enter the tar. Those can be stripped with some extra options,
+# but _only_ in GNU tar...
+#
+# The elaborate code below was taken from Extra CMake Modules / KDEPackageAppTemplates.cmake, where the same problem is faced.
+find_program(_tar_executable NAMES gtar tar)
+if(_tar_executable)
+	execute_process(
+		COMMAND ${_tar_executable} --sort=name --version
+		TIMEOUT 3
+		RESULT_VARIABLE _tar_exit
+		OUTPUT_VARIABLE _tar_version
+		ERROR_VARIABLE _tar_stderr
+	)
+	if("${_tar_exit}" EQUAL 0 AND "${_tar_version}" MATCHES "GNU tar")
+		set(GNU_TAR_FOUND ON)
+	else()
+		set(GNU_TAR_FOUND OFF)
+	endif()
+else()
+	set(GNU_TAR_FOUND OFF)
+endif()
+
+
 MACRO(createRpackage name)
 	FILE(GLOB_RECURSE rkwardfiles${name} LIST_DIRECTORIES true CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${name}/*")
-	IF(UNIX AND (${CMAKE_SYSTEM_NAME} STREQUAL "Linux"))
-		# For reproducible builds, avoid getting user name/id into the tar. Works with GNU tar, only, unfortunately.
-		ADD_CUSTOM_COMMAND(OUTPUT ${name}.tgz
-			COMMAND tar "cfz" "${CMAKE_CURRENT_BINARY_DIR}/${name}.tgz" "--owner=0" "--group=0" "--numeric-owner" "${name}"
+        if(GNU_TAR_FOUND)
+		# Honour SOURCE_DATE_EPOCH if set
+		if(DEFINED ENV{SOURCE_DATE_EPOCH})
+			set(TIMESTAMP $ENV{SOURCE_DATE_EPOCH})
+		else()
+		execute_process(
+			COMMAND "date" "+%s"
+			OUTPUT_VARIABLE TIMESTAMP
+			OUTPUT_STRIP_TRAILING_WHITESPACE)
+		endif()
+
+		# Make tar archive reproducible, the arguments are only available with GNU tar
+		add_custom_command(OUTPUT ${name}.tgz
+			COMMAND ${_tar_executable} ARGS
+			cfz "${CMAKE_CURRENT_BINARY_DIR}/${name}.tgz" "${name}"
+			--sort=name
+			--numeric-owner --owner=0 --group=0
+			--mtime="@${TIMESTAMP}"
+			--pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime
 			WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
 			DEPENDS ${rkwardfiles${name}})
-	ELSE(UNIX AND (${CMAKE_SYSTEM_NAME} STREQUAL "Linux"))
+	ELSE(GNU_TAR_FOUND)
 		ADD_CUSTOM_COMMAND(OUTPUT ${name}.tgz
 			COMMAND ${CMAKE_COMMAND} -E tar "cfz" "${CMAKE_CURRENT_BINARY_DIR}/${name}.tgz" "${name}"
 			WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
 			DEPENDS ${rkwardfiles${name}})
-	ENDIF(UNIX AND (${CMAKE_SYSTEM_NAME} STREQUAL "Linux"))
+	ENDIF(GNU_TAR_FOUND)
 ENDMACRO()
 
 createRpackage(rkward)
diff --git a/rkward/rbackend/rpackages/rkward_0.7.3.tar.gz b/rkward/rbackend/rpackages/rkward_0.7.3.tar.gz
deleted file mode 100644
index 0cff173c..00000000
Binary files a/rkward/rbackend/rpackages/rkward_0.7.3.tar.gz and /dev/null differ


More information about the rkward-tracker mailing list