diff --git a/.github/workflows/pip.yml b/.github/workflows/pip.yml index 7b74a60b..0c5955c1 100644 --- a/.github/workflows/pip.yml +++ b/.github/workflows/pip.yml @@ -59,12 +59,12 @@ jobs: run: | mkdir -p build cd build - cmake .. -DUNITS_BUILD_SHARED_LIBRARY=ON -DUNITS_BUILD_STATIC_LIBRARY=OFF -DUNITS_INSTALL=ON + cmake .. -DBUILD_SHARED_LIBS=ON -DUNITS_INSTALL=ON -DUNITS_ENABLE_TESTS=OFF make -j 4 sudo make install cd .. python -m pip install pytest - pip install -vv -C cmake.define.UNITS_BUILD_SHARED_LIBRARY:BOOL=ON -C cmake.define.UNITS_BUILD_STATIC_LIBRARY:BOOL=OFF . + pip install -vv -C cmake.define.BUILD_SHARED_LIBS:BOOL=ON . - name: Test run: | @@ -91,7 +91,7 @@ jobs: - name: Build and install run: | python -m pip install pytest - pip install -vv -C cmake.define.UNITS_BUILD_SHARED_LIBRARY:BOOL=ON -C cmake.define.UNITS_BUILD_STATIC_LIBRARY:BOOL=OFF -C cmake.define.UNITS_PYTHON_INSTALL_SHARED_LIBRARY:BOOL=ON . + pip install -vv -C cmake.define.BUILD_SHARED_LIBS:BOOL=ON -C cmake.define.UNITS_PYTHON_INSTALL_SHARED_LIBRARY:BOOL=ON . - name: Test run: python -m pytest ./test/python diff --git a/CMakeLists.txt b/CMakeLists.txt index 5aa67331..8a74850d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -211,16 +211,36 @@ add_subdirectory(units) if(UNITS_BUILD_FUZZ_TARGETS) add_subdirectory(FuzzTargets) elseif(UNITS_ENABLE_TESTS AND NOT CMAKE_VERSION VERSION_LESS 3.13) - include(updateGitSubmodules) - if(UNITS_ENABLE_SUBMODULE_UPDATE) - enable_testing() - if(NOT EXISTS "${PROJECT_SOURCE_DIR}/ThirdParty/googletest/CMakeLists.txt") - submod_update(ThirdParty/googletest) - endif() - else() + enable_testing() + option( + UNITS_USE_EXTERNAL_GTEST + "use an installed or external version of GTest instead of the included submodule" + OFF + ) + mark_as_advanced(UNITS_USE_EXTERNAL_GTEST) + + if(UNITS_USE_EXTERNAL_GTEST) include(FindPkgConfig) find_package(GTest REQUIRED) pkg_check_modules(GMock gmock REQUIRED) + else() + if(NOT EXISTS "${PROJECT_SOURCE_DIR}/ThirdParty/googletest/CMakeLists.txt") + include(updateGitSubmodules) + if(${UNITS_CMAKE_PROJECT_NAME}_ENABLE_SUBMODULE_UPDATE) + submod_update(ThirdParty/googletest) + else() + include(FindPkgConfig) + find_package(GTest REQUIRED) + pkg_check_modules(GMock gmock REQUIRED) + if(NOT GTest_FOUND) + message( + ERROR + "GTest not found, and submodule not found and unable to update install gtest or enable submodule updating to build a local copy of gtest" + ) + endif() + endif() + endif() + endif() if(BUILD_TESTING) add_subdirectory(test) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 1120778a..e5acec6b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -32,14 +32,28 @@ jobs: - script: git diff --exit-code --color displayName: Check tidy - - job: Native + - job: Native_gtest strategy: matrix: Linux14: vmImage: 'ubuntu-latest' + units.options: -DUNITS_USE_EXTERNAL_GTEST=ON Linux14shared: vmImage: 'ubuntu-latest' - units.options: -DUNITS_BUILD_SHARED_LBIRARY=ON + units.options: -DBUILD_SHARED_LIBS=ON -DUNITS_USE_EXTERNAL_GTEST=ON + pool: + vmImage: $(vmImage) + steps: + - script: | + sudo apt-get update -qq -y # It's good practice to update before installing + sudo apt-get install -qq -y libgtest-dev libgmock-dev + displayName: 'Install gtest' # Optional: Add a display name for the step + - template: .ci/azure-build.yml + - template: .ci/azure-test.yml + + - job: Native + strategy: + matrix: macOS17: vmImage: 'macOS-latest' units.std: 17 @@ -48,7 +62,7 @@ jobs: units.std: 11 Windows17: vmImage: 'windows-2019' - units.options: -DUNITS_BUILD_SHARED_LBIRARY=ON + units.options: -DUNITS_BUILD_SHARED_LIBRARY=ON -DUNITS_BUILD_STATIC_LIBRARY=OFF units.std: 17 Windows32bit: vmImage: 'windows-2019' diff --git a/config/AddGoogletest.cmake b/config/AddGoogletest.cmake index 681184aa..05a276fe 100644 --- a/config/AddGoogletest.cmake +++ b/config/AddGoogletest.cmake @@ -11,31 +11,34 @@ # Add make check, as well, which gives output on failed tests without having to set an # environment variable. # + include(extraMacros) -set(CMAKE_WARN_DEPRECATED - OFF - CACHE INTERNAL "" FORCE -) -set(gtest_force_shared_crt - ON - CACHE INTERNAL "" -) - -set(BUILD_SHARED_LIBS - OFF - CACHE INTERNAL "" -) -set(HAVE_STD_REGEX - ON - CACHE INTERNAL "" -) - -set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS - 1 - CACHE INTERNAL "" -) - -if(NOT GTest_FOUND) + +if(NOT UNITS_USE_EXTERNAL_GTEST AND NOT GTest_FOUND) + + set(CMAKE_WARN_DEPRECATED + OFF + CACHE INTERNAL "" FORCE + ) + set(gtest_force_shared_crt + ON + CACHE INTERNAL "" + ) + + set(BUILD_SHARED_LIBS + OFF + CACHE INTERNAL "" + ) + set(HAVE_STD_REGEX + ON + CACHE INTERNAL "" + ) + + set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS + 1 + CACHE INTERNAL "" + ) + add_subdirectory( ${CMAKE_SOURCE_DIR}/ThirdParty/googletest ${CMAKE_BINARY_DIR}/ThirdParty/googletest EXCLUDE_FROM_ALL @@ -55,6 +58,36 @@ if(NOT GTest_FOUND) gmock_main PUBLIC "-Wno-undef" "-Wno-c++17-attribute-extensions" ) endif() + + hide_variable(gmock_build_tests) + hide_variable(gtest_build_samples) + hide_variable(gtest_build_tests) + hide_variable(gtest_disable_pthreads) + hide_variable(gtest_hide_internal_symbols) + hide_variable(BUILD_GMOCK) + hide_variable(BUILD_GTEST) + hide_variable(INSTALL_GTEST) + hide_variable(GTEST_HAS_ABSL) + + set_target_properties(gtest gtest_main gmock gmock_main PROPERTIES FOLDER "Extern") + + if(MSVC) + # add_compile_options( /wd4459) + if(MSVC_VERSION GREATER_EQUAL 1900) + target_compile_definitions( + gtest PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING + ) + target_compile_definitions( + gtest_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING + ) + target_compile_definitions( + gmock PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING + ) + target_compile_definitions( + gmock_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING + ) + endif() + endif() endif() if(GOOGLE_TEST_INDIVIDUAL) @@ -85,35 +118,3 @@ macro(add_gtest TESTNAME) endif() endmacro() - -hide_variable(gmock_build_tests) -hide_variable(gtest_build_samples) -hide_variable(gtest_build_tests) -hide_variable(gtest_disable_pthreads) -hide_variable(gtest_hide_internal_symbols) -hide_variable(BUILD_GMOCK) -hide_variable(BUILD_GTEST) -hide_variable(INSTALL_GTEST) -hide_variable(GTEST_HAS_ABSL) - -if(NOT GTest_FOUND) - set_target_properties(gtest gtest_main gmock gmock_main PROPERTIES FOLDER "Extern") -endif() - -if(MSVC) - # add_compile_options( /wd4459) - if(MSVC_VERSION GREATER_EQUAL 1900) - target_compile_definitions( - gtest PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING - ) - target_compile_definitions( - gtest_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING - ) - target_compile_definitions( - gmock PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING - ) - target_compile_definitions( - gmock_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING - ) - endif() -endif() diff --git a/config/addBoost.cmake b/config/addBoost.cmake new file mode 100644 index 00000000..8a6a5316 --- /dev/null +++ b/config/addBoost.cmake @@ -0,0 +1,198 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Copyright (c) 2017-2025, Battelle Memorial Institute; Lawrence Livermore +# National Security, LLC; Alliance for Sustainable Energy, LLC. +# See the top-level NOTICE for additional details. +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +show_variable(BOOST_INSTALL_PATH PATH "Boost root directory" "${BOOST_INSTALL_PATH}") + +mark_as_advanced(BOOST_INSTALL_PATH) + +if(WIN32 AND NOT UNIX_LIKE) + + if(MSVC_VERSION GREATER_EQUAL 1930) + if(CMAKE_SIZE_OF_VOID_P EQUAL 4) + set(BOOST_MSVC_LIB_PATH lib32-msvc-14.3) + else() + set(BOOST_MSVC_LIB_PATH lib64-msvc-14.3) + endif() + else() + if(CMAKE_SIZE_OF_VOID_P EQUAL 4) + set(BOOST_MSVC_LIB_PATH lib32-msvc-14.2) + else() + set(BOOST_MSVC_LIB_PATH lib64-msvc-14.2) + endif() + endif() + set(boost_versions + boost_1_87_0 + boost_1_86_0 + boost_1_85_0 + boost_1_84_0 + boost_1_83_0 + boost_1_82_0 + boost_1_81_0 + boost_1_80_0 + boost_1_79_0 + boost_1_78_0 + boost_1_77_0 + boost_1_76_0 + boost_1_75_0 + boost_1_74_0 + boost_1_73_0 + boost_1_72_0 + boost_1_71_0 + boost_1_70_0 + ) + + set(poss_prefixes + C: + C:/local + C:/boost + C:/local/boost + C:/Libraries + "C:/Program Files/boost" + C:/ProgramData/chocolatey/lib + D: + D:/local + D:/boost + D:/local/boost + D:/Libraries + ) + + # create an empty list + list(APPEND boost_paths "") + mark_as_advanced(BOOST_INSTALL_PATH) + foreach(boostver ${boost_versions}) + foreach(dir ${poss_prefixes}) + if(IS_DIRECTORY ${dir}/${boostver}) + if(EXISTS ${dir}/${boostver}/boost/version.hpp) + list(APPEND boost_paths ${dir}/${boostver}) + endif() + endif() + endforeach() + endforeach() + message(STATUS "${boost_paths}") + find_path( + BOOST_TEST_PATH + NAMES boost/version.hpp + HINTS ENV BOOST_INSTALL_PATH + PATHS ${BOOST_INSTALL_PATH} ${boost_paths} + ) + if(BOOST_TEST_PATH) + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.30) + find_path( + BOOST_CMAKE_PATH + NAMES BoostConfig.cmake + PATHS ${BOOST_TEST_PATH}/${BOOST_MSVC_LIB_PATH}/cmake + PATH_SUFFIXES + Boost-1.87.0 + Boost-1.86.0 + Boost-1.85.0 + Boost-1.84.0 + Boost-1.83.0 + Boost-1.82.0 + Boost-1.81.0 + Boost-1.80.0 + Boost-1.79.0 + Boost-1.78.0 + Boost-1.77.0 + Boost-1.76.0 + Boost-1.75.0 + Boost-1.74.0 + Boost-1.73.0 + Boost-1.72.0 + Boost-1.71.0 + Boost-1.70.0 + ) + set(Boost_ROOT ${BOOST_CMAKE_PATH}) + else() + set(Boost_ROOT ${BOOST_TEST_PATH}) + endif() + endif(BOOST_TEST_PATH) +endif() +# Minimum version of Boost required for building a project + +if(NOT Boost_ROOT) + message(STATUS "Boost root not found ${Boost_ROOT}") + if(BOOST_INSTALL_PATH) + set(Boost_ROOT "${BOOST_INSTALL_PATH}") + elseif($ENV{BOOST_INSTALL_PATH}) + set(Boost_ROOT "$ENV{BOOST_INSTALL_PATH}") + else() + set(Boost_ROOT "$ENV{BOOST_ROOT}") + endif() +endif() + +if(NOT BOOST_ROOT) + set(BOOST_ROOT ${Boost_ROOT}) + message(STATUS "setting BOOST_ROOT ${BOOST_ROOT}") +endif() + +hide_variable(BOOST_TEST_PATH) + +if(NOT BOOST_REQUIRED_LIBRARIES) + set(BOOST_REQUIRED_LIBRARIES) +endif() + +set(BOOST_MINIMUM_VERSION 1.70) + +if(BOOST_REQUIRED_LIBRARIES) + find_package( + Boost ${BOOST_MINIMUM_VERSION} QUIET COMPONENTS ${BOOST_REQUIRED_LIBRARIES} + ) +else() + find_package(Boost ${BOOST_MINIMUM_VERSION} QUIET) +endif() + +if(NOT Boost_FOUND) + message(STATUS "in boost not found looking in ${Boost_ROOT} and ${BOOST_ROOT}") + find_path( + Boost_INCLUDE_DIR + NAMES boost/version.hpp boost/config.hpp + PATHS ${BOOST_ROOT} ${Boost_ROOT} + ) + message(STATUS "boost Include dir = ${Boost_INCLUDE_DIR}") + if(Boost_INCLUDE_DIR) + + set(version_file ${Boost_INCLUDE_DIR}/boost/version.hpp) + if(EXISTS "${version_file}") + file(STRINGS "${version_file}" contents + REGEX "#define BOOST_(LIB_)?VERSION " + ) + if(contents MATCHES "#define BOOST_VERSION ([0-9]+)") + set(Boost_VERSION_MACRO "${CMAKE_MATCH_1}") + endif() + if(contents MATCHES "#define BOOST_LIB_VERSION \"([0-9_]+)\"") + set(Boost_LIB_VERSION "${CMAKE_MATCH_1}") + endif() + math(EXPR Boost_VERSION_MAJOR "${Boost_VERSION_MACRO} / 100000") + math(EXPR Boost_VERSION_MINOR "${Boost_VERSION_MACRO} / 100 % 1000") + math(EXPR Boost_VERSION_PATCH "${Boost_VERSION_MACRO} % 100") + + message(STATUS "Boost VERSION ${Boost_VERSION_MACRO}") + endif() + if(Boost_VERSION_MINOR GREATER_EQUAL ${BOOST_MINIMUM_VERSION}) + add_library(Boost::headers INTERFACE IMPORTED) + set_target_properties( + Boost::headers PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES + "${Boost_INCLUDE_DIR}" + ) + add_library(Boost::boost INTERFACE IMPORTED) + set_target_properties( + Boost::boost PROPERTIES INTERFACE_LINK_LIBRARIES Boost::headers + ) + + set(Boost_FOUND ON) + message(STATUS "Setting boost found to true") + endif() + + endif() +endif() +if(NOT Boost_FOUND) + message(FATAL_ERROR " Unable to find BOOST library") +endif() +# Minimum version of Boost required for building test suite +set(BOOST_VERSION_LEVEL ${Boost_MINOR_VERSION}) diff --git a/docs/installation/cmake_variables.rst b/docs/installation/cmake_variables.rst index 0f297d84..db54126b 100644 --- a/docs/installation/cmake_variables.rst +++ b/docs/installation/cmake_variables.rst @@ -14,6 +14,7 @@ CMake variables - `BUILD_SHARED_LIBS`: Controls the defaults for the previous two options, overriding them takes precedence - `UNITS_BUILD_FUZZ_TARGETS`: If set to `ON`, the library will try to compile the fuzzing targets for clang libFuzzer - `UNITS_BUILD_WEB_SERVER`: If set to `ON`, build a webserver, This uses boost::beast and requires boost 1.70 or greater to build it also requires CMake 3.12 or greater +- `UNITS_USE_EXTERNAL_GTEST`: Defaults to `OFF` only used if `UNIT_ENABLE_TESTS` is also on, but if set to `ON` will search for an external Gtest and GMock libraries - `UNITS_BUILD_CONVERTER_APP`: enables building a simple command line converter application that can convert units from the command line - `UNITS_ENABLE_EXTRA_COMPILER_WARNINGS`: Turn on bunch of extra compiler warnings, on by default - `UNITS_ENABLE_ERROR_ON_WARNINGS`: Mostly useful in some testing contexts but will turn on `Werror` so any normal warnings generate an error. @@ -31,7 +32,7 @@ CMake variables When compiling with C++17 (or higher), this can be set to, e.g., `mynamespace::units` to avoid name clashes with other libraries defining `units`. - `UNITS_INSTALL`: This is set to `ON` normally but defaults to `OFF` if used as a subproject. This controls whether anything gets installed by the install target. - `UNITS_CMAKE_PROJECT_NAME`: This is set to `UNITS` by default. If using this in a package manager or wish to rename the project this variable can be set to another name to change the name of the package. This will change the install path and cmake target names. For example setting `-DUNITS_CMAKE_PROJECT_NAME=LLNL-UNITS` will create cmake project llnl-units::units, and llnl-units::header_only and will install in a llnl-units directory with appropriate cmake files. - +- `${UNITS_CMAKE_PROJECT_NAME}_ENABLE_SUBMODULE_UPDATE` this can be set to off to disable submodule updates which impacts Gtest, in which case if this is off and the submodule is not preset it will try to find and external Gtest, similar to `UNITS_USE_EXTERNAL_GTEST` If compiling as part of a subproject then a few other options are useful - `UNITS_HEADER_ONLY`: Only generate the header only target, sets `UNITS_BUILD_STATIC_LIBRARY` and `UNITS_BUILD_SHARED_LIBRARY` to OFF diff --git a/test/files/si_examples.csv b/test/files/si_examples.csv index 3690aae1..1e7c412b 100644 --- a/test/files/si_examples.csv +++ b/test/files/si_examples.csv @@ -13,7 +13,7 @@ luminance,candela per square meter,cd/m^2 angular velocity,radian per second,rad/s angular acceleration,radian per second squared,rad/s^2 dynamic viscosity,pascal second,Pa.s -moment of force,newton meter,N.m +moment of force,newton meter per radian,N.m/rad surface tension,newton per meter,N/m heat flux density,watt per square meter,W/m^2 radiant intensity,watt per steradian,W/sr diff --git a/test/test_equation_units.cpp b/test/test_equation_units.cpp index 17a84898..ce97dca9 100644 --- a/test/test_equation_units.cpp +++ b/test/test_equation_units.cpp @@ -426,15 +426,13 @@ TEST_P(beaufort, beaufortTests) { auto p = GetParam(); auto bnumber = p.first; - auto wspeed = p.second; + auto wspeed = static_cast(p.second); auto conv = convert(wspeed, precise::mph, precise::special::beaufort); EXPECT_EQ(std::round(conv), std::floor(bnumber)); EXPECT_NEAR( - convert(conv, precise::special::beaufort, precise::mph), - static_cast(wspeed), - 0.5); + convert(conv, precise::special::beaufort, precise::mph), wspeed, 0.5); } static const std::vector> testBValues{ @@ -476,15 +474,13 @@ TEST_P(fujita, fujitaTests) { auto p = GetParam(); auto fnumber = p.first; - auto wspeed = p.second; + auto wspeed = static_cast(p.second); auto conv = convert(wspeed, precise::mph, precise::special::fujita); EXPECT_EQ(std::round(conv), std::floor(fnumber)); EXPECT_NEAR( - convert(conv, precise::special::fujita, precise::mph), - static_cast(wspeed), - 0.5); + convert(conv, precise::special::fujita, precise::mph), wspeed, 0.5); } static const std::vector> testFValues{ diff --git a/units/units_conversion_maps.hpp b/units/units_conversion_maps.hpp index 261e127b..85b73eb9 100644 --- a/units/units_conversion_maps.hpp +++ b/units/units_conversion_maps.hpp @@ -3403,9 +3403,9 @@ std::array, 247> defined_measurement_types{ {"specificenergy", precise::J / precise::kg}, {"specificheat", precise::J / precise::kg / precise::K}, {"engcnc", precise::J / precise::m.pow(3)}, - {"momentofforce", precise::N* precise::m}, - {"moment", precise::N* precise::m}, - {"torque", precise::N* precise::m}, + {"torque", precise::N* precise::m / precise::radian}, + {"momentofforce", precise::N* precise::m / precise::radian}, + {"moment", precise::N* precise::m / precise::radian}, {"angularvelocity", precise::rad / precise::s}, {"rotationalspeed", precise::rad / precise::s}, {"rotationalvelocity", precise::rad / precise::s}, diff --git a/webserver/CMakeLists.txt b/webserver/CMakeLists.txt index 65e2ad7e..2053f062 100644 --- a/webserver/CMakeLists.txt +++ b/webserver/CMakeLists.txt @@ -16,7 +16,7 @@ if(CMAKE_VERSION VERSION_GREATER 3.12) if(UNITS_BUILD_WEBSERVER) - find_package(Boost 1.70.0 REQUIRED) + include(addBoost) add_executable(units_webserver unit_web_server.cpp) target_link_libraries( units_webserver PUBLIC ${UNITS_LC_PROJECT_NAME}::units compile_flags_target diff --git a/webserver/unit_web_server.cpp b/webserver/unit_web_server.cpp index 0e1cc37b..e43e30f0 100644 --- a/webserver/unit_web_server.cpp +++ b/webserver/unit_web_server.cpp @@ -133,7 +133,7 @@ static std::pair< target = target.substr(param_mark + 1); } else { results.first = target; - target.clear(); + target = ""; } if (results.first.starts_with('/')) { results.first.remove_prefix(1);