【问题标题】:Search for all .c and .cpp files and compiling them in one makefile搜索所有 .c 和 .cpp 文件并将它们编译到一个 makefile 中
【发布时间】:2020-02-20 22:48:37
【问题描述】:

我正在尝试创建一个 makefile,它将查找所有现有的 .c 和 .cpp 文件然后编译它们。

我以How to place object files in separate subdirectory 为模板,并将其与How to make a makefile for C and C++, with sources in subdirectories 结合使用。假设我已经定义了所有变量(我只是将它们排除在外,因为它们是不必要的)。

我不断收到的错误是make: *** No rule to make target 'obj/<randoCfile>.c', needed by '<target>'. Stop.

SOURCES := $(call rwildcard,$(SRCDIR),*.c)
SOURCES += $(call rwildcard,$(SRCDIR),*.cpp)
OBJECTS     := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:%.c=%.c.o))
OBJECTS     += $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:%.cpp=%.cpp.o))

#Default Make
all: $(TARGET)

#Remake
remake: cleaner all

#Make the Directories
directories:
    @mkdir -p $(TARGETDIR)
    @mkdir -p $(BUILDDIR)

#Clean only Objecst
clean:
    @$(RM) -rf $(BUILDDIR)

#Full Clean, Objects and Binaries
cleaner: clean
    @$(RM) -rf $(TARGETDIR)

#Link
$(TARGET): $(OBJECTS)
    $(CC) -o $(TARGETDIR)/$(TARGET) $^ $(LIB)

$(BUILDDIR)/%.c.o:
    $(CC) $(INC) $(CFLAGS) -c -o $@ $<

$(BUILDDIR)/%.cpp.o:
    $(CXX) $(INC) $(CXXFLAGS) -c -o $@ $<

#Non-File Targets
.PHONY: all remake clean cleaner resources

关于如何解决我的问题有什么建议吗? 我在 Windows 上运行(这就是为什么我使用通配符而不是我发现的一个示例中的 shell(find...)

【问题讨论】:

  • 你不能。您必须列出要编译的每个源文件。
  • 你不能按照你的要求去做,因为 make 文件不能使用通配符。花几分钟时间创建一个合适的 makefile - 你可能已经完成了它并在你创建这篇文章所花费的时间内工作。
  • 查看您的规则,您似乎正在为每个源文件制作单独的可执行文件,而不是从所有源文件制作单个可执行文件。如果是这种情况,最简单的解决方案可能是删除 Makefile 并让 make 对所有内容使用默认规则。例如,rm Makefile; make $(basename *.c *.cc | sed 's/\..*$//') 之类的东西应该没问题。它不会将目标文件放在不同的目录中,但它很简单。使用默认规则;他们的存在是为了提供帮助。
  • 真的不清楚你现在的情况。请清楚地说明您拥有哪些文件(以及当前的项目层次结构)以及您希望从这些文件中生成哪些文件。另外,说明你打算如何从命令行调用make
  • 听起来cmake 更有可能更轻松地解决您的任务,您仍然需要生成一个源文件列表。您是否考虑过安装 cygwin 以便拥有像 find 这样的 linux 工具?

标签: c++ c makefile


【解决方案1】:

你有几个问题。最重要的在这里:

SOURCES := $(call rwildcard,$(SRCDIR),*.c)
SOURCES += $(call rwildcard,$(SRCDIR),*.cpp)

假设这导致SOURCES 的值如下:

SOURCES := src/foo.c src/bar/bar.c src/biz/biz.cpp src/boz.cpp

现在OBJECTS 在以下之后会是什么?

OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:%.c=%.c.o))
OBJECTS += $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:%.cpp=%.cpp.o))

它将是(假设BUILDDIRobj):

OBJECTS := obj/foo.c.o obj/bar/bar.c.o obj/biz/biz.cpp obj/boz.cpp \
           obj/foo.c obj/bar/bar.c obj/biz/biz.cpp.o obj/boz.cpp.o

为什么?因为像$(SOURCES:%.c=%.c.o) 这样的翻译不会返回only 匹配模式的单词...它返回ALL 单词,然后翻译只有那些与模式匹配的。

由于您只是将.o 添加到后缀而不是替换后缀,因此您可以将其简化为:

SOURCES := $(call rwildcard,$(SRCDIR),*.c)
SOURCES += $(call rwildcard,$(SRCDIR),*.cpp)

OBJECTS := $(SOURCES:$(SRCDIR)/%=$(BUILDDIR)/%.o))

这个规则也不对:

$(BUILDDIR)/%.c.o:
        $(CC) $(INC) $(CFLAGS) -c -o $@ $<

这里您没有声明任何先决条件。也许你在没有向我们展示的其他地方这样做,但最好是这样:

$(BUILDDIR)/%.c.o: $(SRCDIR)/%.c
        $(CC) $(INC) $(CFLAGS) -c -o $@ $<

当然,.cpp 文件也是如此。

【讨论】:

  • 感谢您采用这种类型进行教学,而不仅仅是批评。实现你在这里所做的和一些其他的小调整让 makefile 完成了我需要的工作!
【解决方案2】:

Make(任何风格)是一个从目标(可执行文件)到源代码的程序,因此您通常从可执行文件(需要构建目标文件列表)开始,而这些对象取决于源代码它们依赖于构建的文件....您正在朝相反的方向思考...搜索源文件,然后朝相反的方向前进。虽然它更具动态性,但它不是 make 的工作方式,因此很可能该解决方案需要使用另一个程序来完成所有工作以编译每个源代码并最终以您可能无法指定的内容结束,并且 make 除了成为在那里执行您的搜索和编译程序。

出于这个原因,Make 的不同风格(例如 gnu make 或 berkely make)已经开发出每种不兼容的方法来尽可能地返回,使用 gnu make 中的函数,并在 berkeley 的情况下具有强大的宏功能制作。只是说这些都不是标准的,并且都需要一些培训才能有效地处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-07
    • 2015-01-16
    • 2012-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    相关资源
    最近更新 更多