帮助简化多个可执行文件的 Makefile

发布于 2024-10-11 13:19:42 字数 1638 浏览 1 评论 0原文

我有多个可执行文件使用的通用代码(例如 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;
}

hello.cpp:

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

hello.h:

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

I have common code (e.g. hello.cpp) that is used by multiple executables. I'm using a single Makefile to build it all:

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++ 
lt; $(OBJ) -o $@    
app2.out: app2.o $(OBJ)
    g++ 
lt; $(OBJ) -o $@    
.cpp.o:
    g++ -c 
lt; -o $@    
clean:
    rm -f $(EXE) $(OBJ) $(OBJ_MAIN)

I'm not very happy about having a separate target for each executable -- the targets are essentially the same. Is there any way to do this with one target for all executables? I was hoping that something like this would work:

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++ 
lt; $(OBJ) -o $@
.cpp.o:
    g++ -c 
lt; -o $@
clean:
    rm -f $(EXE) $(OBJ) $(OBJ_MAIN)

But I get a linking error:

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

For some reason it tries to build app1.out without building its dependency hello.o. Can anyone explain why this doesn't work, and suggest something that does?

Here's the rest of the dummy code, just in case.

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;
}

hello.cpp:

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

hello.h:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

枕花眠 2024-10-18 13:19:42

问题似乎是您正在使用旧式后缀规则。从制作信息来看:

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

<前><代码> .co: foo.h
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

告诉如何从先决条件文件“foo.h”创建文件“.co”,
并且完全不像模式规则:

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

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

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

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

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

The problem appears to be that you are using old-style suffix rules. From the make info:

Suffix rules cannot have any prerequisites of their own. If they
have any, they are treated as normal files with funny names, not as
suffix rules. Thus, the rule:

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

tells how to make the file '.c.o' from the prerequisite file 'foo.h',
and is not at all like the pattern rule:

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

which tells how to make '.o' files from '.c' files, and makes all '.o'
files using this pattern rule also depend on 'foo.h'.

The solution is to use new-style pattern rules:

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

(Also note that you don't need to define a .cpp to .o rule; make has a sensible default.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文