#conan
#conan
Вопрос:
У меня есть пакет с 2 двоичными файлами. Двоичные файлы отличаются только одним параметром.
Пакет представляет собой библиотеку. Как теперь связать этот пакет с конкретным пакетом, который мне требуется?
Ответ №1:
Есть несколько вариантов:
Вы можете использовать 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 amp;amp; 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"]
Как вы можете видеть, рецепт создает пакет с двумя библиотеками, foo
и bar
, и использует разные компоненты для каждой из них. Поскольку camelCase предпочтительнее для целевых объектов CMake, имя 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 amp;amp; cd build
conan install ..
cmake ..
cmake --build .
./myapp
Conan сгенерирует FindMyPackage.cmake
in build/
, который будет загружен вашим CMakeLists.txt
.
Обе демонстрации достигают того, что вы просили, но я предпочитаю вторую, потому что она безопаснее, поскольку вы можете создать конкретную цель и избежать любой ошибки со стороны клиента.
ПРИМЕЧАНИЕ: Для компонентов функций требуется Conan > = 1.27.