Skip to content

Commit 0bf1332

Browse files
committed
[Auditor] Make running the auditor multithreaded
1 parent edecf34 commit 0bf1332

File tree

2 files changed

+53
-49
lines changed

2 files changed

+53
-49
lines changed

azure-pipelines.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ variables:
3030
BINARYBUILDER_AUTOMATIC_APPLE: true
3131
BINARYBUILDER_USE_CCACHE: true
3232
CI: true
33+
# Auditor is now multi-threaded, run tests with multiple threads
34+
JULIA_NUM_THREADS: 3
3335

3436
jobs:
3537
- job: Info

src/Auditor.jl

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,15 @@ function audit(prefix::Prefix, src_name::AbstractString = "";
6565
end
6666

6767
# If this is false then it's bedtime for bonzo boy
68-
all_ok = true
68+
all_ok = Threads.Atomic{Bool}(true)
6969

7070
# Translate absolute symlinks to relative symlinks, if possible
7171
translate_symlinks(prefix.path; verbose=verbose)
7272

7373
# Inspect binary files, looking for improper linkage
7474
predicate = f -> (filemode(f) & 0o111) != 0 || valid_library_path(f, platform)
7575
bin_files = collect_files(prefix, predicate; exclude_externalities=false)
76-
for f in collapse_symlinks(bin_files)
76+
Threads.@threads for f in collapse_symlinks(bin_files)
7777
# If `f` is outside of our prefix, ignore it. This happens with files from our dependencies
7878
if !startswith(f, prefix.path)
7979
continue
@@ -89,38 +89,38 @@ function audit(prefix::Prefix, src_name::AbstractString = "";
8989
end
9090
else
9191
# Check that the ISA isn't too high
92-
all_ok &= check_isa(oh, platform, prefix; verbose, silent)
92+
all_ok[] &= check_isa(oh, platform, prefix; verbose, silent)
9393
# Check that the OS ABI is set correctly (often indicates the wrong linker was used)
94-
all_ok &= check_os_abi(oh, platform; verbose)
94+
all_ok[] &= check_os_abi(oh, platform; verbose)
9595
# Make sure all binary files are executables, if libraries aren't
9696
# executables Julia may not be able to dlopen them:
9797
# https://github.com/JuliaLang/julia/issues/38993. In principle this
9898
# should be done when autofix=true, but we have to run this fix on MKL
9999
# for Windows, for which however we have to set autofix=false:
100100
# https://github.com/JuliaPackaging/Yggdrasil/pull/922.
101-
all_ok &= ensure_executability(oh; verbose, silent)
101+
all_ok[] &= ensure_executability(oh; verbose, silent)
102102

103103
# If this is a dynamic object, do the dynamic checks
104104
if isdynamic(oh)
105105
# Check that the libgfortran version matches
106-
all_ok &= check_libgfortran_version(oh, platform; verbose, has_csl)
106+
all_ok[] &= check_libgfortran_version(oh, platform; verbose, has_csl)
107107
# Check whether the library depends on any of the most common
108108
# libraries provided by `CompilerSupportLibraries_jll`.
109-
all_ok &= check_csl_libs(oh, platform; verbose, has_csl)
109+
all_ok[] &= check_csl_libs(oh, platform; verbose, has_csl)
110110
# Check that the libstdcxx string ABI matches
111-
all_ok &= check_cxxstring_abi(oh, platform; verbose)
111+
all_ok[] &= check_cxxstring_abi(oh, platform; verbose)
112112
# Check that this binary file's dynamic linkage works properly. Note to always
113113
# DO THIS ONE LAST as it can actually mutate the file, which causes the previous
114114
# checks to freak out a little bit.
115-
all_ok &= check_dynamic_linkage(oh, prefix, bin_files;
116-
platform, silent, verbose, autofix, src_name)
115+
all_ok[] &= check_dynamic_linkage(oh, prefix, bin_files;
116+
platform, silent, verbose, autofix, src_name)
117117
end
118118
end
119119
end
120120
end
121121

122122
# Ensure this file is codesigned (currently only does something on Apple platforms)
123-
all_ok &= ensure_codesigned(f, prefix, platform; verbose, subdir=src_name)
123+
all_ok[] &= ensure_codesigned(f, prefix, platform; verbose, subdir=src_name)
124124
catch e
125125
if !isa(e, ObjectFile.MagicMismatch)
126126
rethrow(e)
@@ -136,7 +136,7 @@ function audit(prefix::Prefix, src_name::AbstractString = "";
136136
# Find all dynamic libraries
137137
shlib_files = filter(f -> startswith(f, prefix.path) && valid_library_path(f, platform), collapse_symlinks(bin_files))
138138

139-
for f in shlib_files
139+
Threads.@threads for f in shlib_files
140140
# Inspect all shared library files for our platform (but only if we're
141141
# running native, don't try to load library files from other platforms)
142142
if platforms_match(platform, HostPlatform())
@@ -172,23 +172,23 @@ function audit(prefix::Prefix, src_name::AbstractString = "";
172172
if !silent
173173
@warn("$(relpath(f, prefix.path)) cannot be dlopen()'ed")
174174
end
175-
all_ok = false
175+
all_ok[] = false
176176
end
177177
end
178178

179179
# Ensure that all libraries have at least some kind of SONAME, if we're
180180
# on that kind of platform
181181
if !Sys.iswindows(platform)
182-
all_ok &= ensure_soname(prefix, f, platform; verbose, autofix, subdir=src_name)
182+
all_ok[] &= ensure_soname(prefix, f, platform; verbose, autofix, subdir=src_name)
183183
end
184184

185185
# Ensure that this library is available at its own SONAME
186-
all_ok &= symlink_soname_lib(f; verbose=verbose, autofix=autofix)
186+
all_ok[] &= symlink_soname_lib(f; verbose=verbose, autofix=autofix)
187187
end
188188

189189
# remove *.la files generated by GNU libtool
190190
la_files = collect_files(prefix, endswith(".la"))
191-
for f in la_files
191+
Threads.@threads for f in la_files
192192
# Make sure the file still exists on disk
193193
if isfile(f)
194194
# sanity check: first byte should be '#', first line should contain 'libtool'
@@ -211,42 +211,44 @@ function audit(prefix::Prefix, src_name::AbstractString = "";
211211

212212
# Make sure that `(exec_)prefix` in pkg-config files use a relative prefix
213213
pc_files = collect_files(prefix, endswith(".pc"))
214-
for f in pc_files, var in ["prefix", "exec_prefix"]
215-
pc_re = Regex("^$var=(/.*)\$")
216-
# We want to replace every instance of `prefix=...` with
217-
# `prefix=${pcfiledir}/../..`
218-
changed = false
219-
buf = IOBuffer()
220-
for l in readlines(f)
221-
m = match(pc_re, l)
222-
if m !== nothing
223-
# dealing with an absolute path we need to relativize;
224-
# determine how many directories we need to go up.
225-
dir = m.captures[1]
226-
f_rel = relpath(f, prefix.path)
227-
ndirs = count('/', f_rel)
228-
prefix_rel = join([".." for _ in 1:ndirs], "/")
229-
l = "$var=\${pcfiledir}/$prefix_rel"
230-
changed = true
214+
Threads.@threads for f in pc_files
215+
for var in ["prefix", "exec_prefix"]
216+
pc_re = Regex("^$var=(/.*)\$")
217+
# We want to replace every instance of `prefix=...` with
218+
# `prefix=${pcfiledir}/../..`
219+
changed = false
220+
buf = IOBuffer()
221+
for l in readlines(f)
222+
m = match(pc_re, l)
223+
if m !== nothing
224+
# dealing with an absolute path we need to relativize;
225+
# determine how many directories we need to go up.
226+
dir = m.captures[1]
227+
f_rel = relpath(f, prefix.path)
228+
ndirs = count('/', f_rel)
229+
prefix_rel = join([".." for _ in 1:ndirs], "/")
230+
l = "$var=\${pcfiledir}/$prefix_rel"
231+
changed = true
232+
end
233+
println(buf, l)
231234
end
232-
println(buf, l)
233-
end
234-
str = String(take!(buf))
235+
str = String(take!(buf))
235236

236-
if changed
237-
# Overwrite file
238-
if verbose
239-
@info("Relocatize pkg-config file $f")
237+
if changed
238+
# Overwrite file
239+
if verbose
240+
@info("Relocatize pkg-config file $f")
241+
end
242+
write(f, str)
240243
end
241-
write(f, str)
242244
end
243245
end
244246

245247
if Sys.iswindows(platform)
246248
# We also cannot allow any symlinks in Windows because it requires
247249
# Admin privileges to create them. Orz
248250
symlinks = collect_files(prefix, islink, exclude_dirs = false)
249-
for f in symlinks
251+
Threads.@threads for f in symlinks
250252
try
251253
src_path = realpath(f)
252254
if isfile(src_path) || isdir(src_path)
@@ -285,7 +287,7 @@ function audit(prefix::Prefix, src_name::AbstractString = "";
285287

286288
# Normalise timestamp of Windows import libraries.
287289
import_libraries = collect_files(prefix, endswith(".dll.a"))
288-
for implib in import_libraries
290+
Threads.@threads for implib in import_libraries
289291
if verbose
290292
@info("Normalising timestamps in import library $(implib)")
291293
end
@@ -296,19 +298,19 @@ function audit(prefix::Prefix, src_name::AbstractString = "";
296298

297299
# Check that we're providing a license file
298300
if require_license
299-
all_ok &= check_license(prefix, src_name; verbose=verbose, silent=silent)
301+
all_ok[] &= check_license(prefix, src_name; verbose=verbose, silent=silent)
300302
end
301303

302304
# Perform filesystem-related audit passes
303305
predicate = f -> !startswith(f, joinpath(prefix, "logs"))
304306
all_files = collect_files(prefix, predicate)
305307

306308
# Search for absolute paths in this prefix
307-
all_ok &= check_absolute_paths(prefix, all_files; silent=silent)
309+
all_ok[] &= check_absolute_paths(prefix, all_files; silent=silent)
308310

309311
# Search for case-sensitive ambiguities
310-
all_ok &= check_case_sensitivity(prefix)
311-
return all_ok
312+
all_ok[] &= check_case_sensitivity(prefix)
313+
return all_ok[]
312314
end
313315

314316

@@ -515,7 +517,7 @@ function collect_files(path::AbstractString, predicate::Function = f -> true;
515517
end
516518
end
517519
end
518-
return collected
520+
return unique!(collected)
519521
end
520522
# Unwrap Prefix objects automatically
521523
collect_files(prefix::Prefix, args...; kwargs...) = collect_files(prefix.path, args...; kwargs...)
@@ -544,7 +546,7 @@ function collapse_symlinks(files::Vector{String})
544546
return false
545547
end
546548
end
547-
return filter(predicate, files)
549+
return unique!(filter(predicate, files))
548550
end
549551

550552
"""

0 commit comments

Comments
 (0)