9

我们身边有 Boost 库。它由大量永不更改的文件组成,并且只使用了一小部分。如果我们要更改版本,我们会交换整个 boost 目录。目前,我们的 SVN 中有 Boost 源文件,这使得结帐操作非常缓慢,尤其是在 Windows 上。

如果有一个符号/插件来处理 ZIP 文件中的 C++ 文件,那就太好了,例如:

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

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

4

5 回答 5

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调用的确切语法,请询问您的手册页。

然后在其他 Makefiles 中,您可以让您的源文件依赖于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指令。

细则:boost/boost_version.h文件不是 Makefile 工作所必需的。您可以将unzip命令放入unpack_boost目标中,但目标实际上是虚假的,即:它将在每次构建期间执行。中间的文件(当然您需要用 zip 存档中实际存在的文件替换)确保unzip仅在必要时运行。

于 2012-06-19T07:37:29.733 回答
7

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

我将团队切换到 git。为了让您了解它比 SVN 好多少,我刚刚创建了一个包含 boost 1.45.0 版本的存储库,然后通过网络克隆了它。(克隆复制所有存储库历史记录,在这种情况下是一次提交,并创建一个工作副本。)

那个克隆花了六分钟。

在前六秒内,存储库的压缩副本被复制到我的机器上。剩下的时间都花在了编写所有这些小文件上。

我衷心建议您尝试 git。学习曲线很陡峭,但我怀疑你会在克隆 boost 副本所需的时间内完成很多预编译器黑客攻击。

于 2012-06-20T14:48:38.463 回答
4

我们公司也遇到过类似的问题。在构建环境中管理 boost 版本绝非易事。拥有 10 多个开发人员,他们都在自己的系统上进行编码,您将需要某种自动化。

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

这是我们现在的管理方法,在尝试了许多不同的方法之后,这对我们最有效。

对于我们使用的每个版本的 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 makefiles,...)定义一个内部变量,导入环境变量,例如:

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

保留 boost 的本地副本的原因是编译速度。它占用了相当多的磁盘空间,尤其是编译后的库,但是存储很便宜,而且开发人员会浪费大量时间编译代码。另外,这只需要复制一次。

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

为了使事情变得更顺畅,我们开发了一个小工具来负责复制和设置全局环境。使用 CLI,这甚至可以包含在构建过​​程中。

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

于 2012-06-19T08:43:41.330 回答
2

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

将文件存储在压缩文件系统上。然后每个应用程序都会自动受益。

于 2012-06-15T18:44:56.680 回答
2

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

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

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

有人知道这是否已经存在吗?我看不出有什么明确的理由不会...

于 2012-06-19T07:55:29.700 回答