Skip to content

Commit 1ca5c7b

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 836f7d8 commit 1ca5c7b

File tree

3 files changed

+90
-72
lines changed

3 files changed

+90
-72
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 & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,21 +1636,12 @@ def add_reverse_deps(need):
16361636
add_reverse_deps(symbols)
16371637

16381638

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'
1639+
def get_libs_to_link(args, forced, only_forced):
1640+
libs_to_link = []
16501641

1651-
handle_reverse_deps(input_files)
1642+
if '-nostdlib' in args:
1643+
return libs_to_link
16521644

1653-
libs_to_link = []
16541645
already_included = set()
16551646
system_libs_map = Library.get_usable_variations()
16561647

@@ -1677,91 +1668,116 @@ def add_library(libname):
16771668
need_whole_archive = lib.name in force_include and lib.get_ext() == '.a'
16781669
libs_to_link.append((lib.get_link_flag(), need_whole_archive))
16791670

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

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

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

16921684
for forced in force_include:
16931685
if forced not in system_libs_map:
16941686
shared.exit_with_error('invalid forced library: %s', forced)
16951687
add_library(forced)
16961688

1689+
if '-nodefaultlibs' in args:
1690+
return libs_to_link
1691+
16971692
if only_forced:
16981693
add_library('libc_rt')
16991694
add_library('libcompiler_rt')
1700-
else:
1701-
if settings.AUTO_NATIVE_LIBRARIES:
1702-
add_library('libGL')
1703-
add_library('libal')
1704-
add_library('libhtml5')
1695+
return libs_to_link
1696+
1697+
if settings.AUTO_NATIVE_LIBRARIES:
1698+
add_library('libGL')
1699+
add_library('libal')
1700+
add_library('libhtml5')
17051701

1706-
sanitize = settings.USE_LSAN or settings.USE_ASAN or settings.UBSAN_RUNTIME
1702+
sanitize = settings.USE_LSAN or settings.USE_ASAN or settings.UBSAN_RUNTIME
17071703

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')
1704+
# JS math must come before anything else, so that it overrides the normal
1705+
# libc math.
1706+
if settings.JS_MATH:
1707+
add_library('libjsmath')
17121708

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

1717-
if settings.ALLOW_UNIMPLEMENTED_SYSCALLS:
1718-
add_library('libstubs')
1713+
if settings.ALLOW_UNIMPLEMENTED_SYSCALLS:
1714+
add_library('libstubs')
1715+
if '-nolibc' not in args:
17191716
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')
17271717
if settings.MALLOC != 'none':
17281718
add_library('libmalloc')
1729-
if settings.STANDALONE_WASM:
1730-
add_library('libstandalonewasm')
1731-
add_library('libc_rt')
1719+
add_library('libcompiler_rt')
1720+
if settings.LINK_AS_CXX:
1721+
add_library('libc++')
1722+
if settings.LINK_AS_CXX or sanitize:
1723+
add_library('libc++abi')
1724+
if settings.EXCEPTION_HANDLING:
1725+
add_library('libunwind')
1726+
if settings.STANDALONE_WASM:
1727+
add_library('libstandalonewasm')
1728+
add_library('libc_rt')
17321729

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

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

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

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

1750-
if sanitize:
1751-
add_library('libsanitizer_common_rt')
1747+
if sanitize:
1748+
add_library('libsanitizer_common_rt')
17521749

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

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

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

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

0 commit comments

Comments
 (0)