Skip to content

Commit 6e10cb9

Browse files
committed
Refactor system library claculation to better handle -nostdlib and friends.
This refactoring splits out `get_libs_to_link` into its own function which can early return once the list is complete. The follow gcc/clang flags are now (kind of) supported: - `-nostartupfiles` - don't link crt1 and other startup files - `-nolibc` - don't link libc - `-nodefualtlibs` - don't link libc or compiler-rt or other stdlibs (but do link startup files) - `-nostdlib` - don't link any system libraries or startup files.
1 parent ef44b94 commit 6e10cb9

File tree

3 files changed

+90
-73
lines changed

3 files changed

+90
-73
lines changed

emcc.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2395,7 +2395,7 @@ def get_full_import_name(name):
23952395
@ToolchainProfiler.profile_block('compile inputs')
23962396
def phase_compile_inputs(options, state, newargs, input_files):
23972397
def is_link_flag(flag):
2398-
if flag.startswith('-nostdlib'):
2398+
if flag in ('-nostdlib', '-nostartfiles', '-nolibc', '-nodefaultlibs'):
23992399
return True
24002400
return flag.startswith(('-l', '-L', '-Wl,'))
24012401

@@ -2561,8 +2561,8 @@ def phase_calculate_system_libraries(state, linker_arguments, linker_inputs, new
25612561
if not settings.SIDE_MODULE:
25622562
# Ports are always linked into the main module, never the size module.
25632563
extra_files_to_link += ports.get_libs(settings)
2564-
if '-nostdlib' not in newargs and '-nodefaultlibs' not in newargs:
2565-
extra_files_to_link += system_libs.calculate([f for _, f in sorted(linker_inputs)] + extra_files_to_link, forced=state.forced_stdlibs)
2564+
all_linker_inputs = [f for _, f in sorted(linker_inputs)] + extra_files_to_link
2565+
extra_files_to_link += system_libs.calculate(all_linker_inputs, newargs, forced=state.forced_stdlibs)
25662566
linker_arguments.extend(extra_files_to_link)
25672567

25682568

tests/test_other.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10081,6 +10081,8 @@ def test_nostdlib(self):
1008110081
libs = ['-lc', '-lcompiler_rt', '-lc_rt']
1008210082
self.run_process([EMCC, test_file('unistd/close.c'), '-nostdlib'] + libs)
1008310083
self.run_process([EMCC, test_file('unistd/close.c'), '-nodefaultlibs'] + libs)
10084+
self.run_process([EMCC, test_file('unistd/close.c'), '-nolibc', '-lc'])
10085+
self.run_process([EMCC, test_file('unistd/close.c'), '-nostartfiles'])
1008410086

1008510087
def test_argument_match(self):
1008610088
# Verify that emcc arguments match precisely. We had a bug where only the prefix

tools/system_libs.py

Lines changed: 85 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,22 +1635,12 @@ def add_reverse_deps(need):
16351635
for symbols in symbolses:
16361636
add_reverse_deps(symbols)
16371637

1638+
def get_libs_to_link(args, forced, only_forced):
1639+
libs_to_link = []
16381640

1639-
def calculate(input_files, forced):
1640-
# Setting this will only use the forced libs in EMCC_FORCE_STDLIBS. This avoids spending time checking
1641-
# for unresolved symbols in your project files, which can speed up linking, but if you do not have
1642-
# the proper list of actually needed libraries, errors can occur. See below for how we must
1643-
# export all the symbols in deps_info when using this option.
1644-
only_forced = os.environ.get('EMCC_ONLY_FORCED_STDLIBS')
1645-
if only_forced:
1646-
# One of the purposes EMCC_ONLY_FORCED_STDLIBS was to skip the scanning
1647-
# of the input files for reverse dependencies.
1648-
diagnostics.warning('deprecated', 'EMCC_ONLY_FORCED_STDLIBS is deprecated. Use `-nostdlib` and/or `-s REVERSE_DEPS=none` depending on the desired result')
1649-
settings.REVERSE_DEPS = 'all'
1650-
1651-
handle_reverse_deps(input_files)
1641+
if '-nostdlib' in args:
1642+
return libs_to_link
16521643

1653-
libs_to_link = []
16541644
already_included = set()
16551645
system_libs_map = Library.get_usable_variations()
16561646

@@ -1677,91 +1667,116 @@ def add_library(libname):
16771667
need_whole_archive = lib.name in force_include and lib.get_ext() == '.a'
16781668
libs_to_link.append((lib.get_link_flag(), need_whole_archive))
16791669

1680-
if settings.USE_PTHREADS:
1681-
add_library('crtbegin')
1670+
if '-nostartfiles' not in args:
1671+
if settings.USE_PTHREADS:
1672+
add_library('crtbegin')
16821673

1683-
if settings.SIDE_MODULE:
1684-
return [l[0] for l in libs_to_link]
1674+
if settings.STANDALONE_WASM:
1675+
if settings.EXPECT_MAIN:
1676+
add_library('crt1')
1677+
else:
1678+
add_library('crt1_reactor')
16851679

1686-
if settings.STANDALONE_WASM:
1687-
if settings.EXPECT_MAIN:
1688-
add_library('crt1')
1689-
else:
1690-
add_library('crt1_reactor')
1680+
if settings.SIDE_MODULE:
1681+
return libs_to_link
16911682

16921683
for forced in force_include:
16931684
if forced not in system_libs_map:
16941685
shared.exit_with_error('invalid forced library: %s', forced)
16951686
add_library(forced)
16961687

1688+
if '-nodefaultlibs' in args:
1689+
return libs_to_link
1690+
16971691
if only_forced:
16981692
add_library('libc_rt')
16991693
add_library('libcompiler_rt')
1700-
else:
1701-
if settings.AUTO_NATIVE_LIBRARIES:
1702-
add_library('libGL')
1703-
add_library('libal')
1704-
add_library('libhtml5')
1694+
return libs_to_link
1695+
1696+
if settings.AUTO_NATIVE_LIBRARIES:
1697+
add_library('libGL')
1698+
add_library('libal')
1699+
add_library('libhtml5')
17051700

1706-
sanitize = settings.USE_LSAN or settings.USE_ASAN or settings.UBSAN_RUNTIME
1701+
sanitize = settings.USE_LSAN or settings.USE_ASAN or settings.UBSAN_RUNTIME
17071702

1708-
# JS math must come before anything else, so that it overrides the normal
1709-
# libc math.
1710-
if settings.JS_MATH:
1711-
add_library('libjsmath')
1703+
# JS math must come before anything else, so that it overrides the normal
1704+
# libc math.
1705+
if settings.JS_MATH:
1706+
add_library('libjsmath')
17121707

1713-
# to override the normal libc printf, we must come before it
1714-
if settings.PRINTF_LONG_DOUBLE:
1715-
add_library('libprintf_long_double')
1708+
# to override the normal libc printf, we must come before it
1709+
if settings.PRINTF_LONG_DOUBLE:
1710+
add_library('libprintf_long_double')
17161711

1717-
if settings.ALLOW_UNIMPLEMENTED_SYSCALLS:
1718-
add_library('libstubs')
1712+
if settings.ALLOW_UNIMPLEMENTED_SYSCALLS:
1713+
add_library('libstubs')
1714+
if '-nolibc' not in args:
17191715
add_library('libc')
1720-
add_library('libcompiler_rt')
1721-
if settings.LINK_AS_CXX:
1722-
add_library('libc++')
1723-
if settings.LINK_AS_CXX or sanitize:
1724-
add_library('libc++abi')
1725-
if settings.EXCEPTION_HANDLING:
1726-
add_library('libunwind')
17271716
if settings.MALLOC != 'none':
17281717
add_library('libmalloc')
1729-
if settings.STANDALONE_WASM:
1730-
add_library('libstandalonewasm')
1731-
add_library('libc_rt')
1718+
add_library('libcompiler_rt')
1719+
if settings.LINK_AS_CXX:
1720+
add_library('libc++')
1721+
if settings.LINK_AS_CXX or sanitize:
1722+
add_library('libc++abi')
1723+
if settings.EXCEPTION_HANDLING:
1724+
add_library('libunwind')
1725+
if settings.STANDALONE_WASM:
1726+
add_library('libstandalonewasm')
1727+
add_library('libc_rt')
17321728

1733-
if settings.USE_LSAN:
1734-
force_include.add('liblsan_rt')
1735-
add_library('liblsan_rt')
1729+
if settings.USE_LSAN:
1730+
force_include.add('liblsan_rt')
1731+
add_library('liblsan_rt')
17361732

1737-
if settings.USE_ASAN:
1738-
force_include.add('libasan_rt')
1739-
add_library('libasan_rt')
1740-
add_library('libasan_js')
1733+
if settings.USE_ASAN:
1734+
force_include.add('libasan_rt')
1735+
add_library('libasan_rt')
1736+
add_library('libasan_js')
17411737

1742-
if settings.UBSAN_RUNTIME == 1:
1743-
add_library('libubsan_minimal_rt')
1744-
elif settings.UBSAN_RUNTIME == 2:
1745-
add_library('libubsan_rt')
1738+
if settings.UBSAN_RUNTIME == 1:
1739+
add_library('libubsan_minimal_rt')
1740+
elif settings.UBSAN_RUNTIME == 2:
1741+
add_library('libubsan_rt')
17461742

1747-
if settings.USE_LSAN or settings.USE_ASAN:
1748-
add_library('liblsan_common_rt')
1743+
if settings.USE_LSAN or settings.USE_ASAN:
1744+
add_library('liblsan_common_rt')
17491745

1750-
if sanitize:
1751-
add_library('libsanitizer_common_rt')
1746+
if sanitize:
1747+
add_library('libsanitizer_common_rt')
17521748

1753-
if settings.PROXY_POSIX_SOCKETS:
1754-
add_library('libsockets_proxy')
1755-
else:
1756-
add_library('libsockets')
1749+
if settings.PROXY_POSIX_SOCKETS:
1750+
add_library('libsockets_proxy')
1751+
else:
1752+
add_library('libsockets')
1753+
1754+
if settings.USE_WEBGPU:
1755+
add_library('libwebgpu_cpp')
1756+
1757+
return libs_to_link
1758+
1759+
1760+
def calculate(input_files, args, forced):
1761+
# Setting this will only use the forced libs in EMCC_FORCE_STDLIBS. This avoids spending time checking
1762+
# for unresolved symbols in your project files, which can speed up linking, but if you do not have
1763+
# the proper list of actually needed libraries, errors can occur. See below for how we must
1764+
# export all the symbols in deps_info when using this option.
1765+
only_forced = os.environ.get('EMCC_ONLY_FORCED_STDLIBS')
1766+
if only_forced:
1767+
# One of the purposes EMCC_ONLY_FORCED_STDLIBS was to skip the scanning
1768+
# of the input files for reverse dependencies.
1769+
diagnostics.warning('deprecated', 'EMCC_ONLY_FORCED_STDLIBS is deprecated. Use `-nostdlib` and/or `-s REVERSE_DEPS=none` depending on the desired result')
1770+
settings.REVERSE_DEPS = 'all'
1771+
1772+
handle_reverse_deps(input_files)
17571773

1758-
if settings.USE_WEBGPU:
1759-
add_library('libwebgpu_cpp')
1774+
libs_to_link = get_libs_to_link(args, forced, only_forced)
17601775

17611776
# When LINKABLE is set the entire link command line is wrapped in --whole-archive by
17621777
# building.link_ldd. And since --whole-archive/--no-whole-archive processing does not nest we
17631778
# shouldn't add any extra `--no-whole-archive` or we will undo the intent of building.link_ldd.
1764-
if settings.LINKABLE:
1779+
if settings.LINKABLE or settings.SIDE_MODULE:
17651780
return [l[0] for l in libs_to_link]
17661781

17671782
# Wrap libraries in --whole-archive, as needed. We need to do this last

0 commit comments

Comments
 (0)