1# 2# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3# 4# SPDX-License-Identifier: BSD-2-Clause 5# 6 7# This module contains functions for creating a cpio archive containing a list 8# of input files and turning it into an object file that can be linked into a binary. 9 10include_guard(GLOBAL) 11 12# Checks the existence of an argument to cpio -o. 13# flag refers to a variable in the parent scope that contains the argument, if 14# the argument isn't supported then the flag is set to the empty string in the parent scope. 15function(CheckCPIOArgument var flag) 16 if(NOT (DEFINED ${var})) 17 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cpio-testfile "Testfile contents") 18 execute_process( 19 COMMAND bash -c "echo cpio-testfile | cpio ${flag} -o" 20 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 21 OUTPUT_QUIET ERROR_QUIET 22 RESULT_VARIABLE result 23 ) 24 if(result) 25 set(${var} "" CACHE INTERNAL "") 26 message(STATUS "CPIO test ${var} FAILED") 27 else() 28 set(${var} "${flag}" CACHE INTERNAL "") 29 message(STATUS "CPIO test ${var} PASSED") 30 endif() 31 file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/cpio-testfile) 32 endif() 33endfunction() 34 35# Function for declaring rules to build a cpio archive that can be linked 36# into another target 37function(MakeCPIO output_name input_files) 38 cmake_parse_arguments(PARSE_ARGV 2 MAKE_CPIO "" "CPIO_SYMBOL" "DEPENDS") 39 if(NOT "${MAKE_CPIO_UNPARSED_ARGUMENTS}" STREQUAL "") 40 message(FATAL_ERROR "Unknown arguments to MakeCPIO") 41 endif() 42 set(archive_symbol "_cpio_archive") 43 if(NOT "${MAKE_CPIO_CPIO_SYMBOL}" STREQUAL "") 44 set(archive_symbol ${MAKE_CPIO_CPIO_SYMBOL}) 45 endif() 46 # Check that the reproducible flag is available. Don't use it if it isn't. 47 CheckCPIOArgument(cpio_reproducible_flag "--reproducible") 48 set(append "") 49 set(commands "bash;-c;cpio ${cpio_reproducible_flag} --quiet --create -H newc --file=${CMAKE_CURRENT_BINARY_DIR}/archive.${output_name}.cpio;&&") 50 foreach(file IN LISTS input_files) 51 # Try and generate reproducible cpio meta-data as we do this: 52 # - touch -d @0 file sets the modified time to 0 53 # - --owner=root:root sets user and group values to 0:0 54 # - --reproducible creates reproducible archives with consistent inodes and device numbering 55 list( 56 APPEND 57 commands 58 "bash;-c;cd `dirname ${file}` && mkdir -p temp_${output_name} && cd temp_${output_name} && cp -a ${file} . && touch -d @0 `basename ${file}` && echo `basename ${file}` | cpio --append ${cpio_reproducible_flag} --owner=root:root --quiet -o -H newc --file=${CMAKE_CURRENT_BINARY_DIR}/archive.${output_name}.cpio && rm `basename ${file}` && cd ../ && rmdir temp_${output_name};&&" 59 ) 60 endforeach() 61 list(APPEND commands "true") 62 separate_arguments(cmake_c_flags_sep NATIVE_COMMAND "${CMAKE_C_FLAGS}") 63 if (CMAKE_C_COMPILER_ID STREQUAL "Clang") 64 list(APPEND cmake_c_flags_sep "${CMAKE_C_COMPILE_OPTIONS_TARGET}${CMAKE_C_COMPILER_TARGET}") 65 endif() 66 67 add_custom_command( 68 OUTPUT ${output_name} 69 COMMAND rm -f archive.${output_name}.cpio 70 COMMAND ${commands} 71 COMMAND 72 sh -c 73 "echo 'X.section ._archive_cpio,\"aw\"X.globl ${archive_symbol}, ${archive_symbol}_endX${archive_symbol}:X.incbin \"archive.${output_name}.cpio\"X${archive_symbol}_end:X' | tr X '\\n'" 74 > ${output_name}.S 75 COMMAND 76 ${CMAKE_C_COMPILER} ${cmake_c_flags_sep} -c -o ${output_name} ${output_name}.S 77 DEPENDS ${input_files} ${MAKE_CPIO_DEPENDS} 78 VERBATIM 79 BYPRODUCTS 80 archive.${output_name}.cpio 81 ${output_name}.S 82 COMMENT "Generate CPIO archive ${output_name}" 83 ) 84endfunction(MakeCPIO) 85