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

2022-04-13 12:02:22 浏览数 (1)

conan 将自己的项目生成conan包

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

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

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

jsonlib示例程序

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

代码语言:javascript复制
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

代码语言:javascript复制
/*
 * 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

代码语言:javascript复制
#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

代码语言:javascript复制
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项目。

代码语言:javascript复制
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配置文件模板。有了模板,在之上修改就可以了:

代码语言:javascript复制
$ 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包项目框架,虽然它不是想我们需要的内容,但有了这个框架总比从头开始写要方便得多:

代码语言:javascript复制
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

代码语言:javascript复制
#include <stdio.h>
#include <jsonlib.h>

int main(int argc, char** argv)
{
    char jstr[] = "{"hello":"world"}";
    printf("JSON:%sn",jstr);

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

    return 0;
}

conan create (编译jsonlib)

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

代码语言:javascript复制
# 注意是 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:Usersguyadong.conandatajsonlib1.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传到私有制品库了:

代码语言:javascript复制
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》

0 人点赞