多平台C ++项目:包含特定于平台的源

时间:2009-07-09 18:42:44

标签: c++ build cmake multiplatform

我的一些课程每个操作系统都有不同的实现 我的源结构是这样的:

  • 包括/ AExample.h
  • 包括/窗/ WindowsExample.h
  • 在include / linux / LinuxExample.h
  • 的src / AExample.cpp
  • 的src /窗/ WindowsExample.cpp
  • src / linux中/ LinuxExample.cpp

A *类是特定实现的接口

我当前的构建系统是cmake - 但目前它只能构建linux版本。

在windows build中,我只需要包含windows / *文件,而只需要在linux上包含linux / *文件

我需要

  • 仅包含与我当前版本相关的文件
  • 当我需要AExample实例
  • 时选择正确的实现

您可以推荐哪些技术以专业的方式实现这一目标?

3 个答案:

答案 0 :(得分:7)

这在CMake中相当容易。

让你的CMakeLists.txt文件检查平台,并根据需要添加适当的文件或包含相应的子目录。

基本语法是:

IF(WIN32)
    # Do windows specific includes
ELSEIF(UNIX)
    # Do linux specific includes
ENDIF(WIN32)

答案 1 :(得分:2)

如果标头具有相同的名称但它们位于不同的层次结构中,则只需为编译器正确设置-I(包含路径)标志即可。这比单独处理所有平台相关包括容易得多。

如果标题位于同一目录中和/或您想要自定义内容,则通常在C / C ++代码中执行此操作:

#ifdef _WIN32
  .. include Win headers ..
#endif

#ifdef LINUX
  .. include Linux headers ...
#endif

除非您确定以后不需要切换构建系统,否则我不推荐使用cmake特定的解决方案。

答案 2 :(得分:0)

虽然我认为使用构建系统来处理跨平台文件是最好的,但是可以简单地编写源代码来通过预处理器来处理它。然而,这种非常常见,快速和脏的方法,在整个代码中进行平台检查是有问题的,应该避免。

相反,您应该使用更高结构化的方法来组织特定于平台的代码,以避免在项目变大时出现问题。

应在文件级别清楚地标识特定于平台的代码:例如,使用包含每个平台目录的目录结构,并将所有特定于平台的源文件放在相应的目录中。源文件不应包含多个平台的代码或任何预处理器平台检查(但有一个例外)。此外,通常不应直接构建平台特定源或#include d。相反,平台特定代码应该仅通过非平台特定源文件间接使用,这些源文件除了平台检查和平台特定文件的#include之外什么都不包含。

示例源组织:

src/
  main.cpp
  foo.h
  foo.cpp
  windows/
    foo.cpp.inc
  posix/
    foo.cpp.inc

示例源内容:

// main.cpp
#include "foo.h"

int main() {
  foo();
}

// foo.h
void foo();

// foo.cpp
#if defined(_WIN32)
#  include "windows/foo.cpp.inc"
#elif __has_include(<unistd.h>)
#  include<unistd.h>
#  if defined(_POSIX_VERSION)
#    include "posix/foo.cpp.inc"
#  endif
#else
#  error Unknown platform
#endif

// windows/foo.cpp.inc
#include "foo.h"

#include <iostream>
#include <Windows.h>

void foo() {
  std::cout << "Windows\n";
}

// posix/foo.cpp.inc
#include "foo.h"

#include <iostream>
#include <unistd.h>

void foo() {
  std::cout << "POSIX\n";
}

Windows构建和输出:

cl.exe /EHsc /W4 /WX src\main.cpp src\foo.cpp
main

  

Linux构建和输出:

g++ -Wall -Wextra -Werror -Isrc src/main.cpp src/foo.cpp
./a.out

  

POSIX

当不同平台的代码可以合理地共享同一文件组织时,上面示例中显示的方法非常有效。如果不同平台的代码足够不同以至于您希望每个平台都有不同的文件结构,那么使用这种技术会更加困难,并且转而使用构建系统来管理不同平台的代码变得更加清晰优异。

也可以将此技术与构建系统混合使用;跨平台共享文件结构的代码可以使用它,而构建系统可以处理不同平台独有的模块。