diff --git a/.github/generate-job-matrix.py b/.github/generate-job-matrix.py index bd14ee00..1c4d4b2b 100644 --- a/.github/generate-job-matrix.py +++ b/.github/generate-job-matrix.py @@ -53,18 +53,20 @@ def make_clang_config( return Configuration(**vars(ret)) -def make_apple_clang_config(version: int) -> Configuration: +def make_apple_clang_config( + os: str, version: str, std_format_support: bool +) -> Configuration: ret = Configuration( name=f"Apple Clang {version}", - os="macos-13", + os=os, compiler=Compiler( type="APPLE_CLANG", - version=f"{version}.0", + version=version, cc="clang", cxx="clang++", ), cxx_modules=False, - std_format_support=False, + std_format_support=std_format_support, ) return ret @@ -95,7 +97,15 @@ configs = { # arm64 runners are expensive; only consider one version if ver == 18 or platform != "arm64" ] - + [make_apple_clang_config(ver) for ver in [15]] + + [ + make_apple_clang_config("macos-13", ver, std_format_support=False) + for ver in ["15.2"] + ] + # std::format is available in Xcode 16.1 or later + + [ + make_apple_clang_config("macos-14", ver, std_format_support=True) + for ver in ["16.1"] + ] + [make_msvc_config(release="14.4", version=194)] } diff --git a/.gitignore b/.gitignore index 2699986c..2ade9412 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,6 @@ CMakeUserPresets.json # cxxdraft-htmlgen docs/api_reference/src/source/ docs/api_reference/gen + +# macOS files +.DS_Store diff --git a/conanfile.py b/conanfile.py index 8026ddf6..696a9447 100644 --- a/conanfile.py +++ b/conanfile.py @@ -99,7 +99,7 @@ class MPUnitsConan(ConanFile): "compiler": { "gcc": "13", "clang": "17", - "apple-clang": "", + "apple-clang": "16", "msvc": "194", }, }, diff --git a/docs/getting_started/cpp_compiler_support.md b/docs/getting_started/cpp_compiler_support.md index 525585c3..c5825684 100644 --- a/docs/getting_started/cpp_compiler_support.md +++ b/docs/getting_started/cpp_compiler_support.md @@ -16,7 +16,7 @@ C++ feature: | C++ Feature | C++ version | gcc | clang | apple-clang | MSVC | |-----------------------------------------------------------|:-----------:|:----:|:-----:|:-----------:|:-----------------------------------------:| | **Minimum support** | 20 | 12 | 16 | 15 | 194 :bug:{ title="BEWARE of MSVC Bugs!" } | -| **`std::format`** | 20 | 13 | 17 | None | 194 | +| **`std::format`** | 20 | 13 | 17 | 16 | 194 | | **C++ modules** | 20 | None | 17 | None | None | | **`import std;`** | 23 | None | 18 | None | None | | **Explicit `this` parameter** | 23 | 14 | 18 | None | None | diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0c7cfb7d..8bb70e4d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,13 +53,15 @@ check_cxx_feature_supported(__cpp_explicit_this_parameter ${projectPrefix}EXPLIC # libc++ has a basic supports for std::format but does not set __cpp_lib_format # https://github.com/llvm/llvm-project/issues/77773 -if(NOT ${projectPrefix}LIB_FORMAT_SUPPORTED - AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang" - AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "17" - AND ${projectPrefix}LIBCXX -) - message(STATUS "Clang 17+ with libc++ detected, overriding `std::format` support") - set(${projectPrefix}LIB_FORMAT_SUPPORTED ON) +if(NOT ${projectPrefix}LIB_FORMAT_SUPPORTED AND ${projectPrefix}LIBCXX) + if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "17") + message(STATUS "Clang 17+ with libc++ detected, overriding `std::format` support") + set(${projectPrefix}LIB_FORMAT_SUPPORTED ON) + endif() + if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "16") + message(STATUS "AppleClang 16+ with libc++ detected, overriding `std::format` support") + set(${projectPrefix}LIB_FORMAT_SUPPORTED ON) + endif() endif() # clang++-18 supports explicit `this` parameter diff --git a/src/core/include/mp-units/bits/hacks.h b/src/core/include/mp-units/bits/hacks.h index 3b8c9a89..f9e98f24 100644 --- a/src/core/include/mp-units/bits/hacks.h +++ b/src/core/include/mp-units/bits/hacks.h @@ -150,5 +150,9 @@ MP_UNITS_DIAGNOSTIC_POP #define MP_UNITS_API_NO_CRTP 1 +#endif + +#if defined(__clang__) && defined(__apple_build_version__) && __apple_build_version__ < 16000026 +#define MP_UNITS_XCODE15_HACKS #endif // NOLINTEND(bugprone-reserved-identifier, cppcoreguidelines-macro-usage) diff --git a/src/core/include/mp-units/framework/representation_concepts.h b/src/core/include/mp-units/framework/representation_concepts.h index ff99bd96..58b806eb 100644 --- a/src/core/include/mp-units/framework/representation_concepts.h +++ b/src/core/include/mp-units/framework/representation_concepts.h @@ -88,7 +88,7 @@ concept Scalar = (!disable_scalar) && { a + b } -> std::common_with; { a - b } -> std::common_with; } && ScalableWith -#if MP_UNITS_COMP_GCC != 12 +#if MP_UNITS_COMP_GCC != 12 && !defined(MP_UNITS_XCODE15_HACKS) && WeaklyRegular #endif ; @@ -177,19 +177,23 @@ constexpr bool disable_complex = false; namespace detail { template -concept Complex = (!disable_complex) && requires(const T a, const T b, const T& c) { - { -a } -> std::common_with; - { a + b } -> std::common_with; - { a - b } -> std::common_with; - { a* b } -> std::common_with; - { a / b } -> std::common_with; - ::mp_units::real(a); - ::mp_units::imag(a); - ::mp_units::modulus(a); - requires ScalableWith; - requires std::constructible_from; -} && WeaklyRegular; - +concept Complex = (!disable_complex) && + requires(const T a, const T b, const T& c) { + { -a } -> std::common_with; + { a + b } -> std::common_with; + { a - b } -> std::common_with; + { a* b } -> std::common_with; + { a / b } -> std::common_with; + ::mp_units::real(a); + ::mp_units::imag(a); + ::mp_units::modulus(a); + requires ScalableWith; + requires std::constructible_from; + } +#ifndef MP_UNITS_XCODE15_HACKS + && WeaklyRegular +#endif + ; namespace magnitude_impl { void magnitude() = delete; // poison pill @@ -238,19 +242,24 @@ constexpr bool disable_vector = false; namespace detail { template -concept Vector = (!disable_vector) && requires(const T a, const T b) { - { -a } -> std::common_with; - { a + b } -> std::common_with; - { a - b } -> std::common_with; - ::mp_units::magnitude(a); - requires ScalableWith; - // TODO should we also check for the below (e.g., when `size() > 1` or `2`) - // ::mp_units::zero_vector(); - // ::mp_units::unit_vector(a); - // ::mp_units::scalar_product(a, b); - // ::mp_units::vector_product(a, b); - // ::mp_units::tensor_product(a, b); -} && WeaklyRegular; +concept Vector = (!disable_vector) && + requires(const T a, const T b) { + { -a } -> std::common_with; + { a + b } -> std::common_with; + { a - b } -> std::common_with; + ::mp_units::magnitude(a); + requires ScalableWith; + // TODO should we also check for the below (e.g., when `size() > 1` or `2`) + // ::mp_units::zero_vector(); + // ::mp_units::unit_vector(a); + // ::mp_units::scalar_product(a, b); + // ::mp_units::vector_product(a, b); + // ::mp_units::tensor_product(a, b); + } +#ifndef MP_UNITS_XCODE15_HACKS + && WeaklyRegular +#endif + ; } // namespace detail