conan入门:将自己的项目生成conan包

Posted 10km

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了conan入门:将自己的项目生成conan包相关的知识,希望对你有一定的参考价值。

conan 将自己的项目生成conan包

Conan 是 C 和 C++ 语言的依赖项和包管理器。它是免费和开源的,适用于所有平台(Windows、Linux、OSX、FreeBSD、Solaris 等),可用于开发所有目标,包括嵌入式、移动(iosandroid)和裸机。它还与 CMake、Visual Studio (MSBuild)、Makefiles、SCons 等所有构建系统集成,包括专有系统。
它专为加速 C 和 C++ 项目的开发和持续集成而设计和优化。通过完整的二进制包管理,它可以为任意数量的不同版本的包创建和重用任意数量的不同二进制文件(用于不同的配置,如架构、编译器版本等),在所有平台上使用完全相同的过程。由于它是去中心化的,因此很容易运行自己的服务器来私下托管自己的包和二进制文件,而无需共享它们。@《Conan官方文档》

在之前的博客《conan入门(四):conan 引用第三方库示例》中我们以cJSON为例说明了如何在项目中引用一个conan 包。

如何将自己设计的模块以conan包形式打包提供给第三方(客户/同事)使用?

本文将以一个基于 cJSON 库实现字符串解析的模块 jsonlib,说明如何将自己的模块封装成conan提供给第三方使用。

jsonlib示例程序

示例的所有源码都保存在GIT仓库 conan_example的jsonlib分支,请直接克隆代码到本地:

git clone https://gitee.com/l0km/conan_example.git -b jsonlib
# -b jsonlib 切换到 jsonlib 分支,等价于 'git checkout jsonlib' 命令 

jsonlib是个很简单的库,只有两个文件:jsonlib.h,jsonlib.c,只实现了一个功能从JSON字符串中解析name指定的字段内容,结果保存到输出缓冲区,JSON解析的工作实际上是调用cJSON来实现的。以下是实现源码。

src/jsonlib.h

/*
 * jsonlib.h
 *  conan example for library
 *  Created on: 2022/02/18
 *      Author: guyadong
 */

#ifndef SRC_JSONLIB_H_
#define SRC_JSONLIB_H_
#ifndef JSONLIB_DLL_DECL
#  if defined(_WIN32) && !defined(__CYGWIN__) && defined(JSONLIB_IS_DLL)
#    if defined(JSONLIB_EXPORTS)
#      define JSONLIB_DLL_DECL  __declspec(dllexport)
#    else
#      define JSONLIB_DLL_DECL  __declspec(dllimport)
#    endif
#  else
#    define JSONLIB_DLL_DECL
#  endif
#endif
#include <stddef.h>
#ifdef __cplusplus
extern "C"

#endif

//************************************
// 从JSON字符串中解析name指定的字段内容,结果保存到输出缓冲区
// @param    const char * cjs JSON 字符串
// @param    const char * name 字段名
// @param    char * buffer [out] 输出缓冲区
// @param    size_t bufsz 输出缓冲区长度
// @return   int 成功返回0,否则返回-1
//************************************
JSONLIB_DLL_DECL int jlib_parse_field(const char* cjs,const char*name, char*buffer,size_t bufsz);
#ifdef __cplusplus

#endif
#endif /* SRC_JSONLIB_H_ */

src/jsonlib.c

#include "jsonlib.h"
#include <cjson/cJSON.h>
#include <string.h>
#include <stdlib.h>

JSONLIB_DLL_DECL int jlib_parse_field(const char* cjs,const char*name, char*buffer,size_t bufsz)

    int c = -1;
    if(cjs && name && buffer && bufsz)
    
        cJSON* j = cJSON_Parse(cjs);
        if(j)
        
            cJSON* item = cJSON_GetObjectItem(j,name);
            if(item)
            
                char* s = cJSON_PrintUnformatted(item);
                if(s && strlen(s) < bufsz)
                
					strncpy(buffer, s, bufsz);
					c = 0;
                
                free(s);
            
        
        cJSON_Delete(j);
    
    return c;

CMakeLists.txt

cmake_minimum_required(VERSION 3.10.3)
# 3.0以上版本才允许使用VERSION option
project(JsonTest VERSION 1.0.0 LANGUAGES C)
find_package(cJSON REQUIRED)
add_library(jsonlib src/jsonlib.c)
set_target_properties(jsonlib PROPERTIES PUBLIC_HEADER "src/jsonlib.h")
target_link_libraries(jsonlib PUBLIC cjson)
target_compile_definitions(jsonlib 
    PRIVATE $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:JSONLIB_EXPORTS>
    PUBLIC $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:JSONLIB_IS_DLL>
)

conan new

现在 jsonlib.h,jsonlib.c,CMakeLists.txt三个文件构成了一个简单但完整的标准CMake项目。

conan_example
│  CMakeLists.txt
│      
└─src
       jsonlib.c
       jsonlib.h

怎么把这个小项目封装为conan包呢?如果你看过我的上一篇博客《conan入门(六):conanfile.txt conanfile.py的区别》以及《conan入门(一):conan 及 JFrog Artifactory 安装》就差不多可以知道,一个conan包最关键的就是需要有一个conanfile.py脚本来定义包的各种配置。

但是要手写一个conanfile.py好像还挺麻烦的,我对python也是只知皮毛。

显然手写是不可能的,conan new 命令就是用于创建一个新的conan配置文件模板。有了模板,在之上修改就可以了:

$ conan new jsonlib/1.0.0 --template cmake_lib
File saved: CMakeLists.txt
File saved: conanfile.py
File saved: src/jsonlib.cpp
File saved: src/jsonlib.h
File saved: test_package/CMakeLists.txt
File saved: test_package/conanfile.py
File saved: test_package/src/example.cpp

conan new jsonlib/1.0.0 --template cmake_lib执行后生成的目录结构如下,可以看到conan很贴心的生成了conanfile.py,jsonlib的源码文件及CMakeLists.txt以及对应的测试代码(test_package)—这是一个完整的conan包项目框架,虽然它不是想我们需要的内容,但有了这个框架总比从头开始写要方便得多:

conan_example
│  CMakeLists.txt
│  conanfile.py
│  
├─src
│      jsonlib.cpp
│      jsonlib.h
│      
└─test_package
    │  CMakeLists.txt
    │  conanfile.py
    │  
    └─src
            example.cpp

上面执行 conan new 命令使用的 --template cmake_lib 参数是Conan的一项目还在实验中的功能,根据指定模板生成Conan项目框架,详细说明参见Conan官方文档:《Package scaffolding for conan new command

conan new命令的详细说明参见Conan官方文档《conan new》

update jsonlib

现在我们在Conan生成的项目框架上,把jsonlib装进去。

conanfile.py

首先如下图修改conanfile.py

CMakeLists.txt

如下图将conan new 生成的CMakeLists.txt的内容合并到jsonlib的CMakeLists.txt中

jsonlib.h jsonlib.c

src/jsonlib.c替换conan new 生成的src/jsonlib.cpp,

src/jsonlib.h 替换conan new生成的src/jsonlib.h

example.cpp

conan new生成的test_package/src/example.cpp替换为如下代码,实现简单的jsonlib接口测试

test_package/src/example.cpp

#include <stdio.h>
#include <jsonlib.h>

int main(int argc, char** argv)

    char jstr[] = "\\"hello\\":\\"world\\"";
    printf("JSON:%s\\n",jstr);

    char fieldbuf[32];
    int c = jlib_parse_field(jstr,"hello",fieldbuf,sizeof(fieldbuf));
    if(0 == c)
        printf("parsed 'hello' field:  %s\\n",fieldbuf);
    

    return 0;

conan create (编译jsonlib)

创建了conanfile.py后,编译conan包非常简单

# 注意是 conan_example jsonlib分支
$ cd conan_example
$ conan create .
Exporting package recipe
jsonlib/1.0.0 exports_sources: Copied 1 '.txt' file: CMakeLists.txt
jsonlib/1.0.0 exports_sources: Copied 1 '.c' file: jsonlib.c
jsonlib/1.0.0 exports_sources: Copied 1 '.h' file: jsonlib.h
jsonlib/1.0.0: A new conanfile.py version was exported
jsonlib/1.0.0: Folder: C:\\Users\\guyadong\\.conan\\data\\jsonlib\\1.0.0\\_\\_\\export
jsonlib/1.0.0: Exported revision: 5f5439068d01c7592ebbcb724712ce89
.....
.....
Capturing current environment in deactivate_conanrunenv-release-x86_64.bat
Configuring environment variables
JSON:"hello":"world"
parsed 'hello' field:  "world"

conan create .根据配置文件 (同级文件夹下的conanfile.py) 构建二进制包
conan create 命令行用法参见Conan官方文档《conan create》

conan create执行成功后,就会将生成的二进制包保存在本地仓库$HOME/.conan/data/jsonlib/1.0.0/_/_package

执行conan search jsonlib/1.0.0@会显示二进制包的信息

conan upload(上传到私有制品库)

项目编译成功就可以上执行conan upload传到私有制品库了:

conan upload jsonlib/1.0.0  -r $repo --all
# $repo为私有制品库的名字

–all 指定上传所有内容(配置文件conanfile.py,源码和二进制包),如果不指定些选项,只上传除二进制包之外的所有文件

关于 conan upload命令的详细说明参见Conan官方文档:《conan upload》

上传成功进入JFrog Artifactory后台就可以看到已经上传的package

总结

上面一套流程做完,可以总结一下,将一个已经有项目封装为conan包的过程:

开始麻烦些,需要用conan new 创建一个模板,然后修改模板,将自己的代码装进去。如果你对python很熟,可以不需要conan new创建模板项目,自己手工改就好了。

后面就很简单 :

conan create 完成conan 二进制包编译

conan upload 负责 conan包的上传发布

参考资料

《conan new》

《conan upload》

《conan create》

Package scaffolding for conan new command

conan系列文章

《conan入门(一):conan 及 JFrog Artifactory 安装》
《conan入门(二):conan 服务配置-密码管理及策略》
《conan入门(三):上传预编译的库(artifact)》
《conan入门(四):conan 引用第三方库示例》
《conan入门(五):conan 交叉编译引用第三方库示例》
《conan入门(六):conanfile.txt conanfile.py的区别》
《conan入门(七):将自己的项目生成conan包》

以上是关于conan入门:将自己的项目生成conan包的主要内容,如果未能解决你的问题,请参考以下文章

conan入门:NDK交叉编译自己的conan包项目塈profile的定义

conan入门(二十五):imports将包安装到本地项目或其他指定位置

conan入门:上传预编译的库(artifact)

conan入门(十五):AttributeError: ‘CMake‘ object has no attribute ‘definitions‘

conan入门(二十六):使用make编译erpc/erpcgen(makefile)

conan入门(二十六):使用make编译erpc/erpcgen(makefile)