在 GNU make 中一次编译多个**更改的**源文件

发布于 2024-11-07 21:28:54 字数 1014 浏览 6 评论 0原文

我知道有几个具有类似标题的问题,但似乎没有一个问题能提供我需要的答案(如果我错了,请纠正我)。

考虑这个makefile:

SOURCES=file1.cpp file2.cpp file3.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=myprog

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CXX) -o $@ $(OBJECTS)

file1.o: file1.cpp file1.h
file2.o: file2.cpp file2.h file1.h
file3.o: file3.cpp

.cpp.o:
    $(CXX) $(CXXFLAGS) -c -o $@ $<

如果我更改file1.h,则会运行以下内容:

g++ -c -o file1.o file1.cpp
g++ -c -o file2.o file2.cpp
g++ -o myprog file1.o file2.o file3.o 

我想要的是:(

g++ -c file1.cpp file2.cpp
g++ -o myprog file1.o file2.o file3.o 

我知道我无法使用GCC指定对象输出目录,但这我可以忍受;应该可以使用一些 cd 命令来解决。)

在 nmake 中,这是通过双冒号推理规则(所谓的“批处理模式规则")。基本上,它将多个目标的推理规则(例如“.obj.cpp:”)分组,并为所有依赖项调用编译器,而不是每个文件调用一次。 $< 变量获取依赖项列表,而不仅仅是第一个。

现在我们正在使用并行构建(make -j),但它有自己的问题,并且 VC++ 编译器在一次调用模式下工作得更好,所以我更喜欢使用它。

I know there have been several questions with similar titles but none seem to provide an answer to what I need (correct me if I'm wrong).

Consider this makefile:

SOURCES=file1.cpp file2.cpp file3.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=myprog

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CXX) -o $@ $(OBJECTS)

file1.o: file1.cpp file1.h
file2.o: file2.cpp file2.h file1.h
file3.o: file3.cpp

.cpp.o:
    $(CXX) $(CXXFLAGS) -c -o $@ 
lt;

If I change file1.h, the following is run:

g++ -c -o file1.o file1.cpp
g++ -c -o file2.o file2.cpp
g++ -o myprog file1.o file2.o file3.o 

What I would like to have is:

g++ -c file1.cpp file2.cpp
g++ -o myprog file1.o file2.o file3.o 

(I know I can't specify object output directory with GCC, but this I can live with; it should be possible to work around with some cd commands.)

In nmake, this is done with a double-colon inference rule (so-called called "batch-mode rule"). Basically, it groups the inference rules (e.g. ".obj.cpp:") for multiple targets and invokes the compiler for all dependencies instead of once per file. The $< variable gets the list of dependencies instead of just the first one.

Right now we're using parallel building (make -j) but it has its own issues, and VC++ compiler works much better in one-invocation mode so I'd prefer using that.

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

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

发布评论

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

评论(2

暮年 2024-11-14 21:28:54

我不明白你为什么想要这种效果,但这是获得它的方法(在 GNUMake 中):

SOURCES=file1.cpp file2.cpp file3.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=myprog

all: $(EXECUTABLE)

$(EXECUTABLE): $(SOURCES)
    $(CXX) $(CXXFLAGS) -c $?
    $(CXX) -o $@ $(OBJECTS)

编辑:
我很惊讶这个解决方案有效——我对 Make 所做的事情的想法有问题——但我认为它不会在你的情况下工作,有头依赖项,没有以下的混乱。 (如果这不起作用,还有一两种其他方法可能有效。)

SOURCES=file1.cpp file2.cpp file3.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=myprog

all: $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CXX) -o $@ $(OBJECTS)

file1.cpp: file1.h
file2.cpp: file2.h file1.h

$(SOURCES):
    @touch $@

$(OBJECTS): $(SOURCES)
    $(CXX) $(CXXFLAGS) -c $?
    @touch $(OBJECTS)

I don't see why you want this effect, but here's how to get it (in GNUMake):

SOURCES=file1.cpp file2.cpp file3.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=myprog

all: $(EXECUTABLE)

$(EXECUTABLE): $(SOURCES)
    $(CXX) $(CXXFLAGS) -c $?
    $(CXX) -o $@ $(OBJECTS)

EDIT:
I'm surprised that that solution works -- there's something wrong with my idea of what Make does -- but I don't think it'll work in your case, with header dependencies, without the following kludge. (There are one or two other approaches that might work, if this doesn't pan out.)

SOURCES=file1.cpp file2.cpp file3.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=myprog

all: $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CXX) -o $@ $(OBJECTS)

file1.cpp: file1.h
file2.cpp: file2.h file1.h

$(SOURCES):
    @touch $@

$(OBJECTS): $(SOURCES)
    $(CXX) $(CXXFLAGS) -c $?
    @touch $(OBJECTS)
国粹 2024-11-14 21:28:54

您可以通过收集要在构建规则中重建的文件,然后在链接时实际构建它们来使 GNUmake 执行您想要的操作:

SOURCES=file1.cpp file2.cpp file3.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=myprog

all: $(EXECUTABLE)

.PHONY: build_list

build_list:
        -rm -f build_list

$(OBJECTS): %.o: %.cpp | build_list
        echo 
lt; >> build_list

$(EXECUTABLE): build_list $(OBJECTS)
        if [ -r build_list ]; then $(CXX) $(CXXFLAGS) -c `cat build_list`; fi
        $(CXX) -o $@ $(OBJECTS)

file1.o: file1.h
file2.o: file2.h file1.h

You can make GNUmake do what you want by collecting the files to be rebuilt in the build rule and then actually building them when you link:

SOURCES=file1.cpp file2.cpp file3.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=myprog

all: $(EXECUTABLE)

.PHONY: build_list

build_list:
        -rm -f build_list

$(OBJECTS): %.o: %.cpp | build_list
        echo 
lt; >> build_list

$(EXECUTABLE): build_list $(OBJECTS)
        if [ -r build_list ]; then $(CXX) $(CXXFLAGS) -c `cat build_list`; fi
        $(CXX) -o $@ $(OBJECTS)

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