@@ -9,12 +9,10 @@ import shutil
9
9
from swift_build_support .swift_build_support import shell
10
10
11
11
12
- def merge_file_lists (src_root_dirs , explicit_src_files , skip_files ,
13
- skip_subpaths ):
12
+ def merge_file_lists (src_root_dirs , skip_files ):
14
13
"""Merges the file lists recursively from all src_root_dirs supplied,
15
14
returning the union of all file paths found.
16
15
Files matching skip_files are ignored and skipped.
17
- Subpaths matching skip_subpaths are not recursed into.
18
16
"""
19
17
file_list = []
20
18
for src_root_dir in src_root_dirs :
@@ -25,20 +23,39 @@ def merge_file_lists(src_root_dirs, explicit_src_files, skip_files,
25
23
if file not in skip_files ]
26
24
file_list .extend (
27
25
filter (lambda file : file not in file_list , rel_files ))
28
- dirs [:] = filter (
29
- lambda dir : os .path .join (rel_dir , dir )
30
- not in skip_subpaths , dirs )
31
-
32
- for file in explicit_src_files :
33
- # If this is an absolute installation path, e.g. /Applications/Xcode/...,
34
- # treat it as being relative to a built toolchain
35
- relative_path = file [1 :] if file .startswith ("/" ) else file
36
- file_list .append (relative_path ) if relative_path not in file_list else file_list
26
+
37
27
return file_list
38
28
39
29
40
- def merge_lipo_files (src_root_dirs , file_list , copy_verbatim_subpaths ,
41
- dest_root_dir , verbose = False , lipo_executable = "lipo" ):
30
+ # Determine if the file paths contain any overlapping architectures.
31
+ def overlapping_lipo_architectures (file_paths , lipo_executable ):
32
+ lipo_cmd = [lipo_executable , "-archs" ]
33
+
34
+ known_archs = []
35
+ for file in file_paths :
36
+ archs = shell .capture (lipo_cmd + [file ], echo = False ).split (' ' )
37
+ for arch in archs :
38
+ arch = arch .strip ()
39
+ if arch in known_archs :
40
+ return True
41
+ known_archs .append (arch )
42
+ return False
43
+
44
+
45
+ # Determine the path to the first file and where it should be installed.
46
+ def get_first_file_and_dest_path (file , src_root_dirs , dest_root_dir ):
47
+ for dir in src_root_dirs :
48
+ orig_file = os .path .join (dir , file )
49
+ if os .path .exists (orig_file ):
50
+ dest_path = os .path .join (
51
+ dest_root_dir , os .path .relpath (orig_file , dir ))
52
+ return (orig_file , dest_path )
53
+
54
+ return None
55
+
56
+
57
+ def merge_lipo_files (src_root_dirs , file_list , dest_root_dir , verbose = False ,
58
+ lipo_executable = "lipo" ):
42
59
"""Recursively merges and runs lipo on all files from file_list in
43
60
src_root_dirs to destRoorDir.
44
61
@@ -48,9 +65,7 @@ def merge_lipo_files(src_root_dirs, file_list, copy_verbatim_subpaths,
48
65
it's lipo'ed together from all src_root_dirs into a fat binary.
49
66
50
67
Any path in file_list that's a directory in src_root_dirs results in a
51
- corresponding subdirectory in dest_root_dir. If the subdirectory path
52
- matches copy_verbatim_subpaths, the whole subdirectory is recursively
53
- copied verbatim.
68
+ corresponding subdirectory in dest_root_dir.
54
69
"""
55
70
lipo_cmd = [lipo_executable , "-create" ]
56
71
@@ -62,8 +77,10 @@ def merge_lipo_files(src_root_dirs, file_list, copy_verbatim_subpaths,
62
77
print ("-- Warning: Can't locate source file %s" % file )
63
78
continue
64
79
65
- dest_path = os .path .join (
66
- dest_root_dir , os .path .relpath (file_paths [0 ], src_root_dirs [0 ]))
80
+ first_file_and_dest = get_first_file_and_dest_path (
81
+ file , src_root_dirs , dest_root_dir )
82
+ orig_file = first_file_and_dest [0 ]
83
+ dest_path = first_file_and_dest [1 ]
67
84
68
85
if all ([os .path .islink (item ) for item in file_paths ]):
69
86
# It's a symlink in all found instances, copy the link.
@@ -73,32 +90,34 @@ def merge_lipo_files(src_root_dirs, file_list, copy_verbatim_subpaths,
73
90
os .remove (dest_path )
74
91
os .symlink (os .readlink (file_paths [0 ]), dest_path )
75
92
elif all ([os .path .isdir (item ) for item in file_paths ]):
76
- # It's a subdir in all found instances.
77
- # See if we should copy verbatim or create the destination subdir.
78
- if file in copy_verbatim_subpaths :
79
- print ("-- Copying subdir verbatim %s" % dest_path )
80
- if os .path .isdir (dest_path ):
81
- shutil .rmtree (dest_path )
82
- shutil .copytree (file_paths [0 ], dest_path , symlinks = True )
83
- else :
84
- print ("-- Creating subdir %s" % dest_path )
85
- if not os .path .isdir (dest_path ):
86
- os .makedirs (dest_path )
93
+ # It's a subdir in all found instances. Create the destination
94
+ # subdir.
95
+ print ("-- Creating subdir %s" % dest_path )
96
+ if not os .path .isdir (dest_path ):
97
+ os .makedirs (dest_path )
87
98
elif all ([os .path .isfile (item ) for item in file_paths ]):
88
99
# It's a regular file in all found instances, see if they're
89
100
# identical.
90
101
if all ([filecmp .cmp (item , file_paths [0 ]) for item in file_paths ]):
91
102
# All instances are identical, just copy the unique file.
92
103
print ("-- Copying file %s" % dest_path )
93
- shutil .copy2 (file_paths [ 0 ] , dest_path )
104
+ shutil .copy2 (orig_file , dest_path )
94
105
elif all ([os .access (item , os .X_OK ) for item in file_paths ]):
95
- # Multiple instances are different and executable, try lipo.
96
- if verbose :
97
- print ("-- Running lipo %s to %s" % (file_paths , dest_path ))
106
+ if overlapping_lipo_architectures (file_paths , lipo_executable ):
107
+ # lipo will fail due to overlapping architectures, so
108
+ # copy the file directly.
109
+ print ("-- Copying file verbatim %s" % dest_path )
110
+ shutil .copy2 (orig_file , dest_path )
98
111
else :
99
- print ("-- Running lipo %s" % dest_path )
100
- shell .call (lipo_cmd + ["-output" , dest_path ] + file_paths ,
101
- echo = verbose )
112
+ # Multiple instances are different and executable, try lipo.
113
+ if verbose :
114
+ print ("-- Running lipo %s to %s" %
115
+ (file_paths , dest_path ))
116
+ else :
117
+ print ("-- Running lipo %s" % dest_path )
118
+ shell .call ((lipo_cmd + ["-output" , dest_path ] +
119
+ file_paths ),
120
+ echo = verbose )
102
121
else :
103
122
# Multiple instances are different, and they're not executable.
104
123
print (
@@ -119,10 +138,6 @@ If all the copies of the file in the source directories are the same,
119
138
the file is copied directly to the destination. If there are different
120
139
files in different directories, but the files are executable,
121
140
lipo is run to merge the files together. Otherwise, a warning is produced.
122
-
123
- Use --copy-subdirs to override normal logic and copy certain sub directory
124
- paths verbatim. This is useful if some subdirectories already contain fat
125
- binaries.
126
141
""" )
127
142
128
143
parser .add_argument ("-v" , "--verbose" , action = 'store_true' ,
@@ -134,19 +149,6 @@ binaries.
134
149
default = ".DS_Store" ,
135
150
help = "Files to ignore and skip merge/copy, default " +
136
151
"is \" .DS_Store\" " )
137
- # A list of files which this script will ensure are merged using lipo.
138
- # The intent is to allow for exceptions to binaries located under
139
- # `copy-subdirs` that are not built fat. However, if more such exceptions
140
- # are added, it would be better to re-think our approach to a more-general
141
- # solution.
142
- parser .add_argument ("--explicit-src-files" , metavar = "<explicit-source-files>" ,
143
- default = "" ,
144
- help = "Optional list of files which should be merged to " +
145
- "be installed" )
146
- parser .add_argument ("--copy-subdirs" , metavar = "<subdirs-to-copy-verbatim>" ,
147
- default = "" ,
148
- help = "Optional list of subdirectory paths that " +
149
- "should be copied verbatim" )
150
152
151
153
required_group = parser .add_argument_group ("required arguments" )
152
154
required_group .add_argument ("--destination" , metavar = "<dest-path>" ,
@@ -159,19 +161,15 @@ binaries.
159
161
args = parser .parse_args ()
160
162
161
163
skip_files = args .skip_files .split ()
162
- explicit_sources = args .explicit_src_files .split ()
163
- copy_verbatim_subpaths = [
164
- subdir .strip ('/' ) for subdir in args .copy_subdirs .split ()]
165
164
166
- file_list = merge_file_lists (args .src_root_dirs , explicit_sources ,
167
- skip_files , copy_verbatim_subpaths )
165
+ file_list = merge_file_lists (args .src_root_dirs , skip_files )
168
166
169
167
if args .verbose :
170
168
print ("Discovered files and dirs: %s" % file_list )
171
169
172
170
merge_lipo_files (
173
- args .src_root_dirs , file_list , copy_verbatim_subpaths ,
174
- args .destination , args . verbose , args . lipo )
171
+ args .src_root_dirs , file_list , args . destination , args . verbose ,
172
+ args .lipo )
175
173
176
174
return 0
177
175
0 commit comments