我的工作目录如以下树所示:
./
|--HelloWorld/
|--|--main.cpp
|--|--Dog/
|--|--|--Dog.h
|--|--|--Dog.cpp
|--Pet/
|--|--Pet.h
|--|--Pet.cpp
|--build/
main.cpp
包括dog.h
和pet.h
。 Dog是Pet的继承类,因此Dog.h
也包括Pet.h
。我知道这是一种组织代码的有线方式,但是我很好奇如何为每个子目录创建makefile.am文件,以便自动工具可以在构建目录中构建项目。
请注意,我想拥有一些其他功能:
build
目录而不是build/HelloWorld/
目录中构建hello.exe?为此,我是否必须将bin_PROGRAMS
放在./Makefile.am
我尝试过的是:
configure.ac
AC_PREREQ([2.69])
AC_INIT([Hello], [1.0], [[email protected]])
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
我刚刚开始学习自动制作东西,并且我知道这些代码根本不起作用。
有人可以帮我修复它们吗?谢谢。
您说您有兴趣
如何为每个子目录创建makefile.am文件,以便自动工具可以在构建目录中构建项目
,但这不是一个适当的目标,如本示例本身所示。没有定义任何要构建的目标的Makefile.am
很少有用或不合适。您已规定您不想将Pet建为库,那么Makefile.am
在其目录中将定义什么目标?如果要避免将其构建为库,则类似的内容适用于Dog
。在这种情况下,使用递归make
几乎没有意义。
但是,我注意到Automake的概念是“便利库”,它是一个中间目标,它从未安装过,但包含可以链接到可执行文件或更大库中的目标代码。我将在稍后进行演示,因为在这种特殊情况下,这是设置所需的每个目录的makefile的最明智的方法。
此外,关于将输出定向到源树中的特定目录:可以这样做,但是可能很浪费精力。 Autotools已经为源外构建提供了一种方便的方法,如果构建项目的人员希望这样做,则可以更轻松地实现将构建结果与源分离的目标。
NEVERTHELESS,the basics of recursive builds with the Autotools非常简单。有两件事要做:
每个Makefile.am
要表示一个或多个子目录的递归,是通过在变量SUBDIRS
中列出每个子目录的相对路径来实现的。
项目configure.ac
必须通过其Makefile
宏指定要构建的AC_CONFIG_FILES
。
这是一般设置递归所需要做的,并且有关如何设置特定目标和选项的详细信息是特定于项目的。
- 是否可以在
build
目录而不是build/HelloWorld/
目录中构建hello.exe?为此,我必须放bin_PROGRAMS
处的./Makefile.am
是,您可以将建筑物指定为build/hello
,而不是build/HelloWorld/hello
。您可能没有严格地have将相应的bin_PROGRAMS
放入顶层Makefile.am
,但您肯定应该将其放置在build/Makefile.am
文件中。我敦促您避免尝试使任何makefile构建目标都植根于该特定makefile所在目录的树之外。
- 我不想将Pet构建为库,我想知道是否有一种方法可以告诉automake在其中查找源代码。不同的位置。
您可以绝对地在Makefile.am
之外的其他目录中指定源文件。只需提供相对于makefile目录的适当路径即可。对于与makefile相同的树中的源,这更有意义,但是使用其他位置的源并不像尝试在其他位置构建目标那样重要。
- 我知道使用非递归的makefile会更容易。但是我只想学习如何为多个创建递归makefile目录。
非递归的makefile不一定比递归的makefile容易,但是它们通常更好,因为它们将整个目标/先决条件树表示为一个单元,而不是将其切成碎片。 make
一次拥有所有信息时,可以做出更好的构建决策。
我刚刚开始学习自动制作东西,而且我知道这些代码并不完全可以。
我对your related question的回答为相关问题提供了递归解决方案。它展示了您似乎缺少的关键原则之一:指定目标源和其他构建属性的变量需要出现在定义目标本身的同一Makefile.am
文件中。每个Makefile.am
对应一个单独的makefile。初步估计,makefile之间不会共享数据,因此构建给定目标所需的所有信息都必须显示在同一文件中。
似乎使这个问题与您的另一个问题区分开的另一件事是,您想要(但是错误地)指定了特定的输出目录在您的makefile中。请记住,无论最初生成的文件在哪里,它都是一个暂存区域–没什么大不了的,因为它们在make install
之前被放置到最终目标位置。即使这样,您也可以通过提供正确的相对路径来指定驻留在其他目录中的目标。当然,对目标名称的这种更改需要反映在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
;它将specifically构建到构建树的build/
子目录中,包括直接在源代码树中构建时的情况。