Fra*_*Boi 1 makefile compilation header-files
我编写了一个Makefile来在OSX(Unix系统中更通用)上编译一个openCV程序。
该代码有一个标头constants.hpp,其中定义了一些常量。
我想使Makefile在此头文件更改时重新编译程序,因为其中的常量值会更改程序行为。
我的Makefile如下
CPP = g++
CPPFLAGS = -std=c++11
all: main.o
main.o: main.cpp
$(CPP) $^ $(CPPFLAGS) -o $@
Run Code Online (Sandbox Code Playgroud)
搜索后,我试图定义CPPFLAGS以下值:
DEPS = constants.hpp
Run Code Online (Sandbox Code Playgroud)
然后由于main.o依赖于它,所以添加依赖关系如下:
main.o: main.cpp $(DEPS)
$(CPP) $^ $(CPPFLAGS) -o $@
Run Code Online (Sandbox Code Playgroud)
但是我得到的错误是clang: error: cannot specify -o when generating multiple output files。
我也尝试了这个答案,并尝试使用M MM标志,但是我丢失了一些东西。
更改头文件时,如何使Makefile重新编译?
编辑:在对DevSolar的评论之后,我不得不完全修改问题,并且他还询问了源代码。由于我发现这里无用地复制所有源代码,因此我用一个简单的hello world程序对其进行了简化。
以下是main.cpp:
#include<iostream>
#include"constants.hpp"
int main()
{
std::cout<<"Hello world, the value is: " << myValue <<"\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
以及以下内容constants.hpp:
static const int myValue = 10;
Run Code Online (Sandbox Code Playgroud)
前言
您正在使用$(CPP)和$(CPPFLAGS)...这是用于预处理程序的。您要使用的是$(CXX)和$(CXXFLAGS),用于C ++编译器。
以下内容假定使用GNU make和与GCC兼容的编译器(使用clang即可)。
步骤1
使用通用规则,而不是每个源文件一个规则-后者很快就会变得毫无用处,并且容易出错。
手动列出您的源文件...
SOURCES := parking.cpp utils.cpp InputStateContext.cpp InputState.cpp InputStateA.cpp
Run Code Online (Sandbox Code Playgroud)
...或自动列出所有源文件:
SOURCES := $(wildcard *.cpp)
Run Code Online (Sandbox Code Playgroud)
您还需要一个目标文件列表(每个.cpp一个.o):
OBJECTS := $(patsubst %.cpp,%.o,$(SOURCES))
Run Code Online (Sandbox Code Playgroud)
现在,根据所有目标文件为可执行文件提供规则。
parking: $(OBJECTS)
$(CXX) $(CXXFLAGS) $^ -o $@
Run Code Online (Sandbox Code Playgroud)
...以及关于如何将单个源文件转换为目标文件的通用规则:
%.o: %.cpp Makefile
$(CXX) $(CXXFLAGS) &< -o $@
Run Code Online (Sandbox Code Playgroud)
使该规则也依赖于Makefile可以确保例如更改也$(CXXFLAGS)触发重新编译。$<解析为第一个依赖项(源文件)。
我们将在以后扩展此规则。
第二步
每个源文件都有一个依赖文件。(在这里与我在一起。)我们可以生成这些文件的列表...
DEPENDS := $(patsubst %.cpp,%.d,$(SOURCES))
Run Code Online (Sandbox Code Playgroud)
...并将它们包含在Makefile中:
-include $(DEPENDS)
Run Code Online (Sandbox Code Playgroud)
在-那里意味着,make如果不存在这些文件不会抱怨-因为他们不这样做,在这一点上。
第三步(问题答案的核心)
让编译器为我们生成那些依赖文件-因为它最了解。为此,我们扩展了构建规则:
%.o: %.cpp Makefile
$(CXX) $(CXXFLAGS) -MMD -MP -c $< -o $@
Run Code Online (Sandbox Code Playgroud)
该-MMD标志生成依赖项文件(%.d),该文件将保存(以Makefile语法)规则,以使所生成的文件(%.o在这种情况下)取决于源文件及其包括的任何非系统头文件。这意味着只要触摸相关源,就会自动重新创建目标文件。如果您还希望依赖系统头文件(即,检查它们的每次编译更新),请-MD改用。
该-MP选项添加了空的虚拟规则,可以避免在从文件系统中删除头文件时出错。
在第一次编译运行时,没有依赖项信息-但是由于目标文件也不存在,因此编译器仍然必须运行。对于每个后续运行,make将包括自动生成的依赖文件,并“做正确的事”。
多合一(添加了更多语法糖):
SOURCES := $(wildcard *.cpp)
OBJECTS := $(patsubst %.cpp,%.o,$(SOURCES))
DEPENDS := $(patsubst %.cpp,%.d,$(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: parking
clean:
$(RM) $(OBJECTS) $(DEPENDS) parking
# Linking the executable from the object files
parking: $(OBJECTS)
$(CXX) $(WARNING) $(CXXFLAGS) $^ -o $@
-include $(DEPENDS)
%.o: %.cpp Makefile
$(CXX) $(WARNING) $(CXXFLAGS) -MMD -MP -c $< -o $@
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1287 次 |
| 最近记录: |