これを行うには、ビルド システムを使用する必要があります。プラットフォームに依存しない関数の宣言とクラスの定義を含むヘッダーを提供する必要があります。次に、ターゲット プラットフォームに応じて、ビルド システムはそれらの関数とクラスの適切な実装をコンパイルする必要があります。
たとえば、グラフィックや GUI 要素を表示するためのウィンドウの作成を考えてみましょう。これを行うためにライブラリを使用していない場合は、クロスプラットフォーム コードを自分で作成する必要があります。まず、プラットフォームに依存しないインターフェイスがどうあるべきかを正確に考える必要があります。おそらく、window
クラスといくつかのヘルパー関数があります。次に、そのクラスの定義とヘルパー関数の宣言をヘッダー ファイルに提供し、プラットフォームごとに個別の実装を提供できます。次に、次のような一連のファイルが作成されます。
window.h
window_wayland.cpp
window_winapi.cpp
window_x11.cpp
これで、クラスと関数を使用する必要があるすべてのファイルは、#include <window.h>
. それらはすべて同じ関数宣言を取得します。ただし、window_x11.cpp
X11 ウィンドウ システムをwindow_wayland.cpp
使用するシステム、Wayland を使用するシステム、およびwindow_winapi
Windows でコンパイルするビルド システムの構成を指定します。これは、構築しているプラットフォームに応じて、ターゲット プラットフォームで動作するヘッダーの実装を取得することを意味します。
これにはいくつかの利点があります。
- ビルドの懸念 (ビルド対象のプラットフォーム) をコードの懸念から分離しました。
- プラットフォームに依存する各実装には、独自のファイルがあります。
- プリプロセッサ ディレクティブで雑然としたファイルや、実行パスをたどるのが難しいファイルはありません。
これは、定義を使用してコードのさまざまな部分を選択的にコンパイルすることに問題があるという意味ではありません。私は、プラットフォームに依存する部分にローカライズされた少量のコードでのみこれを確認することを好みます。理想的には、プラットフォームに依存するコードを関数でラップ#ifdef
し、実装を交換するだけです。
この選択的なビルドを正確に行う方法は、使用しているビルド システムによって異なります。GNU ビルド システムでは、automake を使用して条件付きコンパイルを実現できます。ドキュメントにいくつかの例が示されています。与えられた簡単な例は次のとおりです。
bin_PROGRAMS = hello
if LINUX
hello_SOURCES = hello-linux.c hello-common.c
else
hello_SOURCES = hello-generic.c hello-common.c
endif
automake
この構成で実行すると、適切なメイクファイルが生成されます。