@@ -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 )
95139endfunction (MakeCPIO )
0 commit comments