用于构建 main.c 和 main.cpp 的单个 Makefile

Posted

技术标签:

【中文标题】用于构建 main.c 和 main.cpp 的单个 Makefile【英文标题】:Single Makefile to build both main.c and main.cpp 【发布时间】:2018-07-15 03:31:28 【问题描述】:

我想make main-cmain.c 构建main-c

make main-cppmain.cpp 构建main-cpp

我有,都在同一个文件夹中:

main.c:

#include <stdio.h>

int main(int argc, char const *argv[]) 
    printf("This ic C\n");

main.cpp:

#include <iostream>

int main(int argc, char const *argv[]) 
    std::cout << "This is C++" << std::endl;

Makefile:

CFLAGS   = -std=gnu11

CXXFLAGS = -std=gnu++11 

CPPFLAGS = -g -Wall -O3
LDFLAGS  = 
LDLIBS   =  
OBJS     = main.o 

APP-C    = main-c
APP-CPP  = main-cpp

default:
    echo "Check README.txt"

main-c: $(OBJS)
    $(CC) $^ $(LDLIBS) -o $@

main-cpp: $(OBJS)
    $(CXX) $^ $(LDLIBS) -o $@

clean:
    -rm -Rf *.o 

distclean: clean
    -rm -Rf $(APP-C) $(APP-CPP) 

所以:

$ make main-c
cc -std=gnu11 -g -Wall -O3  -c -o main.o main.c
cc main.o  -o main-c

但是(也从 .c 构建):

$ make main-cpp
cc -std=gnu11 -g -Wall -O3  -c -o main.o main.c
c++ main.o  -o main-cpp

我期待 make main-cpp 使用 $(CXX) $^ $(LDLIBS) -o $@ 并从 .cpp 构建。我错过了什么?

【问题讨论】:

不要折磨自己。将源文件重命名为具有唯一 root 名称的文件(例如)main-cpp.cppmain-c.c 并相应地调整依赖关系(例如:main-cpp: main-cpp.omain-c: main-c.o)。或者明确说明所有规则(根据 vu1p3n0x)。但是,即使你可以让它工作,IMO 将 main.cmain.cpp 放在同一个目录中也会让人类和 make 感到困惑,如果可能的话应该避免 make main-cpp --debug 将帮助您了解正在发生的事情。 【参考方案1】:

我希望 make main-cpp 使用 $(CXX) $^ $(LDLIBS) -o $@ 并从 .cpp 构建。

是的。 make main-cpp --debug 将帮助您了解正在发生的事情。

问题是您依赖默认规则来生成main-cppmain-c 目标所需的main.o,但是当调用make-cpp 目标时您需要不同的构建。在这种情况下,您需要定义不同的非默认规则来构建 .o 文件。如果您只是让make-cppmain-c 依赖于具有不同名称的.o,这是最简单的。由于它们是不同的版本,因此无论如何它们都应该具有不同的名称:

CFLAGS   = -std=gnu11
CXXFLAGS = -std=gnu++11 
CPPFLAGS = -g -Wall -O3
LDFLAGS  = 
LDLIBS   =  
APP-C   = main-c
APP-CPP  = main-cpp

default:
    echo "Check README.txt"

main-c: %:%.o
    $(CC) $^ $(LDLIBS) -o $@

main-cpp: %:%.o
    $(CXX) $^ $(LDLIBS) -o $@

main-cpp.o: main.cpp
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $? -o $@

main-c.o: main.c
    $(CC) $(CPPFLAGS) $(CFLAGS) -c $? -o $@

clean:
    -rm -Rf *.o 

distclean: clean
    -rm -Rf $(APP-C) $(APP-CPP)

【讨论】:

%%:%是什么意思? 这是一个static pattern rule。在这里使用它没有多大意义,因为它只是一个目标。在上述情况下,它仅等同于main-c: main-c.o @spinkus:我可以建议您从答案中删除静态模式规则吗?它们在这里不需要,并且使您的提案难以理解。 @RenaudPacalet 看过一次就很容易理解。知道以后何时更新脚本的有用速记。示例您可以只在两个链接目标中使用 g++ 并合并为一个规则,因为它只是链接。【参考方案2】:

main-cmain-cpp 这两个规则都需要创建 main.o 才能完成,但您没有创建 main.o 的规则。

您正在使用make's implicit object file creation,这是用于从源文件创建“.o”文件的内置规则。它可以使用“.c”或“.cpp/cc/C”文件,并将使用适当的变量进行构建。但是,由于您同时拥有main.cmain.cpp,因此看起来它默认使用C 版本。

您可能需要为每个规则创建明确的规则(并且可能使用不同的名称)。

【讨论】:

以上是关于用于构建 main.c 和 main.cpp 的单个 Makefile的主要内容,如果未能解决你的问题,请参考以下文章

C/C++语言中,如何在main.c或main.cpp中调用另一个.c文件

来自 Qt 中 main.cpp 代码的 MainWindow

如何将 automake 文件写入递归构建子目录?

Cmake实现样例

用于 MongoDB 的单例

C++ 的 main.cpp 中的结构声明问题