Conan打包
Conan-center中保存了许多的c++包,但是还是有许多的c++源没有被打包,这次一边学习一边尝试为Clang进行打包
为第三方库进行打包
- 构建一个新pkg
conan new Clang/12.0.0 -t |
- 修改conanfile.py
直接去https://github.com/conan-io/conan-center-index/blob/master/recipes/
下面参考各种打包的流程即可
- 下载代码到本地调试构建
注意每次build的时候最好把build目录的CmakeCache.txt删除了再开始,不然有时候你以为你成功,但其实只是偶尔的cache是正确的。
conan export . Clang/12.0.0@demo/testing # 修改代码后需要export才能生效 |
- 打包上传云端
如果上面的步骤之后,本地去include对应的代码可以正常编译,那么就可以导出pkg了
conan create .
注意点
- 如果需要修改第三方库的源码,可以用patch的形式,调用conan的方法进行修改。
通常都是要在第三方库中添加如下信息的,因为你所有的依赖都是交给conan了,而不是有的通过本机,有的通过Conan。conan会给所有的第三方库都生成一个findxxx.cmake,通过conan_basic_setup去执行,执行完毕后,find_package就可以找到来自与Conan的包了。同时这里的${CONAN_BIN_DIRS}
也可以添加,添加之后可以调用预编译lib中的一些可执行文件。
还有就是有的库写的find_package都是用xxx_DIR的方式去寻找xxxConfig.cmake的,这种方式和conan的行为不一致,需要修改。
message(STATUS "Loading conan scripts for Clang dependencies...") |
list(APPEND CMAKE_PROGRAM_PATH ${CONAN_BIN_DIRS})
对于LLVM来说,最好不能使用
BUILD_SHARED_LIBS
,因为LLVM依赖于全局数据,这些数据最终可能会在共享库之间复制可能会导致错误。也就是默认是static的。conan官方的一些包的recipe里面是把他们的一些cmake文件删除了,比如他的llvm-core只有一堆静态库,这就非常蛋疼了,想依赖这个lib去构建clang是不行的。所以还得自己打包。
默认的conan的build_folder就是同个目录,他都是打包结束后直接从当前文件夹下面选择性的去拷贝到package_folder下面。当然这个过程可以随便自定义,我觉得直接cmake install到package目录就完事了。
报错
ConanException: llvm-core/12.0.0 package_info(): Package require 'libxml2' not used in components requires
我用官方的llvm-core就有这个问题,我一开始一直以为是我的问题,然后发现他可能打包的时候就出问题了。conan的设计思路是每个package_info里面提供了每个库的详细信息,像llvm这种库,是由多个组件构成的,为了详细起见,他得把每个component的requires写清楚,所以llvm的打包脚本里面就先用cmake生成依赖关系,然后packeage info里面解析依赖关系添加依赖,这个问题的出现就是因为,明明整个库要求了libxml2,但是里面没有一个component去依赖这个库,那不就说明不需要依赖吗,所以直接报错。
我找了一下发现libxml2是被LLVMWindowsManifest引用的,但是输出依赖信息:
windowsmanifest ['support']
,并没有添加这个依赖。目前猜想要么是patch没有打上,要么是依赖关系没有生成正确。还有就是他的component.json不知道是哪里弄出来的,cmake和conan的文档里面都没有写生成这个文件的地方。
如果直接include整个导出的llvm-core,会报错找不到一些动态链接库,然后我发现llvm官方打包的二进制里面是没有的。应该是conan生成package info的时候没有删除这些不需要的依赖。
conan可以生成Conan find package,然后在cmake中调用find package可以找到对应的包
用打包出来的llvm-core去链接,一直报错找不到一个函数的定义(那个函数里面有个string),各种尝试才发现是conan自己生成的
conan_basic_setup
里面默认会从系统的profile中读取定义compiler.libcxx=libstdc++
,然后设置-D_GLIBCXX_USE_CXX11_ABI=0
。但是问题在于我也是用相同的编译器选项去编译llvm的,为什么生成的llvmlib却需要GLIBCXX_USE_CXX11_ABI=1
呢?先用命令查看一下目前的编译器abi版本,发现默认是cxx11的
在cmake中可以用如下命令查看添加了说明编译定义。gcc -v 2>&1 | sed -n 's/.*\(--with-default-libstdcxx-abi=new\).*/\1/p'
--with-default-libstdcxx-abi=new最后发现是我自己忘记在编译llvm的时候添加上conan basic setup了,导致没有指定。get_directory_property( DirDefs COMPILE_DEFINITIONS )
message( "COMPILE_DEFINITIONS = ${DirDefs}" )libxmls nanohttp.c:(.text+0x507): undefined reference to 'fcntl64'
发现conan这东西出发点是好的,但是一定得需要把一个包所有的依赖全部展示清楚才好,上面这个问题就是预编译好的xml2需要的fcntl64包我的系统并没有。以后还是不要搞跨平台了,直接都用docker+linux完事了,没有环境问题。不然再怎么打包都会有奇怪的问题。。 这个问题估计是因为预编译的libxml2的版本ubuntu20的,但是我是ubuntu18的,所以重新编译安装xml2。
LLVM ERROR: inconsistency in registered CommandLine options
我不知道为啥编译出来的clang居然是动态链接的,而llvm是静态编译的,从而导致的问题。但是clang的cmake根本就不接受动态链接的编译配置啊,重新configure一下编译就解决了。。
利用cmake运行Conan,因为很多开发环境是不支持自动执行conan再cmake编译的,这样就不能提供自动补全、直接debug等功能了,所以需要自动化这个流程。但是我们要对开发的库进行conan打包的时候,又需要执行conan的命令,所以conan官方的解决方案是这里
https://github.com/conan-io/cmake-conan
,对cmake需要做以下修改:if(CONAN_EXPORTED) # in conan local cache
# standard conan installation, deps will be defined in conanfile.py
# and not necessary to call conan again, conan is already running
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
else() # in user space
include(conan.cmake)
# Make sure to use conanfile.py to define dependencies, to stay consistent
conan_cmake_configure(REQUIRES fmt/6.1.2 GENERATORS cmake_find_package)
conan_cmake_autodetect(settings)
conan_cmake_install(PATH_OR_REFERENCE . BUILD missing REMOTE conan-center SETTINGS ${settings})
endif()CONAN_PKG::xxxx
这个是Conan setup时候的一个选项,如果添加了TARGETS
的选项,使用Conan添加的lib都用统一的接口,但是这样其实不是很好,如果当前开发环境比较混乱的话(引用的包引用了conan的包,但是你只想直接调用,就会报错找不到CONAN_PKG::xxxx
),所以要么都设置成相同的依赖,要么cmake里面再多写点。想要正确的导出conan包,让他和原来的包一样使用,还是比较非常麻烦。比如
halide
,原始的halide中有个target叫Halide::Generator
,他的属性中包含了GenGen.cpp这个文件。首先如果想在cmake中使用这个target,conan打包就需要把这个component明确导出,但是只要导出一个componet,你所有的requirs都得指定到对应的component。llvm中就是先分析依赖图,然后手动解析,构建出对应的component列表,然后在一个个字符串处理,找到对应的依赖、系统库依赖。上面的事情都做完了,你还是没办法使用conan导出的Halide::Generator
,因为conan还不支持为component添加文件属性,真的无语了。