@@ -39,57 +39,101 @@ function(MakeCPIO output_name input_files)
39
39
if (NOT "${MAKE_CPIO_UNPARSED_ARGUMENTS} " STREQUAL "" )
40
40
message (FATAL_ERROR "Unknown arguments to MakeCPIO" )
41
41
endif ()
42
+
42
43
set (archive_symbol "_cpio_archive" )
43
44
if (NOT "${MAKE_CPIO_CPIO_SYMBOL} " STREQUAL "" )
44
45
set (archive_symbol ${MAKE_CPIO_CPIO_SYMBOL} )
45
46
endif ()
46
47
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
+ )
50
58
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.
52
70
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 "
56
88
)
57
89
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
+ )
72
124
73
125
separate_arguments (cmake_c_flags_sep NATIVE_COMMAND "${CMAKE_C_FLAGS} " )
74
126
if (CMAKE_C_COMPILER_ID STREQUAL "Clang" )
75
127
list (APPEND cmake_c_flags_sep "${CMAKE_C_COMPILE_OPTIONS_TARGET}${CMAKE_C_COMPILER_TARGET} " )
76
128
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.
78
132
add_custom_command (
79
133
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} "
86
134
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} "
93
137
COMMENT "Generate CPIO archive ${output_name} "
94
138
)
95
139
endfunction (MakeCPIO)
0 commit comments