From fbecbfd5e27d3718e229e13723cf6c1f1cc23e6e Mon Sep 17 00:00:00 2001 From: Alessio Podda Date: Mon, 29 Sep 2025 08:20:00 +0200 Subject: [PATCH 1/3] Add support for more linkers with LTO Link-time optimization requires close coordination between the compiler and the linker, so not all combinations of compiler and linker support it. Previously, when compiling with Clang, we checked only for lld. With this commit, we expand the list of supported linkers we check for. --- meson.build | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 4315d697c6..66b76da732 100644 --- a/meson.build +++ b/meson.build @@ -923,13 +923,33 @@ assert( # LTO +# Taken from Meson's compilers/mixins/clang.py:get_lto_compile_args +# (technically mold requires version 1.1) +supported_clang_lto_linkers = [ + 'ld64', + 'lld-link', + 'ld.lld', + 'ld.gold', + 'ld.mold', +] + +# On Mac OS, the has_argument check returns true, but compilation fails, so we +# simply disable LTO. +has_fat_lto = cc.has_argument('-ffat-lto-objects') and host_machine.system() != 'darwin' +if not has_fat_lto + warning( + 'Your platform does not support fat lto objects but -Dnamed-lto was not set to off. Building without LTO anyway.', + ) + named_lto_opt = 'off' +endif + static_lto_c_args = [] static_lto_link_args = [] if named_lto_opt == 'full' static_lto_c_args = ['-ffat-lto-objects', '-flto'] static_lto_link_args = ['-flto'] -elif named_lto_opt == 'thin' and cc.get_id() == 'clang' and cc.get_linker_id() == 'ld.lld' +elif named_lto_opt == 'thin' and cc.get_id() == 'clang' and cc.get_linker_id() in supported_clang_lto_linkers # Per LLVM docs [1], -ffat-lto-objects is supported only with lld and gold, # and gold is deprecated/unmantained. # [1]: https://llvm.org/docs/FatLTO.html @@ -940,7 +960,17 @@ elif named_lto_opt == 'thin' and cc.get_id() == 'gcc' static_lto_c_args = ['-ffat-lto-objects', '-flto=auto'] static_lto_link_args = ['-flto=auto'] elif named_lto_opt == 'thin' - error('LTO requires clang with ld.lld, or gcc with any linker') + if cc.get_id() == 'clang' + error( + 'Clang ThinLTO only works with gold, lld, lld-link, ld64 or mold, not ' + + cc.get_linker_id() + + '. To build, use a supported linker or disable LTO with -Dnamed-lto=off.', + ) + else + error( + 'Unsupported configuration for LTO. To build, use a supported linker or disable LTO with -Dnamed-lto=off.', + ) + endif endif add_project_arguments(static_lto_c_args, language: 'c') From d5b8adf084845befccc4a76a3b2c3445ff72cfd3 Mon Sep 17 00:00:00 2001 From: Alessio Podda Date: Tue, 30 Sep 2025 09:19:00 +0200 Subject: [PATCH 2/3] Rename -Dnamed-lto=off to -Dnamed-lto=disabled Meson boolean options are usually configured with enabled/disabled instead of on/off. Make things more consistent with other meson options by renaming -Dnamed-lto=off to -Dnamed-lto=disabled. --- .gitlab-ci.yml | 4 ++-- meson.build | 16 ++++++++-------- meson.options | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 29b3f627f8..2f6b58b9a9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1511,7 +1511,7 @@ clang:tsan: CC: "${CLANG}" CFLAGS: "${CFLAGS_COMMON}" LDFLAGS: "-Wl,--disable-new-dtags" - EXTRA_CONFIGURE: "${TSAN_CONFIGURE_FLAGS_COMMON} -Db_lundef=false -Dnamed-lto=off --native-file ci/clang-trixie.ini" + EXTRA_CONFIGURE: "${TSAN_CONFIGURE_FLAGS_COMMON} -Db_lundef=false -Dnamed-lto=disabled --native-file ci/clang-trixie.ini" <<: *build_job system:clang:tsan: @@ -1985,7 +1985,7 @@ respdiff:tsan: CC: "${CLANG}" CFLAGS: "${CFLAGS_COMMON}" LDFLAGS: "-Wl,--disable-new-dtags" - EXTRA_CONFIGURE: "${TSAN_CONFIGURE_FLAGS_COMMON} -Dnamed-lto=off -Db_lundef=false" + EXTRA_CONFIGURE: "${TSAN_CONFIGURE_FLAGS_COMMON} -Dnamed-lto=disabled -Db_lundef=false" MAX_DISAGREEMENTS_PERCENTAGE: "0.3" TSAN_OPTIONS: "${TSAN_OPTIONS_DEBIAN}" script: diff --git a/meson.build b/meson.build index 66b76da732..199f1a2c65 100644 --- a/meson.build +++ b/meson.build @@ -938,9 +938,9 @@ supported_clang_lto_linkers = [ has_fat_lto = cc.has_argument('-ffat-lto-objects') and host_machine.system() != 'darwin' if not has_fat_lto warning( - 'Your platform does not support fat lto objects but -Dnamed-lto was not set to off. Building without LTO anyway.', + 'Your platform does not support fat lto objects but -Dnamed-lto was not set to `disabled`. Building without LTO anyway.', ) - named_lto_opt = 'off' + named_lto_opt = 'disabled' endif static_lto_c_args = [] @@ -964,17 +964,17 @@ elif named_lto_opt == 'thin' error( 'Clang ThinLTO only works with gold, lld, lld-link, ld64 or mold, not ' + cc.get_linker_id() - + '. To build, use a supported linker or disable LTO with -Dnamed-lto=off.', + + '. To build, use a supported linker or disable LTO with -Dnamed-lto=disabled.', ) else error( - 'Unsupported configuration for LTO. To build, use a supported linker or disable LTO with -Dnamed-lto=off.', + 'Unsupported configuration for LTO. To build, use a supported linker or disable LTO with -Dnamed-lto=disabled.', ) endif endif add_project_arguments(static_lto_c_args, language: 'c') -if named_lto_opt != 'off' and cc.get_id() == 'clang' and sanitizer.contains('address') +if named_lto_opt != 'disabled' and cc.get_id() == 'clang' and sanitizer.contains('address') # Needed to suppress the # warning: Redundant instrumentation detected, with module flag: # nosanitize_address [-Werror,-Wbackend-plugin] @@ -987,7 +987,7 @@ if named_lto_opt != 'off' and cc.get_id() == 'clang' and sanitizer.contains('add add_project_arguments('-Wno-backend-plugin', language: 'c') endif -if meson_lto and named_lto_opt != 'off' +if meson_lto and named_lto_opt != 'disabled' # Meson's builtin LTO settings do not set -ffat-lto-objects, which can cause # build issues. # Since we don't want two, possibly conflicting, sets of LTO flags, we @@ -996,7 +996,7 @@ if meson_lto and named_lto_opt != 'off' error( ''' Meson builtin -Db_lto and BIND's -Dnamed-lto options are incompatible. - Either disable named-lto with -Dnamed-lto=off, or avoid setting + Either disable named-lto with -Dnamed-lto=disabled, or avoid setting -Db_lto. Note that using -Db_lto is not a recommended configuration, might @@ -1572,7 +1572,7 @@ executable( named_deps = [] -if named_lto_opt == 'off' +if named_lto_opt == 'disabled' named_deps = [ libdns_dep, libisc_dep, diff --git a/meson.options b/meson.options index 0fac926a4a..73f70be303 100644 --- a/meson.options +++ b/meson.options @@ -199,7 +199,7 @@ option( option( 'named-lto', type: 'combo', - choices: ['off', 'thin', 'full'], + choices: ['disabled', 'thin', 'full'], value: 'thin', description: 'Enable Link Time Optimization for named.', ) From 1378aeefa5ab01cb301678ea708ba3e7ba95266d Mon Sep 17 00:00:00 2001 From: Alessio Podda Date: Tue, 30 Sep 2025 12:16:53 +0200 Subject: [PATCH 3/3] Add auto LTO option Add an auto option to named-lto that disables weird setups like clang + ld.bfd. --- .gitlab-ci.yml | 1 + doc/arm/build.inc.rst | 8 ++++--- meson.build | 49 ++++++++++++++++++++++++++++++------------- meson.options | 4 ++-- 4 files changed, 43 insertions(+), 19 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2f6b58b9a9..0f3d564ad0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -381,6 +381,7 @@ stages: -Ddeveloper=enabled -Dleak-detection=enabled -Doptimization=1 + -Dnamed-lto=thin $EXTRA_CONFIGURE build diff --git a/doc/arm/build.inc.rst b/doc/arm/build.inc.rst index 0dfaec1ab3..9999b89157 100644 --- a/doc/arm/build.inc.rst +++ b/doc/arm/build.inc.rst @@ -89,9 +89,11 @@ required when in use. To further improve performance, compilation with link-time optimization is recommended. This is enabled by default via the ``-Dnamed-lto`` option -(default: ``thin``). Link-time optimization can be disabled if needed by -using ``-Dnamed-lto=off``. The optimization level can be controlled with -``-Dnamed-lto=thin`` or ``-Dnamed-lto=full``. +(default: ``auto``). Link-time optimization can be disabled if needed by +using ``-Dnamed-lto=disabled``. The optimization level can be controlled with +``-Dnamed-lto=thin`` or ``-Dnamed-lto=full``. The ``auto`` option enables +thin LTO when supported by the compiler and linker combination, and disables +LTO otherwise. Link-time optimization requires close coordination between the compiler and the linker. Due to ``clang`` limitations, compiling ``named`` with ``clang`` diff --git a/meson.build b/meson.build index 199f1a2c65..cb7a6e2620 100644 --- a/meson.build +++ b/meson.build @@ -933,27 +933,48 @@ supported_clang_lto_linkers = [ 'ld.mold', ] -# On Mac OS, the has_argument check returns true, but compilation fails, so we -# simply disable LTO. -has_fat_lto = cc.has_argument('-ffat-lto-objects') and host_machine.system() != 'darwin' -if not has_fat_lto - warning( - 'Your platform does not support fat lto objects but -Dnamed-lto was not set to `disabled`. Building without LTO anyway.', - ) - named_lto_opt = 'disabled' +is_darwin = host_machine.system() == 'darwin' +is_auto_lto = named_lto_opt == 'auto' +is_supported_linker = cc.get_linker_id() in supported_clang_lto_linkers +has_fat_lto = cc.has_argument('-ffat-lto-objects') and not is_darwin +has_fuzzing_backend = fuzzing_backend_opt != 'none' + +# First, resolution of the 'auto' case for LTO. +if is_auto_lto + if has_fuzzing_backend + # Fuzzers might need sanitizer converage sections, which LTO discards. + # Disable LTO when a fuzzing backend is configured. + # NB: enabling -Dfuzzing is fine since it justs builds the binaries. + named_lto_opt = 'disabled' + elif is_darwin + # On Mac OS, the has_argument('-ffat-lto-objects') check returns true, + # but compilation fails, so we simply disable LTO. + named_lto_opt = 'disabled' + elif not has_fat_lto + # Some very old compilers don't support fat lto objects. + named_lto_opt = 'disabled' + elif cc.get_id() == 'clang' and not is_supported_linker + # Per LLVM docs [1], -ffat-lto-objects is supported only with lld and gold, + # and gold is deprecated/unmantained. Manual testing shows that mold + # works too though. + named_lto_opt = 'disabled' + elif get_option('auto_features').disabled() + # Fake being a boolean option for the purpose of -Dauto-features + named_lto_opt = 'disabled' + else + named_lto_opt = 'thin' + endif endif static_lto_c_args = [] static_lto_link_args = [] -if named_lto_opt == 'full' +if developer_mode and is_auto_lto + # Build a static `named` but do not enable -flto to improve compilation speed. +elif named_lto_opt == 'full' static_lto_c_args = ['-ffat-lto-objects', '-flto'] static_lto_link_args = ['-flto'] -elif named_lto_opt == 'thin' and cc.get_id() == 'clang' and cc.get_linker_id() in supported_clang_lto_linkers - # Per LLVM docs [1], -ffat-lto-objects is supported only with lld and gold, - # and gold is deprecated/unmantained. - # [1]: https://llvm.org/docs/FatLTO.html - +elif named_lto_opt == 'thin' and cc.get_id() == 'clang' and is_supported_linker static_lto_c_args = ['-ffat-lto-objects', '-flto=thin'] static_lto_link_args = ['-flto=thin'] elif named_lto_opt == 'thin' and cc.get_id() == 'gcc' diff --git a/meson.options b/meson.options index 73f70be303..ca0d2fc6e1 100644 --- a/meson.options +++ b/meson.options @@ -199,7 +199,7 @@ option( option( 'named-lto', type: 'combo', - choices: ['disabled', 'thin', 'full'], - value: 'thin', + choices: ['disabled', 'auto', 'thin', 'full'], + value: 'auto', description: 'Enable Link Time Optimization for named.', )