将 object 个文件放在非递归构建中的不同目录中

placing object files in different directories in nonrecursive build

背景

我们为 Matlab 和 Octave 构建 .mex 文件。源代码对于 Matlab 和 Octave 都是通用的,但在这里和那里略有修改(通过代码中的宏条件处理)。作为参考,源结构是:

                      mex/
                       |
              ------------------------------
              |                            |
           sources/                      build/
              |                            |
        -----------            -------------------------------
        |         |            |          |        |         |
       mex1/ ... mexN/       octave/  mex1.am ... mexN.am  matlab/
        |                      |                             |
    -----------           -------------                -------------
    |         |           |           |                |           |
file1.cc ... fileM.cc  configure.ac  Makefile.am   configure.ac  Makefile.am

.mex 个源文件位于 mex/sources/mex*/ 中,我们编译多个 .mex 个文件。

Matlab 构建系统位于 mex/build/matlab/,我们 运行 './configure' 定位 link 编译所需的 headers/libraries Matlab .mex 个文件。类似的 configure.acMakefile.am 文件存在于 /mex/build/octave/ 中,经过修改以找到 Octave headers 和库。

Matlab 和 Octave 通用的 automake 构建指令(源文件的路径,要构建的 .mex 文件)存在于名为 /mex/build/mex*.am 的文件中,通常如下所示:

mexI_PROGRAMS += mexI

nodist_mexI_SOURCES = \
    ../../sources/mexI/mexI.c \
    ../../sources/mexI/mexI_file1.c \
    ../../sources/mexI/mexI_fileN.c

递归 make 非常适合我们的设置(我们曾经有名为 /mex/build/matlab/mex*//mex/build/octave/mex*/ 的目录,其中包含 Makefile.am 个文件;object 个文件将在那里编译并且输出文件将位于那里)。鉴于 GNU subdir-objects 的变化,现在我们正在转向 non-recursive 构建。从 Matlab 构建开始,我能够对其进行修改以 non-recursive 正常工作,没有任何问题。

问题

在移动到 non-recursive 构建时,object 文件现在在与其源文件相同的目录中生成, /mex/sources/mex*/.由于我已经编译了 Matlab .mex 文件,因此 *.o 文件存在于这些源目录中。因此,当我编译 Octave 文件时,make 直接跳到 linking 步骤,因为它已经在目录中看到最近的 *.o 文件。当然,问题是这些 *.o 文件是用 Matlab headers 编译的,因此不能在 Octave 构建中运行。

最简单的解决方案是简单地定义一个放置 object 文件的目录。目前,一个典型的构建编译命令看起来像(删除标志):

gcc ... -o ../../sources/mex1/mex1.o ../../sources/mex1/mex1.c

我只想更改传递给 -o 标志的文件的位置,但不知道如何在 automake 中执行此操作。 除非,当然,还有更优雅的解决方案。

I would just like to change the location of the file passed to the -o flag, but don't see how to do this in automake. Unless, of course, there's a more elegant solution.

我首先观察到编译后的目标文件被放置在源文件旁边,因为这就是你说要做的 通过给 Automake subdir-objects选项并执行源内构建(或实际上是两个)。将它们放置在其他地方有多种选​​择,但其中两个脱颖而出,因为它们与问题的原因直接相关:

  1. 删除 subdir-objects Automake 选项。您的中间 .o 文件应该最终位于您 运行 make 所在的构建目录中。这有点混乱,但这不是问题,因为生成的 Makefile 知道它们是哪些文件,因此可以在必要时将它们与可安装产品区分开来。这里的主要问题是您可能 运行 遇到与为同一目标构建的不同 .mex 文件关联的目标文件之间的冲突。

  2. 执行源外构建而不是源内构建,每个主要目标(octave / matlab)一个,每个都在自己的构建树中。与您的想法相反,您现在正在做的 不是 ,至少从 Autotools 的角度来看不是。当您执行源外构建时,所有生成的文件都会写入构建树,因此为 Octave 和 Matlab 设置单独的构建树应该可以彻底解决您的问题。这是我推荐的选项。

Autotools 自动支持外源构建。您需要做的就是创建所需的构建目录,将其作为您的工作目录,然后从那里 运行 项目的 configure 脚本。如果您愿意,构建目录可以是源代码根目录的子目录,但不一定是。要理解的关键是 "top source directory" 是包含 configure 脚本的那个,而 "top build directory" 是您 运行 该脚本所在的工作目录.因此,如果您在项目根目录中,您可以这样做:

$ cd build
$ mkdir build-octave build-matlab

$ cd build-octave
$ ../octave/configure
$ make
$ make install

$ cd ../build-matlab
$ ../matlab/configure
$ make
$ make install

但是可以通过假设在源代码中构建来破坏这种支持的方式来编写您的 Makefile.am 文件。您提供的 Makefile.am 摘录正是通过依赖从构建目录到源代码的特定相对路径来实现的。如果您的 Makefile.am 想要引用相对于顶级源目录的源文件(而不是构建文件),那么它可以使用 Automake 提供的自动 $(top_srcdir) 变量。 (这也不会干扰源内构建。)例如,您应该能够这样做:

nodist_mexI_SOURCES = \
    $(top_srcdir)/../../sources/mexI/mexI.c \
    $(top_srcdir)/../../sources/mexI/mexI_file1.c \
    $(top_srcdir)/../../sources/mexI/mexI_fileN.c

我不太喜欢引用顶级源目录上方的资源,但它应该有用。


更新:

同时考虑修改 Autotooling,使两种目标类型只有一个构建系统。 Autoconf 支持定义您自己的 --enable--with 选项,您可以在 运行 configure 时使用它们来 select 目标类型。 Autoconf 和 A​​utomake 支持各种条件,可以使用这些和其他标准来调整构建的细节。与单独维护并行构建系统相比,这可能是一个巨大的胜利。这一切都可以很好地与外源构建一起工作。