你如何为 clang 和 gcc 编写一个 makefile?
Posted
技术标签:
【中文标题】你如何为 clang 和 gcc 编写一个 makefile?【英文标题】:How do you write a makefile for both clang and gcc? 【发布时间】:2018-11-29 04:08:27 【问题描述】:我想在我的代码中使用 std::experimental::filesystem
,这需要我使用带有 GCC 的 -lstdc++fs
和带有 Clang 的 -lc++experimental
进行编译。目前我有一个 makefile
和 makefile.clang
反映编译的差异,或者我考虑过使用 clang 构建目标,以便我可以运行 build clang
。
是否有一些规范的方法可以在 makefile 中设置特定于编译器的标志?
【问题讨论】:
无关:您应该可以通过升级到支持 C++17 的编译器来避免这种情况 你能发布你当前使用的makefile吗? 假设您使用 GNU Make(或一些兼容的make
程序),您可以使用 conditions 设置某些标志。或者您可以使用另一个构建系统来为您生成正确的 makefile。
请edit您的问题提供有用的附加文本信息(作为文本)。
我知道这是旧的,但这个网站对任何寻找答案的人都有帮助:hiltmon.com/blog/2015/09/28/… ...我已经使用这种方法很长时间没有问题
【参考方案1】:
您可以使用 CMake 来实现。如果您想拥有可移植的代码,最好使用它。
CMake 允许生成适合您系统的 Makefile(例如您的系统默认编译器)。 CMake 有很多功能对于检查实际系统配置非常有用。
在这个答案中,您有示例:In cmake, how can I test if the compiler is Clang?
一个可靠的检查是使用 CMAKE__COMPILER_ID 变量。例如,检查 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()
如果你仍然想使用 Makefile,你应该检查这个答案:https://***.com/a/2826178/7042963
【讨论】:
【参考方案2】:正如用户“一些程序员老兄”所提到的,GNU make 中有conditionals。您可以通过这种方式轻松检查编译器版本:
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++ test
或make CXX=clang test
对其进行编译,它应该将适当的标志传递给每个编译器。
#include <iostream>
int main()
std::cout << "Hello World " << MESSAGE << std::endl;
return 0;
【讨论】:
我会接受这个作为答案,因为它可能是你只使用 make 时能得到的最接近的东西。它存在别名问题,例如 MacOS 将g++
别名为 clang
,而像 g++-7
这样的版本化编译器可能无法正常工作。【参考方案3】:
为了处理版本化编译器,就像您在接受答案的评论中提到的那样,您需要使用 $(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
这里需要注意的是,您不能使用$(findstring g++,$(CXX))
,因为它会无意中匹配clang++
。
更精确地处理事情的更深入的替代方法是:
# 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
【讨论】:
以上是关于你如何为 clang 和 gcc 编写一个 makefile?的主要内容,如果未能解决你的问题,请参考以下文章
你如何为 getInitialProps 编写 Jest 测试?
用于解释自定义 c++11 属性的 Clang/GCC 插件