I am trying to use precompiled headers in my project, but I’m finding a strange issue. I put together a simple reproducer, where I have a header which I want to precompile when building a shared library (lib1) and then reuse when building another library (lib2). The compiler issues a warning when compiling the latter, informing that the PCH cannot be reused due to the -Dlib1_EXPORTS flag being missing.
According to my investigations the -Dlib1_EXPORTS compiler flag is automatically added by CMake when compiling lib1 and also the PCH, while for lib2 it just adds -Dlib2_EXPORTS. These different flags make the reusage of the PCH impossible.
I didn’t find any hint about the meaning of these flags, why they are added, and eventually how to remove them; I only saw that they are not added to executable targets, but this says not much to me. The documentation about target_precompile_headers does not prescribe any particular care to be taken to avoid this issue in the Reusing Precompile Headers section; it just says that the flags must be identical. It seems really strange to me that the PCH reusage machinery fails like this in this very simple case, so I must be doing something terribly wrong, but I cannot figure out what.
You are correct to say that this one is added automatically by CMake. It happens when the library is SHARED (so that one could do #ifdef SomeLibrary_EXPORTS in their sources).
From what I see in the documentation, you’d need to unset (or set to FALSE?) ENABLE_EXPORTS for the target(s) or CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS for the entire project (to affect all the targets).
Why does that happen, and what one should do in this case (as removing the *_EXPORTS compile definitions doesn’t seem to be the way to go) - that I don’t know, and I’d be curious to see what others have to say on the matter.
From what I understood from the ENABLE_EXPORTS documentation you linked, disabling exports for a shared library would prevent the possibility to link it to an executable, actually making it almost useless. If this is correct then I’d say this is not a solution that would work for me…
You’re not going to like this answer… While what you’re trying to do seems reasonable, it can’t get past the fundamental restriction that to re-use a PCH, all options have to be identical. Because you have shared libraries involved with symbol visibility enabled, you can’t satisfy that requirement. When building the shared library whose PCH you want to re-use, a compiler define has to be set to a certain value to make symbols get exported. For literally all other code using that shared library, that same compiler define has to have a different value, which is how all that other code imports rather than exports those symbols.
What does this mean for you? Well, if you’re building shared libraries, you won’t be able to re-use PCH between them. Static libraries, yes that would be fine, but not shared libraries. Or you could throw away all the goodness that symbol visibility gives you, which would remove the need for symbol exporting and importing, but please don’t do that!