在 Windows 和 Linux 上编译 C++:ifdef 开关 [重复]

Posted

技术标签:

【中文标题】在 Windows 和 Linux 上编译 C++:ifdef 开关 [重复]【英文标题】:C++ compiling on Windows and Linux: ifdef switch [duplicate] 【发布时间】:2011-10-02 18:11:21 【问题描述】:

我想在 Linux 和 Windows 上运行一些 c++ 代码。我只想为一个操作系统而不是另一个操作系统包含一些代码。有没有一个标准的#ifdef 曾经可以使用?

类似:

  #ifdef LINUX_KEY_WORD
    ... // linux code goes here.
  #elif WINDOWS_KEY_WORD
    ... // windows code goes here.
  #else 
  #error "OS not supported!"
  #endif

这个问题确实是重复的,但这里的答案要好得多,尤其是接受的那个。

【问题讨论】:

@MooingDuck:我确认我想决定目标操作系统,而不是使用的编译器。 How to detect reliably Mac OS X, ios, Linux, Windows in C preprocessor?, Detect Windows or Linux in C, C++ 【参考方案1】:

你可以这样做:

#if MACRO0
    //code...
#elif MACRO1
    //code...
#endif

…标识符可以是:

    __linux__       Defined on Linux
    __sun           Defined on Solaris
    __FreeBSD__     Defined on FreeBSD
    __NetBSD__      Defined on NetBSD
    __OpenBSD__     Defined on OpenBSD
    __APPLE__       Defined on Mac OS X
    __hpux          Defined on HP-UX
    __osf__         Defined on Tru64 UNIX (formerly DEC OSF1)
    __sgi           Defined on Irix
    _AIX            Defined on AIX
    _WIN32          Defined on Windows

【讨论】:

【参考方案2】:

我知道这不是答案,但如果有人在 Qt 中看起来相同,则添加

在 Qt 中

https://wiki.qt.io/Get-OS-name-in-Qt

QString Get::osName()

#if defined(Q_OS_android)
    return QLatin1String("android");
#elif defined(Q_OS_BLACKBERRY)
    return QLatin1String("blackberry");
#elif defined(Q_OS_IOS)
    return QLatin1String("ios");
#elif defined(Q_OS_MAC)
    return QLatin1String("osx");
#elif defined(Q_OS_WINCE)
    return QLatin1String("wince");
#elif defined(Q_OS_WIN)
    return QLatin1String("windows");
#elif defined(Q_OS_LINUX)
    return QLatin1String("linux");
#elif defined(Q_OS_UNIX)
    return QLatin1String("unix");
#else
    return QLatin1String("unknown");
#endif

【讨论】:

【参考方案3】:

此响应与宏战争无关,但如果找不到匹配的平台,则会产生错误。

#ifdef LINUX_KEY_WORD   
... // linux code goes here.  
#elif WINDOWS_KEY_WORD    
... // windows code goes here.  
#else     
#error Platform not supported
#endif

如果不支持#error,您可以使用static_assert (C++0x) 关键字。或者您可以实现自定义 STATIC_ASSERT,或者只声明一个大小为 0 的数组,或者使用具有重复案例的开关。简而言之,在编译时而不是在运行时

产生错误

【讨论】:

#error 必须被支持(不像#warning是一个扩展)。但我同意这不一定是构建失败的最佳方式。 @Thomas:确实。幸运的是,如果 #error 在某些不兼容的实现中不受支持,那么不正确的预处理器语句的结果就是,嗯 --- 一个错误。如果它也不是一个错误,那么编译器就是一个REALLY REALLY蹩脚的编译器,无论如何都不值得支持(尽管我高度怀疑这样的编译器是否存在)。【参考方案4】:

这取决于使用的编译器。

例如,Windows 的定义可以是WIN32_WIN32

Linux 的定义可以是UNIX__unix__LINUX__linux__

【讨论】:

有这样一个标准。那些不遵守它的工具链,要么是错误的,要么是石器时代的,要么就是坏的。 WIN32Windows.h 内部定义。因此,如果不包含标头,则类型开关将不起作用。 _WIN32 应该默认定义。【参考方案5】:

不,这些定义取决于编译器。您可以做什么,使用您自己的一组定义,并将它们设置在 Makefile 上。请参阅this thread 了解更多信息。

【讨论】:

正确,但没有帮助 @Cicada:当所有编译器(值得讨论)都做同样的事情时,依赖编译器就没有意义了。 然而,没有标准来定义这个,而这正是他所要求的。我正在更新答案以将其指向有关此问题的有用参考 我很高兴您建议使用 makefile 作为“编译器依赖”定义的替代方案。与使用 makefile 相比,更多的编译器使用相同的定义。 编译器不使用makefile,makefile使用编译器。【参考方案6】:

这取决于编译器。如果您在 Linux 上使用 G++ 和在 Windows 上使用 VC++ 进行编译,则可以这样做:

#ifdef linux
    ...
#elif _WIN32
    ...
#else
    ...
#endif

【讨论】:

这总是会的。所有编译器都以相同的方式实现这一点。 linux 上的 Clang 模仿 GCC,Windows 上的 Clang 和 GCC 模仿 MSVC。 @rubenvb:所有现有编译器,方便。这种行为不是标准化的,对于一些没人使用的编译器来说也可能有所不同。【参考方案7】:

使用:

#ifdef __linux__ 
    //linux code goes here
#elif _WIN32
    // windows code goes here
#else

#endif

【讨论】:

以上是关于在 Windows 和 Linux 上编译 C++:ifdef 开关 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

C++/LapackE 代码在 Windows 上编译良好,但相同的代码在 Linux 上编译失败

在 Windows 上编译+分发 Linux 代码

使用 cmake 在 windows 上编译 c++ 数据库时出错

在 Linux 服务器上编译 C++ 程序时 Intel 编译器的语法

Linux 和 Windows 上编译 proj.4 库

Linux 和 Windows 上编译 proj.4 库