我可以让我的 Makefile 自动使 GCC 使用它支持的最新标准吗?
Can I have my Makefile automatically make GCC use the most recent standard it supports?
我的C++03项目需要升级到C++11,我可以保证至少在我想使用的所有GCC中都可以获得对它的实验性支持。
但是,这可能是-std=c++0x
的,也可能是来自较新的 GCC 的实际-std=c++11
。总有一天它会-std=c++14
(当 CentOS 赶上来时......
我怎样才能形成一个 GNU Makefile,根据哪个标志会成功,将"最佳"标志添加到CXXFLAGS
?
我可以说"好吧,我最早使用的 GCC 仍然没有生产就绪的 C++11 支持,所以我应该坚持使用 C++03",但是嗯。
这将选择$(CXX)
编译器支持的最佳选项:
CXX_MODE.42 := -std=c++98
CXX_MODE.43 := $(CXX_MODE.42)
CXX_MODE.44 := $(CXX_MODE.43)
CXX_MODE.45 := $(CXX_MODE.44)
CXX_MODE.46 := -std=c++0x
# Unnecessary, since -std=c++0x still works, but hey why not:
CXX_MODE.47 := -std=c++11
CXX_MODE.48 := $(CXX_MODE.47)
CXX_MODE.49 := $(CXX_MODE.48)
CXX_MODE.5 := -std=c++14
CXX_MODE.6 := $(CXX_MODE.5)
GXX_VERSION := $(shell $(CXX) -dumpversion | awk -F. '$$1<5{print $$1$$2} $$1>=5{print $$1}')
CXX_MODE := $(CXX_MODE.$(GXX_VERSION))
CXXFLAGS += $(CXX_MODE)
为了获得额外的乐趣,您可以根据其他变量在c++
和gnu++
模式之间进行选择:
CXX_MODE.42 := 98
CXX_MODE.43 := $(CXX_MODE.42)
CXX_MODE.44 := $(CXX_MODE.43)
CXX_MODE.45 := $(CXX_MODE.44)
CXX_MODE.46 := 0x
# Unnecessary, since -std=c++0x still works, but hey why not:
CXX_MODE.47 := 11
CXX_MODE.48 := $(CXX_MODE.47)
CXX_MODE.49 := $(CXX_MODE.48)
CXX_MODE.5 := 14
CXX_MODE.6 := $(CXX_MODE.5)
GXX_VERSION := $(shell $(CXX) -dumpversion | awk -F. '$$1<5{print $$1$$2} $$1>=5{print $$1}')
CXX_MODE := $(CXX_MODE.$(GXX_VERSION))
ifneq($(STRICT),)
CXXFLAGS += -std=c++$(CXX_MODE) -pedantic -pedantic-errors
else
CXXFLAGS += -std=gnu++$(CXX_MODE)
endif
不完全是一个答案,因为这不提供自动选择,但我认为无论如何它都很有用。
您可以使用 make 命令行选项来选择所需的内容:
ifeq($(CPP11),Y)
CXXFLAGS+=-std=c++11
endif
ifeq($(CPP14),Y)
CXXFLAGS+=-std=c++14
endif
调用将按以下方式完成:
make <target> CPP11=Y
或
make <target> CPP14=Y
这个话题现在已经很老了,但无论如何我都想提交我的答案,因为它可能会帮助一些有同样问题的人。
我做了一个bash脚本(名为c ++ _latest_version.sh),它尝试从C++23到C++98的所有C++标准,由Makefile调用。
#!/bin/bash
# Some error handling of arguments.
echo "int main(){}" > /tmp/c++_version.cpp
if (( $? != 0 )); then
echo "Cannot create temporary file in /tmp directory." >&2
exit 2
fi
if [[ "$2" == "NO_WIP_STANDARD" ]]; then
cpp_versions=(23 20 17 14 11 03 98)
else
cpp_versions=(23 2b 20 2a 17 1z 14 1y 11 0x 03 98)
fi
for cpp_version in ${cpp_versions[@]}; do
version_flag="-std=c++$cpp_version"
"$1" $version_flag /tmp/c++_version.cpp -o /tmp/c++_version.out &> /dev/null
if (( $? == 0 )); then
echo "-std=c++$cpp_version"
exit 0
fi
done
echo "How in the hell your compiler can't even run c++98 code ?" >&2
exit 3
该脚本称为 './c++_latest_standard.sh [g++ 或 clang++] [NO_WIP_STANDARD]。
然后是制作文件:
# Uncomment this line if encountering compile-related issues with C++2b, C++2a, C++1z, C++1y or C++0x (C++ version is displayed by the Makefile).
# WIP_STANDARD_MODE=NO_WIP_STANDARD
# Comment those two lines if you're using another compiler than g++ and clang++, and don't forget to set yourself the C++ standard you want in CXX_VERSION (or replace it in CXX_FLAGS below).
CXX_VERSION_ERROR = $(shell ./c++_latest_version.sh $(CXX) $(WIP_STANDARD_MODE) 2>&1)
CXX_VERSION = $(shell ./c++_latest_version.sh $(CXX) $(WIP_STANDARD_MODE) 2> /dev/null)
CXXFLAGS += ... $(CXX_VERSION)
# write your compiling stuff here
您应该已经注意到我编写的NO_WIP_STANDARD变量,它用于禁用"正在进行中"标准,例如部分实现的 C++23 的 c++2b,因为它可能会导致编译问题。在我的机器(Arch Linux)上,我在使用clang++时遇到了问题,使用C++2b编译OpenGL(cmath标头存在潜在问题,可能兼容性设置不正确)。
如果有人希望我发布整个 bash 脚本,我可以做到(到目前为止还没有只发布绝对必要的内容。
我也同意每个编译器都应该有一个标志来编译最新的标准,而不是诉诸测试每个标志等不优雅的技巧,直到找到最新的标志。如果有人考虑改进,我愿意接受您的建议。希望我帮助:)
- 编译时未启用intel oneApi CUDA支持
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 使用CMake检测支持的C++标准
- 为什么istream不支持右值提取
- 当我编译webrtc服务器时,Windows上只支持clang-cl
- 扩展光电二极管探测器以支持多个传感器
- MSVC是否支持C++11样式的属性而不是__declspec
- 在使用GPU支持编译Tensorflow时,会遇到CUDA_TOOLKIT_PATH未绑定变量
- 当使用比格式支持的精度更高的精度来显示数字时,会写出什么数据
- 原子读取是否保证读取最新值
- 错误:(-210:不支持的格式或格式组合)功能'create'中的硬件视频解码器不支持视频源
- 哪个C++规范开始支持 std::vector
- 如何检测VS C++编译器是否支持C++11?
- CertGetCertificateChain 具有支持的内存存储和证书信任列表
- Casablanca/cpprestsdk listener.support接受函数,但不支持方法
- 将 IPv6 支持添加到雨量计
- 为什么C++不支持对未初始化变量进行智能分析?
- 最新的英特尔c++编译器是否支持隐式移动构造函数和移动赋值
- Mingw构建具有最新标准支持
- 我可以让我的 Makefile 自动使 GCC 使用它支持的最新标准吗?