如何重定向生成大量单独输出文件的实用程序的输出?

时间:2011-12-30 08:53:29

标签: build makefile build-process build-automation

我的构建过程使用了大量的闭源第三方实用程序。这些工具生成大量文件,分为三类:我想要的文件,报告和废话。有时我可以选择其中一个或两个文件的输出目录,但不是全部。其余文件只出现在当前目录或全新的子目录中。大多数这些不需要的文件都没有记录。新的不需要的文件出现在这些实用程序的每个新版本中。

有没有办法运行这些实用程序并将所有文件系统操作重定向到某个指定的子目录,在那里我可以在删除其余文件之前复制好文件?我可以更改为一个子目录来运行工具,但由于构建过程相对于项目的根目录,这会使事情变得混乱。 (这些工具无法找到正确的文件。)

更新:

我希望找到对文件系统使用某种写时复制方法的答案,以便工具在顶层运行,但所有文件都生成有效的自己的子目录。如果这不是一个选项,那么我认为下一个最好的事情是更改为一个子目录来运行该工具。那么新的问题就变成了如何修复工具的输入,以便工具可以找到正确的源文件?这不重要。要修复的输入示例是配置文件中的命令行参数和文件路径。这似乎是一个容易出错且可能难以处理的问题。

3 个答案:

答案 0 :(得分:1)

让我们考虑一下构建生成的一些ep ,,我在这个例子中主要考虑ab

示例:依赖文件

    一个例子是gcc的** - MD **或** - MDD **标志,它生成依赖文件,有助于理解自上次构建以来发生的变化。对于开发者编辑代码,是的,那些很容易被认为是垃圾 - 但是如果你不想在每次运行时都不得不重建_everything_,那么它们就非常重要。&#39;。< / UL>
      在这种情况下,您可以为目标文件使用不同的目标目录,这会将您的依赖项文件放在同一个目录中。

    示例:编译的目标文件

      现在,这个例子可能与你有关,也可能不属于你,但有许多类似的工件生成,工具需要正确地工作,如果你想把它带到一个极端,&#39;的.o&#39;同样可以将文件视为“废话”。由开发人员尝试在具有&#39; .o&#39;的目录中查找源文件的人和&#39; .c / .cpp&#39;文件混合。
      在这种情况下,您可以使用不同的对象目录,这是一个相当标准的模式,在运行GCC时,您可以执行类似的操作
      gcc -c file.c -o ../objs/file.o

    示例:没有,**废话是废话**

      但是,让我们假设** crap ** _really_意味着**废话**。在构建之后,您永远不会想要看到&#39;类型&#39;在构建期间生成的文件,它的随机数据或其他内容*必须*每次构建时重新生成。
      在这种情况下,只需在构建结束时添加一个步骤,在成功构建产品后将其删除。就那么简单。这也是夜间构建中的标准模式,其中中间文件(对象,依赖项等)不重要,只要构建正确执行并且您的产品工件通过任何通常的最低期望,不是非-zero来自子任务,所有目标都正确构建并且打包成功。
      在构建失败的情况下,清理epthmera的下一步没有运行,你可以进入并在构建上执行验尸以了解原因并修复它。
      如果这些建议都不能与您产生共鸣,我建议您详细了解您正在使用的工具以及您认为的废话&#39;每种构建工具或语言都有它&#39; 39;自己的味道和策略(即蚂蚁,maven,制作,cmake,gcc,flex,java,perl,python,scones,quake等等)所以没有额外的信息可能很难真正拿出来如何最好地解决您的问题的一个很好的解释。

    更新:

    其他可能的解决方案

    的unionfs

      如果您正在使用Linux来运行构建,那么实现所需内容的工具无关的方法是使用[unionfs] [1],您可以在其中堆叠&#39;目录在彼此之上。它相当聪明,因为你有以下目录:
      /主页/登录/ src目录/ /建设/登录/ output_YY_MM_DD
      您可以在/ home / login / src /上透明地执行/ build / yourlogin / some_project_YY_MM_DD的unionfs挂载,但是当您运行构建时,所有生成的文件实际上都会在/ build / login / output_YY_MM_DD中结束 - 这实际上是实现你想要的。但是,再次,只有你使用unionfs运行Linux。 (遗憾的是,这并不适用于NFS,从未尝试过SMB,但怀疑相同......)
      要做到这一点,你必须运行一个启用了unionfs的内核(我相信你必须安装一个补丁包),然后执行以下操作:
      mount -t unionfs -o dirs=/build/login/output_YY_MM_DD/=rw:/home/login/src/=ro

    重定向输出

      只要确保链中的所有内容都能理解这一点,大多数构建工具都支持定位其输出的能力。它通常沿着&#39; -o output_filename&#39;的行,虽然在你的情况下对于某些工具(例如Xilinx&#39; reportgen)&#39; -o&#39;真的是指输出目录。
      请注意,如果您真的只有三种基本类型的输出,那么您只需要找出生成它们的工具以及如何修改输出的位置。
      这种方法唯一需要注意的是,如果你重新定位构建后续阶段所需的一些构建ep,那么很明显它不会存在 - 因此链中的所有东西都需要了解重定向。这确实很棘手。

    环境变量魔法

      通常情况下,如果你四处搜寻,你可以找到环境变量,这些变量会触发通过配置文件或命令行选项立即可用或不可用的行为。例如,Xilinx的** Compxlib **荣誉** USE_OUTPUT_DIR_ENV **,这几乎与名称有关(您指定指向要重新定位到的目录的环境变量)。
      使用环境变量的好处是,不必通过附加并重写所有编译规则来重新定位其他目录,只需附加&#39; -o blah&#39;,每个遵循环境变量的工具都将自动捡起来。
      如果您有多个体系结构可以构建某些内容但希望使用单个源树中的源,则此技术也很有用。

      提示:相对目录和构建配置变量

      如果您可以在此处粘贴相关目录并使用变量,则可以更加动态地使用事物
      
      NIGHTLY_BUILD_DIR=.build/${ARCH}
      USE_OUTPUT_DIR_ENV=NIGHTLY_BUILD_DIR
      

    Xilinx特定

      您应该查看IDE工具,看看哪些可以提供一些高级方法来完成您想要的工作 - 可能通过修改**编辑&gt;中的**设计目标**。偏好&gt; ISE一般&gt;设计目标&amp;策略**?我不确定。但
      PlanAhead几乎无疑会有一些设置来更改工作目录或忽略ephemera来分离不同目标的构建。这是一种相当常见的模式。

    忽略文件

      可能需要做一些,但你可能只是隐藏了#39;你不想看到的垃圾。当使用可以根据文件扩展名隐藏文件的GUI文件浏览工具时,Windows和OSX(以及我假设Linux)都支持机制。或者,如果您正在使用像&#39; ls&#39;或者&#39; grep&#39;你可以过滤掉你不想看到的东西。正如源控制程序可以配置为忽略ephemera。
      以下几个例子:
      • ls --ignore = * .d
      • rsync --exclude = .svn,*。d
      • grep --exclude = * .d

答案 1 :(得分:0)

为每个cd实用程序写一个包装器脚本到相应的目录,然后从那里运行实际的实用程序。将这些包装脚本保存在“本地”bin目录中,并将此目录放在$ PATH。

如果工具在执行第三方实用程序时使用完整路径,则会失败。

您可以从命令行在Makefile中指定override the PATH variable,如下所示:

$ make PATH=foo:$PATH

答案 2 :(得分:0)

简答:不。如果这些工具必须在项目根目录中运行,那么它们就必须运行,如果它们弄乱了嵌套,那么这就是他们所做的。

更长的答案:也许吧。如果他们真的必须在项目根目录中运行,那么就这样吧,但是可能有办法自动清理它们的臭味。您事先不知道不需要的文件和目录的名称,但如果您知道想要的文件和目录的名称,则可以将它们列入白名单并删除其他所有文件和目录。

或者,根据项目和操作系统的具体情况,您可以创建一个临时目录,其中包含指向项目根目录中文件的符号链接;对于第三方工具,它看起来就像真正的根目录,但是当工作完成后,您可以选择好的文件并删除其余文件,就像普通的临时文件一样。只要该工具不尝试在预先存在的子目录中创建文件,这将很好地工作 - 换句话说,它可能会工作,但没有承诺。