我正在通过制作教程.我正在尝试构建的非常简单的测试项目只有3个文件:./ src/main.cpp ./src/implementation.cpp和./include/header.hpp这是make文件.
VPATH = src include
CPPFLAGS = -I include
main: main.o implementation.o
main.o: header.hpp
implementation.o: header.hpp
Run Code Online (Sandbox Code Playgroud)
当调用时没有任何参数使得建立唯一对象的文件,但不链接的可执行文件.应该有一个隐含的前卫规则或我错过了什么?我真的需要有人指出我正确的方向.
谢谢.
我使第一个目标名称与源文件的前缀相同.现在调用cc来链接目标文件.
g++ -I include -c -o main.o src/main.cpp
g++ -I include -c -o implementation.o src/implementation.cpp
cc main.o implementation.o -o main
Run Code Online (Sandbox Code Playgroud)
由于某些原因,与g ++链接工作,但与cc链接不起作用.
我可以明确指定规则,但想学习如何使用隐式规则.
Has*_*kun 15
根据make手册,如果其中一个与可执行文件名匹配,则可以将隐式链接规则与多个对象一起使用,例如:
VPATH = src include
CPPFLAGS = -I include
main: implementation.o
main.o: header.hpp
implementation.o: header.hpp
Run Code Online (Sandbox Code Playgroud)
这将从main.o和implementation.o构建一个名为main的可执行文件.
但请注意,内置隐式规则使用C编译器进行链接,默认情况下不会链接到C++ std库,您需要将其明确地添加到LDFLAGS
对于最小的Makefile,这个怎么样:
SOURCES = src/main.cpp src/implementation.cpp
CXX = g++
CXXFLAGS = -g -W -Wall -Werror
LDFLAGS = -g
OBJECTS = $(SOURCES:.cpp=.o)
prog: $(OBJECTS)
$(CXX) $(LDFLAGS) -o $@ $^
clean::
$(RM) prog
.cpp.o:
$(CXX) -MD -MP $(CXXFLAGS) -o $@ -c $<
clean::
$(RM) src/*.o
DEPENDS = $(SOURCES:.cpp=.d)
-include $(DEPENDS)
%.d:
@touch $@
clean::
$(RM) src/*.d
Run Code Online (Sandbox Code Playgroud)
这假定GNU make和gcc,但它添加了适当的依赖关系跟踪,因此不需要显式列出头文件依赖关系.
应该有一个隐含的前卫规则或我错过了什么?
没有隐含的规则.make不知道如何构建,prog因为它不知道prog应该是一个可执行文件.make仅使用文件名作为模式来推断构建规则.prog是没有扩展名的通用文件名,所以make不知道如何对待它.
我的答案(一个巧妙的解决方案):添加
LDLIBS = -lstdc++
Run Code Online (Sandbox Code Playgroud)
到 Makefile。根据手册:
-lfoo应改为将库 ( ) 添加到LDLIBS变量中。
LDFLAGS专为库目录标志而设计,例如-L. 在我的 Linux (Ubuntu 14.04) 上,LDFLAGS = -lstdc++产生
cc -lstdc++ main.o -o main
Run Code Online (Sandbox Code Playgroud)
这不起作用,而LDLIBS = -lstdc++产生
cc main.o -lstdc++ -o main
Run Code Online (Sandbox Code Playgroud)
哪个有效。我不知道为什么顺序很重要,但根据两个内置变量的作用,它是有道理的。我不喜欢的别名CC到CXX这似乎是黑客攻击,以及为读者混淆。
我刚刚试过,发现这个编译器不适用于LDFLAGS = -lstdc++:
但以下编译器接受LDFLAGS = -lstdc++:
所以它大部分时间都有效,但不能保证。如果您希望您的 makefile 更便携,请使用LDLIBS适用于上述所有环境的文件。
Hasturkun:有main.o规则
main: main.o implementation.o
Run Code Online (Sandbox Code Playgroud)
不会导致错误。该main.o是没有必要的,但它仍然会。
Simon Richter:该解决方案不需要跟踪标题(这真的很棒),但是 OP 需要一个隐式规则。我们实际上可以充分利用两者:
LDLIBS = -lstdc++
Run Code Online (Sandbox Code Playgroud)
这做他所做的,以及利用隐含规则。然而,这个完整的解决方案不应该在这里,因为它不是 OP 所希望的:OP 只是想知道为什么他的 Makefile 不起作用,以及为什么。“Auto-Dependency Generation”是另一个值得一整个教程(就像这个)的巨大话题。所以我很抱歉,但他的回答实际上并没有回答这个问题。
Jerome:我曾经LINK.o从$(CC) $(LDFLAGS) $(TARGET_ARCH)改为$(CXX) $(LDFLAGS) $(TARGET_ARCH)并且它起作用了,但我更喜欢编辑,LDLIBS因为LINK.o没有记录(并且可能不是公共 API 的一部分)并且没有未来证明。我会称之为黑客。