Makefile 将对象文件放置在非递归生成中的不同目录中

Makefile 将对象文件放置在非递归生成中的不同目录中,makefile,build,autotools,autoconf,automake,Makefile,Build,Autotools,Autoconf,Automake,背景 我们为Matlab和Octave构建.mex文件。源代码对于Matlab和Octave都是通用的,但是在这里和那里都有轻微的修改(通过代码中的宏条件进行处理)。作为参考,源结构为: mex/ | ------------------------------ | | sou

背景

我们为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 build系统位于
mex/build/Matlab/
中,我们在其中运行“/configure”,以找到编译Matlab
.mex
文件所需的链接头/库。类似的
configure.ac
Makefile.am
文件存在于
/mex/build/octave/
中,修改后可查找octave头和库

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
文件;对象文件将在那里编译,输出文件将位于那里)。现在,考虑到GNU
subdir对象的变化,我们将转向非递归构建。从Matlab构建开始,我能够修改它,使其以非递归方式工作,没有任何问题

问题

在移动到非递归构建时,对象文件现在与源文件在相同的目录中生成,即
/mex/sources/mex*/
。由于我已经编译了Matlab
.mex
文件,因此
*.o
文件存在于这些源目录中。因此,当我编译倍频程文件时,
make
直接跳过链接步骤,因为它已经在目录中看到最近的
*.o
文件。当然,问题是这些
*.o
文件是用Matlab头编译的,因此不能在倍频程构建中工作

最简单的解决方案是简单地定义一个目录,对象文件将放在其中。当前,典型的生成编译命令如下所示(删除标志):

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

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

首先,我注意到编译后的对象文件被放置在源文件旁边,因为这就是您所说的,通过给Automake
subdir objects
选项并执行源代码内构建(或者实际上是两个)。将它们放在其他地方有几种选择,但其中两种选择很突出,因为它们与问题的原因直接相关:

  • 删除
    subdir对象
    Automake选项。然后,您的中间.o文件应该在运行
    make
    的生成目录中结束。这有点混乱,但这不应该引起关注,因为生成的Makefile知道它们是哪些文件,因此可以在必要时将它们与可安装产品区分开来。这里的主要问题是,与为同一目标生成的不同
    .mex
    文件关联的对象文件之间可能会发生冲突

  • 执行源代码外构建,而不是源代码内构建,每个主目标(octave/matlab)一个构建,每个构建在自己的构建树中。与你可能认为的相反,这不是你现在正在做的,至少从自动工具的角度来看不是这样。当您执行源代码外构建时,所有生成的文件都会写入构建树,因此为octave和matlab创建单独的构建树应该可以清楚地解决您的问题。这是我推荐的选择

  • 自动工具可自动为源代码外的构建提供支持。您只需创建所需的构建目录,将其设置为工作目录,然后从那里运行项目的
    configure
    脚本。如果您愿意,构建目录可以是源根目录的子目录,尽管不必是。要理解的关键是“顶级源目录”是包含
    configure
    脚本的目录,“顶级构建目录”是运行该脚本的工作目录。因此,如果您在项目根目录中,您可以执行以下操作:

    $ 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\u srcdir)
    变量。(这也不会干扰源代码构建。)例如,您应该能够做到:

    nodist_mexI_SOURCES = \
        $(top_srcdir)/../../sources/mexI/mexI.c \
        $(top_srcdir)/../../sources/mexI/mexI_file1.c \
        $(top_srcdir)/../../sources/mexI/mexI_fileN.c
    
    我不太喜欢引用顶级源代码目录之上的资源,但它应该可以工作


    更新:

    还可以考虑修改自动冷却,使两种目标类型都只有一个生成系统。Autoconf支持使用
    选项定义自己的--启用和--您可以使用这些选项在运行配置时选择目标类型。Autoconf和Automake支持各种条件,可以使用这些条件和其他条件来调整buil的详细信息
    nodist_mexI_SOURCES = \
        $(top_srcdir)/../../sources/mexI/mexI.c \
        $(top_srcdir)/../../sources/mexI/mexI_file1.c \
        $(top_srcdir)/../../sources/mexI/mexI_fileN.c