私はOpenCLフレームワークを使ってGPU計算を行うことができるライブラリを持っています。残念ながら、OpenCLはすべてのプラットフォームで利用できるわけではありません。しかし、私はまだOpenCLの機能を除いて、それらのプラットフォームで自分のコードをコンパイルできるようにしたいと思います。ライブラリAPIを台無しにすることなく条件付きコンパイルを実装するにはどうすればよいですか?
この質問は、常に利用可能なわけではない可能性のある外部リソースを条件付きでコンパイルするすべての状況に当てはまり、ライブラリAPIを使いこなすことになります。
現在、私はそれがこのように設定している:
CMakeの:
if(ENABLE_OPENCL)
add_definitions(-DENABLE_OPEN_CL)
find_package(OpenCL REQUIRED)
include_directories(${OpenCL_INCLUDE_DIR})
target_link_libraries(mylibrary ${OpenCL_LIBRARY})
endif()
C++
// settings.hpp, exposed to public API
class settings
{
int general_setting_1;
bool general_setting_2;
// ... Other general settings
#ifdef ENABLE_OPEN_CL
int open_cl_platform_id;
// ... Other settings available only when OpenCL is available
#endif
// More settings, possibly also conditionally compiled on other external libraries
};
// computation.cpp, internal to the library
#ifdef ENABLE_OPEN_CL
#include <CL/cl.hpp>
#endif
void do_things()
{
// ...
#ifdef ENABLE_OPEN_CL
if(settings.open_cl_platform_id != -1)
{
// Call OpenCL code
}
#endif
// ...
}
だから私ならば、私は、ライブラリのコンパイル私はOpenCLを有効にしたいcmake .. -DENABLE_OPEN_CL
。
これは動作しますが、クライアントはENABLE_OPEN_CL
でコンパイルされたライブラリを消費している場合、それは同じENABLE_OPEN_CL
を定義するためにクライアントを強制し、そうでない場合は付属のライブラリのヘッダファイルがクライアントで使用されるものと一致していない、と非常に悪いこと起こる。
これは、ワームの完全な蓋を開きます。例えば、クライアントがそれをやめたらどうしますか?同じ識別子の名前を他のものに使用するとどうなりますか?
これを避けることはできますか?そうでなければ、ヘッダファイルがクライアントとライブラリで一致することを確認してコンパイルエラーを起こすことができる方法はありますか?または、少なくとも実行時例外をスローしますか?このシナリオに対する正しいアプローチは何ですか?
ダイナミックローディングとレイトバインディングについて考えましたか? –
ENABLE_OPEN_CL定義に依存しないヘッダーを作成できますか?しかし、このフラグを付けずにコンパイルした場合は、すべてのAPIに対して空のスタブ関数の実装を提供します。つまり、ERROR_NOTIMPLEMENTEDを返します。クライアントは何も定義する必要はありませんが、OpenCLをサポートしないライブラリに対してリンクすると、十分に文書化された方法)? –
もう1つの方法は、ビルド設定に基づいてすべての適切な定義を含むヘッダーファイル(library_config.h)を生成し、このヘッダーをクライアント(配布するパブリックHファイルに含めます)に配布して、クライアントが追加する必要がないようにすることです任意のコードを定義する –