The Quantum Physicist The Quantum Physicist - 17 days ago 7
Linux Question

Correct way to include a header file that is different for precompiled binaries vs manually compiled binaries

So I have a program that uses OpenBLAS, and I use cmake to make it.

The problem is that I want it to compile smoothly for 2 different situations:


  1. For a Linux system, say Debian, one could install a pre-compiled
    libopenblas
    with
    apt-get install libopenblas
    , which works fine with my program. This is because I have the include:

    #include <openblas/cblas.h>



Now this option is good for tests and not for the real deal. The performance of my program will be better if used with a user-compiled version of OpenBLAS, because OpenBLAS compiles differently for every computer (processor dependent). But this pre-compiled version is good if you wanna play around with the program.


  1. For a version that anyone compiles by themselves, the structure of an OpenBLAS installation is:

    ├── bin
    ├── include
    │   ├── cblas.h
    │   ├── f77blas.h
    │   ├── lapacke_config.h
    │   ├── lapacke.h
    │   ├── lapacke_mangling.h
    │   ├── lapacke_utils.h
    │   └── openblas_config.h
    └── lib
    ├── libopenblas.a -> libopenblas_haswellp-r0.2.19.a
    ├── libopenblas_haswellp-r0.2.19.a
    ├── libopenblas_haswellp-r0.2.19.so
    ├── libopenblas.so -> libopenblas_haswellp-r0.2.19.so
    └── libopenblas.so.0 -> libopenblas_haswellp-r0.2.19.so



As you see here, there's no directory called "openblas", which means my include should be:

#include <cblas.h>


but then this is dangerous, because the file
cblas.h
is not only for OpenBLAS, and may be available from other implementations of BLAS. This leads to the file being available, but the function I need from it
openblas_set_num_threads(int num_threads);
not being available. So if I, by default, add the directory
openblas
to my cmake's include list, the wrong file may be included if the user doesn't have a custom installation of OpenBLAS.

So my question is: How would you deal with this correctly, such that if a pre-compiled version of OpenBLAS is not present, then do the correct include without the
openblas
directory?

Let me know if you require more details.

Answer

So the solution I found is to make a DEFINE in cmake if a local, compiled library is found

if(${foundOpenBLAS})
    message("I found OpenBLAS that you compiled.")
    TARGET_LINK_LIBRARIES(mylibs -L"${OpenBLASPath}/lib")
else()
    message("I couldn't find OpenBLAS that you compiled, so I'm assuming that you have it installed in your system.")
    add_definitions(-DOPENBLAS_FROM_SYSTEM)
endif()

Now in the C++ code, we do this:

#ifdef OPENBLAS_FROM_SYSTEM
#include <openblas/cblas.h>
#else
#include "include/cblas.h"
#endif

The first version is when OpenBLAS isn't found, and it's the default Debian include. The other case, is if OpenBLAS is found. This will include the right file.

Comments