问题
Background
We build .mex
files for both Matlab and Octave. The source code is common to both Matlab and Octave but with slight modifications here and there (taken care of via macro conditionals in the code). For reference, the source structure is:
root_dir/
|
---------------------------------------------------
| | | |
configure.ac mex/ Makefile.am non-mex-source/
|
------------------------------
| |
sources/ build/
| |
----------- -------------------------------
| | | | | |
mex1/ ... mexN/ octave/ mex1.am ... mexN.am matlab/
| | |
----------- ------------- -------------
| | | | | |
file1.cc ... fileM.cc configure.ac Makefile.am configure.ac Makefile.am
The root configure.ac
and Makefile.am
control the configuration and compilation in mex/build/matlab/
, mex/build/octave/
and the non-mex binaries we create in non-mex-source/
.
The .mex
source files are located in mex/sources/mex*/
and we compile multiple .mex
files.
The Matlab build system is located in mex/build/matlab/
. The configure.ac
and Makefile.am
located here are called from the configure.ac
in the root directory via AC_CONFIG_SUBDIRS([mex/build/matlab])
. The same setup holds true for /mex/build/octave/
, where the configure.ac
has been modified to find Octave-specific headers and libraries.
The automake build instructions (the paths to the source files, the .mex
files to be built) common to both Matlab and Octave exist in the files named /mex/build/mex*.am
and typically look like:
mex_PROGRAMS += mexI
nodist_mexI_SOURCES = \
../../sources/mexI/mexI.c \
../../sources/mexI/mexI_file1.c \
../../sources/mexI/mexI_fileN.c
Recursive make
worked perfectly for our setup (we used to have directories named /mex/build/matlab/mex*/
and /mex/build/octave/mex*/
that contained Makefile.am
files; object files would be compiled there and the output files would be located there).
Problem
We are moving to a non-recursive build given the changes that GNU subdir-objects
change. I have already come up with a solution where the sources are soft-linked into the /mex/build/matlab/mex*/
and /mex/build/octave/mex*/
directories (using BUILT_SOURCES
= .mexfileslinked and seting up the sources to depend on the existence of this file; the rule for this file being to link in the sources and touch .mexfileslinked
) when the source is compiled the first time through. This works well but I am left thinking that there must be a more elegant solution.
I have created a minimum working example that shows the current setup and the warnings encountered when we run autoreconf -si
. The files are as follow:
root_dir/configure.ac
:
AC_PREREQ([2.69])
AC_INIT([soquestion], [2.0])
AC_CONFIG_SRCDIR([configure.ac])
AM_INIT_AUTOMAKE([1.15.1 foreign])
# config stuff for other, non-mex binaries we are building
AC_CONFIG_SUBDIRS([mex/build/matlab])
AC_CONFIG_SUBDIRS([mex/build/octave])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
root_dir/Makefile.am
:
SUBDIRS = mex/build/matlab mex/build/octave
root_dir/mex/build/mex1.am
:
mex_PROGRAMS = mex1
mexdir = $(libdir)/mex/matlab
nodist_mex1_SOURCES = \
$(top_srcdir)/../../sources/mex1/mex1.cc
root_dir/mex/build/matlab/configure.ac
and
root_dir/mex/build/octave/configure.ac
:
AC_PREREQ([2.69])
AC_INIT([soquestion], [2.0])
AC_CONFIG_SRCDIR([configure.ac])
AM_INIT_AUTOMAKE([1.15.1 foreign])
AC_PROG_CXX
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
root_dir/mex/build/matlab/Makefile.am
and root_dir/mex/build/octave/Makefile.am
:
include ../mex1.am
Running autoreconf -si
from root_dir
results in the warnings:
../mex1.am:5: warning: source file '$(top_srcdir)/../../sources/mex1/mex1.cc' is in a subdirectory,
../mex1.am:5: but option 'subdir-objects' is disabled
Makefile.am:1: '../mex1.am' included from here
automake: warning: possible forward-incompatibility.
automake: At least a source file is in a subdirectory, but the 'subdir-objects'
automake: automake option hasn't been enabled. For now, the corresponding output
automake: object file(s) will be placed in the top-level directory. However,
automake: this behaviour will change in future Automake versions: they will
automake: unconditionally cause object files to be placed in the same subdirectory
automake: of the corresponding sources.
automake: You are advised to start using 'subdir-objects' option throughout your
automake: project, to avoid future incompatibilities.
../mex1.am:5: warning: source file '$(top_srcdir)/../../sources/mex1/mex1.cc' is in a subdirectory,
../mex1.am:5: but option 'subdir-objects' is disabled
Makefile.am:1: '../mex1.am' included from here
automake: warning: possible forward-incompatibility.
automake: At least a source file is in a subdirectory, but the 'subdir-objects'
automake: automake option hasn't been enabled. For now, the corresponding output
automake: object file(s) will be placed in the top-level directory. However,
automake: this behaviour will change in future Automake versions: they will
automake: unconditionally cause object files to be placed in the same subdirectory
automake: of the corresponding sources.
automake: You are advised to start using 'subdir-objects' option throughout your
automake: project, to avoid future incompatibilities.
Of course, I could simply add subdir-objects
to the AM_INIT_AUTOMAKE
command to remove the warnings. But, then I would run into the problem outlined here, where the object files created by the matlab build are viewed as valid by the octave build, causing the octave build to fail (the octave build being run after the matlab build).
To solve that problem, I'd like to build the Matlab .mex
files from mex/build/matlab/objects
and the Octave .mex
files from mex/build/octave/objects
(or, even better, mex/build/matlab/objects/mex1
... mex/build/matlab/objects/mexN
). I understand that we could usually change into these directories then run ../configure
but I don't see how to do this from the root_dir/configure.ac
as AC_CONFIG_SUBDIRS
takes only the sub directory as an argument.
回答1:
I have already come up with a solution where the sources are soft-linked into the
/mex/build/matlab/mex*/
and/mex/build/octave/mex*/
directories [...] but I am left thinking that there must be a more elegant solution.
Indeed, as I wrote in answer to your previous question, the most elegant solution would normally be to use out-of-source builds, which the Autotools make available to you automatically. There is at least one other alternative, too, which I'll describe later.
You go on to say,
Running autoreconf -si from root_dir results in [warnings about not using Automake's
subdir-objects
option ....] Of course, I could simply add subdir-objects to the AM_INIT_AUTOMAKE command to remove the warnings. But, then I would run into the problem outlined [in my previous question].
Out-of-source building is still usually the best solution to problems of this sort. You can turn on subdir-objects
for your out-of-source builds to silence the warning; the built files will still go into the build tree, not the source tree, when those differ. With the option enabled, they will be arranged in the build tree in a directory structure parallel to that of the source tree, which is a good and useful thing. Thus, if you do a separate out-of-source build for each target type then you will have separate outputs.
To solve that problem, I'd like to build the Matlab
.mex
files frommex/build/matlab/objects
and the Octave.mex
files frommex/build/octave/objects
(or, even better,mex/build/matlab/objects/mex1
...mex/build/matlab/objects/mexN
).
You seem to be focusing on a particular solution idea instead of considering the overall problem more broadly. You can cause your intermediate object files to be built in the directory of your choice. To do so, you would need to create explicit make
rules for building them in their desired target directories, and additional explicit rules for building the final outputs from those. At that point, you would be throwing away many of the advantages that Automake provides, and mostly just writing ordinary Makefiles, directly. You can do that if you want to do, but I think you would be spending more effort than necessary, and producing a more fragile build system than you might otherwise have done.
In this regard, you need to understand that the name of the directory in which a target file is built, as expressed to make
, is an integral part of that target's identifier as far as make
is concerned. You cannot just build the same file in a different directory by flipping a switch -- if you build something in a different directory then for that reason, it is a different file. All the make
rules involving that file as either a target or a dependency then need to change.
I understand that we could usually change into these directories then run ../configure but I don't see how to do this from the root_dir/configure.ac as AC_CONFIG_SUBDIRS takes only the sub directory as an argument.
Well, the root-directory configure.ac
is a new wrinkle that you didn't mention in your previous question. By using AC_CONFIG_SUBDIRS
to associate the mex
components as sub-projects of a larger project, you lose the ability to perform separate out-of-source builds for those two, at least in the context of one build of the master project. Additionally, you are therefore not producing a non-recursive build, as your earlier question asserted -- you are just flattening out your build a bit. At minimum, the top-level Makefile will still recurse into the subproject Makefiles.
If the top-level project has no build dependencies on the subprojects' build outputs, however, then that's just fine. In that case, substantially none of the advantages that non-recursive builds have over recursive ones would apply to those files, relative to the main projects'. That holds open the door to using out-of-source builds for the sub-projects, but you will need to use a different mechanism than AC_CONFIG_SUBDIRS
to configure them.
I would suggest using AC_CONFIG_COMMANDS
to set up the separate out-of-source builds. This will not be quite as clean as AC_CONFIG_SUBDIRS
would be, and it gives up recursive help, but it provides the needed flexibility. Maybe something along these lines (untested):
AC_CONFIG_COMMANDS([mex-matlab], [
mkdir -p mex-matlab
cd mex-matlab
"$[]top_srcdir"/mex/build/matlab/configure
], [top_srcdir=`dirname "$[]0"`])
AC_CONFIG_COMMANDS([mex-octave], [
mkdir -p mex-octave
cd mex-octave
"$[]top_srcdir"/mex/build/octave/configure
], [top_srcdir=`dirname "$[]0"`])
The top-level Makefile.am would then need to specify the sub-project build directories (mex-matlab and mex-octave in the above example) in its SUBDIRS
variable.
There is also at least one other completely different approach: Automake has built-in support for building different targets from the same sources with different options. You do not leverage that in your current build system because you have segregated the octave and matlab bits into separate builds, but if you merged those into one Automake-based build system that built both pieces (perhaps conditionally) then Automake should take care of avoiding the object-file collisions where needed. It does this by using different names for the intermediate files, instead of putting them in different directories. Thus, with this approach, too, you could just add the subdir-objects
option to resolve Automake's warning.
The key parts might follow this general pattern:
File (note well:) mex/build/Makefile.am
:
mex_PROGRAMS += matlab/mexI octave/mexI
nodist_matlab_mexI_SOURCES = \
../sources/mexI/mexI.c \
../sources/mexI/mexI_file1.c \
../sources/mexI/mexI_fileN.c
# Need at least one target-specific flags variable, but that will
# come naturally in your case
matlab_mexI_CPPFLAGS = ...
nodist_octave_mexI_SOURCES = \
../sources/mexI/mexI.c \
../sources/mexI/mexI_file1.c \
../sources/mexI/mexI_fileN.c
# ...
Of course, since with this approach you don't want separate build systems for your mex files, you might consider completely or partially flattening the mex/build
subtree.
I mention this alternative second because it probably would require much more significant modifications to your existing build system than the other would, and also because I had already talked about out-of-source builds in my answer to your other question. For the present question, however, the complication that you are currently setting up the mex bits as subprojects of the main project alters the calculus a bit. This alternative is cleaner from an Autotools perspective than is arranging separate out-of-source builds for the sub-projects.
来源:https://stackoverflow.com/questions/46340991/vpath-out-of-source-build