Gediminas Masaitis
Gediminas Masaitis

Reputation: 3212

How to implement conditional compilation without messing up the library API?

I have a library which can do GPU computation using the OpenCL framework. Sadly, OpenCL is not available on all platforms. However I would still like to be able to compile my code on those platforms, just excluding OpenCL functionality.

I think this question applies to all situations where you want to conditionally compile some external resource which may not always be available, and it messes with your library API.

Currently I have it set up like this:

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

    // ...
}

So when I compile the library, if I want to enable OpenCL I do cmake .. -DENABLE_OPEN_CL.

This works, but if the client is consuming the library compiled with ENABLE_OPEN_CL, it forces the client to define the same ENABLE_OPEN_CL, otherwise the included library's header file don't match the one used in the client, and very bad things happen.

This opens a whole can of worms, for example what if the client forgets to do it? What if it uses the same identifier name for something else?

Can I avoid this? If not, is there some way I could verify that the header files match on the client and the library, and cause a compilation error? Or at least throw a run-time exception? What is the correct approach to this scenario?

Upvotes: 2

Views: 706

Answers (1)

The obvious way to do it, is to leave open_cl_platform_id as a member of settings even if OpenCL is not supported. The user then gets a run-time error if they try to use OpenCL functionality when the library hasn't been compiled for it.

Alternatively, have two header files settings_no_open_cl.hpp and settings_open_cl.hpp, and require the user to include the right one.

Upvotes: 2

Related Questions