【问题标题】:Help simplifying a Makefile for multiple executables帮助简化多个可执行文件的 Makefile
【发布时间】:2011-06-07 15:16:24
【问题描述】:

我有多个可执行文件使用的通用代码(例如hello.cpp)。我正在使用一个 Makefile 来构建它:

EXE=app1.out app2.out
SRC=hello.cpp
OBJ=$(SRC:.cpp=.o)
SRC_MAIN=app1.cpp app2.cpp
OBJ_MAIN=$(SRC_MAIN:.cpp=.o)
all: $(EXE)    
app1.out: app1.o $(OBJ)
    g++ $< $(OBJ) -o $@    
app2.out: app2.o $(OBJ)
    g++ $< $(OBJ) -o $@    
.cpp.o:
    g++ -c $< -o $@    
clean:
    rm -f $(EXE) $(OBJ) $(OBJ_MAIN)

我对每个可执行文件都有一个单独的目标不太满意——目标基本上是相同的。有没有办法用一个目标为所有可执行文件做到这一点?我希望这样的事情会起作用:

EXE=app1.out app2.out
SRC=hello.cpp
OBJ=$(SRC:.cpp=.o)
SRC_MAIN=app1.cpp app2.cpp
OBJ_MAIN=$(SRC_MAIN:.cpp=.o)
all: $(EXE)
.o.out: $(OBJ)
    g++ $< $(OBJ) -o $@
.cpp.o:
    g++ -c $< -o $@
clean:
    rm -f $(EXE) $(OBJ) $(OBJ_MAIN)

但我得到一个链接错误:

misha@misha-desktop:~/cpp/stack$ make -f Makefile2
g++ -c app1.cpp -o app1.o
g++ app1.o hello.o -o app1.out
g++: hello.o: No such file or directory
make: *** [app1.out] Error 1
rm app1.o

出于某种原因,它尝试构建 app1.out 而不构建其依赖项 hello.o。谁能解释为什么这不起作用,并提出一些可行的建议?

这是其余的虚拟代码,以防万一。

app1.cpp:

#include "hello.h"   
int
main(void)
{
    print_hello();
}

app2.cpp:

#include "hello.h"    
int
main(void)
{
    for (int i = 0; i < 4; ++i)
        print_hello();
    return 0;
}

你好.cpp:

#include "hello.h"    
#include <stdio.h>    
void
print_hello()
{
    printf("hello world!\n");
}

你好.h:

#ifndef HELLO_H
#define HELLO_H
void
print_hello();
#endif

【问题讨论】:

    标签: c++ makefile


    【解决方案1】:

    问题似乎是您使用的是旧式后缀规则。来自制作信息:

    后缀规则不能有任何自己的先决条件。如果他们 有任何,它们被视为具有有趣名称的普通文件,而不是 后缀规则。因此,规则:

      .c.o: foo.h
              $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
    

    告诉如何从先决条件文件“foo.h”制作文件“.c.o”, 而且一点也不像模式规则:

      %.o: %.c foo.h
              $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
    

    它告诉如何从 '.c' 文件生成 '.o' 文件,并生成所有 '.o' 使用此模式规则的文件也依赖于 'foo.h'。

    解决方案是使用新样式的模式规则:

    %.out: %.o $(OBJ)
        g++ $< $(OBJ) -o $@
    %.o: %.cpp
        g++ -c $< -o $@
    

    (另请注意,您不需要定义 .cpp 到 .o 规则;make 有一个合理的默认值。)

    【讨论】:

    • 感谢您的回答。我使用 .cpp 到 .o 规则为编译器提供自定义 CPPFLAGS。我没有在示例代码中显示它们,因为我让事情变得简单。 make 默认值是否仍包含“默认”变量名称(例如 CFLAGSCPPFLAGSLDFLAGS 等)?
    • 是的,但CPPFLAGS 用于 C 预处理器。 CXXFLAGS 用于 C++ 标志。
    猜你喜欢
    • 2018-11-14
    • 2013-05-21
    • 1970-01-01
    • 2011-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多