From 461ac6deefb44c004953cf2e4fc3f7ca13a576a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Di=20Remigio=20Eik=C3=A5s?= Date: Fri, 3 Jul 2026 10:42:33 +0200 Subject: [PATCH 1/4] build: enable LTO for libmonoprop.so --- src/monoprop/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/monoprop/CMakeLists.txt b/src/monoprop/CMakeLists.txt index b9848917..bd278d0f 100644 --- a/src/monoprop/CMakeLists.txt +++ b/src/monoprop/CMakeLists.txt @@ -55,6 +55,8 @@ set_target_properties( hidden VISIBILITY_INLINES_HIDDEN YES + INTERPROCEDURAL_OPTIMIZATION + ON PUBLIC_HEADER "${monoprop_PUBLIC_HEADERS}" PRIVATE_HEADER From 6aca8606813950293b08ffa78b54502e2750df3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Di=20Remigio=20Eik=C3=A5s?= Date: Fri, 3 Jul 2026 10:42:56 +0200 Subject: [PATCH 2/4] build(nanobind): re-enable LTO for bindings, suppress warnings --- src/monoprop/bindings/CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/monoprop/bindings/CMakeLists.txt b/src/monoprop/bindings/CMakeLists.txt index f96ae89f..44a4cbf0 100644 --- a/src/monoprop/bindings/CMakeLists.txt +++ b/src/monoprop/bindings/CMakeLists.txt @@ -115,9 +115,11 @@ configure_file( ) nanobind_add_module(_core - STABLE_ABI # Perform a stable ABI build - NB_STATIC # Compile the core nanobind library as a static library - NOMINSIZE # Don’t perform optimizations to minimize binary size + STABLE_ABI # perform a stable ABI build + NB_SUPPRESS_WARNINGS # suppress warnings from nanobind and Python headers + NB_STATIC # compile the core nanobind library as a static library + NOMINSIZE # don’t perform optimizations to minimize binary size + LTO # perform link-time optimization ${CMAKE_CURRENT_BINARY_DIR}/bindings.cpp ${_bind_cpps} # List of generated binders ) From 02e2ebda33859005a415e796b6305f08e1a2d988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Di=20Remigio=20Eik=C3=A5s?= Date: Mon, 13 Jul 2026 08:06:09 +0200 Subject: [PATCH 3/4] build: generate header for multiversioning Added also a variant and machine_flags functions (generated) that report the chosen variant and corresponding machine-dependent compiler flags --- cmake/compiler_flags/CXXFlags.cmake | 126 ++++++++++++++++-- include/monoprop/FunctionMultiversioning.h.in | 75 +++++++++++ include/monoprop/Info.h.in | 4 +- src/monoprop/__init__.py | 2 + src/monoprop/bindings/bindings.cpp.in | 19 +-- tests/test_gcc_target_help_clean.py | 98 ++++++++++++++ tools/gcc-target-help-clean.py | 80 +++++++++++ 7 files changed, 382 insertions(+), 22 deletions(-) create mode 100644 include/monoprop/FunctionMultiversioning.h.in create mode 100644 tests/test_gcc_target_help_clean.py create mode 100644 tools/gcc-target-help-clean.py diff --git a/cmake/compiler_flags/CXXFlags.cmake b/cmake/compiler_flags/CXXFlags.cmake index 345dc776..b7ef5a13 100644 --- a/cmake/compiler_flags/CXXFlags.cmake +++ b/cmake/compiler_flags/CXXFlags.cmake @@ -15,9 +15,7 @@ # - ``CMAKE_CXX_FLAGS_`` are build-type specific compiler flags. # The defaults are compiler-dependent: have a look at the ``GNU.CXX.cmake``, # ``Clang.CXX.cmake``, and ``Intel.CXX.cmake`` files. -# - ``ARCH_FLAG`` is the architecture-dependent optimization flag, *e.g.* -# vectorization. Default is empty. -# - ``monoprop_CXX_FLAGS`` are monoprop-specific flags to be used for all builds. +# - ``monoprop_CXX_FLAGS`` are monorop-specific flags to be used for all builds. # The defaults are compiler-dependent: have a look at the ``GNU.CXX.cmake``, # ``Clang.CXX.cmake``, and ``Intel.CXX.cmake`` files. # - ``EXTRA_CXXFLAGS`` useful if you need to append certain flags to the full @@ -26,7 +24,7 @@ # # Variables used:: # -# monoprop_ENABLE_ARCH_FLAGS +# monoprop_ENABLE_MULTIVERSIONING # EXTRA_CXXFLAGS # # Variables modified:: @@ -37,7 +35,7 @@ # # CXXFLAGS -option_with_print(monoprop_ENABLE_ARCH_FLAGS "Enable architecture-specific compiler flags" ON) +option_with_print(monoprop_ENABLE_MULTIVERSIONING "Enable function multiversioning" ON) # code needs C++23 at least set(CMAKE_CXX_STANDARD 23) @@ -52,19 +50,121 @@ set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) set(CMAKE_CXX_VISIBILITY_PRESET "hidden") set(CMAKE_VISIBILITY_INLINES_HIDDEN TRUE) -set(ARCH_FLAG "") -if(monoprop_ENABLE_ARCH_FLAGS AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug") - if(CMAKE_CXX_COMPILER_ID MATCHES GNU) - set(ARCH_FLAG "-march=native") +# Query the machine-dependent flags for a given -march value and store the +# cleaned, space-separated string in the variable named by OUTPUT_VARIABLE. A +# MARCH of "default" queries the default target (no -march flag). +# +# Usage: +# _monoprop_query_machine_flags(MARCH OUTPUT_VARIABLE ) +function(_monoprop_query_machine_flags) + set(_one_value_args MARCH OUTPUT_VARIABLE) + cmake_parse_arguments(PARSE_ARGV 0 _arg "" "${_one_value_args}" "") + + if(NOT _arg_OUTPUT_VARIABLE) + message(FATAL_ERROR "_monoprop_query_machine_flags: OUTPUT_VARIABLE is required") + endif() + if(NOT _arg_MARCH) + message(FATAL_ERROR "_monoprop_query_machine_flags: MARCH is required") endif() - if(CMAKE_CXX_COMPILER_ID MATCHES Clang) - set(ARCH_FLAG "-march=native") + + if(_arg_MARCH STREQUAL "default") + set(_march_args "") + else() + set(_march_args "-march=${_arg_MARCH}") + endif() + execute_process( + COMMAND ${CMAKE_CXX_COMPILER} ${_march_args} -Q --help=target + COMMAND ${Python_EXECUTABLE} ${_machine_flags_cleaner} + OUTPUT_VARIABLE _flags + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE _result + ) + if(NOT _result EQUAL 0) + message( + FATAL_ERROR + "Failed to query machine-dependent flags for '${_arg_MARCH}' (exit code ${_result})" + ) endif() - if(CMAKE_CXX_COMPILER_ID MATCHES Intel) - set(ARCH_FLAG "-xHost") + set(${_arg_OUTPUT_VARIABLE} "${_flags}" PARENT_SCOPE) +endfunction() + +# Report the machine-dependent flags GCC uses for each target variant by +# querying `gcc -march= -Q --help=target` and cleaning the output with +# tools/gcc-target-help-clean.py. +find_package(Python COMPONENTS Interpreter REQUIRED QUIET) +set(_machine_flags_cleaner "${PROJECT_SOURCE_DIR}/tools/gcc-target-help-clean.py") + +set(monoprop_MACHINE_FLAGS_DEFAULT "") +_monoprop_query_machine_flags(MARCH default OUTPUT_VARIABLE monoprop_MACHINE_FLAGS_DEFAULT) + +set(monoprop_TARGET_CLONES "") +set(monoprop_VARIANTS "") +set(monoprop_MACHINE_FLAGS_VARIANTS "") +# function multiversioning is only enabled in release builds on x86_64 architectures +if( + monoprop_ENABLE_MULTIVERSIONING + AND + NOT + CMAKE_BUILD_TYPE + STREQUAL + "Debug" + AND + CMAKE_HOST_SYSTEM_PROCESSOR + MATCHES + "x86_64" +) + if(NOT CMAKE_CXX_COMPILER_ID MATCHES GNU) + message( + FATAL_ERROR + "Multiversioning is only supported with GNU compilers. Please disable monoprop_ENABLE_MULTIVERSIONING or use a GNU compiler." + ) + else() + list( + APPEND _targets + "x86-64-v2" + "x86-64-v3" + "x86-64-v4" + "icelake-server" + "sapphirerapids" + "graniterapids" + "znver3" + "znver4" + "znver5" + ) + + set(_targets_arch "") + foreach(_target IN LISTS _targets) + list(APPEND _targets_arch "\"arch=${_target}\"") + endforeach() + list(JOIN _targets_arch ", " TARGETS) + + message(STATUS "Function multiversioning targets: \"default\", ${TARGETS}") + set(monoprop_TARGET_CLONES "[[using gnu: flatten, target_clones(\"default\", ${TARGETS})]]") + set(_variants "") + foreach(_target IN LISTS _targets) + string(APPEND _variants "monoprop_FMV_VARIANT(\"${_target}\")\n") + endforeach() + set(monoprop_VARIANTS "${_variants}") + + set(_machine_flags_variants "") + foreach(_target IN LISTS _targets) + _monoprop_query_machine_flags(MARCH "${_target}" OUTPUT_VARIABLE _target_machine_flags) + string( + APPEND _machine_flags_variants + "monoprop_FMV_MACHINE_FLAGS(\"${_target}\", \"${_target_machine_flags}\")\n" + ) + endforeach() + set(monoprop_MACHINE_FLAGS_VARIANTS "${_machine_flags_variants}") endif() endif() +# generate a header file with a macro containing (or not) the function multiversioning attribute +configure_file( + ${PROJECT_SOURCE_DIR}/include/monoprop/FunctionMultiversioning.h.in + ${PROJECT_BINARY_DIR}/include/monoprop/FunctionMultiversioning.h + @ONLY +) + set(monoprop_CXX_FLAGS "") include(${CMAKE_CURRENT_LIST_DIR}/GNU.CXX.cmake) include(${CMAKE_CURRENT_LIST_DIR}/Intel.CXX.cmake) diff --git a/include/monoprop/FunctionMultiversioning.h.in b/include/monoprop/FunctionMultiversioning.h.in new file mode 100644 index 00000000..af7edc38 --- /dev/null +++ b/include/monoprop/FunctionMultiversioning.h.in @@ -0,0 +1,75 @@ +// Copyright 2026 Algorithmiq +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +/** + * @brief Attribute used to enable function multiversioning target clones. + * + * This macro is configured at build time and expands to the compiler-specific + * attribute declaration. + */ +// clang-format off +#define monoprop_TARGET_CLONES @monoprop_TARGET_CLONES@ +// clang-format on + +/** + * @brief Declares a compile-time function that reports the active FMV variant. + * + * Expands to a `consteval` function named `variant()` with a GNU + * `target("arch=...")` attribute bound to the provided architecture string. + * + * @param archstr Architecture suffix used in `arch=`. + */ +#define monoprop_FMV_VARIANT(archstr) \ + [[using gnu: target("arch=" archstr)]] consteval auto variant() noexcept -> std::string_view { \ + return "arch=" archstr; \ + } + +/** + * @brief Declares a compile-time function that reports the machine-dependent + * flags GCC applies for the given FMV variant. + * + * Expands to a `consteval` function named `machine_flags()` with a GNU + * `target("arch=...")` attribute bound to the provided architecture string. The + * returned value is the cleaned, space-separated list of machine flags GCC uses + * for that architecture, as reported by `gcc -march= -Q --help=target`. + * + * @param archstr Architecture suffix used in `arch=`. + * @param flagsstr Machine-dependent flags reported for the architecture. + */ +#define monoprop_FMV_MACHINE_FLAGS(archstr, flagsstr) \ + [[using gnu: target("arch=" archstr)]] consteval auto machine_flags() noexcept -> std::string_view { \ + return flagsstr; \ + } + +namespace monoprop { +[[using gnu: target("default")]] consteval auto variant() noexcept -> std::string_view { + return "default"; +} + +// clang-format off +@monoprop_VARIANTS@ + // clang-format on + + [[using gnu: target("default")]] consteval auto machine_flags() noexcept -> std::string_view { + return "@monoprop_MACHINE_FLAGS_DEFAULT@"; +} + +// clang-format off +@monoprop_MACHINE_FLAGS_VARIANTS@ +// clang-format on +} // namespace monoprop diff --git a/include/monoprop/Info.h.in b/include/monoprop/Info.h.in index 21e6ee9e..e7247955 100644 --- a/include/monoprop/Info.h.in +++ b/include/monoprop/Info.h.in @@ -18,6 +18,8 @@ #include #include +#include "monoprop/FunctionMultiversioning.h" + namespace monoprop { static constexpr auto version() noexcept -> std::string_view { return "@PROJECT_VERSION_FULL@"; @@ -35,7 +37,7 @@ static auto compiler_flags() noexcept -> std::map { return { {"from-environment", "@CMAKE_CXX_FLAGS@"}, {"build-type-flags", "@_cmake_build_type_specific_flags@"}, - {"vectorization", "@ARCH_FLAG@"}, + {"machine-flags", std::string(machine_flags())}, {"project-defaults", "@CMAKE_CXX23_STANDARD_COMPILE_OPTION@ @monoprop_CXX_FLAGS@"}, {"user-appended", "@EXTRA_CXXFLAGS@"}, }; diff --git a/src/monoprop/__init__.py b/src/monoprop/__init__.py index 95f82fe7..69ba6c0d 100644 --- a/src/monoprop/__init__.py +++ b/src/monoprop/__init__.py @@ -25,6 +25,7 @@ MAX_NUM_MODES, __build_type__, __compiler_flags__, + __variant__, antihermitian_generator_correction, has_mpi, is_antihermitian, @@ -60,6 +61,7 @@ "PauliPropagator", "__build_type__", "__compiler_flags__", + "__variant__", "__version__", "antihermitian_generator_correction", "expand_monomials", diff --git a/src/monoprop/bindings/bindings.cpp.in b/src/monoprop/bindings/bindings.cpp.in index 16573ce3..8598ae49 100644 --- a/src/monoprop/bindings/bindings.cpp.in +++ b/src/monoprop/bindings/bindings.cpp.in @@ -20,10 +20,11 @@ #endif #include "generated/bind.h" +#include "monoprop/FunctionMultiversioning.h" #include "monoprop/Info.h" #include "monoprop/MPFunctions.h" -#include "monoprop/detail/mpi/MPICompat.h" #include "monoprop/Threading.h" +#include "monoprop/detail/mpi/MPICompat.h" using namespace monoprop; using namespace nanobind::literals; @@ -48,10 +49,10 @@ auto get_mpi_comm(nb::object obj) -> MPI_Comm { auto cutoff_type_str_2_enum(const std::string &cutoff_type) -> CutoffType { if (cutoff_type == "length") { - return monoprop::CutoffType::Length; + return CutoffType::Length; } else if (cutoff_type == "support") { - return monoprop::CutoffType::Support; + return CutoffType::Support; } else { throw std::invalid_argument( @@ -62,9 +63,9 @@ auto cutoff_type_str_2_enum(const std::string &cutoff_type) -> CutoffType { auto cutoff_type_enum_2_str(CutoffType cutoff_type) -> std::string { switch (cutoff_type) { - case monoprop::CutoffType::Length: + case CutoffType::Length: return "length"; - case monoprop::CutoffType::Support: + case CutoffType::Support: return "support"; default: throw std::invalid_argument("Unknown CutoffType enum value"); @@ -85,13 +86,15 @@ NB_MODULE(_core, m) { #endif // initialize threading - monoprop::threading::init_from_env(); + threading::init_from_env(); // clang-format off m.attr("MAX_NUM_MODES") = static_cast(@monoprop_MAX_NUM_MODES@); // clang-format on m.attr("__build_type__") = std::string(build_type()); m.attr("__compiler_flags__") = compiler_flags(); + m.attr("__variant__") = std::string(variant()); + #ifdef monoprop_ENABLE_MPI m.attr("has_mpi") = true; #else @@ -99,11 +102,11 @@ NB_MODULE(_core, m) { #endif m.def("is_antihermitian", - &monoprop::is_antihermitian, + &is_antihermitian, "indices"_a, "Check if a Majorana operator (represented by indices) is antihermitian."); m.def("antihermitian_generator_correction", - &monoprop::antihermitian_generator_correction, + &antihermitian_generator_correction, "indices"_a, "Get the generator correction for a Majorana operator (represented by indices)."); // clang-format off diff --git a/tests/test_gcc_target_help_clean.py b/tests/test_gcc_target_help_clean.py new file mode 100644 index 00000000..20a34020 --- /dev/null +++ b/tests/test_gcc_target_help_clean.py @@ -0,0 +1,98 @@ +# Copyright 2026 Algorithmiq +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for the ``gcc -Q --help=target`` output cleaner.""" + +from __future__ import annotations + +import importlib.util +from pathlib import Path + +_MODULE_PATH = Path(__file__).parents[1] / "tools" / "gcc-target-help-clean.py" +_spec = importlib.util.spec_from_file_location("gcc_target_help_clean", _MODULE_PATH) +assert _spec is not None +assert _spec.loader is not None +_module = importlib.util.module_from_spec(_spec) +_spec.loader.exec_module(_module) +clean_target_help = _module.clean_target_help + + +def _wrap(body: str) -> str: + return ( + "The following options are target specific:\n" + f"{body}\n" + "\n" + " Known assembler dialects (for use with the -masm= option):\n" + " att intel\n" + ) + + +def test_enabled_keeps_only_name() -> None: + text = _wrap(" -m64 \t\t[enabled]") + assert clean_target_help(text) == "-m64" + + +def test_disabled_is_dropped() -> None: + text = _wrap(" -m16 \t\t[disabled]") + assert clean_target_help(text) == "" + + +def test_equals_joins_with_value() -> None: + text = _wrap(" -mabi= \t\tsysv") + assert clean_target_help(text) == "-mabi=sysv" + + +def test_equals_empty_value_is_dropped() -> None: + text = _wrap(" -mcpu= \t\t") + assert clean_target_help(text) == "" + + +def test_equals_default_value_is_dropped() -> None: + text = _wrap(" -mcmodel= \t\t[default]") + assert clean_target_help(text) == "" + + +def test_alias_line_keeps_both_fields() -> None: + text = _wrap(" -msse5 \t\t-mavx") + assert clean_target_help(text) == "-msse5 -mavx" + + +def test_range_hint_is_stripped() -> None: + text = _wrap(" -mbranch-cost=<0,5> \t\t3") + assert clean_target_help(text) == "-mbranch-cost=3" + + +def test_only_section_between_markers_is_used() -> None: + text = ( + "-mignored-before \t\t[enabled]\n" + "The following options are target specific:\n" + " -m64 \t\t[enabled]\n" + " Known assembler dialects (for use with the -masm= option):\n" + " -mignored-after \t\t[enabled]\n" + ) + assert clean_target_help(text) == "-m64" + + +def test_missing_start_marker_returns_empty() -> None: + assert clean_target_help("nothing relevant here") == "" + + +def test_multiple_entries_joined_by_space() -> None: + text = _wrap( + " -m64 \t\t[enabled]\n" + " -m16 \t\t[disabled]\n" + " -mabi= \t\tsysv\n" + " -msse5 \t\t-mavx" + ) + assert clean_target_help(text) == "-m64 -mabi=sysv -msse5 -mavx" diff --git a/tools/gcc-target-help-clean.py b/tools/gcc-target-help-clean.py new file mode 100644 index 00000000..71d2d843 --- /dev/null +++ b/tools/gcc-target-help-clean.py @@ -0,0 +1,80 @@ +# Copyright 2026 Algorithmiq +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ruff: noqa: INP001 + +"""Clean up the output of ``gcc -Q --help=target``. + +Reads the command's output from stdin, extracts the target-specific options +section, normalizes each line, and prints a single space-separated string. +""" + +from __future__ import annotations + +import re +import sys + +_START_MARKER = "The following options are target specific:" +_END_MARKER = "Known assembler dialects (for use with the -masm= option):" +_MULTISPACE = re.compile(r"\s{2,}") +_HINT = re.compile(r"<[^>]*>") + + +def clean_target_help(text: str) -> str: + """Normalize ``gcc -Q --help=target`` output into a single string. + + Args: + text: The full stdout of ``gcc -Q --help=target``. + + Returns: + A single space-separated string of the cleaned options. Rules: + lines containing ``[disabled]`` are dropped; lines whose value is + ``[enabled]`` keep only the option name; options ending in ``=`` are + joined to their value unless the value is empty or ``[default]`` (in + which case the line is dropped); any remaining line keeps both fields + joined by a single space. + """ + start = text.find(_START_MARKER) + if start == -1: + return "" + end = text.find(_END_MARKER, start) + section = text[start + len(_START_MARKER) : end if end != -1 else None] + + entries: list[str] = [] + for raw in section.splitlines(): + line = raw.strip() + if not line or "[disabled]" in line: + continue + fields = _MULTISPACE.split(line, maxsplit=1) + name = _HINT.sub("", fields[0]) + value = fields[1].strip() if len(fields) > 1 else "" + + if "[enabled]" in value: + entries.append(name) + elif "=" in name: + if value and value != "[default]": + entries.append(name + value) + else: + entries.append(f"{name} {value}".strip()) + + return " ".join(entries) + + +def main() -> None: + """Read stdin and print the cleaned target options.""" + sys.stdout.write(clean_target_help(sys.stdin.read()) + "\n") + + +if __name__ == "__main__": + main() From 96c7872d0909e09829cf4cad24c302055ed47dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Di=20Remigio=20Eik=C3=A5s?= Date: Mon, 20 Jul 2026 21:25:04 +0200 Subject: [PATCH 4/4] style: format cmake files --- cmake/compiler_flags/CXXFlags.cmake | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/cmake/compiler_flags/CXXFlags.cmake b/cmake/compiler_flags/CXXFlags.cmake index b7ef5a13..de8eb155 100644 --- a/cmake/compiler_flags/CXXFlags.cmake +++ b/cmake/compiler_flags/CXXFlags.cmake @@ -57,11 +57,18 @@ set(CMAKE_VISIBILITY_INLINES_HIDDEN TRUE) # Usage: # _monoprop_query_machine_flags(MARCH OUTPUT_VARIABLE ) function(_monoprop_query_machine_flags) - set(_one_value_args MARCH OUTPUT_VARIABLE) + set( + _one_value_args + MARCH + OUTPUT_VARIABLE + ) cmake_parse_arguments(PARSE_ARGV 0 _arg "" "${_one_value_args}" "") if(NOT _arg_OUTPUT_VARIABLE) - message(FATAL_ERROR "_monoprop_query_machine_flags: OUTPUT_VARIABLE is required") + message( + FATAL_ERROR + "_monoprop_query_machine_flags: OUTPUT_VARIABLE is required" + ) endif() if(NOT _arg_MARCH) message(FATAL_ERROR "_monoprop_query_machine_flags: MARCH is required") @@ -73,8 +80,10 @@ function(_monoprop_query_machine_flags) set(_march_args "-march=${_arg_MARCH}") endif() execute_process( - COMMAND ${CMAKE_CXX_COMPILER} ${_march_args} -Q --help=target - COMMAND ${Python_EXECUTABLE} ${_machine_flags_cleaner} + COMMAND + ${CMAKE_CXX_COMPILER} ${_march_args} -Q --help=target + COMMAND + ${Python_EXECUTABLE} ${_machine_flags_cleaner} OUTPUT_VARIABLE _flags OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE _result @@ -92,7 +101,10 @@ endfunction() # querying `gcc -march= -Q --help=target` and cleaning the output with # tools/gcc-target-help-clean.py. find_package(Python COMPONENTS Interpreter REQUIRED QUIET) -set(_machine_flags_cleaner "${PROJECT_SOURCE_DIR}/tools/gcc-target-help-clean.py") +set( + _machine_flags_cleaner + "${PROJECT_SOURCE_DIR}/tools/gcc-target-help-clean.py" +) set(monoprop_MACHINE_FLAGS_DEFAULT "") _monoprop_query_machine_flags(MARCH default OUTPUT_VARIABLE monoprop_MACHINE_FLAGS_DEFAULT) @@ -139,7 +151,10 @@ if( list(JOIN _targets_arch ", " TARGETS) message(STATUS "Function multiversioning targets: \"default\", ${TARGETS}") - set(monoprop_TARGET_CLONES "[[using gnu: flatten, target_clones(\"default\", ${TARGETS})]]") + set( + monoprop_TARGET_CLONES + "[[using gnu: flatten, target_clones(\"default\", ${TARGETS})]]" + ) set(_variants "") foreach(_target IN LISTS _targets) string(APPEND _variants "monoprop_FMV_VARIANT(\"${_target}\")\n")