关于c ++:你如何为clang和gcc编写一个makefile?

How do you write a makefile for both clang and gcc?

我想在代码中使用std::experimental::filesystem,这要求我使用-lstdc++fs和gcc进行编译,使用-lc++experimental和clang进行编译。目前我有一个makefilemakefile.clang,反映了编译的不同,或者我考虑使用clang构建目标,这样我就可以运行build clang

在makefile中是否有一些设置编译器特定标志的规范方法?


正如用户"某个程序员"所提到的,GNUmake中有一些条件。您可以通过以下方式轻松检查编译器版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
CXXFLAGS = -Og -Wall -Wextra

GCC_CXXFLAGS = -DMESSAGE='"Compiled with GCC"'
CLANG_CXXFLAGS = -DMESSAGE='"Compiled with Clang"'
UNKNOWN_CXXFLAGS = -DMESSAGE='"Compiled with an unknown compiler"'

ifeq ($(CXX),g++)
  CXXFLAGS += $(GCC_CXXFLAGS)
else ifeq ($(CXX),clang)
  CXXFLAGS += $(CLANG_CXXFLAGS)
else
  CXXFLAGS += $(UNKNOWN_CXXFLAGS)
endif

给定以下源文件test.cpp,您可以使用make CXX=g++ testmake CXX=clang test编译它,它应该向每个编译器传递适当的标志。

1
2
3
4
5
6
#include <iostream>

int main() {
  std::cout <<"Hello World" << MESSAGE << std::endl;
  return 0;
}


您可以使用cmake来实现这一点。如果您想拥有可移植代码,最好使用它。

cmake允许生成适合您的系统的makefile(例如,系统默认编译器)。CMAKE有许多特性,对于检查实际的系统配置非常有用。

在这个答案中,您有这样一个例子:在cmake中,如何测试编译器是否发出clang?

A reliable check is to use the CMAKE__COMPILER_ID variables. E.g., to check the C++ compiler:

1
2
3
4
5
6
7
8
9
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL"Clang")
  # using Clang
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL"GNU")
  # using GCC
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL"Intel")
  # using Intel C++
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL"MSVC")
  # using Visual Studio C++
endif()

如果仍要使用makefile,请检查以下答案:https://stackoverflow.com/a/2826178/7042963


为了处理版本化编译器,如您在接受答案的注释中提到的,您需要使用$(findstring find,in),如下所示:

1
2
3
4
5
6
# Detect if CXX is g++ or clang++, in this order.
ifeq '' '$(findstring clang++,$(CXX))'
  LDLIBS = -lstdc++fs
else
  LDLIBS = -lc++experimental
endif

这里要注意的是,您不能使用$(findstring g++,$(CXX)),因为它会无意中与clang++匹配。

更深入地处理事情的另一个选择是:

1
2
3
4
5
6
# Detect if CXX is clang++ or g++, in this order.
ifneq '' '$(findstring clang++,$(CXX))'
  LDLIBS = -lc++experimental
else ifneq '' '$(findstring g++,$(CXX))'
  LDLIBS = -lstdc++fs
endif