简体   繁体   English

你如何为 clang 和 gcc 编写一个 makefile?

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

I would like to use std::experimental::filesystem in my code, this requires me to compile using -lstdc++fs with GCC and -lc++experimental with Clang.我想在我的代码中使用std::experimental::filesystem ,这需要我使用带有 GCC 的-lstdc++fs和带有 Clang 的-lc++experimental进行编译。 At the moment I have a makefile and makefile.clang reflecting the difference in compilation, alternatively I've thought about using a clang build target so I can run build clang .目前我有一个makefilemakefile.clang反映了编译的差异,或者我考虑过使用 clang 构建目标,这样我就可以运行build clang

Is there some canonical way to set compiler-specific flags in a makefile?是否有一些规范的方法可以在生成文件中设置特定于编译器的标志?

As the user "Some programmer dude" mentioned, there areconditionals in GNU make.正如用户“一些程序员老兄”所提到的,GNU make 中有条件 You could easily check for the compiler version this way:您可以通过这种方式轻松检查编译器版本:

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

Given the following source file test.cpp you can compile it with make CXX=g++ test or make CXX=clang test and it should pass the appropriate flags to each compiler.给定以下源文件test.cpp ,您可以使用make CXX=g++ testmake CXX=clang test编译它,它应该将适当的标志传递给每个编译器。

#include <iostream>

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

You can use CMake to achieve that.您可以使用 CMake 来实现这一点。 It is a better to use if you want to have portable code.如果您想拥有可移植的代码,最好使用它。

CMake allows to generate Makefile that is appropriate for your system(eg your system default compiler). CMake 允许生成适合您系统的 Makefile(例如您的系统默认编译器)。 CMake has a lot of features that can be very useful to check actual system configuration. CMake 有很多功能对于检查实际系统配置非常有用。

In this answer, you have example how do that: In cmake, how can I test if the compiler is Clang?在这个答案中,您有示例如何做到这一点: 在 cmake 中,我如何测试编译器是否是 Clang?

A reliable check is to use the CMAKE__COMPILER_ID variables.一个可靠的检查是使用 CMAKE__COMPILER_ID 变量。 Eg, to check the C++ compiler:例如,检查 C++ 编译器:

 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()

If you still want to use Makefile you should check this answer: https://stackoverflow.com/a/2826178/7042963如果您仍想使用 Makefile,您应该检查此答案: https ://stackoverflow.com/a/2826178/7042963

In order to handle versioned compilers, like you mentioned in the comment to the accepted answer, you need to use $(findstring find,in) as such:为了处理版本化编译器,就像您在接受答案的评论中提到的那样,您需要使用$(findstring find,in)

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

The caveat here is that you cannot use $(findstring g++,$(CXX)) since it'll match clang++ unintentionally.这里需要注意的是,您不能使用$(findstring g++,$(CXX))因为它会无意中匹配clang++

A more in-depth alternative to handle things more precisely would be:更精确地处理事情的更深入的替代方法是:

# 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

This approach parses the compiler's version string looking for clang .这种方法解析编译器的版本字符串以寻找clang If it doesn't find clang then it looks for g++ in order to resolve an issue with macOS, where g++ is aliased to clang .如果它没有找到clang ,那么它会寻找g++以解决 macOS 的问题,其中g++别名为clang

# Set compiler-specific flags
GCC_CXXFLAGS = -DMESSAGE='"Compiled with GCC"'
CLANG_CXXFLAGS = -DMESSAGE='"Compiled with Clang"'
UNKNOWN_CXXFLAGS = -DMESSAGE='"Compiled with an unknown compiler"'

# Detect if CXX is clang++ or g++, in this order.
COMPILER_VERSION := $(shell $(CXX) --version)
ifneq '' '$(findstring clang,$(COMPILER_VERSION))'
  CFLAGS += $(CLANG_CXXFLAGS)
else ifneq '' '$(findstring g++,$(COMPILER_VERSION))'
  CFLAGS += $(GCC_CXXFLAGS)
else
  $(warning Unknown compiler)
  CFLAGS += $(UNKNOWN_CXXFLAGS)
endif

Credit to @bit2shift's answer, which inspired this one.感谢@bit2shift 的回答,它启发了这个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM