如何使用 autotool 在单独的目录中构建
Posted
技术标签:
【中文标题】如何使用 autotool 在单独的目录中构建【英文标题】:How to build in a separate directory with autotool 【发布时间】:2019-10-12 08:15:06 【问题描述】:我有一个工作目录如下:
./ |----HelloWorld/ |----|----main.cpp |----|----Makefile.am |----宠物/ |----|----宠物.h |----|----Pet.cpp |----构建/ |----configure.ac |----Makefile.am
我想用autotool构建makefile,然后在build目录下构建项目。
./configure.ac 是
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
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_CONFIG_FILES([Makefile])
AC_OUTPUT
./Makefile.am 是
include HelloWorld/Makefile.am
请注意,我使用包含来确保 exe 位于 make 命令运行的目录中。
./HelloWorld/Makefile.am是
AM_CPPFLAGS=-I%D%/../Pet/ -I%D% -I%C%
#VPATH = ./HelloWorld ./Pet
bin_PROGRAMS=hello
hello_SOURCES=%D%/../Pet/Pet.h
hello_SOURCES+=%D%/../Pet/Pet.cpp
hello_SOURCES+=%D%/main.cpp
如果有人想在自己的电脑上尝试,我在这里附上其他源代码: main.cpp
#include <stdio.h>
#include <vector>
#include "Pet.h"
int main()
printf("Hello World\n");
std::vector<Pet*> all_pets;
Pet *dog = new Pet(string("Apple"));
all_pets.push_back(dog);
Pet *cat = new Pet(string("Pear"));
all_pets.push_back(cat);
for (int i = 0; i < all_pets.size(); i++)
all_pets[i]->showName();
return 0;
**Pet.h**
#pragma once
#include <string>
using namespace std;
class Pet
public:
Pet(string name);
~Pet();
void showName();
void showIndex();
string _name;
int _index;
;
Pet.cpp
#include "Pet.h"
Pet::Pet(string name)
_name = name;
srand(2345);
_index = (rand() % 100);
Pet::~Pet()
void Pet::showIndex()
printf("Index is %d\n", _index);
void Pet::showName()
printf("Name is %s\n", _name.c_str());
问题陈述
-
运行可以成功创建makefile
./ $autoreconf --install
-
使用以下命令可以在根目录成功构建项目
./ $./configure
./ $make
-
在目录 ./build 中构建时出错。命令是:
./build/ $../configure
./build/ $make
出现如下图所示的错误:
build error image
我认为这个错误是由于编译器无法成功找到头文件造成的。我的第一个问题是为什么makefile.am 中的AM_CPPFLAGS=-I%D%/../Pet/ -I%D% -I%C%
不能解决这个问题?
由于编译器将在构建目录中创建 .o 文件,从而使构建树具有与源树相同的子目录布局。所以我可以通过将 Pet.h 文件复制到 \build\Pet 来解决这个问题。但是,这意味着我总是需要将头文件复制到构建目录,这很不方便。
我找到了一些关于VPATH 的信息。所以我在./HelloWorld/Makefile.am 中注释掉了#VPATH = ./HelloWorld ./Pet
。但是,它会给我一个新的问题:
automake error image
我的假设是 VPATH 设置与包含 makefile.am 有某种冲突。我的第二个问题是如何使用包含 makefile 正确使用 VPATH?
【问题讨论】:
【参考方案1】:为什么makefile.am中的
AM_CPPFLAGS=-I%D%/../Pet/ -I%D% -I%C%
不能解决这个问题?
因为%D%
和%C%
生成include
d makefile 片段的路径相对于包含它的makefile,而不是相对于构建目录。它们不适用于或不适合处理源外构建,但如果使用得当,它们不会对此产生干扰。
如何通过包含 makefile 正确使用 VPATH?
你想太多问题了。 Automake 自动支持源外构建。您不需要(也不应该)自己设置VPATH
。
您还使用 Makefile include
指令为自己制造麻烦。该指令肯定有很好的用途,但您可以通过将所有内容合并到***Makefile.am
或设置递归make
来做得更好。你不应该需要 %D%
和 %C%
的东西。
Automake 将为您设置VPATH
,并在您执行源外构建时负责定位先决条件。大多数情况下,您只需指定相对于Makefile.am
和/或configure.ac
位置的源和目标路径。
有时您确实需要参考源目录,在这种情况下,您应该使用适当的$(srcdir)
、$(top_srcdir)
、$(abs_srcdir)
或$(abs_top_srcdir)
之一来确保源外构建正常工作。
您的项目布局有点奇怪,但这些替代方案中的任何一个都应该这样做:
递归
Makefile.am
SUBDIRS = HelloWorld
HelloWorld/Makefile.am
# VPATH helps *make* identify prerequisites, but the compiler doesn't know about it.
# We therefore need to give compiler options with real paths. But we shouldn't need
# any extra options to support sources that #include headers via (correct) paths expressed
# relative to the sources' own location.
AM_CPPFLAGS = -I$(srcdir)/../Pet
# Note: builds 'hello' in subdirectory HelloWorld/ of the build directory
bin_PROGRAMS = hello
hello_SOURCES = \
../Pet/Pet.h \
../Pet/Pet.cpp \
main.cpp
非递归
Makefile.am
AM_CPPFLAGS = -I$(srcdir)/Pet
# Builds 'hello' directly in the build directory
bin_PROGRAMS = hello
hello_SOURCES = \
Pet/Pet.h \
Pet/Pet.cpp \
HelloWorld/main.cpp
HelloWorld/Makefile.am
(无)
无论哪种方式,您都可以像尝试做的那样执行源外构建:更改到想要的构建目录,如有必要首先创建它,从那里通过适当的路径运行 configure
脚本,然后然后继续make
。
$ mkdir build
$ cd build
$ path/to/configure
$ make
【讨论】:
谢谢@John Bollinger,我认为非递归方式对我来说是最简单的解决方案。我还有一些关于如何以递归方式创建 makefile 的问题question,你介意看看吗。非常感谢。 我会看看你的另一个问题,@Burton。同时,如果您对这个或另一个答案令人满意地回答了问题感到满意,那么通常(但不是强制性)通过单击其左侧的复选标记(靠近其分数)“接受”一个答案。【参考方案2】:我无意中将 ./HelloWorld/Makefile.am 更改为
AM_CPPFLAGS=-I%D%/../../Pet/ -I%D% -I%C%
#VPATH = ../Pet
#srcdir = @srcdir@
#VPATH = %D/Pet/
bin_PROGRAMS=hello
hello_SOURCES=%D%/../../Pet/Pet.h
hello_SOURCES+=%D%/../Pet/Pet.cpp
hello_SOURCES+=%D%/main.cpp
请注意,hello_SOURCES 的路径已更改,并且标头路径与源路径不同。但是为什么这会解决问题呢?
【讨论】:
这为您解决了问题是您对构建目录的特定选择的一个怪癖。显然您选择了***源目录的子目录。如果您在任何其他位置选择一个目录——比方说,更深一层,或者靠近***源目录——那么这将不起作用(但您可以生成一个类似的“解决方案”,适用于那种相对位置)。 具体来说:-I%D%/../../Pet/
恰好适合编译器定位标头,而 hello_SOURCES+=%D%/../Pet/Pet.cpp
和 hello_SOURCES+=%D%/main.cpp
恰好与为 @987654326 自动生成的 VPATH
一起正常工作@ 定位 C++ 源代码。请注意,在 _SOURCES
中列出标头没有编译时影响;它只是确保标头包含在通过 make dist
构建的分发包中。以上是关于如何使用 autotool 在单独的目录中构建的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 autotools 与库同时构建 Python 接口
如何在 c++ Autotools 项目中使用不同版本的 g++ 进行编译