Good practices for common ancestor target

Sorry this is very basic and open-ended but I’d like to just have some up-to-date input.

Provided I have several libraries that are variations of the same abstract base target if you will (eg building shared and static libs of the same thing in the same project, if on Linux building a version of the shared library with -fPIC etc that does not spill over into the static one): what is a good approach to collecting as many shared properties as possible on the “base” before branching off and making the “actually-built” libraries, and how to propagate the properties to them?

To provoke with a proposed solution: is an interface library a good candidate for such an “abstract base target” and if so, does everything follow along if I just link the concrete lib to the interface one, or? I have seen variants where the concrete lib has to extract the compile definitions through INTERFACE_COMPILE_DEFINITIONS so is that necessary? What about other properties than compile definitions? Do they all follow along if we just link the concrete to the interface lib?

Any suggested best practices or recommendations would be much appreciated. Please flame away for asking this fuzzy question.

Edit: I tried to find a few similar projects on github and eg Tensorflow if built for Windows builds both a shared and a static lib of the same thing but then it’s a great deal of repetition of getting sources from earlier object libs, not a great look.

I usually suggest just making a static and a shared build and installing to the same prefix if you really need this (though you’ll need to not conflict in things like library filenames, export configurations, etc.).

As for the “common target”, an INTERFACE target with whatever target_compile_options you want sounds like what I’ve done in CMake as well for such things.

Thanks, INTERFACE seems to work quite well.