diff --git a/CMakeLists.txt b/CMakeLists.txt index da6df7b79..03b9bf5a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,84 +1,30 @@ cmake_minimum_required(VERSION 3.15) +include(cmake/ThirdParty.cmake) +project(novatel_edie VERSION 3.3.7 LANGUAGES CXX) option(BUILD_TESTS "Build tests" ON) option(BUILD_EXAMPLES "Build examples" ON) option(CMAKE_POSITION_INDEPENDENT_CODE "Set -fPIC" ON) option(WARNINGS_AS_ERRORS "Treat warnings as errors" OFF) option(COVERAGE "Coverage" OFF) -option(USE_STATIC_LIBS "Statically link dependencies" OFF) - -if(USE_STATIC_LIBS) - # Set Conan statically link dependencies - unset(CONAN_INSTALL_ARGS CACHE) - set(CONAN_OPTIONS -o spdlog/*:shared=False -o fmt/*:shared=False) -else() - # Set Conan dynamically link dependencies - unset(CONAN_INSTALL_ARGS CACHE) - set(CONAN_OPTIONS -o spdlog/*:shared=True -o fmt/*:shared=True) -endif() - -include(cmake/third_party.cmake) -project(novatel-edie VERSION 3.3.7 LANGUAGES CXX) if(NOT DEFINED CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() -# Check platforms -if(CMAKE_HOST_WIN32) - set(WINDOWS 1) - cmake_host_system_information(RESULT OS_NAME QUERY OS_NAME) - set(DISTRIB_NAME ${OS_NAME}) -elseif(CMAKE_HOST_UNIX) - set(LINUX 1) - cmake_host_system_information(RESULT DISTRIB_NAME QUERY DISTRIB_NAME) - cmake_host_system_information(RESULT DISTRIB_VERSION_ID QUERY DISTRIB_VERSION_ID) - set(DISTRIB_NAME "${DISTRIB_NAME}-${DISTRIB_VERSION_ID}") -else() - message(WARNING "Unable to identify OS. Update script to support distribution or OS") +if(NOT DEFINED CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) endif() - -set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -if(MSVC) - set_property(GLOBAL PROPERTY USE_FOLDERS ON) - if(NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY) - # shared spdlog requires MultiThreadedDLL - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") - endif() - add_definitions(-DWIN32 -D_WINDOWS) - add_compile_options(/W4 /GR /EHsc /utf-8 /wd4244 /wd4996) - add_compile_options("$<$:/Ox;/Ob2>") - if(WARNINGS_AS_ERRORS) - add_compile_options(/WX) - endif() -elseif(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$") - add_compile_options(-Wall -Wextra -pedantic) - add_compile_options("$<$:-O3>") +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) - if(WINDOWS) - # TODO: we shouldn't have to do this, something is bloating an object file - add_compile_options($<$:-O1>) - endif() - - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - add_compile_options(-Wno-format-truncation) - endif() - - if(WARNINGS_AS_ERRORS) - add_compile_options(-Werror) - endif() - - if(COVERAGE) - message("Coverage is On") - add_compile_options(--coverage) - add_link_options(--coverage) - endif() -else() - message(WARNING "Unable to identify compiler.") -endif() +include(GNUInstallDirs) +include(cmake/CompilerOptions.cmake) +include(cmake/Utils.cmake) +# For custom Find*.cmake modules +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules") # Output all binaries in the same directory for easier testing string(TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE) @@ -92,25 +38,16 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${BUILD_TYPE} "${OUTPUT_DIR}") # Look for shared libs in the same directory as the executable when running tests set(CMAKE_BUILD_RPATH "\$ORIGIN") -# Find Git package, if not need to install manually or through .yml file -find_package(Git) -if(NOT Git_FOUND) - message(FATAL_ERROR "Git was not found. Install Git and make sure it is in your PATH.") -endif() - +find_package(Git REQUIRED) if(NOT DEFINED GIT_BRANCH) set(GIT_BRANCH "main") endif() - -# Build version of EDIE through cmake -if(GIT_EXECUTABLE) - execute_process(COMMAND ${CMAKE_COMMAND} - -D SRC=${CMAKE_CURRENT_SOURCE_DIR}/src/version.h.in - -D DST=${CMAKE_CURRENT_SOURCE_DIR}/include/novatel_edie/version.h - -D GIT_EXECUTABLE=${GIT_EXECUTABLE} - -D GIT_BRANCH=${GIT_BRANCH} - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/GenerateVersionHeader.cmake) -endif() +execute_process(COMMAND ${CMAKE_COMMAND} + -D SRC=${CMAKE_CURRENT_SOURCE_DIR}/src/version.h.in + -D DST=${CMAKE_CURRENT_SOURCE_DIR}/include/novatel_edie/version.h + -D GIT_EXECUTABLE=${GIT_EXECUTABLE} + -D GIT_BRANCH=${GIT_BRANCH} + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/GenerateVersionHeader.cmake) # Build EDIE components add_subdirectory(src/common) @@ -140,20 +77,11 @@ if(BUILD_EXAMPLES) add_subdirectory(examples) endif() -# Copy third-party shared libs to the build directory for tests +# Copy shared libs to the build output directory for tests +copy_cpp_runtime_dlls("${OUTPUT_DIR}") copy_third_party_shared_libs("${OUTPUT_DIR}") -# Copy the C++ runtime DLL for non-MSVC compilers on Windows -if(WIN32 AND NOT MSVC) - if(NOT EXISTS CMAKE_CXX_COMPILER) - find_program(CXX_COMPILER_PATH NAMES "${CMAKE_CXX_COMPILER}") - else() - set(CXX_COMPILER_PATH "${CMAKE_CXX_COMPILER}") - endif() - get_filename_component(COMPILER_BIN_DIR "${CXX_COMPILER_PATH}" DIRECTORY) - foreach(stdcpp_library libstdc++-6.dll libc++.dll) - if(EXISTS "${COMPILER_BIN_DIR}/${stdcpp_library}") - file(COPY "${COMPILER_BIN_DIR}/${stdcpp_library}" DESTINATION "${OUTPUT_DIR}") - endif() - endforeach() -endif() +# Install +install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +install(FILES database/messages_public.json DESTINATION ${CMAKE_INSTALL_DATADIR}/novatel_edie) +install_novatel_edie_cmake_config() diff --git a/cmake/CompilerOptions.cmake b/cmake/CompilerOptions.cmake new file mode 100644 index 000000000..144b3e01d --- /dev/null +++ b/cmake/CompilerOptions.cmake @@ -0,0 +1,40 @@ +if(MSVC) + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + if(NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY) + if(BUILD_SHARED_LIBS) + # shared spdlog requires MultiThreadedDLL + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") + else() + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + endif() + endif() + add_definitions(-DWIN32 -D_WINDOWS) + add_compile_options(/W4 /GR /EHsc /utf-8 /wd4244 /wd4996) + add_compile_options("$<$:/Ox;/Ob2>") + if(WARNINGS_AS_ERRORS) + add_compile_options(/WX) + endif() +elseif(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$") + add_compile_options(-Wall -Wextra -pedantic) + add_compile_options("$<$:-O3>") + + if(CMAKE_HOST_WIN32) + add_compile_options($<$:-Wa,-mbig-obj>) + endif() + + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + add_compile_options(-Wno-format-truncation) + endif() + + if(WARNINGS_AS_ERRORS) + add_compile_options(-Werror) + endif() + + if(COVERAGE) + message("Coverage is On") + add_compile_options(--coverage) + add_link_options(--coverage) + endif() +else() + message(WARNING "Unable to identify compiler.") +endif() diff --git a/cmake/ThirdParty.cmake b/cmake/ThirdParty.cmake new file mode 100644 index 000000000..abbccc5e6 --- /dev/null +++ b/cmake/ThirdParty.cmake @@ -0,0 +1,70 @@ +include(CMakeDependentOption) + +if(CMAKE_TOOLCHAIN_FILE MATCHES "conan_toolchain.cmake") + set(CONAN_ALREADY_ACTIVE 1) +endif() + +cmake_dependent_option(USE_CONAN "Use Conan to automatically manage dependencies" ON + "NOT DEFINED VCPKG_TOOLCHAIN AND NOT CONAN_ALREADY_ACTIVE" OFF) + +if(USE_CONAN) + if(CMAKE_VERSION VERSION_LESS 3.24) + message(FATAL_ERROR "Automatic Conan integration requires CMake 3.24 or later.") + endif() + if(NOT DEFINED CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) + endif() + if(NOT DEFINED CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) + endif() + list(APPEND CMAKE_PROJECT_TOP_LEVEL_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/conan_provider.cmake) +endif() + +# Copy third-party shared libs to the build directory for tests +function(copy_third_party_shared_libs target_dir) + if(USE_CONAN) + get_property(conan_generators_folder GLOBAL PROPERTY CONAN_GENERATORS_FOLDER) + include("${conan_generators_folder}/conan_runtime_paths.cmake") + endif() + if(NOT DEFINED CONAN_RUNTIME_LIB_DIRS) + if(USE_CONAN) + message(FATAL_ERROR "Failed to load CONAN_RUNTIME_LIB_DIRS") + endif() + # TODO: Add support for vcpkg + message(STATUS "Not using Conan, skipping copying third-party shared libraries.") + return() + endif() + + message(STATUS "Copying third-party shared libraries to ${target_dir}...") + + if(WIN32) + set(pattern "*.dll") + elseif(APPLE) + set(pattern "*.dylib") + else() + set(pattern "*.so*") + endif() + + set(copied_files) + foreach(path ${CONAN_RUNTIME_LIB_DIRS}) + message(STATUS "Copying shared libraries from ${path}") + file(GLOB libs "${path}/${pattern}") + file(COPY ${libs} DESTINATION "${target_dir}") + list(APPEND copied_files ${libs}) + endforeach() + + # Set RPATH to $ORIGIN for the copied libraries + if(NOT WIN32) + find_program(PATCHELF_EXECUTABLE patchelf REQUIRED) + foreach(lib ${copied_files}) + get_filename_component(lib_name ${lib} NAME) + if(APPLE) + execute_process(COMMAND install_name_tool -add_rpath @loader_path "${target_dir}/${lib_name}" + COMMAND_ERROR_IS_FATAL ANY) + else() + execute_process(COMMAND "${PATCHELF_EXECUTABLE}" --set-rpath \$ORIGIN "${target_dir}/${lib_name}" + COMMAND_ERROR_IS_FATAL ANY) + endif() + endforeach() + endif() +endfunction() diff --git a/cmake/Utils.cmake b/cmake/Utils.cmake new file mode 100644 index 000000000..3fcccf932 --- /dev/null +++ b/cmake/Utils.cmake @@ -0,0 +1,44 @@ +# Copy the C++ runtime DLL for non-MSVC compilers on Windows +function(copy_cpp_runtime_dlls target_dir) + if(WIN32 AND NOT MSVC) + if(NOT EXISTS CMAKE_CXX_COMPILER) + find_program(CXX_COMPILER_PATH NAMES "${CMAKE_CXX_COMPILER}") + else() + set(CXX_COMPILER_PATH "${CMAKE_CXX_COMPILER}") + endif() + get_filename_component(COMPILER_BIN_DIR "${CXX_COMPILER_PATH}" DIRECTORY) + foreach(stdcpp_library libstdc++-6.dll libc++.dll) + if(EXISTS "${COMPILER_BIN_DIR}/${stdcpp_library}") + file(COPY "${COMPILER_BIN_DIR}/${stdcpp_library}" DESTINATION "${target_dir}") + endif() + endforeach() + endif() +endfunction() + +# Generate and install nova_edie-config.cmake +function(install_novatel_edie_cmake_config) + include(GNUInstallDirs) + set(CMAKE_CONFIG_INSTALL_DIR lib/cmake/novatel_edie) + + install(TARGETS novatel_edie EXPORT novatel_edie-targets) + install(EXPORT novatel_edie-targets + NAMESPACE novatel_edie:: + FILE novatel_edie-targets.cmake + DESTINATION ${CMAKE_CONFIG_INSTALL_DIR} + COMPONENT novatel_edie) + + include(CMakePackageConfigHelpers) + configure_package_config_file(cmake/novatel_edie-config.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/novatel_edie-config.cmake" + INSTALL_DESTINATION ${CMAKE_CONFIG_INSTALL_DIR} + PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_DATADIR) + + write_basic_package_version_file(novatel_edie-config-version.cmake + VERSION ${novatel_edie_VERSION} + COMPATIBILITY SameMajorVersion) + + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/novatel_edie-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/novatel_edie-config-version.cmake" + DESTINATION ${CMAKE_CONFIG_INSTALL_DIR} + COMPONENT novatel_edie) +endfunction() diff --git a/cmake/modules/Findspdlog_setup.cmake b/cmake/modules/Findspdlog_setup.cmake new file mode 100644 index 000000000..8c5b93a96 --- /dev/null +++ b/cmake/modules/Findspdlog_setup.cmake @@ -0,0 +1,49 @@ +# Findspdlog_setup.cmake +# +# This module tries to locate the spdlog_setup library using find_package(spdlog_setup CONFIG). +# If not found, it falls back to downloading and configuring it from an official release. + +find_package(spdlog_setup CONFIG QUIET) + +if(NOT spdlog_setup_FOUND) + set(spdlog_setup_VERSION "1.1.0") + set(spdlog_setup_URL "https://github.com/gegles/spdlog_setup/archive/refs/tags/v${spdlog_setup_VERSION}.tar.gz") + set(spdlog_setup_SHA256 "80a37463a1cd2735f6f7af0b0dfb01a1ecc0a271b33fb29966564b9758f7c309") + set(spdlog_setup_SOURCE_DIR "${CMAKE_BINARY_DIR}/third_party/spdlog_setup") + set(spdlog_setup_INCLUDE_DIR "${spdlog_setup_SOURCE_DIR}/include") + + find_package(cpptoml REQUIRED CONFIG) + + if(POLICY CMP0135) + cmake_policy(SET CMP0135 NEW) + endif() + include(FetchContent) + FetchContent_Declare( + spdlog_setup + URL "${spdlog_setup_URL}" + URL_HASH SHA256=${spdlog_setup_SHA256} + SOURCE_DIR "${spdlog_setup_SOURCE_DIR}" + EXCLUDE_FROM_ALL + ) + FetchContent_GetProperties(spdlog_setup) + if(NOT EXISTS "${spdlog_setup_INCLUDE_DIR}") + message(STATUS "spdlog_setup not found. Fetching it from ${spdlog_setup_URL} instead...") + FetchContent_MakeAvailable(spdlog_setup) + endif() + + add_library(spdlog_setup::spdlog_setup INTERFACE IMPORTED) + target_include_directories(spdlog_setup::spdlog_setup INTERFACE + "$" + "$" + ) + target_link_libraries(spdlog_setup::spdlog_setup INTERFACE cpptoml) + + install(DIRECTORY "${spdlog_setup_SOURCE_DIR}/include/" + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/novatel_edie/third_party + ) + + set(spdlog_setup_FOUND TRUE CACHE INTERNAL "") + set(spdlog_setup_VENDORED TRUE CACHE INTERNAL "") +else() + set(spdlog_setup_VENDORED FALSE CACHE INTERNAL "") +endif() diff --git a/cmake/novatel_edie-config.cmake.in b/cmake/novatel_edie-config.cmake.in new file mode 100644 index 000000000..198a83ec5 --- /dev/null +++ b/cmake/novatel_edie-config.cmake.in @@ -0,0 +1,21 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +include("${CMAKE_CURRENT_LIST_DIR}/novatel_edie-targets.cmake") + +set_and_check(novatel_edie_INCLUDE_DIRS "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") +set_and_check(novatel_edie_DATA_DIR "@PACKAGE_CMAKE_INSTALL_DATADIR@") +set(novatel_edie_LIBRARIES novatel_edie::novatel_edie) +check_required_components(novatel_edie) + +find_dependency(nlohmann_json) +find_dependency(spdlog) + +if(@spdlog_setup_VENDORED@) + # spdlog_setup has been vendored, find its dependencies + find_dependency(cpptoml) +else() + # use external spdlog_setup + find_dependency(spdlog_setup) +endif() diff --git a/cmake/third_party.cmake b/cmake/third_party.cmake deleted file mode 100644 index dba38b5e2..000000000 --- a/cmake/third_party.cmake +++ /dev/null @@ -1,67 +0,0 @@ -if(NOT DEFINED CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) -endif() - -option(USE_CONAN "Use Conan to automatically manage dependencies" TRUE) - -if(NOT DEFINED CONAN_INSTALL_ARGS) - set(CONAN_INSTALL_ARGS - --build=missing - # Deploy the installed dependencies in the build dir for easier installation - --deployer=full_deploy "--deployer-folder=${CMAKE_BINARY_DIR}" - # Set cppstd without relying on CMAKE_CXX_STANDARD - --settings compiler.cppstd=17 - # Use options set by the project - ${CONAN_OPTIONS} - ) - if(WIN32) - list(APPEND CONAN_INSTALL_ARGS -c tools.deployer:symlinks=False) - endif() - set(CONAN_INSTALL_ARGS "${CONAN_INSTALL_ARGS}" CACHE INTERNAL "" FORCE) -endif() - -if(USE_CONAN AND NOT DEFINED VCPKG_TOOLCHAIN AND NOT CMAKE_TOOLCHAIN_FILE MATCHES "conan_toolchain.cmake") - if(CMAKE_VERSION GREATER_EQUAL 3.24) - list(APPEND CMAKE_PROJECT_TOP_LEVEL_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/conan_provider.cmake) - else() - message(WARNING - "CMake 3.24 or greater is required to install Conan dependencies automatically. " - "You will have to run 'conan install . ${CONAN_INSTALL_ARGS}' manually in the source directory instead." - ) - # To use the output from the Conan CMakeDeps generator - list(PREPEND CMAKE_PREFIX_PATH - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/generators - ${CMAKE_CURRENT_BINARY_DIR}/build/${CMAKE_BUILD_TYPE}/generators - ) - endif() -endif() - -set(CONAN_DEPLOYER_DIR "${CMAKE_BINARY_DIR}/full_deploy/host") - -function(copy_third_party_shared_libs target_dir) - if(WIN32) - set(pattern "*.dll") - elseif(APPLE) - set(pattern "*.dylib") - else() - set(pattern "*.so*") - endif() - - file(GLOB_RECURSE libs "${CONAN_DEPLOYER_DIR}/*/${pattern}") - file(COPY ${libs} DESTINATION "${target_dir}") - - # Set RPATH to $ORIGIN for the copied libraries - if(NOT WIN32) - file(GLOB_RECURSE PATCHELF_EXECUTABLE "${CMAKE_BINARY_DIR}/full_deploy/build/*/patchelf") - foreach(lib ${libs}) - get_filename_component(lib_name ${lib} NAME) - if(APPLE) - execute_process(COMMAND install_name_tool -add_rpath @loader_path "${target_dir}/${lib_name}" - COMMAND_ERROR_IS_FATAL ANY) - else() - execute_process(COMMAND "${PATCHELF_EXECUTABLE}" --set-rpath \$ORIGIN "${target_dir}/${lib_name}" - COMMAND_ERROR_IS_FATAL ANY) - endif() - endforeach() - endif() -endfunction() diff --git a/conanfile.py b/conanfile.py index 71407aab3..803ea8c4c 100644 --- a/conanfile.py +++ b/conanfile.py @@ -1,22 +1,105 @@ +import os +import re +from pathlib import Path + from conan import ConanFile +from conan.errors import ConanInvalidConfiguration +from conan.tools.build import check_min_cppstd +from conan.tools.cmake import CMake, cmake_layout, CMakeToolchain, CMakeDeps +from conan.tools.files import copy, rmdir + +required_conan_version = ">=2.0" -class NovatelEdiePackage(ConanFile): +class NovatelEdieConan(ConanFile): + name = "novatel_edie" + description = ("EDIE (Encode Decode Interface Engine) is a C++ SDK that can encode and decode messages " + "from NovAtel's OEM7 receivers from one format into another.") + url = "https://github.com/novatel/novatel_edie" + license = "MIT" + package_type = "library" settings = "os", "compiler", "build_type", "arch" - requires = [ - "nlohmann_json/[>=3.11 <3.12]", - "gegles-spdlog_setup/[>=1.1 <2]", - "spdlog/[>=1.13 <2]" - ] + options = { + "shared": [True, False], + "fPIC": [True, False], + } default_options = { - # Statically linking against spdlog causes its singleton registry to be - # re-instantiated in each shared library or executable that links against it. - "spdlog/*:shared": True, - "fmt/*:shared": True + "shared": False, + "fPIC": True, } - generators = "CMakeDeps", "CMakeToolchain" - cmake_layout = "cmake_layout" + + exports_sources = ["cmake/*", "database/*", "include/*", "src/*", "LICENSE", "!doc", "!test", "CMakelists.txt"] + + def set_version(self): + cmakelists_content = Path(self.recipe_folder, "CMakeLists.txt").read_text() + self.version = re.search(r"novatel_edie VERSION ([\d.]+)", cmakelists_content).group(1) + + def config_options(self): + if self.settings.os == "Windows": + del self.options.fPIC + + def configure(self): + if self.options.shared: + self.options.rm_safe("fPIC") + self.options["spdlog"].shared = True + + def layout(self): + cmake_layout(self) + + def requirements(self): + self.requires("nlohmann_json/[>=3.11 <3.12]", transitive_headers=True) + self.requires("spdlog/[>=1.13 <2]", transitive_headers=True, transitive_libs=True) + self.requires("gegles-spdlog_setup/[>=1.1 <2]", transitive_headers=True) + + def validate(self): + if self.settings.compiler.cppstd: + check_min_cppstd(self, 17) + + if self.options.shared and not self.dependencies["spdlog"].options.shared: + # Statically linking against spdlog causes its singleton registry to be + # re-instantiated in each shared library and executable that links against it. + raise ConanInvalidConfiguration("spdlog must be dynamically linked when building novatel_edie as a shared library") def build_requirements(self): self.test_requires("gtest/[>=1.14 <1.15]") if self.settings.os in ["Linux", "FreeBSD"]: - self.tool_requires("patchelf/0.18") + self.tool_requires("patchelf/[*]") + + def generate(self): + tc = CMakeToolchain(self) + tc.cache_variables["BUILD_TESTS"] = False + tc.cache_variables["BUILD_EXAMPLES"] = False + tc.cache_variables["CMAKE_INSTALL_DATADIR"] = "res" + tc.generate() + + deps = CMakeDeps(self) + deps.generate() + + # A workaround for conan_provider.cmake not loading conan_toolchain.cmake + toolchain_lines = Path(self.generators_folder, "conan_toolchain.cmake").read_text().splitlines() + runtime_paths = "\n".join(l for l in toolchain_lines if ("CONAN_RUNTIME_LIB_DIRS" in l or "CMAKE_PROGRAM_PATH" in l)) + Path(self.generators_folder, "conan_runtime_paths.cmake").write_text(runtime_paths) + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + cmake = CMake(self) + cmake.install() + copy(self, "LICENSE", self.source_folder, os.path.join(self.package_folder, "licenses")) + rmdir(self, os.path.join(self.source_folder, "lib", "cmake")) + + def package_info(self): + self.cpp_info.set_property("cmake_file_name", "novatel_edie") + self.cpp_info.set_property("cmake_target_name", "novatel_edie::novatel_edie") + self.cpp_info.resdirs = ["res"] + self.cpp_info.libs = [ + # Note: the order of the listed libs matters when linking statically. + "edie_oem_decoder", + "edie_stream_interface", + "edie_decoders_common", + "edie_common", + ] + db_path = os.path.join(self.package_folder, "res", "novatel_edie", "messages_public.json") + self.runenv_info.define_path("EDIE_DATABASE_FILE", db_path) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 9f504ac90..8618e8c88 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME "common") file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) -add_library(${TARGET_NAME} STATIC ${SOURCES}) +add_library(${TARGET_NAME} ${SOURCES}) set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME "edie_${TARGET_NAME}" FOLDER "common" @@ -12,10 +12,17 @@ target_include_directories(${TARGET_NAME} PUBLIC target_compile_features(${TARGET_NAME} PUBLIC cxx_std_17) find_package(spdlog REQUIRED CONFIG) -find_package(spdlog_setup REQUIRED CONFIG) +find_package(spdlog_setup REQUIRED MODULE) target_link_libraries(${TARGET_NAME} PUBLIC spdlog_setup::spdlog_setup $ $ ) + +install(TARGETS ${TARGET_NAME} + EXPORT novatel_edie-targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/src/decoders/common/CMakeLists.txt b/src/decoders/common/CMakeLists.txt index b606719c6..1c482a1a7 100644 --- a/src/decoders/common/CMakeLists.txt +++ b/src/decoders/common/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME "decoders_common") file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) -add_library(${TARGET_NAME} STATIC ${SOURCES}) +add_library(${TARGET_NAME} ${SOURCES}) set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME "edie_${TARGET_NAME}" FOLDER "decoders" @@ -16,3 +16,10 @@ target_link_libraries(${TARGET_NAME} PUBLIC common nlohmann_json::nlohmann_json ) + +install(TARGETS ${TARGET_NAME} + EXPORT novatel_edie-targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/src/decoders/oem/CMakeLists.txt b/src/decoders/oem/CMakeLists.txt index 1d3863ff3..d6e1a4906 100644 --- a/src/decoders/oem/CMakeLists.txt +++ b/src/decoders/oem/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME "oem_decoder") file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) -add_library(${TARGET_NAME} STATIC ${SOURCES}) +add_library(${TARGET_NAME} ${SOURCES}) set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME "edie_${TARGET_NAME}" FOLDER "decoders" @@ -10,3 +10,10 @@ target_include_directories(${TARGET_NAME} PUBLIC $ $ ) + +install(TARGETS ${TARGET_NAME} + EXPORT novatel_edie-targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/src/stream_interface/CMakeLists.txt b/src/stream_interface/CMakeLists.txt index 1e9806401..fcb0422e0 100644 --- a/src/stream_interface/CMakeLists.txt +++ b/src/stream_interface/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME "stream_interface") file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) -add_library(${TARGET_NAME} STATIC ${SOURCES}) +add_library(${TARGET_NAME} ${SOURCES}) set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME "edie_${TARGET_NAME}" FOLDER "hw_interface" @@ -10,3 +10,10 @@ target_include_directories(${TARGET_NAME} PUBLIC $ $ ) + +install(TARGETS ${TARGET_NAME} + EXPORT novatel_edie-targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/test_package/conanfile.py b/test_package/conanfile.py index 6e4eaee6c..228c22cd0 100644 --- a/test_package/conanfile.py +++ b/test_package/conanfile.py @@ -25,8 +25,7 @@ def build(self): def test(self): if can_run(self): bin_path = os.path.join(self.cpp.build.bindir, "CommandEncoding") - datadir = self.dependencies["novatel_edie"].cpp_info.resdirs[0] - database_json = os.path.join(datadir, "messages_public.json") + database_json = self.dependencies["novatel_edie"].runenv_info.vars(self).get("EDIE_DATABASE_FILE") format = "ASCII" command = "RTKTIMEOUT 30" self.run(f"{bin_path} {database_json} {format} {command}", env="conanrun")