如何将automake文件写入递归构建子目录?
How to write automake files to recursive build subdirectories?
我的工作目录如下树所示:
./
|--HelloWorld/
|--|--main.cpp
|--|--Dog/
|--|--|--Dog.h
|--|--|--Dog.cpp
|--Pet/
|--|--Pet.h
|--|--Pet.cpp
|--build/
main.cpp
包括dog.h
和pet.h
。 Dog 是 Pet 的继承 class,所以 Dog.h
也包括 Pet.h
。我知道这是组织代码的一种有线方式,但我只是好奇 如何为每个子目录创建 makefile.am 文件,以便 autotool 可以在构建目录中构建项目。
请注意,我想要一些额外的功能:
- 我们可以在
build
目录而不是 build/HelloWorld/
目录中构建 hello.exe 吗?为此,我是否必须将 bin_PROGRAMS
放在 ./Makefile.am
- 我不想将 Pet 构建为库,我想知道是否有一种方法可以告诉 automake 在不同位置查找源代码。
- 我知道使用非递归 makefile 会更容易。但我只想学习如何为多个目录创建递归 makefile。
我试过的是:
configure.ac
AC_PREREQ([2.69])
AC_INIT([Hello], [1.0], [qub@oregonstate.edu])
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
AC_CONFIG_SRCDIR([HelloWorld/main.cpp])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CXX
AC_PROG_CC
#AC_PROG_CPP
AC_CONFIG_FILES([Makefile
HelloWorld/Makefile
Pet/Makefile
HelloWorld/Dog/Makefile])
AC_OUTPUT
Makefile.am
SUBDIRS = HelloWorld Pet
HelloWorld/Makefile.am
AM_CPPFLAGS=-I$(srcdir)/../Pet -I$(srcdir)/Dog
SUBDIRS = Dog
bin_PROGRAMS=hello
hello_SOURCES = main.cpp
Pet/Makefile.am
hello_SOURCES = Pet.h Pet.cpp
HelloWorld/Dog/Makefile.am
AM_CPPFLAGS=-I$(srcdir)/../../Pet
hello_SOURCES = Dog.h Dog.cpp
我刚开始学习automake的东西,我知道这些代码根本行不通。
谁能帮我解决这些问题?谢谢。
你说你对
感兴趣
how to create makefile.am files for each subdirectories so that autotool can build the project in the build directory
,但这不是一个合适的目标,正如这个例子本身所展示的那样。没有定义任何要构建的目标的 Makefile.am
很少有用或不合适。您已经规定您不想将 Pet 构建为库,那么其目录中的 Makefile.am
将定义什么目标?如果您想避免将其构建为库,则类似适用于 Dog
。在这种情况下使用递归 make
几乎没有意义。
不过,我注意到 Automake 有一个 "convenience library" 的概念,它是一个中间目标,它本身从未安装过,但包含可以链接到可执行文件或更大库的目标代码.稍后我将对此进行演示,因为这是设置您在此特定情况下要求的每个目录的 makefile 结构的最明智的方法。
此外,关于将输出定向到源代码树中的特定目录:这是可以做到的,但这可能是一种浪费。 Autotools 已经为外源构建提供了一种方便的方法,如果构建项目的人希望这样做,可以更轻松地实现将构建结果与源代码分离的目标。
NEVERTHELESS, the basics of recursive builds with the Autotools 非常简单。主要有两件事要做:
each Makefile.am
想要表达对一个或多个子目录的递归,方法是在变量 SUBDIRS
.[= 中列出每个子目录的相对路径。 48=]
项目 configure.ac
必须指定要通过其 AC_CONFIG_FILES
宏构建的 Makefile
。
这就是设置递归所需要做的全部工作,如何设置特定目标和选项的详细信息因项目而异。
- Is that possible we build the hello.exe at
build
directory instead of build/HelloWorld/
directory? To do this, do I have to put
the bin_PROGRAMS
at the ./Makefile.am
是的,您可以指定构建到 build/hello
而不是 build/HelloWorld/hello
。你可能没有严格的有把相应的bin_PROGRAMS
放到顶层Makefile.am
,但你肯定应该 把它放在那里或放在 build/Makefile.am
文件中。我强烈建议您避免尝试在以该特定 makefile 所在目录为根目录的树之外设置任何 makefile 构建目标。
- I do not want to build Pet as librarys, I'm wondering whether there is a way I can just tell automake to find source codes in
different locations.
您绝对可以在与 Makefile.am
不同的目录中指定源文件。只需提供相对于 makefile 目录的适当路径。这对于与 makefile 位于同一树中的源更有意义,但使用位于其他地方的源并不像尝试在其他地方构建目标那么严重。
- I know that using non-recursive makefile would be easier. But I just want to learn how to create recursive makefiles for multiple
directories.
非递归 makefile 不一定比递归 makefile 更容易,但它们通常 更好,因为它们将整个目标/先决条件树表示为一个单元而不是将其切碎成为碎片。 make
当它同时拥有所有信息时,可以做出更好的构建决策。
I just started learning automake things, and I know these codes do not
work at all.
我对 your related question 的回答提供了相关问题的递归解决方案。它演示了您似乎缺少的关键原则之一:指定目标源和其他构建属性的变量需要出现在定义目标本身的同一个 Makefile.am
文件中。每个 Makefile.am
对应一个单独的 makefile。初步估计,makefile 之间不共享数据,因此构建给定目标所需的所有信息都需要出现在同一个文件中。
似乎将此问题与您的其他问题区分开来的另一件事是您想要(然而是错误的)在您的 makefile 中指定一个特定的输出目录 。请记住,无论构建的文件最初放在什么地方,它都是一个暂存区——这并不重要,因为它们会在 make install
之前被放入它们的最终目的地。即使这样,您也可以通过提供正确的相对路径来指定驻留在不同目录中的目标。当然,这样修改target名称需要在the names of the variables derived from the target name.
中体现出来
那么,这是一个递归的 Automake 设置,它应该为每个源目录使用一个 makefile 来构建您的示例项目:
Makefile.am
SUBDIRS = Pet HelloWorld
# Note: specifying output into a different directory
bin_PROGRAMS = build/hello
# Note the form of the following names:
build_hello_SOURCES = HelloWorld/main.cpp
build_hello_CPPFLAGS = -I$(srcdir)/Pet -I$(srcdir)/HelloWorld/Dog
# Note that library order matters
build_hello_LDADD = HelloWorld/Dog/libDog.a Pet/libPet.a
Pet/Makefile.am
noinst_LIBRARIES = libPet.a
libPet_a_SOURCES = \
Pet.cpp \
Pet.h
HelloWorld/Makefile.am
SUBDIRS = Dog
# No own targets defined here, just the recursion into Dog. This could have been
# skipped altogether, but I'm sticking to the letter of one Makefile.am per source
# directory.
HelloWorld/Dog/Makefile.am
noinst_LIBRARIES = libDog.a
libDog_a_SOURCES = \
Dog.cpp \
Dog.h
libDog_a_CPPFLAGS = -I$(top_srcdir)/Pet
您的 configure.ac
应该可以按原样使用。
注意这不依赖于VPATH
;它专门构建到构建树的build/
子目录中,包括当您直接在源代码树中构建时。
我的工作目录如下树所示:
./
|--HelloWorld/
|--|--main.cpp
|--|--Dog/
|--|--|--Dog.h
|--|--|--Dog.cpp
|--Pet/
|--|--Pet.h
|--|--Pet.cpp
|--build/
main.cpp
包括dog.h
和pet.h
。 Dog 是 Pet 的继承 class,所以 Dog.h
也包括 Pet.h
。我知道这是组织代码的一种有线方式,但我只是好奇 如何为每个子目录创建 makefile.am 文件,以便 autotool 可以在构建目录中构建项目。
请注意,我想要一些额外的功能:
- 我们可以在
build
目录而不是build/HelloWorld/
目录中构建 hello.exe 吗?为此,我是否必须将bin_PROGRAMS
放在./Makefile.am
- 我不想将 Pet 构建为库,我想知道是否有一种方法可以告诉 automake 在不同位置查找源代码。
- 我知道使用非递归 makefile 会更容易。但我只想学习如何为多个目录创建递归 makefile。
我试过的是:
configure.ac
AC_PREREQ([2.69])
AC_INIT([Hello], [1.0], [qub@oregonstate.edu])
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
AC_CONFIG_SRCDIR([HelloWorld/main.cpp])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CXX
AC_PROG_CC
#AC_PROG_CPP
AC_CONFIG_FILES([Makefile
HelloWorld/Makefile
Pet/Makefile
HelloWorld/Dog/Makefile])
AC_OUTPUT
Makefile.am
SUBDIRS = HelloWorld Pet
HelloWorld/Makefile.am
AM_CPPFLAGS=-I$(srcdir)/../Pet -I$(srcdir)/Dog
SUBDIRS = Dog
bin_PROGRAMS=hello
hello_SOURCES = main.cpp
Pet/Makefile.am
hello_SOURCES = Pet.h Pet.cpp
HelloWorld/Dog/Makefile.am
AM_CPPFLAGS=-I$(srcdir)/../../Pet
hello_SOURCES = Dog.h Dog.cpp
我刚开始学习automake的东西,我知道这些代码根本行不通。
谁能帮我解决这些问题?谢谢。
你说你对
感兴趣how to create makefile.am files for each subdirectories so that autotool can build the project in the build directory
,但这不是一个合适的目标,正如这个例子本身所展示的那样。没有定义任何要构建的目标的 Makefile.am
很少有用或不合适。您已经规定您不想将 Pet 构建为库,那么其目录中的 Makefile.am
将定义什么目标?如果您想避免将其构建为库,则类似适用于 Dog
。在这种情况下使用递归 make
几乎没有意义。
不过,我注意到 Automake 有一个 "convenience library" 的概念,它是一个中间目标,它本身从未安装过,但包含可以链接到可执行文件或更大库的目标代码.稍后我将对此进行演示,因为这是设置您在此特定情况下要求的每个目录的 makefile 结构的最明智的方法。
此外,关于将输出定向到源代码树中的特定目录:这是可以做到的,但这可能是一种浪费。 Autotools 已经为外源构建提供了一种方便的方法,如果构建项目的人希望这样做,可以更轻松地实现将构建结果与源代码分离的目标。
NEVERTHELESS, the basics of recursive builds with the Autotools 非常简单。主要有两件事要做:
each
Makefile.am
想要表达对一个或多个子目录的递归,方法是在变量SUBDIRS
.[= 中列出每个子目录的相对路径。 48=]项目
configure.ac
必须指定要通过其AC_CONFIG_FILES
宏构建的Makefile
。
这就是设置递归所需要做的全部工作,如何设置特定目标和选项的详细信息因项目而异。
- Is that possible we build the hello.exe at
build
directory instead ofbuild/HelloWorld/
directory? To do this, do I have to put thebin_PROGRAMS
at the./Makefile.am
是的,您可以指定构建到 build/hello
而不是 build/HelloWorld/hello
。你可能没有严格的有把相应的bin_PROGRAMS
放到顶层Makefile.am
,但你肯定应该 把它放在那里或放在 build/Makefile.am
文件中。我强烈建议您避免尝试在以该特定 makefile 所在目录为根目录的树之外设置任何 makefile 构建目标。
- I do not want to build Pet as librarys, I'm wondering whether there is a way I can just tell automake to find source codes in different locations.
您绝对可以在与 Makefile.am
不同的目录中指定源文件。只需提供相对于 makefile 目录的适当路径。这对于与 makefile 位于同一树中的源更有意义,但使用位于其他地方的源并不像尝试在其他地方构建目标那么严重。
- I know that using non-recursive makefile would be easier. But I just want to learn how to create recursive makefiles for multiple directories.
非递归 makefile 不一定比递归 makefile 更容易,但它们通常 更好,因为它们将整个目标/先决条件树表示为一个单元而不是将其切碎成为碎片。 make
当它同时拥有所有信息时,可以做出更好的构建决策。
I just started learning automake things, and I know these codes do not work at all.
我对 your related question 的回答提供了相关问题的递归解决方案。它演示了您似乎缺少的关键原则之一:指定目标源和其他构建属性的变量需要出现在定义目标本身的同一个 Makefile.am
文件中。每个 Makefile.am
对应一个单独的 makefile。初步估计,makefile 之间不共享数据,因此构建给定目标所需的所有信息都需要出现在同一个文件中。
似乎将此问题与您的其他问题区分开来的另一件事是您想要(然而是错误的)在您的 makefile 中指定一个特定的输出目录 。请记住,无论构建的文件最初放在什么地方,它都是一个暂存区——这并不重要,因为它们会在 make install
之前被放入它们的最终目的地。即使这样,您也可以通过提供正确的相对路径来指定驻留在不同目录中的目标。当然,这样修改target名称需要在the names of the variables derived from the target name.
那么,这是一个递归的 Automake 设置,它应该为每个源目录使用一个 makefile 来构建您的示例项目:
Makefile.am
SUBDIRS = Pet HelloWorld
# Note: specifying output into a different directory
bin_PROGRAMS = build/hello
# Note the form of the following names:
build_hello_SOURCES = HelloWorld/main.cpp
build_hello_CPPFLAGS = -I$(srcdir)/Pet -I$(srcdir)/HelloWorld/Dog
# Note that library order matters
build_hello_LDADD = HelloWorld/Dog/libDog.a Pet/libPet.a
Pet/Makefile.am
noinst_LIBRARIES = libPet.a
libPet_a_SOURCES = \
Pet.cpp \
Pet.h
HelloWorld/Makefile.am
SUBDIRS = Dog
# No own targets defined here, just the recursion into Dog. This could have been
# skipped altogether, but I'm sticking to the letter of one Makefile.am per source
# directory.
HelloWorld/Dog/Makefile.am
noinst_LIBRARIES = libDog.a
libDog_a_SOURCES = \
Dog.cpp \
Dog.h
libDog_a_CPPFLAGS = -I$(top_srcdir)/Pet
您的 configure.ac
应该可以按原样使用。
注意这不依赖于VPATH
;它专门构建到构建树的build/
子目录中,包括当您直接在源代码树中构建时。