conan快速上手

@vrqq  May 9, 2020

conan客户端安装

  • pip3 install conan --user
  • ~/.conan/profiles 里生成default profile,包括下载包时候想要的 系统platform/编译器/ReleaseOrDebug等等,这个叫Setting
  • ~/.conan/remotes.json 里是repo信息,仅使用私有库时可以删除公有repo

JFrog Artifactory C++ CE服务端

是个repo私服,注意Artifactory OSS版本不支持conan客户端。(社区版CE注意合规哇)

  • 墙内速度慢,开个ssh Tunnels
  • 墙外机

    sudo useradd -s /sbin/nologin uproxy
    mkdir /home/uproxy/.ssh/
    chmod 600 /home/uproxy/.ssh
    cd /home/uproxy/.ssh
    ssh-keygen
    cat id_rsa.pub > authorized_keys
    chmod 644 authorized_keys
  • 墙内机ssh -NCD 127.0.0.1:10024 uproxy@myproxy.com -i id_rsa
  • 直接docker/podman安装 HTTPS_PROXY=socks5://127.0.0.1:10024 podman run --name myrepo -d -v /mnt/data/artifactory:/var/opt/jfrog/artifactory:Z -p 8081:8081 docker.bintray.io/jfrog/artifactory-cpp-ce:latest
  • podman默认用户态 -V映射uid变了 还没解决,测试机没有映射,凑合的话可以使用Volume

然后就装完了,私服关掉anonymous读本地repo的权限

  • 本地ssh myserver -L 8081:127.0.0.1:8081 -L 8082:127.0.0.1:8082
  • 打开http://localhost:8081直接配置admin:password

当软件包管理器使用

  • conan search "*" 默认搜索本地缓存
  • conan search poco --remote=conan-center 官方例子搜索官方默认repo,怕手欠可以在remote配置关掉官方repo

conan的管理方式是默认将包都存在~/.conan/data下面,而不是跟着工程走。
例如cmake工程,conan的install指的是 “install依赖到当前project开发环境下”

  • 建立/conanfile.txt/conanfile.py描述该工程的依赖项
  • /build下执行conan install ..他会按上述描述生成conanbuildinfo.cmake,我们就可以直接在CMakeList.txt里用

高级用法

  • conan install .. -s build_type=Debug 覆盖setting里build_type的默认设置
  • conan install .. -if ../conandeps 没啥特别的 if是install_folder的缩写

附: 在.cmake里支持多个,例如这样vs.sln打开就可以按一按切换target
https://docs.conan.io/en/latest/reference/generators/cmakemulti.html#cmakemulti-generator
https://docs.conan.io/en/latest/reference/generators/visualstudiomulti.html#visual-studio-multi

在CMake中引用 建议看这里剽窃更多美丽cmake
https://github.com/conan-io/examples

project(hello_world CXX)
include(/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)

add_executable(exe1 main.cpp)
target_link_libraries(exe1 CONAN_PKG::folly)

创建自己的包

理不清头绪?当然要多抄了!
https://docs.conan.io/en/latest/creating_packages/getting_started.html
很短 建议看完,官方试图用一个conanfile.py (又称recipe)描述当前的工程,从source 到build 再到package 一条龙
Please note that Conan generates different binary packages for different introduced configuration (in this case settings) for the same recipe.

无论是做一个源码编译的脚本 还是binary only,都需要:

  • 创建一个recipe:conanfile.py,使用conan new hello/0.1
  • (可选)创建一个test测试conanfile.py好不好使,在上面那条命令后面加-test
  • 改conanfile.py
  • 上传``

快速上手 只传binary
我们已经有基于CMakeFile.txt的开发环境了,苦于依赖包处理起来费时,还有更新包,不如拿起现有的轮子用一用,比手工CI高到不知道哪里了,和大厂谈笑风生!(大厂:我们跑得快是因为轮子多)
在当前目录下准备config.json和libs/working.so

$ conan new hello/0.1 --bare
$ vim conanfile.py # 然后修改conanfile.py
$ conan create . hello/0.1@whichuser/whichchannel #(可选)测试下相当于export -> install -> test
$ conan export-pkg . hello/0.1@myuser/dev -s compiler=gcc --package-folder=pkgfolder #未指定的-s为默认值
$ conan upload hello/0.1@myuser/dev -r myrepo --all #指定all就可以把上述--package-folder送进远程repo
    def package(self):
        self.copy("*.so", dst="lib", keep_path=True)
        self.copy("*")

另起炉灶,另一个文件夹下 拉一下我们刚才的包,先准备conanfile.txt文件

[requires]
hello/0.12345@myuser/dev
[generators]
cmake
[imports]
include, * -> 3rd/include
lib, * -> 3rd/lib
$ conan install .

然后再CMakeList.txt中加入下面这段即可(见上文 当软件包管理器使用)

include(/conanbuildinfo.cmake)
conan_basic_setup()

上传到仓库

很好理解

$ conan remote add artifactory http://localhost:8081/artifactory/api/conan/myrepo
$ conan upload hello -r=artifactory

$ conan upload hello -r=artifactory
Are you sure you want to upload 'hello/0.1@demo/testing' to 'artifactory'? (yes/no): no
Are you sure you want to upload 'hello/0.12345@myuser/dev' to 'artifactory'? (yes/no): yes
Uploading to remote 'artifactory':
Uploading hello/0.12345@myuser/dev to remote 'artifactory'
Uploaded conanfile.py -> hello/0.12345@myuser/dev [0.46k]
Uploaded conanmanifest.txt -> hello/0.12345@myuser/dev [0.06k]
Uploaded conan recipe 'hello/0.12345@myuser/dev' to 'artifactory': http://localhost:8081/artifactory/api/conan/myrepo

从conan-center挪到我们的仓库

$ conan conan download protobuf/3.11.4@ -r conan-center -re
$ conan upload protobuf/3.11.4@ -r myrepo

查包详细信息

conan search protobuf/3.9.1@ -q

多说一点,使用conan创建cmake工程后在vs里无缝切换debug和release

windows下是个坑,dll没有rpath
使用generators=cmake_multi,这个是生成cmake文件的,然后因为cmake又和vs兼容处理的好,才能无缝切换的。
如果使用generators=visual_studio_multi这个生成vs的props,这个是给纯windows然后把这个文件导入sln的,不适用于我们的cmake方案。

方法1 所以要不我们就把依赖目录放进PATH,方法是在CMakeFiles里添加CMAKE_VS_SDK_EXCLUDE_DIRECTORIES
https://stackoverflow.com/a/51994924/12529885

方法2 就是把依赖从conan底下拽出来,无论是softlink还是直接copy,按照不同的target放入不同的目录

    def imports(self):
        print("Copy runtime library for", self.settings.build_type)
        self.copy("*.dll", dst=str(self.settings.build_type), keep_path=False)
###### BEGIN conan config patch
include(${CMAKE_BINARY_DIR}/conanbuildinfo_multi.cmake)
conan_basic_setup(TARGETS KEEP_RPATHS)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}/Release)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR}/Release)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR}/Release)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/Debug)
message("CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG   ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}")
message("CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}")
###### END conan config patch

同时期待conan 2.0能友好支持cmake_multi
https://github.com/conan-io/conan/issues/330
https://github.com/conan-io/conan/issues/1180

QA

疑问 conan导出功能好像和cmake install有重叠啊?
来看看:https://docs.conan.io/en/latest/howtos/cmake_install.html

  • 如果有了cmake install 直接用就ok
  • 如果用CMake install进行了RPATH处理也可以直接用,即添加了conan_basic_setup(KEEP_RPATHS)
  • 如果没有添加KEEP_RPATHS 那么conan_basic_setup()时候会默认清掉(详见下面问题)
  • RPATH参数看下面的问题
  • 如果没写cmake install那么用conan的package功能也不错
  • 很惭愧 intro写得比原文还长

疑问 RPath
前面的没看懂会导致这里看着乱,建议往前看完sample
Linux下rpath老大难问题:https://docs.conan.io/en/latest/howtos/manage_shared_libraries/rpaths.html

简单说:Windows下没问题,mac下没搞过,Linux下 一上来就想让我配环境变量?我偏不!
并且导入recipe中需要[imports]复制依赖库到

往下翻往下翻 终于看到了set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
这里面指的是install之后的RPATH,编译完的binary,rpath都是指向真实路径的,可以直接运行,但是不建议直接distrubute。。

RPATH多说一点,如果一个套娃依赖,lib又依赖lib,每个lib里面都有RPATH,那只要记住个结论:除了环境变量,当前文件rpath目录下找不到想要的,就往其上级文件的rpath目录里找。
所以我们可以把所有依赖都放进lib文件夹,找不到依赖 到最后都会去binary的rpath里找,最后就都会找到。

时间如流水一般 没完没了的

写这个其实没想达到 看完就了如指掌,只是想让人大概了解这个软件的boundary,有啥feature,以及它和现有cmake如何配合的,在用之前多了解下这种快速cookbook,可以明确自己真的需要吗?

这也唤醒了我之前的小农思维,花钱省时间,和花时间造钱,之间总有一个白嫖的空隙吧!
小农可不会白嫖,每个白嫖者都是潜在付费客户。
(这一点套路云玩的六 需要向他学习)

续一些经验 CMakeFile.txt如何生成VS工程并且在VS里面随意切换

Statement 今天是2020年6月11日

  • 目前CMakeLists.txt 支持cmake_multi,可以针对某个library配置debug/release/relwithdbg等等
  • 但是不能生成多个platform,即便是vs的.sln支持多个platform,cmake也不支持把多个platform打包进一个sln

所以有两条路可以选:
1)用cmake按照x86 x64生成两个sln放到两个文件夹里,如果使用conan.cmake(内置conan)配置import即可,如果使用外置命令,需要和cmake的输出目录指定一致

  • conan对于不同平台(arch)生成的cmakebuildinfo_multi.cmake也要放在不同文件夹里,和上述vs的sln放一起就行
  • 好处是可以设置VS独有的property选项卡

2)用VS2019去管理CMakeLists.txt

  • 把VS当成文本编辑器+文件管理+代码提示+辅助工具。。。
  • 其实是vs针对cmake规则砍掉了自己的solution管理器,理论上也可以用makefile。
  • 上一条的原理见 https://docs.microsoft.com/en-us/visualstudio/ide/customize-build-and-debug-tasks-in-visual-studio?view=vs-2019
  • 设置靠CMakeSetting.json生成不同的target,如果配置文件里选了VS还是会生成sln,然后通过命令控制sln编译(可以把这个当作中间产物),也就是说在当前IDE窗口里并不会打开那个sln。
  • 如果选了ninja就不会生成sln,接下来靠ninja驱动编译器。。
  • 运行目录VS_DEBUGGER_WORKING_DIRECTORY用不了了,因为这个目录是vs的project property,这里没有.vcprog自然就不能用。。(希望后面cmake做出些兼容更新!多生成几个何妨啊!)
  • 上一条:虽然可以生成,但是请把当前VS窗口看作文本编辑器,它没有打开sln,在当前(文本编辑器)窗口中启动的exe,是通过launch.vs.json控制,而不是通过上述生成的vcproj控制。。

详见:https://stackoverflow.com/a/62309569/12529885
(来给我点赞哇!)


添加新评论