Skip to content

Commit 43d1f80

Browse files
authored
[NFC] Split optz functions out of libc (#17179)
Put them in a new libc_optz library that will override parts of libc with the size-optimized versions instead. This avoids rebuilding all of libc for optz, and can save a few minutes on build-linux on CI. Avoid optz in MAIN_MODULE=1, because this override method (link in libc_optz first so it overrides libc) conflicts with it. But that is fine, as in MAIN_MODULE=1 the code size benefit of optz is not noticeable anyhow. Add a test for MAIN_MODULE=1 + -Oz, which was missing before. That test would fail without the previous paragraph.
1 parent 47dd661 commit 43d1f80

File tree

4 files changed

+74
-40
lines changed

4 files changed

+74
-40
lines changed

embuilder.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
'libcompiler_rt',
3131
'libc',
3232
'libc-debug',
33-
'libc-optz',
34-
'libc-optz-debug',
33+
'libc_optz',
34+
'libc_optz-debug',
3535
'libc++abi',
3636
'libc++abi-except',
3737
'libc++abi-noexcept',
@@ -67,6 +67,8 @@
6767
'libcompiler_rt-wasm-sjlj',
6868
'libc-mt',
6969
'libc-mt-debug',
70+
'libc_optz-mt',
71+
'libc_optz-mt-debug',
7072
'libc++abi-mt',
7173
'libc++abi-mt-noexcept',
7274
'libc++-mt',

src/library.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,11 @@ mergeInto(LibraryManager.library, {
364364

365365
// In -Oz builds, we replace memcpy() altogether with a non-unrolled wasm
366366
// variant, so we should never emit emscripten_memcpy_big() in the build.
367-
// In STANDALONE_WASM we aviud the emscripten_memcpy_big dependency so keep
367+
// (However, in MAIN_MODULE=1 mode we link in all system libraries, which does
368+
// end up adding code that refers to this.)
369+
// In STANDALONE_WASM we avoid the emscripten_memcpy_big dependency so keep
368370
// the wasm file standalone.
369-
#if SHRINK_LEVEL < 2 && !STANDALONE_WASM
371+
#if (SHRINK_LEVEL < 2 || MAIN_MODULE == 1) && !STANDALONE_WASM
370372

371373
emscripten_memcpy_big__sig: 'vppp',
372374
#if MIN_CHROME_VERSION < 45 || MIN_EDGE_VERSION < 14 || MIN_FIREFOX_VERSION < 34 || MIN_IE_VERSION != TARGET_NOT_SUPPORTED || MIN_SAFARI_VERSION < 100101

tests/test_other.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12028,9 +12028,10 @@ def test_memory64(self):
1202812028
self.do_runf(test_file('hello_world.c'), 'hello, world', emcc_args=['-sMEMORY64', opt])
1202912029

1203012030
# Verfy that MAIN_MODULE=1 (which includes all symbols from all libraries)
12031-
# works with -sPROXY_POSIX_SOCKETS.
12032-
def test_dylink_proxy_posix_sockets(self):
12033-
self.do_runf(test_file('hello_world.cpp'), emcc_args=['-lwebsocket.js', '-sMAIN_MODULE=1', '-sPROXY_POSIX_SOCKETS'])
12031+
# works with -sPROXY_POSIX_SOCKETS and -Oz, both of which affect linking of
12032+
# system libraries in different ways.
12033+
def test_dylink_proxy_posix_sockets_oz(self):
12034+
self.do_runf(test_file('hello_world.cpp'), emcc_args=['-lwebsocket.js', '-sMAIN_MODULE=1', '-sPROXY_POSIX_SOCKETS', '-Oz'])
1203412035

1203512036
def test_in_tree_header_usage(self):
1203612037
# Using headers directly from where they live in the source tree does not work.

tools/system_libs.py

Lines changed: 62 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -529,32 +529,6 @@ def get_default_variation(cls, **kwargs):
529529
return super().get_default_variation(is_debug=settings.ASSERTIONS, **kwargs)
530530

531531

532-
class OptimizedAggressivelyForSizeLibrary(Library):
533-
def __init__(self, **kwargs):
534-
self.is_optz = kwargs.pop('is_optz')
535-
super().__init__(**kwargs)
536-
537-
def get_base_name(self):
538-
name = super().get_base_name()
539-
if self.is_optz:
540-
name += '-optz'
541-
return name
542-
543-
def get_cflags(self):
544-
cflags = super().get_cflags()
545-
if self.is_optz:
546-
cflags += ['-DEMSCRIPTEN_OPTIMIZE_FOR_OZ']
547-
return cflags
548-
549-
@classmethod
550-
def vary_on(cls):
551-
return super().vary_on() + ['is_optz']
552-
553-
@classmethod
554-
def get_default_variation(cls, **kwargs):
555-
return super().get_default_variation(is_optz=settings.SHRINK_LEVEL >= 2, **kwargs)
556-
557-
558532
class Exceptions(IntEnum):
559533
"""
560534
This represents exception handling mode of Emscripten. Currently there are
@@ -727,7 +701,6 @@ class libnoexit(Library):
727701

728702
class libc(MuslInternalLibrary,
729703
DebugLibrary,
730-
OptimizedAggressivelyForSizeLibrary,
731704
AsanInstrumentedLibrary,
732705
MTLibrary):
733706
name = 'libc'
@@ -782,7 +755,6 @@ def get_libcall_files(self):
782755
'__math_oflow.c', '__math_oflowf.c',
783756
'__math_uflow.c', '__math_uflowf.c',
784757
'__math_invalid.c', '__math_invalidf.c', '__math_invalidl.c',
785-
'pow_small.c', 'log_small.c', 'log2_small.c',
786758
'pow.c', 'pow_data.c', 'log.c', 'log_data.c', 'log2.c', 'log2_data.c'
787759
]
788760
math_files = files_in_path(path='system/lib/libc/musl/src/math', filenames=math_files)
@@ -908,10 +880,10 @@ def get_files(self):
908880
'proxying_stub.c',
909881
])
910882

911-
if self.is_optz:
912-
ignore += ['pow.c', 'pow_data.c', 'log.c', 'log_data.c', 'log2.c', 'log2_data.c']
913-
else:
914-
ignore += ['pow_small.c', 'log_small.c', 'log2_small.c']
883+
# These files are in libc directories, but only built in libc_optz.
884+
ignore += [
885+
'pow_small.c', 'log_small.c', 'log2_small.c'
886+
]
915887

916888
ignore = set(ignore)
917889
for dirpath, dirnames, filenames in os.walk(musl_srcdir):
@@ -1041,6 +1013,56 @@ def customize_build_cmd(self, cmd, filename):
10411013
return cmd
10421014

10431015

1016+
# Contains the files from libc that are optimized differently in -Oz mode, where
1017+
# we want to aggressively optimize them for size. This is linked in before libc
1018+
# so we can override those specific files, when in -Oz.
1019+
class libc_optz(libc):
1020+
name = 'libc_optz'
1021+
1022+
cflags = ['-Os', '-fno-builtin', '-DEMSCRIPTEN_OPTIMIZE_FOR_OZ']
1023+
1024+
def __init__(self, **kwargs):
1025+
super().__init__(**kwargs)
1026+
self.non_lto_files = self.get_libcall_files()
1027+
1028+
def get_libcall_files(self):
1029+
# see comments in libc.customize_build_cmd
1030+
1031+
# some files also appear in libc, and a #define affects them
1032+
mem_files = files_in_path(
1033+
path='system/lib/libc',
1034+
filenames=['emscripten_memcpy.c', 'emscripten_memset.c',
1035+
'emscripten_memmove.c'])
1036+
1037+
# some functions have separate files
1038+
math_files = files_in_path(
1039+
path='system/lib/libc/musl/src/math',
1040+
filenames=['pow_small.c', 'log_small.c', 'log2_small.c'])
1041+
1042+
return mem_files + math_files
1043+
1044+
def get_files(self):
1045+
libcall_files = self.get_libcall_files()
1046+
1047+
# some files also appear in libc, and a #define affects them
1048+
mem_files = files_in_path(
1049+
path='system/lib/libc/musl/src/string',
1050+
filenames=['memcmp.c'])
1051+
1052+
return libcall_files + mem_files
1053+
1054+
def customize_build_cmd(self, cmd, filename):
1055+
if filename in self.non_lto_files:
1056+
# see comments in libc.customize_build_cmd
1057+
cmd = [a for a in cmd if not a.startswith('-flto')]
1058+
cmd = [a for a in cmd if not a.startswith('-O')]
1059+
cmd += ['-O2']
1060+
return cmd
1061+
1062+
def can_use(self):
1063+
return super(libc_optz, self).can_use() and settings.SHRINK_LEVEL >= 2
1064+
1065+
10441066
class libprintf_long_double(libc):
10451067
name = 'libprintf_long_double'
10461068
cflags = ['-DEMSCRIPTEN_PRINTF_LONG_DOUBLE']
@@ -1835,9 +1857,16 @@ def add_library(libname):
18351857
if settings.JS_MATH:
18361858
add_library('libjsmath')
18371859

1838-
# to override the normal libc printf, we must come before it
1860+
# C libraries that override libc must come before it
18391861
if settings.PRINTF_LONG_DOUBLE:
18401862
add_library('libprintf_long_double')
1863+
# libc_optz is a size optimization, and therefore not really important when
1864+
# MAIN_MODULE=1 (which links in all system libraries, leading to a large
1865+
# size far bigger than any savings from libc_optz). Also, libc_optz overrides
1866+
# parts of libc, which will not link due to --whole-archive in MAIN_MODULE=1
1867+
# currently.
1868+
if settings.SHRINK_LEVEL >= 2 and settings.MAIN_MODULE != 1:
1869+
add_library('libc_optz')
18411870

18421871
if settings.STANDALONE_WASM:
18431872
add_library('libstandalonewasm')

0 commit comments

Comments
 (0)