diff --git a/recipes/cyclonedds-cxx/all/cmake/Generate.cmake b/recipes/cyclonedds-cxx/all/cmake/Generate.cmake new file mode 100644 index 0000000000..a399ac1aa2 --- /dev/null +++ b/recipes/cyclonedds-cxx/all/cmake/Generate.cmake @@ -0,0 +1,64 @@ +# +# Copyright(c) 2020 to 2022 ZettaScale Technology and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# + +# NOTE: This function was leveraged from the upstream cyclonedds-cxx project +# and modified to find the direct path to the cycloneddsidlcxx library as +# opposed to leveraging the native CycloneDDS-CXX::idlcxx cmake target. +# Because Conan redeclares its own targets using INTERFACE libs, the upstream +# version of this function was incompatible. If the upstream implementation of +# this functionality changes, a modification to this file may be required. +# See: https://github.com/eclipse-cyclonedds/cyclonedds-cxx/blob/master/src/idlcxx/Generate.cmake + +find_package(CycloneDDS REQUIRED) + +# find idlcxx shared library +set(CMAKE_FIND_LIBRARY_SUFFIXES .dll ${CMAKE_FIND_LIBRARY_SUFFIXES}) +if(CMAKE_CROSSCOMPILING) + find_library(_idlcxx_shared_lib cycloneddsidlcxx NO_CMAKE_FIND_ROOT_PATH REQUIRED) +else() + find_library(_idlcxx_shared_lib + NAMES cycloneddsidlcxx + PATHS ${CMAKE_CURRENT_LIST_DIR}/../../bin/ + ${CMAKE_CURRENT_LIST_DIR}/../../lib/ + NO_DEFAULT_PATH) +endif() + +if(_idlcxx_shared_lib) + set(_idlcxx_depends "") +else() + message(FATAL_ERROR "Cannot find idlcxx shared library") +endif() + +function(IDLCXX_GENERATE) + set(one_value_keywords TARGET DEFAULT_EXTENSIBILITY BASE_DIR OUTPUT_DIR) + set(multi_value_keywords FILES FEATURES INCLUDES WARNINGS) + cmake_parse_arguments( + IDLCXX "" "${one_value_keywords}" "${multi_value_keywords}" "" ${ARGN}) + + idlc_generate_generic(TARGET ${IDLCXX_TARGET} + BACKEND ${_idlcxx_shared_lib} + BASE_DIR ${IDLCXX_BASE_DIR} + FILES ${IDLCXX_FILES} + FEATURES ${IDLCXX_FEATURES} + INCLUDES ${IDLCXX_INCLUDES} + WARNINGS ${IDLCXX_WARNINGS} + DEFAULT_EXTENSIBILITY ${IDLCXX_DEFAULT_EXTENSIBILITY} + SUFFIXES .hpp .cpp + OUTPUT_DIR ${IDLCXX_OUTPUT_DIR} + DEPENDS ${_idlcxx_depends} + ) + if(CYCLONEDDS_CXX_ENABLE_LEGACY) + target_include_directories(${IDLCXX_TARGET} + INTERFACE ${Boost_INCLUDE_DIR} + ) + endif() +endfunction() diff --git a/recipes/cyclonedds-cxx/all/conandata.yml b/recipes/cyclonedds-cxx/all/conandata.yml new file mode 100644 index 0000000000..46c0203bb5 --- /dev/null +++ b/recipes/cyclonedds-cxx/all/conandata.yml @@ -0,0 +1,4 @@ +sources: + "0.10.4": + url: "https://github.com/eclipse-cyclonedds/cyclonedds-cxx/archive/refs/tags/0.10.4.tar.gz" + sha256: "ca09d738b150a7dc1fa63dcb5ad211a4ba516c92710ebff7b9fe817c7c5a257e" diff --git a/recipes/cyclonedds-cxx/all/conanfile.py b/recipes/cyclonedds-cxx/all/conanfile.py new file mode 100644 index 0000000000..723b2660af --- /dev/null +++ b/recipes/cyclonedds-cxx/all/conanfile.py @@ -0,0 +1,162 @@ +from conan import ConanFile +from conan.errors import ConanInvalidConfiguration +from conan.tools.build import check_min_cppstd +from conan.tools.cmake import CMakeToolchain, CMake, CMakeDeps, cmake_layout +from conan.tools.files import copy, get, rm, rmdir, replace_in_file +from conan.tools.scm import Version +import os + +required_conan_version = ">=1.61.0" + +class CycloneDDSCXXConan(ConanFile): + name = "cyclonedds-cxx" + license = "EPL-2.0" + homepage = "https://cyclonedds.io/" + url = "https://github.com/conan-io/conan-center-index" + description = "Eclipse Cyclone DDS C++ Binding- An implementation"\ + " of the OMG Data Distribution Service (DDS) specification" + topics = ("dds", "ipc", "ros", "middleware") + package_type = "library" + settings = "os", "arch", "compiler", "build_type" + options = { + "shared": [True, False], + "fPIC": [True, False], + } + default_options = { + "shared": False, + "fPIC": True, + } + + @property + def _min_cppstd(self): + return "17" + + @property + def _compilers_minimum_version(self): + return { + "gcc": "7", + "Visual Studio": "16", + "msvc": "192", + "clang": "7", + "apple-clang": "10", + } + + def _has_idlc(self, info=False): + # don't build idllib when it makes little sense or not supported + host_os = self.info.settings.os if info else self.settings.os + return host_os not in ["Android", "iOS", "watchOS", "tvOS", "Neutrino"] + + def export_sources(self): + copy(self, os.path.join("cmake", "Generate.cmake"), self.recipe_folder, self.export_sources_folder) + + 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") + + def layout(self): + cmake_layout(self, src_folder="src") + + def requirements(self): + # Use the corresponding version of cyclonedds with transitive headers + #INFO: is used in several public headers including: + # :29 + # :31 + # :26 + # :34 + self.requires("cyclonedds/{}".format(self.version), transitive_headers=True) + + def validate(self): + if self.settings.compiler.get_safe("cppstd"): + check_min_cppstd(self, self._min_cppstd) + minimum_version = self._compilers_minimum_version.get(str(self.settings.compiler), False) + if minimum_version and Version(self.settings.compiler.version) < minimum_version: + raise ConanInvalidConfiguration( + f"{self.ref} requires C++{self._min_cppstd}, which your compiler does not support." + ) + + def build_requirements(self): + self.tool_requires("cmake/[>=3.16 <4]") + + def source(self): + get(self, **self.conan_data["sources"][self.version], strip_root=True) + + def generate(self): + tc = CMakeToolchain(self) + tc.variables["BUILD_DDSLIB"] = True + tc.variables["BUILD_IDLLIB"] = self._has_idlc() + tc.variables["BUILD_DOCS"] = False + tc.variables["BUILD_TESTING"] = False + tc.variables["BUILD_EXAMPLES"] = False + # variables which effects build + tc.variables["ENABLE_LEGACY"] = False + tc.variables["ENABLE_SHM"] = self.dependencies["cyclonedds"].options.with_shm + tc.variables["ENABLE_TYPE_DISCOVERY"] = self.dependencies["cyclonedds"].options.enable_discovery + tc.variables["ENABLE_TOPIC_DISCOVERY"] = self.dependencies["cyclonedds"].options.enable_discovery + tc.variables["ENABLE_COVERAGE"] = False + tc.generate() + cd = CMakeDeps(self) + cd.generate() + + def _patch_sources(self): + cmakelists = os.path.join(self.source_folder, "CMakeLists.txt") + replace_in_file(self, cmakelists, + "get_target_property(cyclonedds_has_shm CycloneDDS::ddsc SHM_SUPPORT_IS_AVAILABLE)", + "set(cyclonedds_has_shm {})".format(self.dependencies["cyclonedds"].options.with_shm)) + replace_in_file(self, cmakelists, + "get_target_property(cyclonedds_has_type_discovery CycloneDDS::ddsc TYPE_DISCOVERY_IS_AVAILABLE)", + "set(cyclonedds_has_type_discovery {})".format(self.dependencies["cyclonedds"].options.enable_discovery)) + replace_in_file(self, cmakelists, + "get_target_property(cyclonedds_has_topic_discovery CycloneDDS::ddsc TOPIC_DISCOVERY_IS_AVAILABLE)", + "set(cyclonedds_has_topic_discovery {})".format(self.dependencies["cyclonedds"].options.enable_discovery)) + + def build(self): + self._patch_sources() + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + cmake = CMake(self) + cmake.install() + rmdir(self, os.path.join(self.package_folder, "share")) + rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig")) + rmdir(self, os.path.join(self.package_folder, "lib", "cmake", "CycloneDDS-CXX")) + copy(self, "LICENSE", self.source_folder, os.path.join(self.package_folder, "licenses")) + copy(self, "Generate.cmake", + src=os.path.join(self.source_folder, os.pardir, "cmake"), + dst=os.path.join(self.package_folder, self._module_path)) + if self.settings.os == "Windows": + for p in ("*.pdb", "concrt*.dll", "msvcp*.dll", "vcruntime*.dll"): + rm(self, p, os.path.join(self.package_folder, "bin")) + + @property + def _module_path(self): + return os.path.join("lib", "cmake") + + def package_info(self): + self.cpp_info.set_property("cmake_find_mode", "both") + self.cpp_info.set_property("cmake_module_file_name", "CycloneDDS-CXX") + self.cpp_info.set_property("cmake_file_name", "CycloneDDS-CXX") + self.cpp_info.set_property("cmake_target_name", "CycloneDDS-CXX::CycloneDDS-CXX") + self.cpp_info.set_property("pkg_config_name", "CycloneDDS-CXX") + build_modules = [ + os.path.join(self._module_path, "Generate.cmake"), + ] + self.cpp_info.set_property("cmake_build_modules", build_modules) + self.cpp_info.includedirs = ["include/ddscxx"] + self.cpp_info.builddirs = [self._module_path] + self.cpp_info.components["ddscxx"].libs = ["ddscxx"] + self.cpp_info.components["ddscxx"].includedirs = ["include/ddscxx"] + self.cpp_info.components["ddscxx"].set_property("cmake_target_name", "CycloneDDS-CXX::ddscxx") + self.cpp_info.components["ddscxx"].set_property("pkg_config_name", "CycloneDDS-CXX") + if self.settings.os in ["Linux", "FreeBSD"]: + self.cpp_info.components["ddscxx"].system_libs = ["m"] + self.cpp_info.components["idlcxx"].libs = ["cycloneddsidlcxx"] + self.cpp_info.components["idlcxx"].set_property("cmake_target_name", "CycloneDDS-CXX::idlcxx") + self.env_info.PATH.append(os.path.join(self.package_folder, "bin")) + self.buildenv_info.append_path("PATH", os.path.join(self.package_folder, "bin")) + self.runenv_info.append_path("PATH", os.path.join(self.package_folder, "bin")) diff --git a/recipes/cyclonedds-cxx/all/test_package/CMakeLists.txt b/recipes/cyclonedds-cxx/all/test_package/CMakeLists.txt new file mode 100644 index 0000000000..4092a05fa5 --- /dev/null +++ b/recipes/cyclonedds-cxx/all/test_package/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.8) +project(test_package CXX) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +find_package(CycloneDDS-CXX REQUIRED) + +add_executable(test_package test_package.cpp) +target_link_libraries(test_package PRIVATE CycloneDDS-CXX::ddscxx CycloneDDS::ddsc) + +if(NOT CMAKE_CROSSCOMPILING) + IDLCXX_GENERATE(TARGET MessageLib FILES Message.idl) + add_executable(test_message test_message.cpp) + target_link_libraries(test_message PRIVATE MessageLib CycloneDDS-CXX::ddscxx CycloneDDS::ddsc) +endif() diff --git a/recipes/cyclonedds-cxx/all/test_package/Message.idl b/recipes/cyclonedds-cxx/all/test_package/Message.idl new file mode 100644 index 0000000000..46b201f63a --- /dev/null +++ b/recipes/cyclonedds-cxx/all/test_package/Message.idl @@ -0,0 +1,6 @@ +module conan { + struct Message { + sequence payload; + }; + #pragma keylist Message +}; diff --git a/recipes/cyclonedds-cxx/all/test_package/conanfile.py b/recipes/cyclonedds-cxx/all/test_package/conanfile.py new file mode 100644 index 0000000000..50b7ececfc --- /dev/null +++ b/recipes/cyclonedds-cxx/all/test_package/conanfile.py @@ -0,0 +1,27 @@ +import os +from conan import ConanFile +from conan.tools.cmake import CMake, cmake_layout +from conan.tools.build import can_run + +class CycloneDDSCXXTestConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "CMakeToolchain", "CMakeDeps", "VirtualRunEnv" + test_type = "explicit" + + def layout(self): + cmake_layout(self) + + def requirements(self): + self.requires(self.tested_reference_str) + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + if can_run(self): + bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package") + self.run(bin_path, env="conanrun") + bin_path = os.path.join(self.cpp.build.bindirs[0], "test_message") + self.run(bin_path, env="conanrun") diff --git a/recipes/cyclonedds-cxx/all/test_package/test_message.cpp b/recipes/cyclonedds-cxx/all/test_package/test_message.cpp new file mode 100644 index 0000000000..2bc38e32ae --- /dev/null +++ b/recipes/cyclonedds-cxx/all/test_package/test_message.cpp @@ -0,0 +1,12 @@ +#include +#include "dds/dds.hpp" +#include "Message.hpp" + +int main() { + dds::domain::DomainParticipant domain_(0); + + conan::Message message; + std::vector payload; + message.payload(std::move(payload)); + return 0; +} diff --git a/recipes/cyclonedds-cxx/all/test_package/test_package.cpp b/recipes/cyclonedds-cxx/all/test_package/test_package.cpp new file mode 100644 index 0000000000..b4cf37cb3f --- /dev/null +++ b/recipes/cyclonedds-cxx/all/test_package/test_package.cpp @@ -0,0 +1,11 @@ +#include +#include "dds/dds.hpp" + +int main() { + + dds::domain::DomainParticipant participant(0); + dds::topic::PublicationBuiltinTopicData topic; + dds::sub::Subscriber subscriber(participant); + + return 0; +} diff --git a/recipes/cyclonedds-cxx/config.yml b/recipes/cyclonedds-cxx/config.yml new file mode 100644 index 0000000000..87e6038632 --- /dev/null +++ b/recipes/cyclonedds-cxx/config.yml @@ -0,0 +1,3 @@ +versions: + "0.10.4": + folder: all