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

g++: Use ZIP files as input

本文关键字:输入 文件 ZIP 使用 g++      更新时间:2023-10-16

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

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

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

g++ 中是否支持编译器钩子?关于ZIP支持有什么努力吗?其他想法?

我假设构建软件的过程中涉及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 指令。

细则:boost/boost_version.h文件对于生成文件的工作并不是绝对必要的。你可以把unzip命令放到unpack_boost目标中,但这样目标实际上是假的,也就是说:它将在每次构建期间执行。中间的文件(当然,您需要将其替换为实际存在于zip存档中的文件)确保unzip仅在必要时运行。

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

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

那个克隆花了六分钟。

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

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

我们公司也面临着类似的问题。在构建环境中管理增强版本绝非易事。有10 +开发人员,都在自己的系统上编码,您将需要某种自动化。

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

以下是我们现在的管理方式,在尝试了很多不同的方法之后,这最适合我们。

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

BOOST_1_48=C:boost1.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 solutions,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,这甚至可以包含在构建过程中。

不同的

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

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

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

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

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

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

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