@@ -80,82 +80,85 @@ function audit(prefix::Prefix, src_name::AbstractString = "";
80
80
# Inspect binary files, looking for improper linkage
81
81
predicate = f -> (filemode (f) & 0o111 ) != 0 || valid_library_path (f, platform)
82
82
bin_files = collect_files (prefix, predicate; exclude_externalities= false )
83
- Threads . @threads for f in collapse_symlinks (bin_files)
83
+ @sync for f in collapse_symlinks (bin_files)
84
84
# If `f` is outside of our prefix, ignore it. This happens with files from our dependencies
85
85
if ! startswith (f, prefix. path)
86
86
continue
87
87
end
88
88
89
- # Peel this binary file open like a delicious tangerine
90
- try
91
- readmeta (f) do ohs
92
- foreach (ohs) do oh
93
- if ! is_for_platform (oh, platform)
94
- if verbose
95
- @warn (" Skipping binary analysis of $(relpath (f, prefix. path)) (incorrect platform)" )
96
- end
97
- else
98
- # Check that the ISA isn't too high
99
- all_ok[] &= check_isa (oh, platform, prefix; verbose, silent)
100
- # Check that the OS ABI is set correctly (often indicates the wrong linker was used)
101
- all_ok[] &= check_os_abi (oh, platform; verbose)
102
- # Make sure all binary files are executables, if libraries aren't
103
- # executables Julia may not be able to dlopen them:
104
- # https://github.com/JuliaLang/julia/issues/38993. In principle this
105
- # should be done when autofix=true, but we have to run this fix on MKL
106
- # for Windows, for which however we have to set autofix=false:
107
- # https://github.com/JuliaPackaging/Yggdrasil/pull/922.
108
- all_ok[] &= ensure_executability (oh; verbose, silent)
109
-
110
- # If this is a dynamic object, do the dynamic checks
111
- if isdynamic (oh)
112
- # Check that the libgfortran version matches
113
- all_ok[] &= check_libgfortran_version (oh, platform; verbose, has_csl)
114
- # Check whether the library depends on any of the most common
115
- # libraries provided by `CompilerSupportLibraries_jll`.
116
- all_ok[] &= check_csl_libs (oh, platform; verbose, has_csl)
117
- # Check that the libstdcxx string ABI matches
118
- all_ok[] &= check_cxxstring_abi (oh, platform; verbose)
119
- # Check that this binary file's dynamic linkage works properly. Note to always
120
- # DO THIS ONE LAST as it can actually mutate the file, which causes the previous
121
- # checks to freak out a little bit.
122
- all_ok[] &= check_dynamic_linkage (oh, prefix, bin_files;
123
- platform, silent, verbose, autofix, src_name)
89
+ Threads. @spawn let
90
+ # Peel this binary file open like a delicious tangerine
91
+ try
92
+ readmeta (f) do ohs
93
+ foreach (ohs) do oh
94
+ if ! is_for_platform (oh, platform)
95
+ if verbose
96
+ @warn (" Skipping binary analysis of $(relpath (f, prefix. path)) (incorrect platform)" )
97
+ end
98
+ else
99
+ # Check that the ISA isn't too high
100
+ all_ok[] &= check_isa (oh, platform, prefix; verbose, silent)
101
+ # Check that the OS ABI is set correctly (often indicates the wrong linker was used)
102
+ all_ok[] &= check_os_abi (oh, platform; verbose)
103
+ # Make sure all binary files are executables, if libraries aren't
104
+ # executables Julia may not be able to dlopen them:
105
+ # https://github.com/JuliaLang/julia/issues/38993. In principle this
106
+ # should be done when autofix=true, but we have to run this fix on MKL
107
+ # for Windows, for which however we have to set autofix=false:
108
+ # https://github.com/JuliaPackaging/Yggdrasil/pull/922.
109
+ all_ok[] &= ensure_executability (oh; verbose, silent)
110
+
111
+ # If this is a dynamic object, do the dynamic checks
112
+ if isdynamic (oh)
113
+ # Check that the libgfortran version matches
114
+ all_ok[] &= check_libgfortran_version (oh, platform; verbose, has_csl)
115
+ # Check whether the library depends on any of the most common
116
+ # libraries provided by `CompilerSupportLibraries_jll`.
117
+ all_ok[] &= check_csl_libs (oh, platform; verbose, has_csl)
118
+ # Check that the libstdcxx string ABI matches
119
+ all_ok[] &= check_cxxstring_abi (oh, platform; verbose)
120
+ # Check that this binary file's dynamic linkage works properly. Note to always
121
+ # DO THIS ONE LAST as it can actually mutate the file, which causes the previous
122
+ # checks to freak out a little bit.
123
+ all_ok[] &= check_dynamic_linkage (oh, prefix, bin_files;
124
+ platform, silent, verbose, autofix, src_name)
125
+ end
124
126
end
125
127
end
126
128
end
127
- end
128
129
129
- # Ensure this file is codesigned (currently only does something on Apple platforms)
130
- all_ok[] &= ensure_codesigned (f, prefix, platform; verbose, subdir= src_name)
131
- catch e
132
- if ! isa (e, ObjectFile. MagicMismatch)
133
- rethrow (e)
134
- end
130
+ # Ensure this file is codesigned (currently only does something on Apple platforms)
131
+ all_ok[] &= ensure_codesigned (f, prefix, platform; verbose, subdir= src_name)
132
+ catch e
133
+ if ! isa (e, ObjectFile. MagicMismatch)
134
+ rethrow (e)
135
+ end
135
136
136
- # If this isn't an actual binary file, skip it
137
- if verbose
138
- @info (" Skipping binary analysis of $(relpath (f, prefix. path)) " )
137
+ # If this isn't an actual binary file, skip it
138
+ if verbose
139
+ @info (" Skipping binary analysis of $(relpath (f, prefix. path)) " )
140
+ end
139
141
end
140
142
end
141
143
end
142
144
143
145
# Find all dynamic libraries
144
146
shlib_files = filter (f -> startswith (f, prefix. path) && valid_library_path (f, platform), collapse_symlinks (bin_files))
145
147
146
- Threads. @threads for f in shlib_files
147
- # Inspect all shared library files for our platform (but only if we're
148
- # running native, don't try to load library files from other platforms)
149
- if platforms_match (platform, HostPlatform ())
150
- if verbose
151
- @info (" Checking shared library $(relpath (f, prefix. path)) " )
152
- end
148
+ @sync for f in shlib_files
149
+ Threads. @spawn let
150
+ # Inspect all shared library files for our platform (but only if we're
151
+ # running native, don't try to load library files from other platforms)
152
+ if platforms_match (platform, HostPlatform ())
153
+ if verbose
154
+ @info (" Checking shared library $(relpath (f, prefix. path)) " )
155
+ end
153
156
154
- # dlopen() this library in a separate Julia process so that if we
155
- # try to do something silly like `dlopen()` a .so file that uses
156
- # LLVM in interesting ways on startup, it doesn't kill our main
157
- # Julia process.
158
- dlopen_cmd = """
157
+ # dlopen() this library in a separate Julia process so that if we
158
+ # try to do something silly like `dlopen()` a .so file that uses
159
+ # LLVM in interesting ways on startup, it doesn't kill our main
160
+ # Julia process.
161
+ dlopen_cmd = """
159
162
using Libdl
160
163
try
161
164
dlopen($(repr (f)) )
@@ -167,30 +170,31 @@ function audit(prefix::Prefix, src_name::AbstractString = "";
167
170
exit(1)
168
171
end
169
172
"""
170
- try
171
- p = open (` $(Base. julia_cmd ()) -e $dlopen_cmd ` )
172
- wait (p)
173
- if p. exitcode != 0
174
- throw (" Invalid exit code!" )
175
- end
176
- catch
177
- # TODO : Use the relevant ObjFileBase packages to inspect why
178
- # this file is being nasty to us.
179
- if ! silent
180
- @warn (" $(relpath (f, prefix. path)) cannot be dlopen()'ed" )
173
+ try
174
+ p = open (` $(Base. julia_cmd ()) -e $dlopen_cmd ` )
175
+ wait (p)
176
+ if p. exitcode != 0
177
+ throw (" Invalid exit code!" )
178
+ end
179
+ catch
180
+ # TODO : Use the relevant ObjFileBase packages to inspect why
181
+ # this file is being nasty to us.
182
+ if ! silent
183
+ @warn (" $(relpath (f, prefix. path)) cannot be dlopen()'ed" )
184
+ end
185
+ all_ok[] = false
181
186
end
182
- all_ok[] = false
183
187
end
184
- end
185
188
186
- # Ensure that all libraries have at least some kind of SONAME, if we're
187
- # on that kind of platform
188
- if ! Sys. iswindows (platform)
189
- all_ok[] &= ensure_soname (prefix, f, platform; verbose, autofix, subdir= src_name)
190
- end
189
+ # Ensure that all libraries have at least some kind of SONAME, if we're
190
+ # on that kind of platform
191
+ if ! Sys. iswindows (platform)
192
+ all_ok[] &= ensure_soname (prefix, f, platform; verbose, autofix, subdir= src_name)
193
+ end
191
194
192
- # Ensure that this library is available at its own SONAME
193
- all_ok[] &= symlink_soname_lib (f; verbose= verbose, autofix= autofix)
195
+ # Ensure that this library is available at its own SONAME
196
+ all_ok[] &= symlink_soname_lib (f; verbose= verbose, autofix= autofix)
197
+ end
194
198
end
195
199
196
200
# remove *.la files generated by GNU libtool
@@ -218,35 +222,37 @@ function audit(prefix::Prefix, src_name::AbstractString = "";
218
222
219
223
# Make sure that `(exec_)prefix` in pkg-config files use a relative prefix
220
224
pc_files = collect_files (prefix, endswith (" .pc" ))
221
- Threads. @threads for f in pc_files
222
- for var in [" prefix" , " exec_prefix" ]
223
- pc_re = Regex (" ^$var =(/.*)\$ " )
224
- # We want to replace every instance of `prefix=...` with
225
- # `prefix=${pcfiledir}/../..`
226
- changed = false
227
- buf = IOBuffer ()
228
- for l in readlines (f)
229
- m = match (pc_re, l)
230
- if m != = nothing
231
- # dealing with an absolute path we need to relativize;
232
- # determine how many directories we need to go up.
233
- dir = m. captures[1 ]
234
- f_rel = relpath (f, prefix. path)
235
- ndirs = count (' /' , f_rel)
236
- prefix_rel = join ([" .." for _ in 1 : ndirs], " /" )
237
- l = " $var =\$ {pcfiledir}/$prefix_rel "
238
- changed = true
225
+ @sync for f in pc_files
226
+ Threads. @spawn let
227
+ for var in [" prefix" , " exec_prefix" ]
228
+ pc_re = Regex (" ^$var =(/.*)\$ " )
229
+ # We want to replace every instance of `prefix=...` with
230
+ # `prefix=${pcfiledir}/../..`
231
+ changed = false
232
+ buf = IOBuffer ()
233
+ for l in readlines (f)
234
+ m = match (pc_re, l)
235
+ if m != = nothing
236
+ # dealing with an absolute path we need to relativize;
237
+ # determine how many directories we need to go up.
238
+ dir = m. captures[1 ]
239
+ f_rel = relpath (f, prefix. path)
240
+ ndirs = count (' /' , f_rel)
241
+ prefix_rel = join ([" .." for _ in 1 : ndirs], " /" )
242
+ l = " $var =\$ {pcfiledir}/$prefix_rel "
243
+ changed = true
244
+ end
245
+ println (buf, l)
239
246
end
240
- println (buf, l)
241
- end
242
- str = String (take! (buf))
247
+ str = String (take! (buf))
243
248
244
- if changed
245
- # Overwrite file
246
- if verbose
247
- @info (" Relocatize pkg-config file $f " )
249
+ if changed
250
+ # Overwrite file
251
+ if verbose
252
+ @info (" Relocatize pkg-config file $f " )
253
+ end
254
+ write (f, str)
248
255
end
249
- write (f, str)
250
256
end
251
257
end
252
258
end
@@ -255,14 +261,16 @@ function audit(prefix::Prefix, src_name::AbstractString = "";
255
261
# We also cannot allow any symlinks in Windows because it requires
256
262
# Admin privileges to create them. Orz
257
263
symlinks = collect_files (prefix, islink, exclude_dirs = false )
258
- Threads. @threads for f in symlinks
259
- try
260
- src_path = realpath (f)
261
- if isfile (src_path) || isdir (src_path)
262
- rm (f; force= true )
263
- cp (src_path, f, follow_symlinks = true )
264
+ @sync for f in symlinks
265
+ Threads. @spawn let
266
+ try
267
+ src_path = realpath (f)
268
+ if isfile (src_path) || isdir (src_path)
269
+ rm (f; force= true )
270
+ cp (src_path, f, follow_symlinks = true )
271
+ end
272
+ catch
264
273
end
265
- catch
266
274
end
267
275
end
268
276
@@ -294,11 +302,13 @@ function audit(prefix::Prefix, src_name::AbstractString = "";
294
302
295
303
# Normalise timestamp of Windows import libraries.
296
304
import_libraries = collect_files (prefix, endswith (" .dll.a" ))
297
- Threads. @threads for implib in import_libraries
298
- if verbose
299
- @info (" Normalising timestamps in import library $(implib) " )
305
+ @sync for implib in import_libraries
306
+ Threads. @spawn let
307
+ if verbose
308
+ @info (" Normalising timestamps in import library $(implib) " )
309
+ end
310
+ normalise_implib_timestamp (implib)
300
311
end
301
- normalise_implib_timestamp (implib)
302
312
end
303
313
304
314
end
@@ -404,7 +414,7 @@ function check_dynamic_linkage(oh, prefix, bin_files;
404
414
# Look at every dynamic link, and see if we should do anything about that link...
405
415
libs = find_libraries (oh)
406
416
ignored_libraries = String[]
407
- Threads . @threads for libname in collect (keys (libs))
417
+ @sync for libname in collect (keys (libs))
408
418
if should_ignore_lib (libname, oh, platform)
409
419
push! (ignored_libraries, libname)
410
420
continue
@@ -421,40 +431,42 @@ function check_dynamic_linkage(oh, prefix, bin_files;
421
431
continue
422
432
end
423
433
424
- if ! isfile (libs[libname])
425
- # If we couldn't resolve this library, let's try autofixing,
426
- # if we're allowed to by the user
427
- if autofix
428
- # First, is this a library that we already know about?
429
- known_bins = lowercase .(basename .(bin_files))
430
- kidx = findfirst (known_bins .== lowercase (basename (libname)))
431
- if kidx != = nothing
432
- # If it is, point to that file instead!
433
- new_link = update_linkage (prefix, platform, path (oh), libs[libname], bin_files[kidx]; verbose, subdir= src_name)
434
-
435
- if verbose && new_link != = nothing
436
- @info (" $(filename) : Linked library $(libname) has been auto-mapped to $(new_link) " )
434
+ Threads. @spawn let
435
+ if ! isfile (libs[libname])
436
+ # If we couldn't resolve this library, let's try autofixing,
437
+ # if we're allowed to by the user
438
+ if autofix
439
+ # First, is this a library that we already know about?
440
+ known_bins = lowercase .(basename .(bin_files))
441
+ kidx = findfirst (known_bins .== lowercase (basename (libname)))
442
+ if kidx != = nothing
443
+ # If it is, point to that file instead!
444
+ new_link = update_linkage (prefix, platform, path (oh), libs[libname], bin_files[kidx]; verbose, subdir= src_name)
445
+
446
+ if verbose && new_link != = nothing
447
+ @info (" $(filename) : Linked library $(libname) has been auto-mapped to $(new_link) " )
448
+ end
449
+ else
450
+ if ! silent
451
+ @warn (" $(filename) : Linked library $(libname) could not be resolved and could not be auto-mapped" )
452
+ if is_troublesome_library_link (libname, platform)
453
+ @warn (" $(filename) : Depending on $(libname) is known to cause problems at runtime, make sure to link against the JLL library instead" )
454
+ end
455
+ end
456
+ all_ok[] = false
437
457
end
438
458
else
439
459
if ! silent
440
- @warn (" $(filename) : Linked library $(libname) could not be resolved and could not be auto-mapped" )
441
- if is_troublesome_library_link (libname, platform)
442
- @warn (" $(filename) : Depending on $(libname) is known to cause problems at runtime, make sure to link against the JLL library instead" )
443
- end
460
+ @warn (" $(filename) : Linked library $(libname) could not be resolved within the given prefix" )
444
461
end
445
462
all_ok[] = false
446
463
end
447
- else
464
+ elseif ! startswith (libs[libname], prefix . path)
448
465
if ! silent
449
- @warn (" $(filename) : Linked library $(libname) could not be resolved within the given prefix" )
466
+ @warn (" $(filename) : Linked library $(libname) (resolved path $(libs[libname]) ) is not within the given prefix" )
450
467
end
451
468
all_ok[] = false
452
469
end
453
- elseif ! startswith (libs[libname], prefix. path)
454
- if ! silent
455
- @warn (" $(filename) : Linked library $(libname) (resolved path $(libs[libname]) ) is not within the given prefix" )
456
- end
457
- all_ok[] = false
458
470
end
459
471
end
460
472
0 commit comments