如何在不搞乱库API的情况下实现条件编译?

时间:2017-10-03 09:37:25

标签: c++ cmake api-design conditional-compilation

我有一个可以使用OpenCL框架进行GPU计算的库。遗憾的是,OpenCL并非在所有平台上都可用。但是我仍然希望能够在这些平台上编译我的代码,只是排除OpenCL功能。

我认为这个问题适用于您想要有条件地编译一些可能并不总是可用的外部资源的所有情况,并且它与您的库API混淆。

目前我的设置如下:

CMake的:

ElementName

C ++

if(ENABLE_OPENCL)
    add_definitions(-DENABLE_OPEN_CL)
    find_package(OpenCL REQUIRED)
    include_directories(${OpenCL_INCLUDE_DIR})
    target_link_libraries(mylibrary ${OpenCL_LIBRARY})
endif()
// 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
};

因此,当我编译库时,如果我想启用OpenCL,我会// 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 // ... }

这样可行,但如果客户端正在使用使用cmake .. -DENABLE_OPEN_CL编译的库,则会强制客户端定义相同的ENABLE_OPEN_CL,否则所包含的库头文件与使用的库文件不匹配客户,非常糟糕的事情发生。

这会打开一大堆蠕虫,例如,如果客户忘记这样做了怎么办?如果它为其他东西使用相同的标识符名称会怎样?

我可以避免这个吗?如果没有,是否有某种方法可以验证头文件在客户端和库上是否匹配,并导致编译错误?或者至少抛出运行时异常?这种情况的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

显而易见的方法是将open_cl_platform_id作为settings的成员,即使不支持OpenCL也是如此。然后,如果用户在没有为其编译库时尝试使用OpenCL功能,则会出现运行时错误。

或者,有两个标题文件settings_no_open_cl.hppsettings_open_cl.hpp,并要求用户包含正确的标题文件。