Skip to content

Commit f0178c4

Browse files
author
Axel Heider
committed
cmake: Improve CPIO creation
- improve maintainability with explicit helper files - sanitize intermediate file names - improve comments - support using a directory in output name also Signed-off-by: Axel Heider <[email protected]>
1 parent cde7502 commit f0178c4

File tree

1 file changed

+78
-34
lines changed

1 file changed

+78
-34
lines changed

cmake-tool/helpers/cpio.cmake

+78-34
Original file line numberDiff line numberDiff line change
@@ -39,57 +39,101 @@ function(MakeCPIO output_name input_files)
3939
if(NOT "${MAKE_CPIO_UNPARSED_ARGUMENTS}" STREQUAL "")
4040
message(FATAL_ERROR "Unknown arguments to MakeCPIO")
4141
endif()
42+
4243
set(archive_symbol "_cpio_archive")
4344
if(NOT "${MAKE_CPIO_CPIO_SYMBOL}" STREQUAL "")
4445
set(archive_symbol ${MAKE_CPIO_CPIO_SYMBOL})
4546
endif()
4647

47-
# intermediate files
48-
set(cpio_archive "archive.${output_name}.cpio")
49-
set(cpio_archive_s "${output_name}.S")
48+
set(cpio_archive "${output_name}.cpio")
49+
50+
# CMake wants absolute paths when calling file(WRITE ...)
51+
get_filename_component(
52+
output_name_abs
53+
"${output_name}"
54+
ABSOLUTE
55+
BASE_DIR
56+
"${CMAKE_CURRENT_BINARY_DIR}"
57+
)
5058

51-
# Check that the reproducible flag is available. Don't use it if it isn't.
59+
# Create a script that prepares CPIO archive contents in a tmp folder and
60+
# then builds the archive. Some cpio versions support the paramter
61+
# "--reproducible" to create the archive with consistent inodes and device
62+
# numbering. In addition, we set each file's the 'modified time' to the
63+
# epoch (ie 0, but simply using 'touch -d @0' is a GNU extension of the
64+
# POSIX standard), and the user/group values to 0:0.
65+
# Since some application access the archive contents by index and not by
66+
# name, the files must be put into the archive in exactly the same order as
67+
# they are listen in 'input_files'. Using simply "ls | cpio ...." instead of
68+
# "printf '%s\\n' \${@##*/} | cpio ..." does not guarantee preserving the
69+
# order.
5270
CheckCPIOArgument(cpio_reproducible_flag "--reproducible")
53-
set(
54-
cpio_cmd
55-
"cpio ${cpio_reproducible_flag} --quiet --create --format=newc --file=${CMAKE_CURRENT_BINARY_DIR}/${cpio_archive}"
71+
set(cpio_archive_creator "${output_name_abs}.sh")
72+
file(
73+
WRITE
74+
"${cpio_archive_creator}"
75+
# content
76+
"#!/bin/sh\n"
77+
"# auto-generated file from MakeCPIO(), do not edit\n"
78+
"set -e\n"
79+
"TMP_DIR=${cpio_archive}.files\n"
80+
"mkdir -p \${TMP_DIR}\n"
81+
"cp -a \"$@\" \${TMP_DIR}/\n"
82+
"touch -d 1970-01-01T00:00:00Z \${TMP_DIR}/*\n"
83+
"(\n"
84+
" cd \${TMP_DIR}\n"
85+
" printf '%s\\n' \${@##*/} | cpio ${cpio_reproducible_flag} --quiet --create --format=newc --owner=+0:+0\n"
86+
") > ${cpio_archive}\n"
87+
"rm -rf \${TMP_DIR}\n"
5688
)
5789

58-
set(tmp_dir "temp_${output_name}")
59-
set(commands "bash;-c;${cpio_cmd};&&")
60-
foreach(file IN LISTS input_files)
61-
# Try and generate reproducible cpio meta-data as we do this:
62-
# - touch -d @0 file sets the modified time to 0
63-
# - --owner=root:root sets user and group values to 0:0
64-
# - --reproducible creates reproducible archives with consistent inodes and device numbering
65-
list(
66-
APPEND
67-
commands
68-
"bash;-c; mkdir -p ${tmp_dir} && cd ${tmp_dir} && cp -a ${file} . && touch -d 1970-01-01T00:00:00Z `basename ${file}` && echo `basename ${file}` | ${cpio_cmd} --append --owner=+0:+0 && rm `basename ${file}` && cd ../ && rmdir ${tmp_dir};&&"
69-
)
70-
endforeach()
71-
list(APPEND commands "true")
90+
# Create a "program" that makes the compiler generate and object file that
91+
# contains the cpio archive.
92+
# CMake wants the absolute name when creating files
93+
set(cpio_archive_s "${output_name_abs}.S")
94+
file(
95+
WRITE
96+
"${cpio_archive_s}"
97+
# content
98+
"# auto-generated file from MakeCPIO(), do not edit\n"
99+
".section ._archive_cpio, \"aw\"\n"
100+
".globl ${archive_symbol}, ${archive_symbol}_end\n"
101+
"${archive_symbol}:\n"
102+
".incbin \"${cpio_archive}\"\n"
103+
"${archive_symbol}_end:\n"
104+
)
105+
106+
# Re-run CMake configuration in case 'cpio_archive_creator' or
107+
# 'cpio_archive_s' is deleted.
108+
set_property(
109+
DIRECTORY
110+
APPEND
111+
PROPERTY CMAKE_CONFIGURE_DEPENDS "${cpio_archive_creator}" "${cpio_archive_s}"
112+
)
113+
114+
# The 'cpio_archive' is no explicit parameter for the command, because it is
115+
# hard-coded already in the specific script we have generated above. The
116+
# 'input_files' are explicit here, because they are a CMake list that
117+
# will be converted to parameters for the invokation,
118+
add_custom_command(
119+
OUTPUT ${cpio_archive}
120+
COMMAND bash "${cpio_archive_creator}" ${input_files}
121+
DEPENDS "${cpio_archive_creator}" ${input_files} ${MAKE_CPIO_DEPENDS}
122+
COMMENT "Generate CPIO archive ${cpio_archive}"
123+
)
72124

73125
separate_arguments(cmake_c_flags_sep NATIVE_COMMAND "${CMAKE_C_FLAGS}")
74126
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
75127
list(APPEND cmake_c_flags_sep "${CMAKE_C_COMPILE_OPTIONS_TARGET}${CMAKE_C_COMPILER_TARGET}")
76128
endif()
77-
129+
# The 'cpio_archive' is no explicit parameter for the command, because it is
130+
# hard-coded already in the specific 'cpio_archive_s' file we have generated
131+
# above.
78132
add_custom_command(
79133
OUTPUT ${output_name}
80-
COMMAND rm -f ${cpio_archive}
81-
COMMAND ${commands}
82-
COMMAND
83-
sh -c
84-
"echo 'X.section ._archive_cpio,\"aw\"X.globl ${archive_symbol}, ${archive_symbol}_endX${archive_symbol}:X.incbin \"${cpio_archive}\"X${archive_symbol}_end:X' | tr X '\\n'"
85-
> "${cpio_archive_s}"
86134
COMMAND
87-
${CMAKE_C_COMPILER} ${cmake_c_flags_sep} -c -o ${output_name} "${cpio_archive_s}"
88-
DEPENDS ${input_files} ${MAKE_CPIO_DEPENDS}
89-
VERBATIM
90-
BYPRODUCTS
91-
"${cpio_archive}"
92-
"${cpio_archive_s}"
135+
${CMAKE_C_COMPILER} ${cmake_c_flags_sep} -c -o "${output_name}" "${cpio_archive_s}"
136+
DEPENDS "${cpio_archive_creator}" "${cpio_archive_s}" "${cpio_archive}"
93137
COMMENT "Generate CPIO archive ${output_name}"
94138
)
95139
endfunction(MakeCPIO)

0 commit comments

Comments
 (0)