aboutsummaryrefslogtreecommitdiff
path: root/cmake/Common/IARArMerge.cmake
blob: e9d19f98d95bd5de057f0a9e278dbb4bef3e3d73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#-------------------------------------------------------------------------------
# Copyright (c) 2020, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
#-------------------------------------------------------------------------------

#A cmake script to merge two archives using IAR iarchive.
#
# The script will first run iarchive to get the list of files in the source archive.
# Then each file is:
#   -extracted
#   -added to the target archive
#   -deleted
#
# The loop is needed to avoid losing files with matching name in the source
# archive.
# The destination archive is updated in a way not to overwrite existing files
# with matching names.
#
#Examples:
#  cmake -DCMAKE_AR=iarchive -DDESTINATION=new_lib.a -DSOURCE=/foo/bar/old_lib.a -P ./IARArMerge.cmake
#
#Parameters:
#  SOURCE      - archive file to copy all members from
#  DESTINATION - archive file to copy members to. If file exists, then new
#                members are added without overwriting existing ones.
#  CMAKE_AR    - GNU AR executable
#

#Execute AR and capture its output
#
# Script execution will stop with a fatal error if AR execution fails.
#
#Examples:
#  List content of archive:
#    run_ar(RESULT t /foo/bar/my_lib.a)
#  Add object file to archive
#    run_ar(RESULT q /foo/bar/my_lib.a new_obj.o)
#
#INPUTS:
#    RESULT - (mandatory) - name of variable to put result in
#    All remaining parameters will be command line options to AR
#
#OUTPUTS
#    RESULT - text output of AR command
#
function(run_ar OUTPUT )
	execute_process(COMMAND ${CMAKE_AR} ${ARGN}
					TIMEOUT 120
					OUTPUT_VARIABLE _RES
					RESULT_VARIABLE _STATUS_CODE
					OUTPUT_STRIP_TRAILING_WHITESPACE)

	if (STATUS_CODE GREATER 0)
		message(FATAL_ERROR "ERROR: Failed to execute \"${CMAKE_AR} ${ARGN}\".")
	endif()
	set(${OUTPUT} ${_RES} PARENT_SCOPE)
endfunction()

#Delete a file
#
# Function to delete a file. No error will be reported if file is missing.
# Script execution will stop with a fatal error if AR execution fails.
#
#Examples:
#  rm(/foo/bar/my_lib.a)
#
#INPUTS:
#    FILE - path to file to delete
#
#OUTPUTS
#    N/A
#
function(rm FILE)
	execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${FILE}
					RESULT_VARIABLE _STATUS_CODE
					TIMEOUT 120)
	if (STATUS_CODE GREATER 0)
		message(FATAL_ERROR "ERROR: Failed to execute \"${CMAKE_COMMAND} -E remove ${FILE}\".")
	endif()
endfunction()


#############################################################################
# Entry point
#############################################################################
#Verify input variables.

if(NOT DEFINED SOURCE)
	message(FATAL_ERROR "GNUArMerge.cmake: Variable SOURCE is not defined.")
endif()

if(NOT DEFINED DESTINATION)
	message(FATAL_ERROR "GNUArMerge.cmake: Variable DESTINATION is not defined.")
endif()

if(NOT DEFINED CMAKE_AR)
	message(FATAL_ERROR "GNUArMerge.cmake: Variable CMAKE_AR is not defined.")
endif()


#Get list of archive members
run_ar("OBJ_LIST" -t ${SOURCE})

#Convert AR output to cmake list
string(REPLACE "\n" ";" OBJ_LIST ${OBJ_LIST})

#Iterate over member list.
foreach(OBJ ${OBJ_LIST})
	#Extract member
	run_ar("_DUMMY" -x ${SOURCE} ${OBJ})
	#Add member to destination archive
	run_ar("_DUMMY" -r ${DESTINATION} ${OBJ})
	#Remove extracted member
	rm("${OBJ}")
endforeach()