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

C++ 多平台C++;项目:包含特定于平台的资源,c++,build,cmake,multiplatform,C++,Build,Cmake,Multiplatform,对于我的一些类,每个操作系统有不同的实现。 我的源结构如下所示: include/AExample.h 包括/windows/WindowsExample.h include/linux/LinuxExample.h src/AExample.cpp src/windows/WindowsExample.cpp src/linux/LinuxExample.cpp A*类是特定实现的接口 我目前的构建系统是cmake,但目前它只能构建linux版本 在windows构建中,我只需要包含win

对于我的一些类,每个操作系统有不同的实现。
我的源结构如下所示:

  • include/AExample.h
  • 包括/windows/WindowsExample.h
  • include/linux/LinuxExample.h
  • src/AExample.cpp
  • src/windows/WindowsExample.cpp
  • src/linux/LinuxExample.cpp
A*类是特定实现的接口

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

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

我需要

  • 仅包括与当前生成相关的文件
  • 当我需要一个AExample实例时,请选择正确的实现

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

这在CMake中相当容易

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

基本语法是:

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

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

如果标题位于同一目录中,并且/或者您希望自定义内容,则通常可以在C/C++代码中执行此操作:

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

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

除非您确定以后不需要切换生成系统,否则我不会推荐特定于cmake的解决方案。

虽然我认为使用生成系统处理跨平台文件是最好的,但可以简单地编写源代码,通过预处理器处理。然而,这种非常常见、快速且肮脏的方法,即在代码中到处散布平台检查,是有问题的,应该避免

相反,您应该使用一种更高度结构化的方法来组织特定于平台的代码,以避免随着项目的扩大而出现问题

特定于平台的代码应该在文件级别明确标识:例如,使用一个目录结构,其中包含每个平台的目录,并将所有特定于平台的源文件放在适当的目录中。源文件不应包含多个平台或任何预处理器平台检查的代码(但有一个例外)。此外,平台特定的源代码通常不应直接构建或包含。相反,平台特定的代码只能通过非平台特定的源文件间接使用,这些源文件除了平台检查和平台特定文件的#includes之外不包含任何内容

示例源组织:

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";
}
//main.cpp
#包括“foo.h”
int main(){
foo();
}
//福安
void foo();
//foo.cpp
#如果已定义(_WIN32)
#包括“windows/foo.cpp.inc”
#elif有一个包含()
#包括
#如果已定义(_POSIX_版本)
#包括“posix/foo.cpp.inc”
#恩迪夫
#否则
#错误未知平台
#恩迪夫
//windows/foo.cpp.inc
#包括“foo.h”
#包括
#包括
void foo(){

std::cout这不能处理在构建中包含不同的源文件的问题。使用CMake通常会适当地进行设置,但也可以包含特定于平台的源文件。这是(许多好的)方法之一首先使用CMAGE的原因。这是一种简单的技术,对于小型项目来说是很好的,但是当项目越来越大时,它会变得有问题。大规模的C++软件设计建议不要在你的源上进行喷洒平台检查。我认为使用构建系统来管理特定于平台的代码是最好的。,但如果您想在源代码本身中执行此操作,则建议使用更多。