如何通过预处理宏来识别平台/编译器?

128

我正在编写一个跨平台的代码,它应该可以在Linux、Windows和Mac OS上编译。在Windows上,我必须支持Visual Studio和MinGW。

有些平台特定的代码,我需要将其放置在#ifdef .. #endif的环境下。例如,在这里我放置了Win32特定的代码:

#ifdef WIN32
#include <windows.h>
#endif

但是我该如何识别Linux和macOS? 我应该使用哪些定义名称(或其他内容)?


4
这里是操作系统宏定义列表 - OCaml
这个问题有一个更好被接受的答案。 - rubenvb
1
建议的重复问题不是相同的问题。那个问题只是问如何识别操作系统,而这个问题还问如何识别编译器,这是两个非常不同的事情。 - JBentley
1
@rubenvb 然后将另一个问题链接作为评论。仅仅因为它有一个更好的答案,并不意味着它是重复的。问题是什么决定了它是否是重复的,而不是答案。关闭这个问题只会确保我们永远不会得到一个关于编译器相关部分的高质量答案,而所谓的“重复”永远无法回答。 - JBentley
你应该使用_WIN32而不是WIN32。https://dev59.com/62ox5IYBdhLWcg3wtmY1 - Melebius
显示剩余4条评论
4个回答

148

对于 Mac OS

#ifdef __APPLE__

对于 Windows 上的 MingW

#ifdef __MINGW32__

对于Linux

#ifdef __linux__

对于其他的Windows编译器,请查看此线程以及此处,了解其他编译器和架构的信息。


3
__APPLE__ 是否区分 macOS 和 iOS? - gman
15
__APPLE__ 适用于 OS X 和 iOS。您可以在 #ifdef __APPLE__ 中包含 <TargetConditionals.h>,然后您就可以使用 TARGET_OS_IPHONE #define - Ted Mielczarek
2
当使用mingw64时,也可以使用__MINGW64__。 - scones
2
由于引用了 __MINGW64__,因此认为在 Windows/MSVC 中提及 _MSC_VER 值得一提(它也可以用于检查 MSVC 版本)。 - ideasman42
很抱歉,但这个答案在所有方面都是错误的,甚至没有回答问题。 - rubenvb
__MINGW64__ 并非 MinGW-w64 作者所认可的,相反,您应该检查是否定义了 __MINGW32__#include <_mingw.h>,并检查 __MINGW64_VERSION_MAJOR - rubenvb

66

6
从1.55版本开始,Predef已经被纳入Boost C++ Libraries - rvalue
我知道你发帖时的规则与现在不同,但我必须要求你编辑这篇帖子并包含更多相关细节。现在链接回答将被强烈反对,我想给你在删除之前保存这篇帖子的机会。 - Mick MacCallum
1
由于这是唯一一个实际回答标题中所述问题的答案,而且问题非常通用和相关,我强烈建议不要删除它。我也不会称其为“仅链接”答案。 - hobb
3
@0x7fffffff: 将其他答案的内容复制到这个答案中,对任何人都有什么可能的好处呢?如果你认为拥有一个单一的确定性答案真的很重要,那么也许你应该自己创建这样的答案(这并不难:只需要以某种合理的顺序将现有的答案粘合在一起即可)。就我个人而言,我有更好的事情可做,但作为一个管理员,显然SO对你来说比对我更重要。 - John Bartholomew

49

这是我使用的:

#ifdef _WIN32 // note the underscore: without it, it's not msdn official!
    // Windows (x64 and x86)
#elif __unix__ // all unices, not all compilers
    // Unix
#elif __linux__
    // linux
#elif __APPLE__
    // Mac OS, not sure if this is covered by __posix__ and/or __unix__ though...
#endif

编辑:尽管上述方法可能适用于基础操作,但请记住通过查看Boost.Predef参考页面来验证您要检查的宏。或者直接使用Boost.Predef。


4
请使用 __linux__,当使用GCC编译时,如果禁用了GNU扩展(例如 -std=c++0x),则无法定义Linux。 - Erbureth
1
@Erbureth 已修复,但是最好使用 predef.sourceforge.net/index.php,这是最高评分答案中提到的。 - rubenvb
@rubenvb:确实。而且我认为它的投票数还太少了 :) … 我已经多次访问过他们的网站了。 - 0xC0000022L
为了保持一致性(也许有点追求完美):第一个 #if 询问是否定义,其他的则测试值。我认为如果使用 #elif defined(__unix__) 等方式会更加一致。 - leonbloy

23

如果您正在编写C ++,我强烈建议使用Boost库。

最新版本(1.55)包括一个新的Predef库,它涵盖了您所需要的内容,以及数十个其他平台和架构识别宏。

#include <boost/predef.h>

// ...

#if BOOST_OS_WINDOWS

#elif BOOST_OS_LINUX

#elif BOOST_OS_MACOS

#endif

鉴于这是boost,此解决方案将适用于不同的平台/操作系统和不同的编译器。 - Trevor Boyd Smith
5
我强烈不建议使用Boost库......我已经评估过Boost三次。它不能通过评估......大多数错误报告如果能得到认可就算是幸运的了。缺乏认可指向工程流程中更深层次的问题。我相信预处理宏和内置的C++标准库是更安全的选择。 - jww

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接