0

I'm (cross-)compiling a shared C library with support for many different platforms which is handled by an hierarchy of CMakeLists files. In those files, several platform specific compiler flags are conditionally produced (with add_definitions()). I can successfully compile and link the source code leading to an appropriate .so file.

But to use the library in any project, I need to provide the right header files, too. The following install command of CMake selects the right header files to copy but does not apply the replacement of preprocessor defines/includes:

install(FILES ${headers} DESTINATION include/mylibrary)

So how can I generate/install the "post-compiled" header files?

What I thought of so far:

  • As add_definitions() should stack my -D's in the COMPILE_DEFINITIONS variable, maybe running a foreach loop on the copied raw headers and replace the define/include placeholders?
  • Using add_custom_command() to apply some logic before copying?

Edit: As pointed out by Tsyvarev, there is an answer quite near to my needs here, but unfortunately not quite it. In summary, the answer gives 2 options:

  • Include a special 'config' header in all of the library's headers and leverage the cmakedefine command to call configure_file() on this header. I can't use this approach because I don't want to alter the library headers.
  • Create a target-specific .cmake file which helps external projects in including the right headers together with all necessary -D defines. I can't use this approach either, because my external projects do not use cmake for building. Plus, I wish to create a library that is as easy to include as possible.

Any other thoughts?

Edit 2: I may have to elaborate on my statement, that the install command of CMake is not replacing defines. Take the following example:

//sampleheader.hpp
#ifndef SAMPLEHEADER_HPP_
#define SAMPLEHEADER_HPP_

#include OS_SPECIFIC_HEADER

//...

Now I have a CMakeLists.txt file that does something like this:

# ...
if (${OS} MATCHES "arm-emblinux")
    add_definitions(-DOS_SPECIFIC_HEADER="emblinuxHeader.hpp")
elseif (${OS} MATCHES "linux")
    add_definitions(-DOS_SPECIFIC_HEADER="linuxHeader.hpp")
endif()
# ...

Everything compiles fine, but when the install command above gets called, I have a header file in my ../include/ directory still with OS_SPECIFIC_HEADER placeholder in it. And of course, this cannot be properly included in any development project.

  • 1
    Possible duplicate of [Library headers and #define](https://stackoverflow.com/questions/20833226/library-headers-and-define) – Tsyvarev May 29 '18 at 08:09
  • 2
    Well, but what do you mean by "does not apply the replacement of preprocessor defines/includes" when talk about installed headers? There is no *binding* of headers and compiler definitions on compiler level; you should either pass compile definitions to compiler via **command line**, or **modify header files**. Do your edit means, that modification of header files isn't acceptible? If so, you should resort to force user to pass additional definitions via command line. If you don't want CMake way, you may create `.pc` file, which is usable via `pkg-config` utility. Is this approach acceptible? – Tsyvarev May 29 '18 at 11:22
  • And I see no specific of your question about "cross-compiling" (you use this tag). Simple "support for many different platforms" doesn't automatically imply cross-compiling. – Tsyvarev May 29 '18 at 11:28
  • @Tsyvarev, please see Edit 2 for clarification. Should have used that example from the beginning, sorry about that. I also removed the cc tag, as I agree with your point. Concerning modifications: I wish not to modify any headers after installing with CMake, no. The same goes for `pkg-config`. But if there is no standalone solution, I'll probably go with that. – Joschka Sondhof May 30 '18 at 14:01
  • `I wish not to modify any headers after installing with CMake, no.` - This clarifies a little... But the example helps a lot, actually. Is follows acceptible to you? 1. Have `sampleheader.hpp.in` header-like file in *source* tree with `#include @OS_SPECIFIC_HEADER@`, 2. Transform it to `sampleheader.hpp` header file in the *build* tree during the *configuration* process with `#include "emblinuxHeader.hpp"`. 3. Use that header for build your project, and 4. Install that header with `install()`? If so, transformation could be done with `configure_file`, described in the referenced question. – Tsyvarev May 30 '18 at 14:15
  • The thing is, I really only want to touch the complex structure of the library source files, if necessary. In other words: I do not even know, which headers are used in the different builds and which -D flags have to be set. I thought, could tell CMake something like "naah, don't use the plain source headers for installation, instead make new ones having all `add_definitions()` flags included"... – Joschka Sondhof May 30 '18 at 14:24
  • `could tell CMake something like "naah, don't use the plain source headers for installation, instead make new ones having all add_definitions() flags included"` - Understand. But no, CMake has no such functionality. CMake install headers like a common files (`install(FILES)`). Also compile definitions may be "attached" to *targets* (executable or library), source files, but not to the header files. It is perfectly correct for the project to have different libraries with different compile options which use same header files. – Tsyvarev May 30 '18 at 16:37

0 Answers0