Skip to content

Commit 6aaf439

Browse files
committed
Map user-specified system libraries to correct variants
Normally users don't specify system libraries such as libc or compiler-rt on the command line. However, when they do it makes sense map them to correct variant. For example, linking with `-pthread` + `-lc` will now end up including `libc-mt.a` rather than `libc.a`. Fixes: #14341
1 parent 2911fd7 commit 6aaf439

File tree

1 file changed

+34
-21
lines changed

1 file changed

+34
-21
lines changed

emcc.py

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -203,15 +203,12 @@ def __init__(self, args):
203203
self.has_dash_c = False
204204
self.has_dash_E = False
205205
self.has_dash_S = False
206-
self.libs = []
207206
self.link_flags = []
208207
self.lib_dirs = []
209208
self.forced_stdlibs = []
210209

211210

212211
def add_link_flag(state, i, f):
213-
if f.startswith('-l'):
214-
state.libs.append((i, f[2:]))
215212
if f.startswith('-L'):
216213
state.lib_dirs.append(f[2:])
217214

@@ -487,6 +484,21 @@ def is_supported(f):
487484
return results
488485

489486

487+
def map_library_names(link_flags):
488+
system_libs_map = system_libs.Library.get_usable_variations()
489+
490+
def map_flag(pair):
491+
flag = pair[1]
492+
if flag.startswith('-l'):
493+
name = 'lib' + strip_prefix(flag, '-l')
494+
if name in system_libs_map:
495+
lib = system_libs_map[name]
496+
return (pair[0], '-l' + strip_prefix(lib.get_base_name(), 'lib'))
497+
return pair
498+
499+
return [map_flag(f) for f in link_flags]
500+
501+
490502
def fix_windows_newlines(text):
491503
# Avoid duplicating \r\n to \r\r\n when writing out text.
492504
if WINDOWS:
@@ -1054,7 +1066,7 @@ def run(args):
10541066
if state.mode == Mode.POST_LINK_ONLY:
10551067
settings.limit_settings(None)
10561068
target, wasm_target = phase_linker_setup(options, state, newargs, settings_map)
1057-
process_libraries(state.libs, state.lib_dirs, [])
1069+
process_libraries(state.link_flags, state.lib_dirs, [])
10581070
if len(input_files) != 1:
10591071
exit_with_error('--post-link requires a single input file')
10601072
phase_post_link(options, state, input_files[0][1], wasm_target, target)
@@ -1115,11 +1127,10 @@ def run(args):
11151127
def phase_calculate_linker_inputs(options, state, linker_inputs):
11161128
using_lld = not (options.oformat == OFormat.OBJECT and settings.LTO)
11171129
state.link_flags = filter_link_flags(state.link_flags, using_lld)
1130+
state.link_flags = map_library_names(state.link_flags)
11181131

11191132
# Decide what we will link
1120-
consumed = process_libraries(state.libs, state.lib_dirs, linker_inputs)
1121-
# Filter out libraries that are actually JS libs
1122-
state.link_flags = [l for l in state.link_flags if l[0] not in consumed]
1133+
state.link_flags = process_libraries(state.link_flags, state.lib_dirs, linker_inputs)
11231134

11241135
# If we are linking to an intermediate object then ignore other
11251136
# "fake" dynamic libraries, since otherwise we will end up with
@@ -1245,7 +1256,7 @@ def phase_setup(options, state, newargs, settings_map):
12451256
# library and attempt to find a library by the same name in our own library path.
12461257
# TODO(sbc): Do we really need this feature? See test_other.py:test_local_link
12471258
libname = strip_prefix(unsuffixed_basename(arg), 'lib')
1248-
state.libs.append((i, libname))
1259+
add_link_flag(state, i, '-l' + libname)
12491260
else:
12501261
input_files.append((i, arg))
12511262
elif arg.startswith('-L'):
@@ -1987,7 +1998,7 @@ def check_memory_setting(setting):
19871998
# When not declaring wasm module exports in outer scope one by one, disable minifying
19881999
# wasm module export names so that the names can be passed directly to the outer scope.
19892000
# Also, if using library_exports.js API, disable minification so that the feature can work.
1990-
if not settings.DECLARE_ASM_MODULE_EXPORTS or 'exports.js' in [x for _, x in state.libs]:
2001+
if not settings.DECLARE_ASM_MODULE_EXPORTS or '-lexports.js' in [x for _, x in state.link_flags]:
19912002
settings.MINIFY_ASMJS_EXPORT_NAMES = 0
19922003

19932004
# Enable minification of wasm imports and exports when appropriate, if we
@@ -3507,13 +3518,17 @@ def find_library(lib, lib_dirs):
35073518
return None
35083519

35093520

3510-
def process_libraries(libs, lib_dirs, linker_inputs):
3521+
def process_libraries(link_flags, lib_dirs, linker_inputs):
3522+
new_flags = []
35113523
libraries = []
3512-
consumed = []
35133524
suffixes = STATICLIB_ENDINGS + DYNAMICLIB_ENDINGS
35143525

35153526
# Find library files
3516-
for i, lib in libs:
3527+
for i, flag in link_flags:
3528+
if not flag.startswith('-l'):
3529+
new_flags.append((i, flag))
3530+
continue
3531+
lib = strip_prefix(flag, '-l')
35173532
logger.debug('looking for library "%s"', lib)
35183533

35193534
path = None
@@ -3525,22 +3540,20 @@ def process_libraries(libs, lib_dirs, linker_inputs):
35253540

35263541
if path:
35273542
linker_inputs.append((i, path))
3528-
consumed.append(i)
3529-
else:
3530-
jslibs = building.map_to_js_libs(lib)
3531-
if jslibs is not None:
3532-
libraries += [(i, jslib) for jslib in jslibs]
3533-
consumed.append(i)
3534-
elif building.map_and_apply_to_settings(lib):
3535-
consumed.append(i)
3543+
continue
3544+
jslibs = building.map_to_js_libs(lib)
3545+
if jslibs is not None:
3546+
libraries += [(i, jslib) for jslib in jslibs]
3547+
elif not building.map_and_apply_to_settings(lib):
3548+
new_flags.append((i, flag))
35363549

35373550
settings.SYSTEM_JS_LIBRARIES += libraries
35383551

35393552
# At this point processing SYSTEM_JS_LIBRARIES is finished, no more items will be added to it.
35403553
# Sort the input list from (order, lib_name) pairs to a flat array in the right order.
35413554
settings.SYSTEM_JS_LIBRARIES.sort(key=lambda lib: lib[0])
35423555
settings.SYSTEM_JS_LIBRARIES = [lib[1] for lib in settings.SYSTEM_JS_LIBRARIES]
3543-
return consumed
3556+
return new_flags
35443557

35453558

35463559
class ScriptSource:

0 commit comments

Comments
 (0)