Skip to content

Commit

Permalink
feat: freestanding support added
Browse files Browse the repository at this point in the history
Resolves #564, #565, and #556
  • Loading branch information
mpusz committed May 30, 2024
1 parent c151740 commit cd36e6f
Show file tree
Hide file tree
Showing 30 changed files with 387 additions and 60 deletions.
152 changes: 152 additions & 0 deletions .github/workflows/ci-freestanding.yml
Original file line number Diff line number Diff line change
@@ -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
6 changes: 4 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
7 changes: 7 additions & 0 deletions conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,15 @@ 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",
"std_format": "auto",
"string_view_ret": "auto",
"no_crtp": "auto",
"contracts": "gsl-lite",
"freestanding": "False",
}
tool_requires = "cmake/[>=3.29]"
implements = "auto_header_only"
Expand Down Expand Up @@ -223,6 +225,10 @@ def validate(self):
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)
Expand Down Expand Up @@ -251,6 +257,7 @@ def generate(self):
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()
Expand Down
7 changes: 7 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand Down
28 changes: 22 additions & 6 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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=$<NOT:$<BOOL:${${projectPrefix}API_FREESTANDING}>>
)
16 changes: 11 additions & 5 deletions src/core/include/mp-units/bits/core_gmf.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include <mp-units/bits/hacks.h>
#include <mp-units/compat_macros.h>
#include <array>
#include <cmath>
#include <compare>
#include <concepts>
#include <cstddef>
Expand All @@ -35,18 +34,23 @@
#include <initializer_list>
#include <iterator>
#include <limits>
#include <locale>
#include <numbers>
#include <numeric>
#include <optional>
#include <random>
#include <sstream>
#include <string>
#include <ranges>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>

#if MP_UNITS_HOSTED
#include <cmath>
#include <locale>
#include <ostream>
#include <random>
#include <sstream>
#include <string>

#if MP_UNITS_USE_FMTLIB
MP_UNITS_DIAGNOSTIC_PUSH
MP_UNITS_DIAGNOSTIC_IGNORE_UNREACHABLE
Expand All @@ -57,6 +61,8 @@ MP_UNITS_DIAGNOSTIC_POP
#include <format>
#endif

#endif

#if __cpp_lib_text_encoding
#include <text_encoding>
#endif
4 changes: 4 additions & 0 deletions src/core/include/mp-units/bits/hacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
29 changes: 29 additions & 0 deletions src/core/include/mp-units/bits/requires_hosted.h
Original file line number Diff line number Diff line change
@@ -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 <mp-units/bits/hacks.h>

#if !MP_UNITS_HOSTED
#error "This header is not available in freestanding mode."
#endif
5 changes: 3 additions & 2 deletions src/core/include/mp-units/bits/text_tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#pragma once

#include <mp-units/bits/ratio.h>
#include <mp-units/compat_macros.h>
#include <mp-units/ext/fixed_string.h>
#include <mp-units/ext/type_traits.h>
#include <mp-units/framework/symbol_text.h>
Expand Down Expand Up @@ -100,12 +101,12 @@ constexpr Out copy(const symbol_text<N, M>& txt, text_encoding encoding, Out out
for (const char8_t ch : txt.unicode()) *out++ = static_cast<char>(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<CharT, char>)
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"));
}
}

Expand Down
Loading

0 comments on commit cd36e6f

Please sign in to comment.