【发布时间】:2020-08-15 12:38:26
【问题描述】:
我有一个包含 2 个二进制文件的包。二进制文件只有一个选项不同。
这个包是一个库。现在如何将此包链接到我需要的特定包?
【问题讨论】:
标签: conan
我有一个包含 2 个二进制文件的包。二进制文件只有一个选项不同。
这个包是一个库。现在如何将此包链接到我需要的特定包?
【问题讨论】:
标签: conan
有几个选项:
您可以使用cmake_paths 并发现库名称:
首先,你添加一个conanfile.txt,声明包名和cmake_paths生成器
[requires]
my_package/0.1.0@user/channel
[generators]
cmake_paths
其次,您从包中搜索所需的库,在您的 cmake 文件中按其名称:
cmake_minimum_required(VERSION 3.0)
project(myapp)
find_library(MY_LIBRARY foo REQUIRED) # the library name foo in this example
add_executable(myapp app.cpp)
target_link_libraries (myapp ${MY_LIBRARY})
最后,你将 cmake_paths 传递给 cmake,所以它会找到你的库
mkdir build && cd build
conan install ..
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_paths.cmake
cmake --build .
./myapp
它可以工作,但它有点脆弱,因为消费者现在需要库名称,并且在找到库时没有来自 CMake 的警告,你必须添加一个条件来检查它。
第二种可能的选择是使用Components 功能,但需要修改配方,您可以为每个库提供不同的目标:
首先,您需要更新您的 conanfile.py,添加组件:
from conans import ConanFile, CMake
class MyPackage(ConanFile):
name = "my_package"
version = "0.1.0"
settings = "os", "compiler", "build_type", "arch"
options = {"shared": [True, False]}
default_options = {"shared": False}
generators = "cmake"
exports_sources = "src/*"
def build(self):
cmake = CMake(self)
cmake.configure(source_folder="src")
cmake.build()
def package(self):
self.copy("*.h", dst="include", src="src")
self.copy("*.lib", dst="lib", keep_path=False)
self.copy("*.dll", dst="bin", keep_path=False)
self.copy("*.dylib*", dst="lib", keep_path=False)
self.copy("*.so", dst="lib", keep_path=False)
self.copy("*.a", dst="lib", keep_path=False)
def package_info(self):
self.cpp_info.names["cmake_find_package"] = "MyPackage"
self.cpp_info.names["cmake_find_package_multi"] = "MyPackage"
self.cpp_info.components["libfoo"].names["cmake_find_package"] = "foo"
self.cpp_info.components["libfoo"].names["cmake_find_package_multi"] = "foo"
self.cpp_info.components["libfoo"].libs = ["foo"]
self.cpp_info.components["libbar"].names["cmake_find_package"] = "bar"
self.cpp_info.components["libbar"].names["cmake_find_package_multi"] = "bar"
self.cpp_info.components["libbar"].libs = ["bar"]
如您所见,配方构建了一个包含 2 个库的包,foo 和 bar,并为每个库使用不同的组件。由于 CMake 目标首选 CamelCase,因此名称 MyPackage 将用于文件名和目标命名空间。结果将是MyPackage::foo 和MyPackage::bar。
作为消费者,您也必须更新您的项目:
现在我们将使用cmake_find_package 生成器,以避免在命令行中使用CMAKE_TOOLCHAIN_FILE:
[requires]
my_package/0.1.0@user/channel
[generators]
cmake_find_package
CMake 文件现在需要包名,但它已由 CMake 检查:
cmake_minimum_required(VERSION 3.0)
project(myapp)
find_package(MyPackage REQUIRED)
add_executable(myapp app.cpp)
target_link_libraries (myapp MyPackage::foo) # We only need libfoo here
最后,但现在更简单的是命令行:
mkdir build && cd build
conan install ..
cmake ..
cmake --build .
./myapp
柯南将在build/ 中生成FindMyPackage.cmake,并由您的CMakeLists.txt 加载。
两个演示都达到了你的要求,但我更喜欢第二个,因为更安全,因为你可以创建一个特定的目标,并避免客户方面的任何错误。
注意:功能组件需要柯南 >=1.27。
【讨论】: