diff --git a/fable/CMakeLists.txt b/fable/CMakeLists.txt index e13857f0b..1fb9ab765 100644 --- a/fable/CMakeLists.txt +++ b/fable/CMakeLists.txt @@ -4,6 +4,8 @@ project(fable LANGUAGES CXX) # NOTE: The variable FABLE_VERSION is used throughout this CMakeLists file # and is supplied from Conan or by hand on the command line. +set(FABLE_VERSION "0.0.0-undefined" CACHE STRING "Fable version as MAJOR.MINOR.PATCH string") +set(FABLE_VERSION_U32 0 CACHE STRING "Fable version as (MAJOR<<16)|(MINOR<<8)|PATCH integer") include(GNUInstallDirs) @@ -40,9 +42,11 @@ set_target_properties(${target} PROPERTIES CXX_STANDARD_REQUIRED ON VERSION ${FABLE_VERSION} ) +configure_file(src/fable/version.hpp.in include/fable/version.hpp @ONLY) target_include_directories(${target} PUBLIC "$" + "$" "$" ) target_link_libraries(${target} @@ -68,6 +72,7 @@ if(BUILD_TESTING) add_executable(test-fable # find src -type f -name "*_test.cpp" + src/fable/version_test.cpp src/fable/environment_test.cpp src/fable/schema/const_test.cpp src/fable/schema/custom_test.cpp @@ -106,6 +111,9 @@ install(TARGETS ${target} install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) install(EXPORT ${namespace}Targets NAMESPACE ${namespace}:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${namespace} diff --git a/fable/conanfile.py b/fable/conanfile.py index b50c1567c..a4971bbed 100644 --- a/fable/conanfile.py +++ b/fable/conanfile.py @@ -1,7 +1,9 @@ # mypy: ignore-errors # pylint: skip-file +import os from pathlib import Path +from semver import SemVer from conan import ConanFile from conan.tools import cmake, files, scm @@ -53,11 +55,22 @@ def build_requirements(self): def layout(self): cmake.cmake_layout(self) + self.cpp.source.includedirs.append(os.path.join(self.folders.build, "include")) def generate(self): + # The version as a single 32-bit number takes the format: + # + # (EPOCH << 24) | (MAJOR_VERSION << 16) | (MINOR_VERSION << 8) | PATCH_VERSION + # + # Each version consists of at most 8 bits, so 256 potential values, including 0. + # The epoch starts with 0, and is bumped after each version naming scheme. + semver = SemVer(self.version, True) + version_u32 = (0<<24) | (semver.major << 16) | (semver.minor << 8) | semver.patch + tc = cmake.CMakeToolchain(self) tc.cache_variables["CMAKE_EXPORT_COMPILE_COMMANDS"] = True tc.cache_variables["FABLE_VERSION"] = self.version + tc.cache_variables["FABLE_VERSION_U32"] = version_u32 tc.cache_variables["FABLE_ALLOW_COMMENTS"] = self.options.allow_comments tc.generate() @@ -85,5 +98,6 @@ def package_info(self): self.cpp_info.set_property("pkg_config_name", "fable") if not self.in_local_cache: self.cpp_info.libs = ["fable"] + self.cpp_info.includedirs.append(os.path.join(self.build_folder, "include")) else: self.cpp_info.libs = files.collect_libs(self) diff --git a/fable/src/fable/version.hpp.in b/fable/src/fable/version.hpp.in new file mode 100644 index 000000000..d4073fc78 --- /dev/null +++ b/fable/src/fable/version.hpp.in @@ -0,0 +1,78 @@ +/* + * Copyright 2023 Robert Bosch GmbH + * + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * \file version.hpp + * + * This file just provides version information. + * + * We expect the CMakeLists.txt to define a constant FABLE_VERSION_U32, + * which takes the following format: + * + * (EPOCH << 24) | (MAJOR_VERSION << 16) | (MINOR_VERSION << 8) | PATCH_VERSION + * + * Each version consists of at most 8 bits, so 256 potential values, including 0. + * The epoch starts with 0, and is bumped after each version naming scheme. + * + * The following macros are defined from FABLE_VERSION_U32: + * + * - FABLE_VERSION_EPOCH + * - FABLE_VERSION_MAJOR + * - FABLE_VERSION_MINOR + * - FABLE_VERSION_PATCH + * + * It's unlikely that EPOCH will ever be changed, but better safe than sorry. + * + * You can check for some Fable version like so: + * + * #if FABLE_VERSION_U32 < VERSION_U32(0, 1, 0, 0) + */ + +#pragma once + +/** + * VERSION_U32 is a helper macro to create 32-bit unsigned + * Epoch-Major-Minor-Patch version integers. + * + * These can be then conveniently used to compare versions with the normal + * integer comparison operators. + * + * For example: + * + * #if FABLE_VERSION_U32 >= VERSION_U32(1, 0, 0, 0) + * #error "fable epoch > 0 not supported" + * #else if (FABLE_VERSION_U32 >= VERSION_U32(0, 1, 0, 0)) && (FABLE_VERSION_U32 < VERSION_U32(0, 1, 2, 0)) + * // Code for fable versions between 1.0 and 1.1.* + * #endif + */ +#ifndef VERSION_U32 +#define VERSION_U32(epoch, major, minor, patch) \ + (((epoch) << 24) | ((major) << 16) | ((minor) << 8) | (patch)) +#endif + +#ifndef FABLE_VERSION +#define FABLE_VERSION "@FABLE_VERSION@" +#endif + +#ifndef FABLE_VERSION_U32 +#define FABLE_VERSION_U32 @FABLE_VERSION_U32@ +#endif + +#define FABLE_VERSION_EPOCH ((FABLE_VERSION_U32 >> 24) && 0xff) +#define FABLE_VERSION_MAJOR ((FABLE_VERSION_U32 >> 16) && 0xff) +#define FABLE_VERSION_MINOR ((FABLE_VERSION_U32 >> 8) && 0xff) +#define FABLE_VERSION_PATCH ((FABLE_VERSION_U32 >> 0) && 0xff) diff --git a/fable/src/fable/version_test.cpp b/fable/src/fable/version_test.cpp new file mode 100644 index 000000000..7e7ff4ee8 --- /dev/null +++ b/fable/src/fable/version_test.cpp @@ -0,0 +1,26 @@ +/* + * Copyright 2023 Robert Bosch GmbH + * + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +TEST(fable_version, check_valid) { + ASSERT_NE(FABLE_VERSION_U32, 0); + ASSERT_NE(FABLE_VERSION, "0.0.0-undefined"); +}