Conan.io 和 header-only 图书馆

Conan.io and header-only library

我正在尝试从现有的 header-only 库创建柯南包。这不是带有 include 文件夹的教科书示例 - 结构如下所示:

public/SomeHeader.hpp
public/CHeader.h
public/anotherFolder/AnotherHeader.hpp

这是我的 conanfile.py 基于 Documentation and some other things.

from conans import ConanFile

class MyLibConan(ConanFile):
    name = "MyLib"
    version = "1.0"

def package_info(self):
    self.cpp_info.includedirs = ["public", "public/anotherFolder"]

def package(self):
    self.copy("*.hpp", dst="public", src="public", keep_path=False)
    self.copy("*.h", dst="public", src="public", keep_path=False)

我应该在 package() 方法中使用 self.copy 还是 cpp_info.includedirs?有什么区别?

我这样导出包,到目前为止没有错误

 export . demo/test

然后在我的主项目中我有conanfile.txt如下:

 [requires]
 MyLib/1.0@demo/test

 [generators]
 cmake

我的CMakeLists.txt之前只是将exec链接到MyLib(INTERFACE库)

include_directories(MyLibFolder)
add_executable(someTarget ...)
target_link_libraries(someTarget MyLib)

现在看起来像这样:

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
...
target_link_libraries(someTarget ${CONAN_LIBS})

编译项目后

mkdir build && cd build
conan install ..
cmake .. -G Ninja
cmake --build .

我收到错误...:(

fatal error: anotherFolder/AnotherHeader.hpp: No such file or directory
#include <anotherFolder/AnotherHeader.hpp>

我对柯南超级陌生,看在上帝的份上,我无法掌握如何构建 conanfile.py。我尝试了很多不同的组合,但都没有成功

提前致谢,

干杯

以下是您案例的一些答案:

Should I use self.copy in package() method or cpp_info.includedirs? What's the difference?

在您的情况下,self.copy is the better option. By default, includedirs 定义为 ["include"],我们通常仅在包安装未按预期遵循正确的文件夹结构时才附加其他文件夹。

Here is my conanfile.py based on Documentation and some other things.

您的示例缺少一个非常重要的属性:exports_sources, without it, Conan won't copy your header files when running conan export 命令。所以,你的食谱应该是这样的:

from conans import ConanFile

class MyLibConan(ConanFile):
    name = "MyLib"
    version = "1.0"
    exports_sources = ["public/*"]
    no_copy_sources = True

    def package(self):
        self.copy("*.hpp", dst="include", src="public")
        self.copy("*.h", dst="include", src="public")

并且您的柯南导出将包含列出的文件:

$ conan export . demo/test
Exporting package recipe
MyLib/1.0@demo/test exports_sources: Copied 1 '.h' file: CHeader.h
MyLib/1.0@demo/test exports_sources: Copied 2 '.hpp' files: Someheader.hpp, AnotherHeader.hpp
MyLib/1.0@demo/test: A new conanfile.py version was exported
MyLib/1.0@demo/test: Folder: /home/uilian/.conan/data/MyLib/1.0/demo/test/export
MyLib/1.0@demo/test: Using the exported files summary hash as the recipe revision: f367d0a701a867835b7ac612b90b3d1c 
MyLib/1.0@demo/test: Exported revision: f367d0a701a867835b7ac612b90b3d1c

但是你还没有柯南包,你需要运行conan install MyLib/1.0@demo/test --build=MyLib。您可以使用更好的命令来创建包,而不是 运行ning 两步,conan create:

$ conan create . demo/test
Exporting package recipe
MyLib/1.0@demo/test exports_sources: Copied 1 '.h' file: CHeader.h
MyLib/1.0@demo/test exports_sources: Copied 2 '.hpp' files: Someheader.hpp, AnotherHeader.hpp
MyLib/1.0@demo/test: A new conanfile.py version was exported
MyLib/1.0@demo/test: Folder: /home/conan/.conan/data/MyLib/1.0/demo/test/export
MyLib/1.0@demo/test: Exported revision: f367d0a701a867835b7ac612b90b3d1c
Configuration:
[settings]
arch=x86_64
arch_build=x86_64
build_type=Release
compiler=gcc
compiler.libcxx=libstdc++
compiler.version=9
os=Linux
os_build=Linux
[options]
[build_requires]
[env]

MyLib/1.0@demo/test: Forced build from source
Installing package: MyLib/1.0@demo/test
Requirements
    MyLib/1.0@demo/test from local cache - Cache
Packages
    MyLib/1.0@demo/test:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 - Build

Installing (downloading, building) binaries...
MyLib/1.0@demo/test: Configuring sources in /home/conan/.conan/data/MyLib/1.0/demo/test/source
MyLib/1.0@demo/test: Copying sources to build folder
MyLib/1.0@demo/test: Building your package in /home/conan/.conan/data/MyLib/1.0/demo/test/build/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9
MyLib/1.0@demo/test: Generator txt created conanbuildinfo.txt
MyLib/1.0@demo/test: Calling build()
MyLib/1.0@demo/test: WARN: This conanfile has no build step
MyLib/1.0@demo/test: Package '5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9' built
MyLib/1.0@demo/test: Build folder /home/conan/.conan/data/MyLib/1.0/demo/test/build/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9
MyLib/1.0@demo/test: Generated conaninfo.txt
MyLib/1.0@demo/test: Generated conanbuildinfo.txt
MyLib/1.0@demo/test: Generating the package
MyLib/1.0@demo/test: Package folder /home/conan/.conan/data/MyLib/1.0/demo/test/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9
MyLib/1.0@demo/test: Calling package()
MyLib/1.0@demo/test package(): Packaged 2 '.hpp' files: Someheader.hpp, AnotherHeader.hpp
MyLib/1.0@demo/test package(): Packaged 1 '.h' file: CHeader.h
MyLib/1.0@demo/test: Package '5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9' created
MyLib/1.0@demo/test: Created package revision d1a54d50f9ded97d33be080f4a1ef606

现在你有更多的输出,因为柯南不仅在导出,还在构建和打包你的包。构建部分实际上是一个谎言,因为我们省略了 build().

I get errors... :(

fatal error: anotherFolder/AnotherHeader.hpp: No such file or directory #include <anotherFolder/AnotherHeader.hpp>

因为这一行:

self.copy("*.hpp", dst="public", src="public", keep_path=False)

您将在包裹中找到它:

$ ls -R public/
public/:
AnotherHeader.hpp  CHeader.h  Someheader.hpp

当你设置keep_path=False时,你告诉柯南复制所有*.h文件并保存到public/文件夹,但不要保留原始路径AnotherFolder/

但是,让我们看一下新的实现:

self.copy("*.hpp", dst="include", src="public")
self.copy("*.h", dst="include", src="public")

现在保留路径,使用 include/ 作为文件夹。为什么? include/ 是用于头文件的通用名称,就像 src/ 用于 .c 和 .cpp 等源文件一样。尽量保持这样的模式。

$ ls -R include/
include/:
CHeader.h  Someheader.hpp  anotherFolder

include/anotherFolder:
AnotherHeader.hpp

现在我们可以看到头文件夹仍然存在,您的错误不会再发生。

此致。