Skip to content

Commit 7b3716a

Browse files
committed
Fix for -lGL + AUTO_NATIVE_LIBRARIES=0
When calling `map_to_js_libs('GL')` we were mapping this to the JS libraries, and not also including the native `libgl` library. Normally this doesn't matter since `libgl` is included by default, but not when `AUTO_NATIVE_LIBRARIES=0` is used. This also happens to fix an old bug (#10171) where we would look on the file system for `libGL.a` before looking in `map_to_js_libs`. Fixes: #10171 Fixes: #14335
1 parent 708b8f2 commit 7b3716a

File tree

4 files changed

+44
-23
lines changed

4 files changed

+44
-23
lines changed

emcc.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,7 +1050,7 @@ def run(args):
10501050
if state.mode == Mode.POST_LINK_ONLY:
10511051
settings.limit_settings(None)
10521052
target, wasm_target = phase_linker_setup(options, state, newargs, settings_map)
1053-
process_libraries(state.link_flags, state.lib_dirs, [])
1053+
process_libraries(state, [])
10541054
if len(input_files) != 1:
10551055
exit_with_error('--post-link requires a single input file')
10561056
phase_post_link(options, state, input_files[0][1], wasm_target, target)
@@ -1113,7 +1113,7 @@ def phase_calculate_linker_inputs(options, state, linker_inputs):
11131113
state.link_flags = filter_link_flags(state.link_flags, using_lld)
11141114

11151115
# Decide what we will link
1116-
state.link_flags = process_libraries(state.link_flags, state.lib_dirs, linker_inputs)
1116+
state.link_flags = process_libraries(state, linker_inputs)
11171117

11181118
linker_args = [val for _, val in sorted(linker_inputs + state.link_flags)]
11191119

@@ -3502,18 +3502,20 @@ def find_library(lib, lib_dirs):
35023502
return None
35033503

35043504

3505-
def process_libraries(link_flags, lib_dirs, linker_inputs):
3505+
def process_libraries(state, linker_inputs):
35063506
new_flags = []
35073507
libraries = []
35083508
suffixes = STATICLIB_ENDINGS + DYNAMICLIB_ENDINGS
35093509
system_libs_map = system_libs.Library.get_usable_variations()
35103510

35113511
# Find library files
3512-
for i, flag in link_flags:
3512+
for i, flag in state.link_flags:
35133513
if not flag.startswith('-l'):
35143514
new_flags.append((i, flag))
35153515
continue
3516+
35163517
lib = strip_prefix(flag, '-l')
3518+
logger.debug('looking for library "%s"', lib)
35173519
# We don't need to resolve system libraries to absolute paths here, we can just
35183520
# let wasm-ld handle that. However, we do want to map to the correct variant.
35193521
# For example we map `-lc` to `-lc-mt` if we are building with threading support.
@@ -3522,23 +3524,30 @@ def process_libraries(link_flags, lib_dirs, linker_inputs):
35223524
new_flags.append((i, '-l' + strip_prefix(lib.get_base_name(), 'lib')))
35233525
continue
35243526

3525-
logger.debug('looking for library "%s"', lib)
3527+
js_libs, native_lib = building.map_to_js_libs(lib)
3528+
if js_libs is not None:
3529+
libraries += [(i, js_lib) for js_lib in js_libs]
3530+
# If native_lib is returned then include it in the link
3531+
# via forced_stdlibs.
3532+
if native_lib:
3533+
state.forced_stdlibs.append(native_lib)
3534+
continue
3535+
3536+
if building.map_and_apply_to_settings(lib):
3537+
continue
35263538

35273539
path = None
35283540
for suff in suffixes:
35293541
name = 'lib' + lib + suff
3530-
path = find_library(name, lib_dirs)
3542+
path = find_library(name, state.lib_dirs)
35313543
if path:
35323544
break
35333545

35343546
if path:
35353547
linker_inputs.append((i, path))
35363548
continue
3537-
jslibs = building.map_to_js_libs(lib)
3538-
if jslibs is not None:
3539-
libraries += [(i, jslib) for jslib in jslibs]
3540-
elif not building.map_and_apply_to_settings(lib):
3541-
new_flags.append((i, flag))
3549+
3550+
new_flags.append((i, flag))
35423551

35433552
settings.SYSTEM_JS_LIBRARIES += libraries
35443553

tests/other/test_explict_gl_linking.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include <EGL/egl.h>
2+
3+
int main() {
4+
return (int)eglGetProcAddress("foo");
5+
}

tests/test_other.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10642,3 +10642,8 @@ def test_standard_library_mapping(self):
1064210642
self.assertContained(' -lc-mt ', err)
1064310643
self.assertContained(' -ldlmalloc-mt ', err)
1064410644
self.assertContained(' -lcompiler_rt-mt ', err)
10645+
10646+
def test_explict_gl_linking(self):
10647+
# ensure libgl exists
10648+
self.run_process([EMBUILDER, 'build', 'libgl'])
10649+
self.run_process([EMCC, test_file('other/test_explict_gl_linking.c'), '-sNO_AUTO_NATIVE_LIBRARIES', '-lGL'])

tools/building.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,10 +1333,14 @@ def is_wasm_dylib(filename):
13331333
return False
13341334

13351335

1336-
# Given the name of a special Emscripten-implemented system library, returns an
1337-
# array of absolute paths to JS library files inside emscripten/src/ that
1338-
# corresponds to the library name.
13391336
def map_to_js_libs(library_name):
1337+
"""Given the name of a special Emscripten-implemented system library, returns an
1338+
pair containing
1339+
1. Array of absolute paths to JS library files, inside emscripten/src/ that corresponds to the
1340+
library name. `None` means there is no mapping and the library will be processed by the linker
1341+
as a require for normal native library.
1342+
2. Optional name of a corresponding native library to link in.
1343+
"""
13401344
# Some native libraries are implemented in Emscripten as system side JS libraries
13411345
library_map = {
13421346
'EGL': ['library_egl.js'],
@@ -1364,23 +1368,21 @@ def map_to_js_libs(library_name):
13641368
# This is the name of GNU's C++ standard library. We ignore it here
13651369
# for compatability with GNU toolchains.
13661370
'stdc++': [],
1367-
# This means that linking against libc with `-lc` is ignored when the
1368-
# library is not found (It does work if library already exists in the
1369-
# sysroot because that case is handled before we call (map_to_js_libs).
1370-
# TODO(sbc): We should probably remove this and allow `-lc` to make to all
1371-
# the way to the linker.
1372-
'c': [],
1371+
}
1372+
# And some are hybrid and require JS and native libraries to be included
1373+
native_library_map = {
1374+
'GL': 'libgl',
13731375
}
13741376

13751377
if library_name in library_map:
13761378
libs = library_map[library_name]
13771379
logger.debug('Mapping library `%s` to JS libraries: %s' % (library_name, libs))
1378-
return libs
1380+
return (libs, native_library_map.get(library_name))
13791381

13801382
if library_name.endswith('.js') and os.path.isfile(path_from_root('src', 'library_' + library_name)):
1381-
return ['library_' + library_name]
1383+
return (['library_' + library_name], None)
13821384

1383-
return None
1385+
return (None, None)
13841386

13851387

13861388
# Map a linker flag to a settings. This lets a user write -lSDL2 and it will have the same effect as

0 commit comments

Comments
 (0)