The Quantum Physicist The Quantum Physicist - 2 months ago 20
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
    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
    ├── ->
    └── ->

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
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
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

Let me know if you require more details.


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

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

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

#include <openblas/cblas.h>
#include "include/cblas.h"

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.