管理C++的第三方库以及编译

第三方库这个说法,不知道出自哪里,但一般是指开发者,系统/平台提供商之外的第三个参与者提供的程序库。
大多数开源软件库在软件系统中都是第三方库。

完全不使用库的开发,在90年代就已经被放弃了,特别MFC/OWL/QT这些先行者。开源运动的兴起使得第三方库
成为主力使用库。

C++领域有一些非常特殊的库,比如早期的STLport和当前的Boost,它们就像是语言的事实标准,基本在每个程序
中都可以见到他们的身影。

但第三方库也会导致相当多的问题,主要总是包括:

  1. 版本不一致。同一个软件系统中,如果引用了同一个第三方库的两个不同版本,那一定会暗生问题。
  2. 编译选项不一致。一般为了减少编译时间,第三方库都会以编译后的.a/.lib形式参与软件编译,第三方库的编译选项与软件系统的编译选项不同,也是会有一些潜在的问题。特别是x86/x64,ansi/utf-8这些选项不同,根本就不能用。
  3. 版本管理库变大。在一些大项目中常常会有几个G的版本库,每次clone代价很大。其实很多都是第三方库,不同版本,不同编译选项生成的库引入。

除了把编译的库引入项目,也有人以源代码的形式引入开源软件,比如GCC、SDL、WxWights、QT。如果第三方库本身编译不复杂,原代码也很简单,这么做比较好。

但是像Boost.Thread这样的库,就不行了(它需要编译成动态库,静态引用会有问题)。

另一方面,如果第三方库升级,就是一个比较复杂的工程,如果不升级,又只能看着第三方库的问题得不到解决。

在Linux上这个问题并不严重,系统级的软件管理工具可以代管大多数的第三方。比如debian系的,可以使用apt得到大多数的开源库,同时如果需要最新版本,也可以通过第三方源来取得。

在交叉编译和window平台上这个问题就非常头痛了。我们需要从几个层次来解决这个问题。

  1. 需要有中心化的第三方源代码获取平台,这个平台需要支持按用户/组织+第三方库+版本的形式取得源代码,同时还需要保证及时跟踪来源。这个类似于bintray/github都可以。公司内部可以使用gitlab来搭建。
  2. 需要有一个构建脚本平台,存放在不同工具链和平台的情况下,这个脚本可以从源代码中心的源代码,把源代码编译成库。同样可以用github这类工具搭建和管理。
  3. 在项目中提供一个配置文件,需要的开源库(只需指定编译脚本,脚本是针对开源库)。这个只需要一个文本文件即可。
  4. 在开发者的机器和编译服务器上,下载编译脚本,生成库。源代码、最终结果可以缓存在本机上。可以使用项目原本的构建工具。

如果只考虑windows+vc这个工具链,最简单的工具是使用msbuild,即为第三方库构建工程,编译结果生成成为vcprops文件,由项目引用。在项目工程中,可以通过prebuild过程加上下载、编译、安装第三方库的过程,因为有缓存,每台机器上应该只需要做一次。

考虑Boost这个最常用的库,并没有一个msbuild可以调用工程,这个方案通用性很差。但对于只使用vc的公司还是非常实用。因为只需要一个内源的源代码管理工具就可以了,没有git甚至可以用svn。

如果有多平台交叉编译,要考虑先统一项目自己的编译工具,使用CMake/Scons/Gyp这些跨平台编译工具,否则需要在不同的编译工具下都做一套。

以CMake为例,最接近这个系统的是CPM这个工具,它用github做前两个服务器,CMake的脚本来完成下载,编译。但受CMake脚本的能力限制,它无法完成更复杂的版本管理工作,只能做为一个试验原型。

使用CPM,可以先把自己的项目改成使用CMake编译,在CMakeLists.txt中引入CPM语句,再引入需要的第三方库。如果第三方库已经在有一个CPM脚本工程,就很简单直接引用即可。但如果没有,就需要自己先建立CPM脚本工程。即一个CMakeLists.txt,可以下载编译第三方库,再提供CPM一些专用宏,以便后续项目能找到这个第三方库。

一个内源第三方库(指公司内共享库)需要两个git工程(或svn目录),一个提供原始代码和维护工作,另一个提供构建脚本,这个脚本甚至可以是专用于某个项目。最后需一个工具能下载,脚本调用,缓存管理这些工作。

基于C++社区不自己发明工具传统,以及cmake/git的流行程度,我考虑使用bash来完成这个部分。基本数据结构设计如下:

CPM_HOME 做为根目录
sources 源代码下载
hosts 下载服务器
groups 用户或组织
library-name 库
scripts
hosts 下载服务器
groups 用户或组织
library-name 库, 源代码构建完成后会安装到这个目录下
bin 二进制结果,包括可执行文件
include 头文件,一般应支持多配置
lib/xx/ 应对不同的配置,参考boost library
flags/xx/ 应对不同的配置,需导出一些编译选项
build
构建目录,对于不支持外部构建目录的开源软件,可以选择复制过来in-source构建
考虑并发构建,应在这里文件锁定操作。
除了锁定目录外,其它目录可以删除以减少空间占用。

repos
project-id 成生特定于项目第三方库包,这样项目只需要引入一个第三方目录。

以上目录都会在本地保存一个hash文件以保持完整和不变性。

类似python我们使用 requirements.txt 项目的需求第三方库,使用cpp_setup requirements.txt来完成预建编译环境。
requirements使用
[host:port/]username/cpm-library-name
全局配置中,可以默认的host:port。这里可以不写host:port。
这里是指向特定的构建脚本,脚本能支持哪些平台,哪些发布版本,哪些运行时库都由脚本自己决定。缺少项目需要的配置时,只会编译失败。

如果项目支持CMake,那么只需要引入CPM即可。

如果项目可以要求生成一个project-id目录来聚合第三方库,方便make/vc++这些工具集成。

C++程序的目录结构、编译、打包、分发的更多相关文章

  1. Android程序的目录结构

    本篇文章我们将介绍Android应用程序的目录结构.本目录下有如图的目录结构: 下面我们来一 一介绍: 1.     Src:该目录中存放的是该项目的源代码 2.     Gen:该目录下的文件全部都 ...

  2. 3-微信小程序开发(小程序的目录结构说明)

    https://www.cnblogs.com/yangfengwu/p/10050784.html 源码下载链接: 或者 这节先说一下小程序的目录结构 自行根据  https://www.cnblo ...

  3. 微信小程序基本目录结构学习

    今天我们就以firstdemo为例,介绍一下小程序的基本目录结构.当我们打开一个微信小程序项目后,点击进入“编辑”菜单,我们可以看到有以下5个文件/文件夹):pages文件夹,utils文件夹,全局文 ...

  4. 大型Vuex应用程序的目录结构

    译者按: 听前端大佬聊聊Vuex大型项目架构的经验 原文: Large-scale Vuex application structures 译者: Fundebug 为了保证可读性,本文采用意译而非直 ...

  5. 微信小程序之目录结构

    小程序,功能不会太多,页面不会太多. 正常情况下,会包含首页,分类页面,个人中心页面,导航页面,其他页面等等. 我们首先要把页面结构布置好,把架子搭建好. 剩下的就是配置一些内容,小程序的基本信息,接 ...

  6. 小程序的目录结构/配置介绍/视图层wxml数据绑定/双线程模型/小程序的启动流程

    安装好微信小程序开发软件,创建项目 小程序文件结构和传统web对比 结构 传统web 微信小程序 结构 HTML WXML 样式 CSS WXSS 逻辑 Javascript Javascript 配 ...

  7. 微信小程序的目录结构解剖

    在微信小程序当中,我们看到有: .js后缀文件,.json后缀文件,.wxss后缀文件,.wxml后缀文件 .js后缀文件就是我们写的普通的js文件 .json后缀文件就是小程序的配置文件,比如:wi ...

  8. Android开发:程序目录结构详解

    HelloWorld程序的目录结构概述 我们可以在文件夹中看到,HelloWorld程序的目录主要包括:src文件夹.gen文件夹.Android文件夹.assets.res文件夹. AndroidM ...

  9. Tomcat的目录结构及部署应用程序

    下载好的二进制的Tomcat,解压会看到7个目录,如下: bin 目录:Tomcat的脚本存放目录,如启动.关闭脚本等.其中 **.bat用于windows平台,**.sh用于Linux平台 conf ...

随机推荐

  1. mysql数据库备份脚本

    mysql数据库备份脚本 mysql数据库分库备份脚本:[root@localhost tmp]# cat mysql.sh #!/bin/bash USER=root PASSWORD=joy4yo ...

  2. ODBC、OLEDB、ADO、SQL的关系

    对于一个刚接触数据库的菜鸟来说(比如我),总是搞不清SQL.ADO.OLE DB.ODBC,大脑中一片混乱,好像懂了,又好像没懂,非常的苦恼,今天下了点功夫研究了一下,贴出来,其中肯定有好多错误,希望 ...

  3. 【转】windows下mysql5.1忘记root密码解决方法

    步骤如下:1.停止mysql服务(以管理员身份,在cmd命令行下运行) net stop mysql D:\>net stop mysql MySQL 服务正在停止. MySQL 服务已成功停止 ...

  4. Diffie-Hellman 密钥交换

    假定有两个全局公开的参数,分别为一个素数p和一个整数g,g是p的一个原根,为了协商共享的会话密钥: 首先,用户A随机选取a,计算出A = g^a mod p,并将A发送给B:然后,用户B随机选取b,计 ...

  5. Dell PowerEdge R720内存安装原则

    Dell PowerEdge R720内存安装原则   摘要:系 统包含 24 个内存插槽,分为两组(每组 12 个),每个处理器一组.每组的 12 个插槽分入四个通道.在每个通道中,第一个插槽的释放 ...

  6. 关于Unity发布iOS平台代码混淆问题

    之前在越狱手机里找到<永恒战士3>的程序发现是用Unity做的,拷出资源出来看的时候发现里面有游戏程序集,立马抽出来反编译了一下,发现里面的代码只有方法签名,没有方法体,还以为用什么高端混 ...

  7. python使用pika链接rabbitmq Connection reset by peer 解决办法

    记录一下, 最近在用机器学习打算做一个Rest API, 数据存入mongo,任务采用消息队列,rabbitmq 由于引擎采用python编写,所以WEB也直接打算用python编写了,比较省事. W ...

  8. Tornado 高并发源码分析之四--- HTTPServer 与 TCPServer 对象

    主要工作: 服务器启动的时候做的事: 1.把包含了各种配置信息的 application 对象封装到了 HttpServer 对象的 request_callback 字段中,等待被调用 2.TCPS ...

  9. 虚拟机之 LNMP

    LNMP就是Linux nginx mysql php 一.mysql 下载安装mysql转至 LAMP (点击“LAMP”即可跳转) 也可以从快照跳转至mysql安装ok 二.php 下载同上, 1 ...

  10. 优于jdbc的mybatis框架入门

    1.什么是mybatis? MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架. MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及对结果集的检索. MyB ...