クロスプラットフォームファイルを処理するためにビルドシステムを使用するのが最善の方法ですが、ソースを記述してプリプロセッサで処理することは可能です。しかし、コード全体にプラットフォームチェックを振りかける、非常に一般的で迅速で汚い方法では問題があり、避けるべきです。
代わりに、プロジェクトが大きくなるにつれて問題を避けるために、プラットフォーム固有のコードを整理する、より高度に構造化された方法を使用する必要があります。
プラットフォーム固有のコードは、ファイルレベルで明確に識別する必要があります。たとえば、各プラットフォーム用のディレクトリを含むディレクトリ構造を使用し、すべてのプラットフォーム固有のソースファイルを適切なディレクトリに置きます。ソースファイルには、複数のプラットフォームのコードやプリプロセッサのプラットフォームチェック(ただし例外が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
上記の例の方法は、異なるプラットフォームのコードが同じファイル構成を合理的に共有できる場合に非常に効果的です。異なるプラットフォームのコードが異なるため、各プラットフォームのファイル構造が異なる場合は、この手法を使用するのが難しくなり、ビルドシステムを使用して異なるプラットフォームのコードを管理する方がより明確に優れています。
ビルドシステムを使用してこの手法を混在させることもできます。プラットフォーム間でファイル構造を共有するコードはこれを使用できますが、異なるプラットフォームに固有のモジュールはビルドシステムで処理できます。
これは、ビルドに異なるソースファイルを含めることはできません。通常、CMakeを使用すると適切に設定されますが、プラットフォーム固有のソースファイルも含めることができます。それは最初の場所でcmakeを使う理由の一つです。 –
これは簡単で小さなプロジェクトではうまくいくが、プロジェクトが大きくなると問題になるテクニックの1つです。 _大規模なC++ソフトウェアDesign_では、ソース全体にプラットフォームチェックを振りかけることを推奨しています。私は、プラットフォーム固有のコードを管理するビルドシステムを使用することが最善だと思いますが、ソース自体でそれを行う場合は、より高度に構造化された組織を使用することをお勧めします(http://stackoverflow.com/a/31304341/365496 )。 – bames53