2009-07-09 16 views
1

OSごとに異なるクラスを実装しています。
私のソース構造は、このようなものです:マルチプラットフォームC++プロジェクト:プラットフォーム固有のソースの追加

  • /窓/ WindowsExample.h
  • は/ Linuxの/ LinuxExample.h
  • のsrc/AExample.cpp
  • を含ん含ま/ AExample.h
  • が含まれます
  • のsrc /窓/ WindowsExample.cpp
  • のsrc/linuxの/ LinuxExample.cpp

Aクラスは特定の実装のインターフェイスです

私の現在のビルドシステムはcmakeですが、現時点ではlinuxバージョンしか構築できません。 Windowsで

私は

  • する必要がある唯一のLinux/*ファイル

    は私の現在のために関連するファイルのみが含まれ、私は唯一の窓/ *ファイルをインクルードする必要が構築し、Linux上で

  • を構築し、私はあなたがプロの方法でこれを実現するためにお勧めすることができますどのような技術AExample

のインスタンスを必要なときに右の実装を選ぶのか?

答えて

7

これはCMakeではかなり簡単です。

CMakeLists.txtファイルでプラットフォームを確認して、適切なファイルを追加するか、必要に応じて適切なサブディレクトリを追加してください。

基本的な構文は次のとおりです。

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

ヘッダが同じ名前を持っていますが、それらは異なる階層に存在する場合、あなたは自分のコンパイラで正しく-I(インクルードパス)フラグを設定することができます。これは、プラットフォームに依存するインクルードを個別に処理するよりはるかに簡単です。

ヘッダが同じディレクトリに存在および/またはあなたがものをカスタマイズしたい場合は、通常、これはあなたのC/C++コードにないでしょう:

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

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

私がない限り、cmakeの具体的なソリューションをお勧めしません後でビルドシステムを切り替える必要はありません。

+1

これは、ビルドに異なるソースファイルを含めることはできません。通常、CMakeを使用すると適切に設定されますが、プラットフォーム固有のソースファイルも含めることができます。それは最初の場所でcmakeを使う理由の一つです。 –

+0

これは簡単で小さなプロジェクトではうまくいくが、プロジェクトが大きくなると問題になるテクニックの1つです。 _大規模なC++ソフトウェアDesign_では、ソース全体にプラットフォームチェックを振りかけることを推奨しています。私は、プラットフォーム固有のコードを管理するビルドシステムを使用することが最善だと思いますが、ソース自体でそれを行う場合は、より高度に構造化された組織を使用することをお勧めします(http://stackoverflow.com/a/31304341/365496 )。 – bames53

0

クロスプラットフォームファイルを処理するためにビルドシステムを使用するのが最善の方法ですが、ソースを記述してプリプロセッサで処理することは可能です。しかし、コード全体にプラットフォームチェックを振りかける、非常に一般的で迅速で汚い方法では問題があり、避けるべきです。

代わりに、プロジェクトが大きくなるにつれて問題を避けるために、プラットフォーム固有のコードを整理する、より高度に構造化された方法を使用する必要があります。

プラットフォーム固有のコードは、ファイルレベルで明確に識別する必要があります。たとえば、各プラットフォーム用のディレクトリを含むディレクトリ構造を使用し、すべてのプラットフォーム固有のソースファイルを適切なディレクトリに置きます。ソースファイルには、複数のプラットフォームのコードやプリプロセッサのプラットフォームチェック(ただし例外が1つあります)が含まれているべきではありません。さらに、プラットフォーム固有のソースは、一般的には直接作成しないでください。#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

のWindows

のLinuxのビルドおよび出力:

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

POSIX

上記の例の方法は、異なるプラットフォームのコードが同じファイル構成を合理的に共有できる場合に非常に効果的です。異なるプラットフォームのコードが異なるため、各プラットフォームのファイル構造が異なる場合は、この手法を使用するのが難しくなり、ビルドシステムを使用して異なるプラットフォームのコードを管理する方がより明確に優れています。

ビルドシステムを使用してこの手法を混在させることもできます。プラットフォーム間でファイル構造を共有するコードはこれを使用できますが、異なるプラットフォームに固有のモジュールはビルドシステムで処理できます。

関連する問題