使用 WiringPi 的简单 Makefile

Posted

技术标签:

【中文标题】使用 WiringPi 的简单 Makefile【英文标题】:Simple Makefile using WiringPi 【发布时间】:2017-11-12 01:57:42 【问题描述】:

我是 Makefile 的新手。我一直在为我的 RaspberyPi 相关项目使用 WiringPi 制作一个简单的 C++ 库。到目前为止,它非常简单,例如 LED 类、DuelLED、电机、按钮等(.h 和 .cpp)。我能够拼凑一个 Makefile,但我收到一个错误 “没有规则来制作 RumPi 需要的目标 RumPi.o”。(注意:我的库的名称被称为 RumPi)

感谢所有帮助,这是最终修复:

CXX = g++
CXXFLAGS = -std=c++11
LDLIBS = -lwiringPi

HEADERS = Components/Headers/RumPi.h ./Common.h Components/Headers/Component.h Components/Headers/Vehicle.h Components/Headers/Motor.h Components/Headers/Receiver.h Components/Headers/DualLED.h Components/Headers/LED.h Components/Headers/RGBLED.h Components/Headers/Relay.h 
OBJECTS = RumPi.o Vehicle.o Motor.o Receiver.o DualLED.o LED.o RGBLED.o Relay.o

default: RumPi

RumPi: $(OBJECTS)
        $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@

%.o: Components/Implementations/%.cpp
        $(CXX) $(CXXFLAGS) -c -o $@ $<

$(OBJECTS): $(HEADERS)

clean:
        -rm -f $(OBJECTS)
        -rm -f RumPi

【问题讨论】:

【参考方案1】:

该消息意味着 make 无法弄清楚如何构建该目标 (RumPi.o)。你有Components/Implementations/RumPi.cpp 文件吗?您在$(HEADERS) 变量中列出的所有头文件是否真的存在?如果其中任何一个不正确,那么您的模式规则将不匹配。如果您的模式规则不匹配(并且默认规则不匹配),则 make 无法确定如何构建目标文件。

如果您需要完整的详细信息,您可以运行make -d 并检查调试输出。您可能希望将其重定向到一个文件,以便您可以使用 less 或文本编辑器查看它,因为有很多输出。

顺便说一句,您不应该将-lwiringPi 选项添加到您的编译行。库仅在链接时使用,而不是编译时使用。

预计到达时间

您应该考虑的其他事情是重写您的模式规则,以便仅将源文件列为先决条件并将标题移动到单独的行:

%.o: Components/Implementations/%.cpp
        gcc -c $< -o $@ -lwiringPi

$(OBJECTS): $(HEADERS)

这样做的好处是,如果未找到其中一个标头,您将收到更清晰的错误消息。当您使用模式规则时,make 将尝试匹配 所有 它可以匹配的模式,如果没有匹配,它会告诉您它不知道如何构建目标。由于通常有许多不同的方法来构建目标,因此 make 不会对每个不匹配的方法都显示错误。

但是如果你在两个文件之间声明一个直接的显式先决关系,而不是使用一个可能匹配也可能不匹配的模式,那么如果有一个丢失的文件,make会直接告诉你。

ETA2

在您原来的 makefile 中,您有这样的规则:

RumPi: $(OBJECTS)
        gcc $(OBJECTS) -o $@ -lwiringPi

但后来你删除了它。你为什么把这个拿出来?你需要这条规则来告诉 make 如何链接你的可执行文件RumPi

另外,您不应该使用gcc 作为 C++ 代码的编译器/链接器; gcc 用于 C,而不是 C++。对于 C++ 代码,您应该使用 g++。最好将这些信息包含在变量中,以便于查找和修改(如果您愿意,甚至可以从命令行)。 C++ 编译器的标准变量名称是CXX 等。

您的 makefile 应该如下所示:

CXX = g++
CXXFLAGS = -std=c++11
LDLIBS = -lwiringPi

HEADERS = Components/Headers/RumPi.h ./Common.h Components/Headers/Component.h \
    Components/Headers/Vehicle.h Components/Headers/Motor.h Components/Headers/Receiver.h \
    Components/Headers/DualLED.h Components/Headers/LED.h Components/Headers/RGBLED.h \
    Components/Headers/Relay.h 
OBJECTS = RumPi.o Vehicle.o Motor.o Receiver.o DualLED.o LED.o RGBLED.o Relay.o

default: RumPi

RumPi: $(OBJECTS)
        $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@

%.o: Components/Implementations/%.cpp
        $(CXX) $(CXXFLAGS) -c -o $@ $<

$(OBJECTS): $(HEADERS)

clean:
        -rm -f $(OBJECTS)
        -rm -f RumPi

【讨论】:

如何添加需要像 gcc 这样运行的库? 是的,我有一个 RumPi.cpp,是的,它们都存在。我运行了 make-d 并没有帮助,只是说它无法制作 RumPi.o 您将库保存在链接行中(构建可执行文件RumPi 的命令)。但是您应该从编译行(构建目标文件(.o 文件)的命令)中删除它。 如果你运行make -d,它将产生大量的输出,准确地描述 make 是如何考虑构建目标的。其中将做出一系列决定来构建RumPi.o 目标。在这组决策中,将是 make 决定无法构建该目标的原因。您必须查看输出并确定 make 正在寻找但找不到的文件。 我进行了您建议的更改并尝试再次运行它。它看起来更好,但我唯一的问题是“Common.h”。 Common.h 是我用于继承的简单接口,但它没有 Common.cpp,因为它是一个简单的标头。我应该如何在 Makefile 中包含“Components/Headers/Common.h”?

以上是关于使用 WiringPi 的简单 Makefile的主要内容,如果未能解决你的问题,请参考以下文章

wiringPi库的pwm配置及使用说明

树莓派wiringPi库详解

(十三)树莓派3B+ wiringPi库的使用--软件PWM

wiringPi 库下用C控制GPIO

(16)WiringPi库函数

树莓派wiringPi经常使用的函数介绍