perf: Link dllbinaryen.so from libbinaryen.a instead of compiling Binaryen twice - #179
Conversation
Under Cygwin/MSYS2 CMake cannot find a usable C/C++ compiler on its own. Previously the shared-library rule configured the same build directory first with -DCMAKE_C_COMPILER/-DCMAKE_CXX_COMPILER/-DCMAKE_SYSTEM_NAME, and the static rule inherited them from CMakeCache.txt. Now that the shared library is linked from the static archive nothing seeds the cache, so give the static rule the same settings on mingw64.
|
The first CI run failed on all three Windows jobs (and on
Previously the shared-library rule ran Verified in a fresh Cygwin + MinGW GCC 14.4 container with OCaml 5.4 (mingw64): |
|
Thanks so much! |
On every platform, the
dunefile compiles the whole Binaryen tree twice: once with-DBUILD_SHARED_LIBS=OFFto producelibbinaryen.a, and then again with-DBUILD_SHARED_LIBS=ONto producedllbinaryen.so. Both runs configure into the samebinaryenbuilddirectory, and because the toggle changes the compile definitions, CMake
rebuilds all ~270 translation units the second time.
The second compile is redundant on these platforms:
CMakeLists.txtalways adds-fPICon non-Windows,non-Emscripten builds, so the objects in the static archive are already
position independent.
BUILD_SHARED_LIBSdefinition is only consulted under_MSC_VERinsrc/binaryen-c.h, so the objects are otherwise identical.llvm_dwarfis anOBJECTlibrary, so its objects are already insidelibbinaryen.a.This change makes the
dllbinaryen.so/dllbinaryen.dllrules depend onlibbinaryen.aand link it withc++ -shared -Wl,--whole-archive(Linux andother Unix, keeping the
-Bsymbolicand--no-undefinedflags Binaryen's ownCMake uses there),
c++ -dynamiclib -Wl,-all_load(macOS), orx86_64-w64-mingw32-g++ -shared -Wl,--whole-archive(mingw64, the compilerthe previous rule passed to CMake).
c++is the compiler CMake picks by default, so the shared object islinked against the same C++ runtime the objects were compiled with (libstdc++
with GCC on Linux, libc++ with Clang on FreeBSD).
Verification (x86_64 Linux, GCC 13, and v129/v132 trees)
nm -D --defined-onlyon the relinkeddllbinaryen.solists exactly thesame exported symbols as the
libbinaryen.soproduced by CMake's ownshared build (25,600 symbols on v129, 15,511 on v132, zero differences).
dune build -p libbinaryen @installanddune runtestpass.dllbinaryen.sothroughocamlrunand runs.dllbinaryen.socreates,validates, optimises and prints a module.
the same 10,480 symbols as CMake's
libbinaryen.dylib, depends on the samelibc++/libSystem, and passes the dlopen and C smoke tests.dllbinaryen.dllexports exactly the same 14,388 symbols as CMake's DLL andimports the same runtime DLLs. The relink takes ~25 s where the second
compile took ~20 min.
Effect
The full Binaryen compile is roughly 50 CPU-minutes on a fast x86_64 machine
and several CPU-hours on RISC-V, so this halves the cost of installing the
package. On the opam-repository CI, the RISC-V workers currently hit the
4-hour job timeout just after finishing the first compile; with this change
they finish with time to spare.
No platform still compiles Binaryen twice; the esy Windows build was not exercised, only the opam/Cygwin one.