diff --git a/.github/workflows/ci-freestanding.yml b/.github/workflows/ci-freestanding.yml new file mode 100644 index 00000000..8607955e --- /dev/null +++ b/.github/workflows/ci-freestanding.yml @@ -0,0 +1,152 @@ +# The MIT License (MIT) +# +# Copyright (c) 2018 Mateusz Pusz +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +name: Freestanding CI + +on: + push: + paths-ignore: + - "docs/**" + pull_request: + paths-ignore: + - "docs/**" + +jobs: + build: + name: "${{ matrix.formatting }} ${{ matrix.contracts }} C++${{ matrix.std }} ${{ matrix.config.name }} ${{ matrix.build_type }}" + runs-on: ${{ matrix.config.os }} + strategy: + fail-fast: false + matrix: + formatting: ["std::format", "fmtlib"] + contracts: ["none"] + std: [23] + config: + - { + name: "GCC-14", + os: ubuntu-24.04, + compiler: + { + type: GCC, + version: 14, + cc: "gcc-14", + cxx: "g++-14", + }, + cxx_modules: "False", + std_format_support: "True", + conan-config: "", + } + - { + name: "Clang-18", + os: ubuntu-24.04, + compiler: + { + type: CLANG, + version: 18, + cc: "clang-18", + cxx: "clang++-18", + }, + lib: "libc++", + cxx_modules: "True", + std_format_support: "True", + conan-config: "", + } + build_type: ["Release", "Debug"] + + env: + CC: ${{ matrix.config.compiler.cc }} + CXX: ${{ matrix.config.compiler.cxx }} + + steps: + - uses: actions/checkout@v4 + - run: echo "cache_id=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_ENV + - name: Cache Conan data + uses: actions/cache@v4 + if: always() + env: + cache-name: cache-conan-data + with: + path: ~/.conan2/p + key: clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}-${{ matrix.config.compiler.type }}-${{ matrix.config.lib }}-${{ matrix.build_type }}-${{ matrix.config.compiler.version }}-${{ matrix.std }}-${{ env.cache_id }} + restore-keys: | + clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}-${{ matrix.config.compiler.type }}-${{ matrix.config.lib }}-${{ matrix.build_type }}-${{ matrix.config.compiler.version }}-${{ matrix.std }}- + clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}-${{ matrix.config.compiler.type }}-${{ matrix.config.lib }}-${{ matrix.build_type }}-${{ matrix.config.compiler.version }}- + clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}-${{ matrix.config.compiler.type }}-${{ matrix.config.lib }}-${{ matrix.build_type }}- + clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}-${{ matrix.config.compiler.type }}-${{ matrix.config.lib }}- + clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}-${{ matrix.config.compiler.type }}- + clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}- + clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}- + clang-tidy-${{ matrix.config.os }}- + - uses: hendrikmuhs/ccache-action@v1.2 + if: runner.os == 'Linux' + with: + key: ${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}-${{ matrix.config.compiler.type }}-${{ matrix.config.lib }}-${{ matrix.build_type }}-${{ matrix.config.compiler.version }}-${{ matrix.std }} + max-size: 50M + - name: Install Clang + if: matrix.config.compiler.type == 'CLANG' + shell: bash + working-directory: ${{ env.HOME }} + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh ${{ matrix.config.compiler.version }} + sudo apt install -y clang-tools-${{ matrix.config.compiler.version }} + - name: Install Libc++ + if: matrix.config.compiler.type == 'CLANG' && matrix.config.lib == 'libc++' + shell: bash + run: | + sudo apt install -y libc++-${{ matrix.config.compiler.version }}-dev libc++abi-${{ matrix.config.compiler.version }}-dev libunwind-${{ matrix.config.compiler.version }}-dev + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.x + - name: Install Ninja + shell: bash + run: | + pip install -U ninja + - name: Install Conan + shell: bash + run: | + pip install -U conan + - name: Configure Conan + shell: bash + run: | + conan profile detect --force + if [[ "${{ matrix.config.compiler.type }}" == "CLANG" ]]; then + sed -i.backup '/^\[settings\]$/,/^\[/ s/^compiler.libcxx=.*/compiler.libcxx=${{ matrix.config.lib }}/' ~/.conan2/profiles/default + fi + sed -i.backup '/^\[settings\]$/,/^\[/ s/^compiler.cppstd=.*/compiler.cppstd=${{ matrix.std }}/' ~/.conan2/profiles/default + sed -i.backup '/^\[settings\]$/,/^\[/ s/^build_type=.*/build_type=${{ matrix.build_type }}/' ~/.conan2/profiles/default + conan profile show -pr default + - run: echo "std_format=$([ "${{ matrix.formatting }}" == "std::format" ] && echo "True" || echo "False")" >> $GITHUB_ENV + - name: Run clang-tidy + shell: bash + run: | + conan build . -b missing -c tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" \ + -c user.mp-units.build:all=True -c tools.build:cxxflags="['-ffreestanding']" \ + -o cxx_modules=${{ matrix.config.cxx_modules }} -o std_format=${{ env.std_format }} -o contracts=${{ matrix.contracts }} -o freestanding=True ${{ matrix.config.conan-config }} + - name: Clean Conan cache before backup + shell: bash + run: | + conan remove *#~latest --confirm + conan remove *:*#~latest --confirm + conan cache clean "*" -s -b -d diff --git a/CMakeLists.txt b/CMakeLists.txt index 88713d7f..a9e82b33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,8 +67,10 @@ endif() # add project code add_subdirectory(src) -# add usage example -add_subdirectory(example) +if(!${projectPrefix}API_FREESTANDING) + # add usage example + add_subdirectory(example) +endif() # add unit tests enable_testing() diff --git a/conanfile.py b/conanfile.py index 50855bd9..4c532637 100644 --- a/conanfile.py +++ b/conanfile.py @@ -66,6 +66,7 @@ class MPUnitsConan(ConanFile): "string_view_ret": ["auto", True, False], "no_crtp": ["auto", True, False], "contracts": ["none", "gsl-lite", "ms-gsl"], + "freestanding": [True, False], } default_options = { "cxx_modules": "auto", @@ -73,6 +74,7 @@ class MPUnitsConan(ConanFile): "string_view_ret": "auto", "no_crtp": "auto", "contracts": "gsl-lite", + "freestanding": "False", } tool_requires = "cmake/[>=3.29]" implements = "auto_header_only" @@ -223,6 +225,10 @@ class MPUnitsConan(ConanFile): for key, value in self._option_feature_map.items(): if self.options.get_safe(key) == True: self._check_feature_supported(key, value) + if self.options.freestanding and self.options.contracts != "none": + raise ConanInvalidConfiguration( + "'contracts' should be set to 'none' for a freestanding build" + ) def layout(self): cmake_layout(self) @@ -251,6 +257,7 @@ class MPUnitsConan(ConanFile): tc.cache_variables["MP_UNITS_API_CONTRACTS"] = str( self.options.contracts ).upper() + tc.cache_variables["MP_UNITS_API_FREESTANDING"] = self.options.freestanding tc.generate() deps = CMakeDeps(self) deps.generate() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d33178c5..b237f37c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -42,6 +42,9 @@ message(STATUS "${projectPrefix}BUILD_AS_SYSTEM_HEADERS: ${${projectPrefix}BUILD option(${projectPrefix}BUILD_CXX_MODULES "Add C++ modules to the list of default targets" OFF) message(STATUS "${projectPrefix}BUILD_CXX_MODULES: ${${projectPrefix}BUILD_CXX_MODULES}") +option(${projectPrefix}API_FREESTANDING "Builds only freestanding part of the library" OFF) +message(STATUS "${projectPrefix}API_FREESTANDING: ${${projectPrefix}API_FREESTANDING}") + if(${projectPrefix}BUILD_AS_SYSTEM_HEADERS) set(${projectPrefix}_AS_SYSTEM SYSTEM) endif() @@ -71,6 +74,10 @@ cache_var_values(API_NO_CRTP AUTO TRUE FALSE) set(${projectPrefix}API_CONTRACTS GSL-LITE CACHE STRING "Enable contract checking") cache_var_values(API_CONTRACTS NONE GSL-LITE MS-GSL) +if(${projectPrefix}API_FREESTANDING AND NOT ${projectPrefix}API_CONTRACTS STREQUAL "NONE") + message(FATAL_ERROR "'${projectPrefix}API_CONTRACTS' should be set to 'NONE' for a freestanding build") +endif() + # C++ features check_cxx_feature_supported(__cpp_lib_format ${projectPrefix}LIB_FORMAT_SUPPORTED) check_cxx_feature_supported("__cpp_constexpr >= 202211L" ${projectPrefix}STATIC_CONSTEXPR_VARS_IN_CONSTEXPR_FUNCTIONS) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8c6aada0..99289ec8 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -35,7 +35,6 @@ endfunction() add_mp_units_module( core mp-units-core HEADERS include/mp-units/bits/core_gmf.h - include/mp-units/bits/fmt.h include/mp-units/bits/get_associated_quantity.h include/mp-units/bits/get_common_base.h include/mp-units/bits/hacks.h @@ -73,14 +72,27 @@ add_mp_units_module( include/mp-units/framework/value_cast.h include/mp-units/compat_macros.h include/mp-units/concepts.h - include/mp-units/format.h include/mp-units/framework.h - include/mp-units/math.h - include/mp-units/ostream.h - include/mp-units/random.h MODULE_INTERFACE_UNIT mp-units-core.cpp ) +if(NOT ${projectPrefix}API_FREESTANDING) + target_sources( + mp-units-core + PUBLIC FILE_SET + HEADERS + BASE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/include + FILES + include/mp-units/bits/fmt.h + include/mp-units/bits/requires_hosted.h + include/mp-units/math.h + include/mp-units/ostream.h + include/mp-units/format.h + include/mp-units/random.h + ) +endif() + set_feature_flag(API_STD_FORMAT) set_feature_flag(API_STRING_VIEW_RET) set_feature_flag(API_NO_CRTP) @@ -133,4 +145,8 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") ) endif() -# target_compile_options(mp-units-core ${${projectPrefix}TARGET_SCOPE} "-ftime-trace") +# Freestanding +target_compile_definitions( + mp-units-core ${${projectPrefix}TARGET_SCOPE} + ${projectPrefix}HOSTED=$> +) diff --git a/src/core/include/mp-units/bits/core_gmf.h b/src/core/include/mp-units/bits/core_gmf.h index 500ef701..21d97e8f 100644 --- a/src/core/include/mp-units/bits/core_gmf.h +++ b/src/core/include/mp-units/bits/core_gmf.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -35,18 +34,23 @@ #include #include #include -#include #include #include #include -#include -#include -#include +#include #include #include #include #include +#if MP_UNITS_HOSTED +#include +#include +#include +#include +#include +#include + #if MP_UNITS_USE_FMTLIB MP_UNITS_DIAGNOSTIC_PUSH MP_UNITS_DIAGNOSTIC_IGNORE_UNREACHABLE @@ -57,6 +61,8 @@ MP_UNITS_DIAGNOSTIC_POP #include #endif +#endif + #if __cpp_lib_text_encoding #include #endif diff --git a/src/core/include/mp-units/bits/hacks.h b/src/core/include/mp-units/bits/hacks.h index f8522059..2dd10f84 100644 --- a/src/core/include/mp-units/bits/hacks.h +++ b/src/core/include/mp-units/bits/hacks.h @@ -73,6 +73,10 @@ #define MP_UNITS_DIAGNOSTIC_IGNORE_DEPRECATED #endif +#if !defined MP_UNITS_HOSTED && defined __STDC_HOSTED__ +#define MP_UNITS_HOSTED __STDC_HOSTED__ +#endif + #if MP_UNITS_COMP_MSVC #define MP_UNITS_TYPENAME typename diff --git a/src/core/include/mp-units/bits/requires_hosted.h b/src/core/include/mp-units/bits/requires_hosted.h new file mode 100644 index 00000000..dbacc01a --- /dev/null +++ b/src/core/include/mp-units/bits/requires_hosted.h @@ -0,0 +1,29 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include + +#if !MP_UNITS_HOSTED +#error "This header is not available in freestanding mode." +#endif diff --git a/src/core/include/mp-units/bits/text_tools.h b/src/core/include/mp-units/bits/text_tools.h index dccd3e91..c79ff946 100644 --- a/src/core/include/mp-units/bits/text_tools.h +++ b/src/core/include/mp-units/bits/text_tools.h @@ -23,6 +23,7 @@ #pragma once #include +#include #include #include #include @@ -100,12 +101,12 @@ constexpr Out copy(const symbol_text& txt, text_encoding encoding, Out out for (const char8_t ch : txt.unicode()) *out++ = static_cast(ch); return out; } else - throw std::invalid_argument("Unicode text can't be copied to CharT output"); + MP_UNITS_THROW(std::invalid_argument("Unicode text can't be copied to CharT output")); } else { if constexpr (is_same_v) return ::mp_units::detail::copy(txt.ascii().begin(), txt.ascii().end(), out); else - throw std::invalid_argument("ASCII text can't be copied to CharT output"); + MP_UNITS_THROW(std::invalid_argument("ASCII text can't be copied to CharT output")); } } diff --git a/src/core/include/mp-units/compat_macros.h b/src/core/include/mp-units/compat_macros.h index a9c21813..026f04e9 100644 --- a/src/core/include/mp-units/compat_macros.h +++ b/src/core/include/mp-units/compat_macros.h @@ -40,6 +40,15 @@ #endif +#if MP_UNITS_HOSTED +#define MP_UNITS_THROW(expr) throw expr +#else +#include +#define MP_UNITS_THROW(expr) std::abort() +#endif + +#if MP_UNITS_HOSTED + #if defined MP_UNITS_API_STD_FORMAT && !MP_UNITS_API_STD_FORMAT #define MP_UNITS_USE_FMTLIB 1 @@ -59,21 +68,7 @@ #define MP_UNITS_FMT_TO_ARG_ID(arg) (arg) #define MP_UNITS_FMT_FROM_ARG_ID(arg) (arg) -// This re-uses code from fmt; -#if FMT_EXCEPTIONS -#if FMT_MSC_VERSION || defined(__NVCC__) -#define MP_UNITS_THROW(x) ::fmt::detail::do_throw(x) -#else -#define MP_UNITS_THROW(x) throw x -#endif -#else -#define MP_UNITS_THROW(x) \ - do { \ - FMT_ASSERT(false, (x).what()); \ - } while (false) -#endif - -#else +#else // MP_UNITS_USE_FMTLIB #if !defined __cpp_lib_format && !defined MP_UNITS_COMP_CLANG #error "std::formatting facility not supported" @@ -83,10 +78,8 @@ #define MP_UNITS_FMT_LOCALE(loc) loc #define MP_UNITS_FMT_TO_ARG_ID(arg) static_cast(arg) #define MP_UNITS_FMT_FROM_ARG_ID(arg) static_cast(arg) -#define MP_UNITS_THROW(arg) throw arg - -#endif +#endif // MP_UNITS_USE_FMTLIB #ifndef MP_UNITS_IN_MODULE_INTERFACE @@ -104,6 +97,8 @@ MP_UNITS_DIAGNOSTIC_POP #endif +#endif // MP_UNITS_HOSTED + #if MP_UNITS_API_CONTRACTS == 2 || __has_include() #include diff --git a/src/core/include/mp-units/ext/fixed_string.h b/src/core/include/mp-units/ext/fixed_string.h index c67332bd..1cfe2369 100644 --- a/src/core/include/mp-units/ext/fixed_string.h +++ b/src/core/include/mp-units/ext/fixed_string.h @@ -35,8 +35,11 @@ #include // IWYU pragma: export #include #include -#include +#include #include +#if MP_UNITS_HOSTED +#include +#endif #endif MP_UNITS_EXPORT @@ -123,11 +126,14 @@ public: return data()[pos]; } +#if MP_UNITS_HOSTED [[nodiscard]] constexpr const_reference at(size_type pos) const { if (pos >= size()) throw std::out_of_range("basic_fixed_string::at"); return (*this)[pos]; } +#endif + [[nodiscard]] constexpr const_reference front() const { MP_UNITS_EXPECTS(!empty()); @@ -239,11 +245,13 @@ public: } // inserters and extractors +#if MP_UNITS_HOSTED friend std::basic_ostream& operator<<(std::basic_ostream& os, const basic_fixed_string& str) { return os << str.c_str(); } +#endif }; // deduction guides @@ -282,6 +290,7 @@ struct std::hash> : std::hash template struct std::hash> : std::hash {}; +#if MP_UNITS_HOSTED // formatting support template struct MP_UNITS_STD_FMT::formatter> : formatter> { @@ -291,4 +300,6 @@ struct MP_UNITS_STD_FMT::formatter> : for return formatter>::format(std::basic_string_view(str), ctx); } }; +#endif + // NOLINTEND(*-avoid-c-arrays) diff --git a/src/core/include/mp-units/format.h b/src/core/include/mp-units/format.h index 0400b492..d901b8dc 100644 --- a/src/core/include/mp-units/format.h +++ b/src/core/include/mp-units/format.h @@ -24,6 +24,8 @@ #pragma once +#include +// #include #include #include diff --git a/src/core/include/mp-units/framework/dimension.h b/src/core/include/mp-units/framework/dimension.h index efa0810a..4aa746dd 100644 --- a/src/core/include/mp-units/framework/dimension.h +++ b/src/core/include/mp-units/framework/dimension.h @@ -37,8 +37,10 @@ #include #include #include -#include #include +#if MP_UNITS_HOSTED +#include +#endif #endif namespace mp_units { @@ -318,9 +320,15 @@ MP_UNITS_EXPORT template buffer; dimension_symbol_to(std::back_inserter(buffer), D{}, fmt); return buffer.size(); +#else + std::array buffer; // TODO unsafe + auto end = dimension_symbol_to(buffer.begin(), D{}, fmt); + return end - buffer.begin(); +#endif }; #if MP_UNITS_API_STRING_VIEW_RET // Permitting static constexpr variables in constexpr functions diff --git a/src/core/include/mp-units/framework/unit.h b/src/core/include/mp-units/framework/unit.h index bc9cdf58..a96c043f 100644 --- a/src/core/include/mp-units/framework/unit.h +++ b/src/core/include/mp-units/framework/unit.h @@ -44,8 +44,10 @@ #include #include #include -#include #include +#if MP_UNITS_HOSTED +#include +#endif #endif namespace mp_units { @@ -718,8 +720,8 @@ constexpr Out print_separator(Out out, const unit_symbol_formatting& fmt) { if (fmt.separator == unit_symbol_separator::half_high_dot) { if (fmt.encoding != text_encoding::unicode) - throw std::invalid_argument( - "'unit_symbol_separator::half_high_dot' can be only used with 'text_encoding::unicode'"); + MP_UNITS_THROW( + std::invalid_argument("'unit_symbol_separator::half_high_dot' can be only used with 'text_encoding::unicode'")); const std::string_view dot = "⋅"; out = detail::copy(dot.begin(), dot.end(), out); } else { @@ -844,9 +846,15 @@ MP_UNITS_EXPORT template buffer; unit_symbol_to(std::back_inserter(buffer), U{}, fmt); return buffer.size(); +#else + std::array buffer; // TODO unsafe + auto end = unit_symbol_to(buffer.begin(), U{}, fmt); + return end - buffer.begin(); +#endif }; #if MP_UNITS_API_STRING_VIEW_RET // Permitting static constexpr variables in constexpr functions diff --git a/src/core/include/mp-units/math.h b/src/core/include/mp-units/math.h index c93883c6..50dd222a 100644 --- a/src/core/include/mp-units/math.h +++ b/src/core/include/mp-units/math.h @@ -22,6 +22,8 @@ #pragma once +#include +// #include #include #include diff --git a/src/core/include/mp-units/ostream.h b/src/core/include/mp-units/ostream.h index e03bb33c..fbf7d575 100644 --- a/src/core/include/mp-units/ostream.h +++ b/src/core/include/mp-units/ostream.h @@ -23,6 +23,8 @@ #pragma once +#include +// #include #include #include diff --git a/src/core/mp-units-core.cpp b/src/core/mp-units-core.cpp index f0278d29..e14347a8 100644 --- a/src/core/mp-units-core.cpp +++ b/src/core/mp-units-core.cpp @@ -8,8 +8,11 @@ export module mp_units.core; #include #include -#include #include + +#if MP_UNITS_HOSTED +#include #include #include #include +#endif diff --git a/src/systems/CMakeLists.txt b/src/systems/CMakeLists.txt index 3f902053..0cac8872 100644 --- a/src/systems/CMakeLists.txt +++ b/src/systems/CMakeLists.txt @@ -25,8 +25,7 @@ cmake_minimum_required(VERSION 3.23) add_mp_units_module( systems mp-units-systems DEPENDENCIES mp-units::core - HEADERS include/mp-units/systems/angular/math.h - include/mp-units/systems/angular/units.h + HEADERS include/mp-units/systems/angular/units.h include/mp-units/systems/iec80000/binary_prefixes.h include/mp-units/systems/iec80000/quantities.h include/mp-units/systems/iec80000/unit_symbols.h @@ -39,9 +38,7 @@ add_mp_units_module( include/mp-units/systems/isq/si_quantities.h include/mp-units/systems/isq/space_and_time.h include/mp-units/systems/isq/thermodynamics.h - include/mp-units/systems/si/chrono.h include/mp-units/systems/si/constants.h - include/mp-units/systems/si/math.h include/mp-units/systems/si/prefixes.h include/mp-units/systems/si/unit_symbols.h include/mp-units/systems/si/units.h @@ -60,3 +57,17 @@ add_mp_units_module( include/mp-units/systems/usc.h MODULE_INTERFACE_UNIT mp-units-systems.cpp ) + +if(NOT ${projectPrefix}API_FREESTANDING) + target_sources( + mp-units-systems + PUBLIC FILE_SET + HEADERS + BASE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/include + FILES + include/mp-units/systems/angular/math.h + include/mp-units/systems/si/math.h + include/mp-units/systems/si/chrono.h + ) +endif() diff --git a/src/systems/include/mp-units/systems/angular.h b/src/systems/include/mp-units/systems/angular.h index 326ea227..41e30bb9 100644 --- a/src/systems/include/mp-units/systems/angular.h +++ b/src/systems/include/mp-units/systems/angular.h @@ -23,7 +23,9 @@ #pragma once // IWYU pragma: begin_exports +#if MP_UNITS_HOSTED #include +#endif #include #ifndef MP_UNITS_IN_MODULE_INTERFACE diff --git a/src/systems/include/mp-units/systems/angular/math.h b/src/systems/include/mp-units/systems/angular/math.h index 00e03b7a..6dc96e86 100644 --- a/src/systems/include/mp-units/systems/angular/math.h +++ b/src/systems/include/mp-units/systems/angular/math.h @@ -22,6 +22,8 @@ #pragma once +#include +// #include #include diff --git a/src/systems/include/mp-units/systems/si.h b/src/systems/include/mp-units/systems/si.h index b9b374d7..95f9fc87 100644 --- a/src/systems/include/mp-units/systems/si.h +++ b/src/systems/include/mp-units/systems/si.h @@ -23,9 +23,11 @@ #pragma once // IWYU pragma: begin_exports +#if MP_UNITS_HOSTED #include -#include #include +#endif +#include #include #include #include diff --git a/src/systems/include/mp-units/systems/si/chrono.h b/src/systems/include/mp-units/systems/si/chrono.h index e0e5422d..2ddd71a1 100644 --- a/src/systems/include/mp-units/systems/si/chrono.h +++ b/src/systems/include/mp-units/systems/si/chrono.h @@ -22,6 +22,8 @@ #pragma once +#include +// #include #include #include diff --git a/src/systems/include/mp-units/systems/si/math.h b/src/systems/include/mp-units/systems/si/math.h index 400a5a25..590a14ea 100644 --- a/src/systems/include/mp-units/systems/si/math.h +++ b/src/systems/include/mp-units/systems/si/math.h @@ -22,6 +22,8 @@ #pragma once +#include +// #include #include #include diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8430bfa4..5519a7df 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -22,5 +22,7 @@ cmake_minimum_required(VERSION 3.5) -add_subdirectory(runtime) +if(!${projectPrefix}API_FREESTANDING) + add_subdirectory(runtime) +endif() add_subdirectory(static) diff --git a/test/static/CMakeLists.txt b/test/static/CMakeLists.txt index 4e5a709e..584e7a23 100644 --- a/test/static/CMakeLists.txt +++ b/test/static/CMakeLists.txt @@ -32,7 +32,6 @@ add_library( unit_tests_static angular_test.cpp cgs_test.cpp - chrono_test.cpp compare_test.cpp concepts_test.cpp # custom_rep_test_min_expl.cpp @@ -40,7 +39,6 @@ add_library( dimension_test.cpp dimension_symbol_test.cpp fixed_string_test.cpp - fractional_exponent_quantity.cpp hep_test.cpp iau_test.cpp iec80000_test.cpp @@ -49,7 +47,6 @@ add_library( isq_test.cpp isq_angle_test.cpp # magnitude_test.cpp - math_test.cpp natural_test.cpp prime_test.cpp quantity_point_test.cpp @@ -64,6 +61,11 @@ add_library( unit_symbol_test.cpp usc_test.cpp ) + +if(NOT ${projectPrefix}API_FREESTANDING) + target_sources(unit_tests_static PRIVATE chrono_test.cpp fractional_exponent_quantity.cpp math_test.cpp) +endif() + target_compile_options(unit_tests_static PRIVATE $<$:-Wno-subobject-linkage>) target_link_libraries(unit_tests_static PRIVATE mp-units::mp-units) target_link_libraries(unit_tests_static PRIVATE unit_tests_static_truncating) diff --git a/test/static/concepts_test.cpp b/test/static/concepts_test.cpp index 65762ddb..b43ed0dd 100644 --- a/test/static/concepts_test.cpp +++ b/test/static/concepts_test.cpp @@ -23,14 +23,18 @@ #include #include #include +#include +#include +#if MP_UNITS_HOSTED #include #include -#include #include -#include +#endif +#if MP_UNITS_HOSTED template inline constexpr bool mp_units::is_scalar> = true; +#endif namespace { @@ -157,7 +161,9 @@ static_assert(!Unit>); static_assert(!Unit, si::second>>); static_assert(!Unit); static_assert(!Unit); +#if MP_UNITS_HOSTED static_assert(!Unit); +#endif // NamedUnit static_assert(detail::NamedUnit); @@ -181,7 +187,9 @@ static_assert(!detail::NamedUnit>); static_assert(!detail::NamedUnit, si::second>>); static_assert(!detail::NamedUnit); static_assert(!detail::NamedUnit); +#if MP_UNITS_HOSTED static_assert(!detail::NamedUnit); +#endif // PrefixableUnit static_assert(PrefixableUnit); @@ -205,7 +213,9 @@ static_assert(!PrefixableUnit>); static_assert(!PrefixableUnit, si::second>>); static_assert(!PrefixableUnit); static_assert(!PrefixableUnit); +#if MP_UNITS_HOSTED static_assert(!PrefixableUnit); +#endif // AssociatedUnit static_assert(AssociatedUnit); @@ -229,7 +239,9 @@ static_assert(!AssociatedUnit>); static_assert(!AssociatedUnit, si::second>>); static_assert(!AssociatedUnit); static_assert(!AssociatedUnit); +#if MP_UNITS_HOSTED static_assert(!AssociatedUnit); +#endif // UnitOf static_assert(UnitOf); @@ -284,27 +296,33 @@ static_assert(!ReferenceOf, is // Representation static_assert(Representation); static_assert(Representation); -static_assert(Representation>); static_assert(!Representation); static_assert(!Representation>); -static_assert(!Representation); +#if MP_UNITS_HOSTED +static_assert(Representation>); static_assert(!Representation); +static_assert(!Representation); +#endif // RepresentationOf static_assert(RepresentationOf); static_assert(RepresentationOf); -static_assert(RepresentationOf, quantity_character::scalar>); static_assert(!RepresentationOf); static_assert(!RepresentationOf, quantity_character::scalar>); +#if MP_UNITS_HOSTED +static_assert(RepresentationOf, quantity_character::scalar>); static_assert(!RepresentationOf); static_assert(!RepresentationOf); +#endif // Quantity static_assert(Quantity>); static_assert(Quantity>); static_assert(Quantity>); static_assert(Quantity>); +#if MP_UNITS_HOSTED static_assert(!Quantity); +#endif static_assert(!Quantity>); static_assert(!Quantity>); @@ -332,8 +350,10 @@ static_assert(!QuantityOf, isq::rotation>); static_assert(!QuantityOf, isq::angular_measure>); // QuantityLike +#if MP_UNITS_HOSTED static_assert(QuantityLike); static_assert(QuantityLike); +#endif static_assert(!QuantityLike>); static_assert(!QuantityLike>); static_assert(!QuantityLike); @@ -349,8 +369,10 @@ static_assert(!QuantityPoint>); static_assert(!QuantityPoint); static_assert(!QuantityPoint); +#if MP_UNITS_HOSTED static_assert(!QuantityPoint); static_assert(!QuantityPoint>); +#endif static_assert(!QuantityPoint); // QuantityPointOf @@ -384,8 +406,10 @@ static_assert(!PointOrigin>); static_assert(!PointOrigin>); static_assert(!PointOrigin>); static_assert(!PointOrigin>); +#if MP_UNITS_HOSTED static_assert(!PointOrigin); static_assert(!PointOrigin>); +#endif static_assert(!PointOrigin); // PointOriginFor @@ -408,13 +432,17 @@ static_assert(!PointOriginFor, isq::radius>); static_assert(!PointOriginFor, isq::time>); static_assert(!PointOriginFor, isq::length>); +#if MP_UNITS_HOSTED static_assert(!PointOriginFor); static_assert(!PointOriginFor, isq::length>); +#endif static_assert(!PointOriginFor); // QuantityPointLike +#if MP_UNITS_HOSTED static_assert(QuantityPointLike>); static_assert(!QuantityPointLike); +#endif static_assert(!QuantityPointLike>); static_assert(!QuantityPointLike>); static_assert(!QuantityPointLike); diff --git a/test/static/fixed_string_test.cpp b/test/static/fixed_string_test.cpp index f1885e0c..f0001c79 100644 --- a/test/static/fixed_string_test.cpp +++ b/test/static/fixed_string_test.cpp @@ -31,12 +31,12 @@ namespace { constexpr std::array array = {'a', 'b', 'c'}; auto from_string = [] { - std::string txt = "abc"; + std::string_view txt = "abc"; return fixed_string<3>(std::from_range, txt); }; auto from_string_iter = [] { - std::string txt = "abc"; + std::string_view txt = "abc"; return fixed_string<3>(txt.begin(), txt.end()); }; @@ -90,6 +90,7 @@ static_assert(txt9[0] == 'c'); static_assert(txt9[1] == 'b'); static_assert(txt9[2] == 'a'); +#if MP_UNITS_HOSTED static_assert(txt1.at(0) == 'a'); static_assert(txt2.at(0) == 'a'); static_assert(txt2.at(1) == 'b'); @@ -97,6 +98,7 @@ static_assert(txt2.at(2) == 'c'); static_assert(txt9.at(0) == 'c'); static_assert(txt9.at(1) == 'b'); static_assert(txt9.at(2) == 'a'); +#endif static_assert(txt1.front() == 'a'); static_assert(txt1.back() == 'a'); diff --git a/test/static/iau_test.cpp b/test/static/iau_test.cpp index fd33c4bc..339c7125 100644 --- a/test/static/iau_test.cpp +++ b/test/static/iau_test.cpp @@ -20,7 +20,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +#if MP_UNITS_HOSTED #include // IWYU pragma: keep +#endif #include #include #include @@ -42,7 +44,7 @@ static_assert(isq::length(1 * LD) == 384'399 * si::kilo); static_assert(isq::length(1 * ly) == 9'460'730'472'580'800 * si::metre); static_assert(isq::length(10'000'000'000 * A) == 1 * si::metre); -#if __cpp_lib_constexpr_cmath || MP_UNITS_COMP_GCC +#if MP_UNITS_HOSTED && (__cpp_lib_constexpr_cmath || MP_UNITS_COMP_GCC) // TODO Should the below work for `1 * pc`? If yes, how to extent the type and how to convert it to a floating-point // representation for comparison purposes? static_assert(round(isq::length(1.L * pc)) == 30'856'775'814'913'673 * si::metre); diff --git a/test/static/quantity_point_test.cpp b/test/static/quantity_point_test.cpp index acc53416..24c5206d 100644 --- a/test/static/quantity_point_test.cpp +++ b/test/static/quantity_point_test.cpp @@ -26,20 +26,25 @@ #include #include #include -#include #include #include #include #include #include +#if MP_UNITS_HOSTED +#include +#endif namespace { using namespace mp_units; using namespace mp_units::si::unit_symbols; using namespace mp_units::usc::unit_symbols; + +#if MP_UNITS_HOSTED using namespace std::chrono_literals; using sys_seconds = std::chrono::time_point; +#endif inline constexpr struct zeroth_length : absolute_point_origin { } zeroth_length; @@ -444,6 +449,7 @@ static_assert(!std::convertible_to, quantity_point, quantity>); static_assert(!std::convertible_to, quantity_point>); +#if MP_UNITS_HOSTED // quantity-like static_assert(!std::constructible_from, std::chrono::seconds>); static_assert(!std::convertible_to>); @@ -453,7 +459,7 @@ static_assert(!std::convertible_to, std::chrono::seconds>); static_assert(!std::convertible_to>); - +#endif // ---------------------- // explicit point origins @@ -499,6 +505,7 @@ static_assert(!std::convertible_to, quantity_point, quantity>); static_assert(!std::convertible_to, quantity_point>); +#if MP_UNITS_HOSTED // quantity-like static_assert(!std::constructible_from>, std::chrono::seconds>); @@ -516,6 +523,7 @@ static_assert( static_assert( !std::convertible_to>>); +#endif /////////////////////////////////////// @@ -775,6 +783,7 @@ static_assert(!std::constructible_from, quantity_point>); +#if MP_UNITS_HOSTED // quantity-point-like static_assert( std::constructible_from>, sys_seconds>); @@ -786,6 +795,7 @@ static_assert( !std::constructible_from>, sys_seconds>); static_assert( !std::convertible_to>>); +#endif ////////////////////////////////// @@ -889,6 +899,7 @@ static_assert(std::is_same_v); +#if MP_UNITS_HOSTED using namespace std::chrono_literals; static_assert(std::is_same_v); static_assert(std::is_same_v, @@ -897,6 +908,7 @@ static_assert(std::is_same_v>); static_assert(quantity_point{sys_seconds{24h}}.unit == si::second); static_assert(quantity_point{sys_seconds{24h}}.quantity_spec == kind_of); +#endif //////////// diff --git a/test/static/quantity_test.cpp b/test/static/quantity_test.cpp index 69b653f7..1489a4df 100644 --- a/test/static/quantity_test.cpp +++ b/test/static/quantity_test.cpp @@ -27,12 +27,14 @@ #include #include #include -#include #include #include #include #include #include +#if MP_UNITS_HOSTED +#include +#endif template<> inline constexpr bool mp_units::is_vector = true; @@ -311,12 +313,13 @@ static_assert(quantity{123. * m}.quantity_spec == kind_of); static_assert(quantity{123. * h}.unit == si::hour); static_assert(quantity{123. * h}.quantity_spec == kind_of); +#if MP_UNITS_HOSTED using namespace std::chrono_literals; static_assert(std::is_same_v); static_assert(std::is_same_v); static_assert(quantity{24h}.unit == si::hour); static_assert(quantity{24h}.quantity_spec == kind_of); - +#endif //////////////////////// // assignment operator