使用组件和可编辑包¶
可以在 layout()
方法中定义组件,以支持 editable
包的情况。也就是说,如果我们想将一个包置于 editable
模式,并且该包定义了 components
,则需要在 layout()
方法中正确定义组件布局。让我们在一个真实的例子中看看它。
请先克隆源代码以重新创建此项目。您可以在 GitHub 上的 examples2 存储库 中找到它们。
$ git clone https://github.com/conan-io/examples2.git
$ cd examples2/examples/conanfile/layout/editable_components
在那里我们找到一个 greetings
子文件夹和包,其中包含 2 个库,hello
库和 bye
库。每个库都被建模为包食谱中的一个 component
。
class GreetingsConan(ConanFile):
name = "greetings"
version = "0.1"
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeDeps", "CMakeToolchain"
exports_sources = "src/*"
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def layout(self):
cmake_layout(self, src_folder="src")
# This "includedirs" starts in the source folder, which is "src"
# So the components include dirs is the "src" folder (includes are
# intended to be included as ``#include "hello/hello.h"``)
self.cpp.source.components["hello"].includedirs = ["."]
self.cpp.source.components["bye"].includedirs = ["."]
# compiled libraries "libdirs" will be inside the "build" folder, depending
# on the platform they will be in "build/Release" or directly in "build" folder
bt = "." if self.settings.os != "Windows" else str(self.settings.build_type)
self.cpp.build.components["hello"].libdirs = [bt]
self.cpp.build.components["bye"].libdirs = [bt]
def package(self):
copy(self, "*.h", src=self.source_folder,
dst=join(self.package_folder, "include"))
copy(self, "*.lib", src=self.build_folder,
dst=join(self.package_folder, "lib"), keep_path=False)
copy(self, "*.a", src=self.build_folder,
dst=join(self.package_folder, "lib"), keep_path=False)
def package_info(self):
self.cpp_info.components["hello"].libs = ["hello"]
self.cpp_info.components["bye"].libs = ["bye"]
self.cpp_info.set_property("cmake_file_name", "MYG")
self.cpp_info.set_property("cmake_target_name", "MyGreetings::MyGreetings")
self.cpp_info.components["hello"].set_property("cmake_target_name", "MyGreetings::MyHello")
self.cpp_info.components["bye"].set_property("cmake_target_name", "MyGreetings::MyBye")
虽然 hello
和 bye
库在最终包中的位置位于最终的 lib
文件夹中,那么在 package_info()
方法中不需要任何特殊操作,除了组件的定义之外。在这种情况下,还包括 CMake 生成的文件名和目标的自定义,但这对于此示例来说不是必需的。
重要的部分是 layout()
定义。除了常见的 cmake_layout
之外,还需要定义组件头文件的位置(self.cpp.source
,因为它们是源代码)以及本地构建库的位置。由于库的位置取决于平台,因此最终的 self.cpp.build.components["component"].libdirs
取决于平台。
使用此食谱,我们可以将包置于可编辑模式并在本地使用以下命令构建它:
$ conan editable add greetings
$ conan build greetings
# we might want to also build the debug config
在 app
文件夹中,我们有一个包食谱来构建 2 个可执行文件,它们链接到 greeting
包组件。那里的 app/conanfile.py
食谱很简单,build()
方法构建并运行使用 CMakeLists.txt
构建的 example
和 example2
这两个可执行文件。
# Note the MYG file name, not matching the package name,
# because the recipe defined "cmake_file_name"
find_package(MYG)
add_executable(example example.cpp)
# Note the MyGreetings::MyGreetings target name, not matching the package name,
# because the recipe defined "cmake_target_name"
# "example" is linking with the whole package, both "hello" and "bye" components
target_link_libraries(example MyGreetings::MyGreetings)
add_executable(example2 example2.cpp)
# "example2" is only using and linking "hello" component, but not "bye"
target_link_libraries(example2 MyGreetings::MyHello)
$ conan build app
hello: Release!
bye: Release!
如果您现在转到 bye.cpp
源文件并修改输出消息,然后在本地构建 greetings
和 app
,则“bye”组件库的最终输出消息应该会发生变化。
$ conan build greetings
$ conan build app
hello: Release!
adios: Release!