我有一个可以使用 OpenCL 框架进行 GPU 计算的库。遗憾的是,OpenCL 并非在所有平台上都可用。不过,我仍然希望能够在这些平台上编译我的代码,只是排除 OpenCL 功能。
我认为这个问题适用于您想要有条件地编译某些可能并不总是可用的外部资源的所有情况,并且它会与您的库 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
,否则包含的库的头文件不会与客户端中使用的不匹配,并且会发生非常糟糕的事情。
这会带来一大堆蠕虫,例如,如果客户忘记这样做怎么办?如果它对其他东西使用相同的标识符名称怎么办?
我可以避免这种情况吗?如果不是,是否有某种方法可以验证头文件在客户端和库上是否匹配,并导致编译错误?或者至少抛出一个运行时异常?这种情况的正确方法是什么?
最佳答案
最明显的方法是,即使不支持 OpenCL,也将 open_cl_platform_id
保留为 settings
的成员。如果用户在尚未编译库的情况下尝试使用 OpenCL 功能,则会收到运行时错误。
或者,有两个头文件 settings_no_open_cl.hpp
和 settings_open_cl.hpp
,并要求用户包含正确的一个。
关于c++ - 如何实现条件编译而不弄乱库API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46541511/