(#17344) cyclonedds-cxx: Add new recipe

* Add cyclonedds-cxx recipe

* Streamline

* remove conan v1 vars

* Tweak

* Add 0.10.4

* Require cyclonedds

* Add find_package

* Use transitive headers

* Update src folder

* Set minimum conan version to >=1.61.0

* Require cxx17 for test package

* Handle cross-compilation

* Try to handle win32 dll scenario

* Help find dll

* Wrong function call

* Mark message as debug

* Appease the linting gods

* Add m to system_libs

* Remove older versions

* Tweak recipe with review feedback

* Document transitive_header reasoning

* Refactor code generation support and use CMakeDeps to include cycloneidlcxx lib

* Use default paths as well

* Tweak search path

* Refactor generate script

* Add builddirs

* Revert back to cmake 3.16+

* Removed unused export_conan_data
This commit is contained in:
wadehunk
2023-12-09 06:44:15 -06:00
committed by GitHub
parent 23c84b31ab
commit 98bd2cfc0c
9 changed files with 304 additions and 0 deletions

View File

@@ -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()

View File

@@ -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"

View File

@@ -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: <dds/dds.h> is used in several public headers including:
# <dds/sub/detail/DataWriter.hpp>:29
# <dds/sub/detail/DataReader.hpp>:31
# <dds/topic/detail/TTopicImpl.hpp>:26
# <dds/topic/detail/Topic.hpp>: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"))

View File

@@ -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()

View File

@@ -0,0 +1,6 @@
module conan {
struct Message {
sequence<octet> payload;
};
#pragma keylist Message
};

View File

@@ -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")

View File

@@ -0,0 +1,12 @@
#include <vector>
#include "dds/dds.hpp"
#include "Message.hpp"
int main() {
dds::domain::DomainParticipant domain_(0);
conan::Message message;
std::vector<unsigned char> payload;
message.payload(std::move(payload));
return 0;
}

View File

@@ -0,0 +1,11 @@
#include <vector>
#include "dds/dds.hpp"
int main() {
dds::domain::DomainParticipant participant(0);
dds::topic::PublicationBuiltinTopicData topic;
dds::sub::Subscriber subscriber(participant);
return 0;
}

View File

@@ -0,0 +1,3 @@
versions:
"0.10.4":
folder: all