g ++:使用ZIP文件作为输入

时间:2012-06-15 13:20:43

标签: c++ boost annotations g++

我们这边有Boost图书馆。它由大量文件组成,这些文件永远不会改变,只使用它的一小部分。如果我们要更改版本,我们会交换整个boost目录。目前我们的SVN中有Boost源,逐个文件,这使得结账操作非常慢,特别是在Windows上。

如果有一个符号/插件来解决ZIP文件中的C ++文件会很好,例如:

// @ZIPFS ASSIGN 'boost' 'boost.zip/boost'
#include <boost/smart_ptr/shared_ptr.hpp>

g ++中是否支持编译器挂钩?有关ZIP支持的任何努力吗?其他想法?

5 个答案:

答案 0 :(得分:9)

我假设在构建软件的过程中涉及make或类似的构建系统。我将zip文件放在存储库中,并在Makefile中添加一条规则,以便在实际构建开始之前将其解压缩。

例如,假设您的zip文件位于“external / boost.zip”的源树中,它应被解压缩为“external / boost”,并在其顶层包含一个文件“boost_version.h”。

# external/Makefile
unpack_boost: boost/boost_version.h

boost/boost_version.h: boost.zip
    unzip $<

我不知道unzip电话的确切语法,请向您的联系人询问此事。

然后在其他Makefile中,您可以让源文件依赖于unpack_boost目标,以便在编译源文件之前让make解压缩Boost。

# src/Makefile (excerpt)
unpack_boost:
    make -C ../external unpack_boost

source_file.cpp: unpack_boost

如果您正在使用Makefile生成器(或完全不同的构建系统),请查看这些程序的文档,了解如何创建自定义目标unpack_boost之类的内容。例如,在CMake中,您可以使用add_custom_command指令。

精细打印:对于Makefile来说,boost/boost_version.h文件并不是绝对必要的。您可以将unzip命令放入unpack_boost目标,但是目标实际上是假的,即:它将在每次构建期间执行。中间的文件(当然,您需要替换为zip存档中实际存在的文件)确保unzip仅在必要时运行。

答案 1 :(得分:7)

一年前,我和你在同一个位置。我们将源代码保留在SVN中,更糟糕的是,在我们自己的代码中包含与同一存储库(相同分支)的boost。试图在多个分支上工作是不可能的,因为一天大部分时间都需要检查一份新的工作副本。将升级转移到单独的供应商存储库有所帮助,但结账仍需要数小时。

我把团队换成了git。为了让您了解它比SVN好多少,我刚刚创建了一个包含boost 1.45.0版本的存储库,然后通过网络克隆它。 (克隆会复制所有存储库历史记录,在本例中为单个提交,并创建工作副本。)

那个克隆花了六分钟。

在前六秒内,存储库的压缩副本被复制到我的计算机上。其余的时间花在写所有这些小文件上。

我衷心建议您尝试使用git。学习曲线很陡,但我怀疑在克隆一个boost副本的时候你会得到很多预编译器黑客攻击。

答案 2 :(得分:4)

我们公司一直面临着类似的问题。在构建环境中管理boost版本绝非易事。有10多个开发人员,他们在自己的系统上编码,你需要某种自动化。

首先,我认为存储大型库的副本(如SVN中的boost或任何SCM系统)并不是一个好主意,这不是那些系统的设计目的,除非您打算自己修改代码中的代码。但是我们假设你没有这样做。

以下是我们现在如何管理它,在尝试了许多不同的方法后,这对我们来说效果最好。

对于我们使用的每个boost版本,我们将整个树(解压缩)放在文件服务器上,我们添加额外的子目录,每个架构/编译器组合一个,我们放置编译库。 我们在每个构建系统上保留这些树的副本,并在全局系统环境中添加变量,如:

BOOST_1_48=C:\boost\1.48 # Windows environment var

BOOST_1_48=/usr/local/boost/1.48 # Linux environment var, e.g. in /etc/profile.d/boost.sh

此目录包含boost树(boost / * .hpp)和添加的预编译库(例如lib / win / x64 / msvc2010 / libboost_system * .lib,...)

所有构建配置(vs解决方案,vs属性文件,gnu makefile,...)定义内部变量,导入环境变量,如:

BOOSTROOT=$(BOOST_1_48) # e.g. in a Makefile, or an included Makefile

以及进一步的构建规则都使用BOOSTROOT设置来定义包含路径和库搜索路径,例如

CXXFLAGS += -I$(BOOSTROOT)
LFLAGS   += -L$(BOOSTROOT)/lib/linux/x64/ubuntu/precise
LFLAGS   += -lboost_date_time

保持本地副本的提升的原因是编译速度。它占用了相当多的磁盘空间,特别是编译的库,但是存储很便宜,开发人员在编译代码时却没有多少时间。另外,这只需要复制一次。

使用全局环境变量的原因是构建配置可以从一个系统转移到另一个系统,因此可以安全地检入您的SCM系统。

为了使事情变得平滑,我们开发了一个小工具来处理复制和设置全局环境。使用CLI,甚至可以将其包含在构建过​​程中。

不同的工作环境意味着不同的规则和文化,但相信我,我们已经尝试了很多东西,最后,我们决定定义某种约定。也许我们可以激励你......

答案 3 :(得分:2)

这是你在g ++中不会做的事情,因为任何其他想要这样做的应用程序也必须被修改。

将文件存储在压缩文件系统中。然后每个应用程序自动获得好处。

答案 4 :(得分:2)

在操作系统中应该可以允许透明访问ZIP文件中的文件。我知道很久以前(2004年左右)我把它放在我自己的操作系统的设计中,但从来没有达到可用的程度。缺点是在ZIP内的文件中向后搜索速度较慢,因为它已被压缩(并且您无法回退压缩器状态,因此您必须从头开始寻找)。这也使得使用zip-inside-a-zip缓慢进行倒带和阅读。幸运的是,大多数情况下只是按顺序读取文件。

对于当前的操作系统,它也应该是可以改装的,至少在客户端空间中是这样。您可以挂钩使用的文件系统访问函数(fopen,open,...)并添加一组虚拟文件描述符,您自己的软件将为给定的文件名返回这些描述符。如果它是一个真正的文件只是传递它,如果它没有打开底层文件(可能再次通过这个功能)并传递一个虚拟句柄。访问文件内容时,直接从zip文件中读取而不进行缓存。

在Linux上,您将使用LD_PRELOAD将其注入现有软件(在使用时),在Windows上,您可以挂钩系统调用或将DLL注入软件空间以挂钩相同的功能。

有人知道这是否已经存在?我看不出有任何明显的理由不会......