Good CMake Style: Inherit Properties - cmake

Daniel Pfeifer, in his presentation "Effective CMake",
makes a point, that it is advisable to avoid variable
definitions as much as possible.
Now, how does one get properties into a variety of build
targets. That is, for example
target_include_directories(base_IncludeFlags
INTERFACE
first/dir
second/dir
...)
defines a set of include directories. Instead of defining
the exact same include directories for target_a, target_b,
and target_c, I would like to let those targets inherit
the include directories from 'base_target', with something like
target_link_libraries(target_a PUBLIC base_IncludeFlags)
target_link_libraries(target_b PUBLIC base_IncludeFlags)
target_link_libraries(target_c PUBLIC base_IncludeFlags)
where base_IncludeFlags is shall not be a real physical target,
rather something like an abstract base class or interface.
On the other hand, I do not want to use include_directories
since this affects all targets. Is it better to use foreach?
What is the most elegant way to do this? Shall I make base_target
a library and add dependencies?

What I want is a target that is not actually physically produced, but which propagates some common properties.
Exactly for that purpose CMake has INTERFACE library - container for different properties, which are propagated when this library is linked into another target.
Example:
# Create "container" target
add_library(base_target INTERFACE)
# Add some INTERFACE properties for that target
target_include_directories(base_target INTERFACE
first/dir
second/dir)
# Some 'other_target' (library or executable) may easily consume all common properties:
target_link_libraries(other_target PUBLIC base_target)
# Now 'other_target' has aforementioned include directories too.
# Instead of PUBLIC other linking types (PRIVATE, INTERFACE) may be used.

What is the most elegant way to do this?
Consider that CMake files are often read and edited by people who aren't experts in CMake. Rather than going for elegance, you may consider going for simplicity: keep it simple, stupid.
If you introduce abstractions, hidden implicit behavior of any kind, it will be harder for everybody to maintain the CMake file.
For me, simple in this case would mean copying (duplicating) the entries, if there are just 2-3. If there's more libraries, I'd put the headers in a variable. The "Effective CMake" presentation makes a point to avoid unnecessary, single-use variable definitions. I'd argue that this header list would be a helpful variable, and worth creating.

Related

In CMake, is there a way to set properties on all target dependencies?

In CMake, we can set target properties as either PRIVATE, PUBLIC, or INTERFACE. Both PUBLIC and INTERFACE properties are inherited by any targets that depend on the current target. However, unless I'm missing something, there doesn't seem to be an easy way to define a property that must propagate in the other direction (i.e., inherited by dependencies of the current target).
Most linkers/compilers require that all linked targets have the same value for certain properties (e.g., the exception handling model). If we want to change one of these properties for an executable it requires that it be set on all of its dependencies. Often these dependencies are submodules in our code where we can't modify their CMakeLists.txt files for our specific use-case. This leaves us with two options:
Set a global property (e.g., CMAKE_CXX_FLAGS or add_compile_options) that propagates to all targets in any subdirectories regardless of whether they are dependencies or not.
Explicitly set the properties on each dependent target using target_compile_options. This gets excessive and repetitive depending on the number of dependencies.
It would be nice if there was a functionality that would pass properties down only to dependency targets without having to specify them all individually. Does anyone know how to do this?
For the case of compiler flags that must be consistent for an entire program (including parts that are dynamically linked), such as MSVC's exception handling model, I think the set-something-global approach is suitable. To me, it seems pragmatic and slightly more robust than adding flags to each third-party target one-by-one (ie. what if you forget to handle to one? or what if third-party targets are added or removed in a new version? it seems like a ripe opportunity for human error).
Setting the environment variable [CMAKE_<LANG>_FLAGS] is a good start. You may need to do more if you are building external projects via ExternalProject.
A word of caution for such settings like the exception handling model: You might be tempted to hardcode this global setting inthe CMake files for your project. If your project is used by people other than just you or your company, and especially if its main component is a library and not an executable, it's good practice not to do that. Don't take away your user's ability to choose something like this (unless for some reason your library requires a certain exception handling model, in which case I would still leave this global setting up to them to set, provide documentation stating this, and look into emitting a CMake warning if a user doesn't comply). Instead, use a feature like CMake presets, or only set it if the project is the top-level project
An intersting side note: CMake currently globally "hard-codes" /EHsc for MSVC builds by default. Here's the ticket discussing this

ClassImp preprocessor macro in ROOT - Is it really needed?

Do I really have to use the ClassImp macro to benefit the automatic dictionary and streamer generation in ROOT? Some online tutorials and examples mention it but I noticed that simply adding the ClassDef(MyClass, <ver>) macro to MyClass.h and processing it with rootcint/rootcling already generates most of such code.
I did look at Rtypes.h where these macros are defined but to follow preprocessor macros calling each other is not easy and so, it would be nice if experts could confirm the role of ClassImp. I am specifically interested in recent versions of ROOT >= 5.34
Here is the answer I got on roottalk mailing list confirming that the usage of ClassImp is essentially outdated.
ClassImp is used to register in the TClass the name of the source file
for the class. This was used in particular by THtml (which has now
been deprecated in favor of Doxygen). So unless you code/framework
needs to know the name of the source files, it is no longer necessary
to have ClassImp.
ClassDef is necessary for class inheriting from TObject (or from any
classes that has a ClassDef). In the other cases, it provide
accelerator that makes the I/O slightly faster (and thus is
technically not compulsory in this case). It also assign a version
number to the schema layout which simplifies writing schema evolution
rules (on the other hand, there is other alternative to assign a
version number to the schema layout).
What exactly are you trying to do? The ClassImp and ClassDef macros add members to the class that provide Run-Time Type Information and allow the class to be written to root files. If you are not interested in that, then don't bother with these macros.
I never use them.

What is the modern method for setting general compile flags in CMake?

There are multiple mechanisms offered by CMake for getting flags to the compiler:
CMAKE_<LANG>_FLAGS_<CONFIG> variables
add_compile_options command
set_target_properties command
Is there one method that is preferred over the other in modern use? If so why? Also, how can this method be used with multiple configuration systems such as MSVC?
For modern CMake (versions 2.8.12 and up) you should use target_compile_options, which uses target properties internally.
CMAKE_<LANG>_FLAGS is a global variable and the most error-prone to use. It also does not support generator expressions, which can come in very handy.
add_compile_options is based on directory properties, which is fine in some situations, but usually not the most natural way to specify options.
target_compile_options works on a per-target basis (through setting the COMPILE_OPTIONS and INTERFACE_COMPILE_OPTIONS target properties), which usually results in the cleanest CMake code, as the compile options for a source file are determined by which project the file belongs to (rather than which directory it is placed in on the hard disk). This has the additional advantage that it automatically takes care of passing options on to dependent targets if requested.
Even though they are little bit more verbose, the per-target commands allow a reasonably fine-grained control over the different build options and (in my personal experience) are the least likely to cause headaches in the long run.
In theory, you could also set the respective properties directly using set_target_properties, but target_compile_options is usually more readable.
For example, to set the compile options of a target foo based on the configuration using generator expressions you could write:
target_compile_options(foo PUBLIC "$<$<CONFIG:DEBUG>:${MY_DEBUG_OPTIONS}>")
target_compile_options(foo PUBLIC "$<$<CONFIG:RELEASE>:${MY_RELEASE_OPTIONS}>")
The PUBLIC, PRIVATE, and INTERFACE keywords define the scope of the options. E.g., if we link foo into bar with target_link_libraries(bar foo):
PRIVATE options will only be applied to the target itself (foo) and not to other libraries (consumers) linking against it.
INTERFACE options will only be applied to the consuming target bar
PUBLIC options will be applied to both, the original target foo and the consuming target bar

Can I create C functions that are only visible to my class which is broken into multiple files?

Using a static function, I can limit the linkage of my function to the file at hand and that is perfect in many cases. But I have a class that is unwieldy as one file, but breaking it up is made more frustrating because there are functions that I would like to keep 'private' but are needed throughout.
One part of the answer must be counter-questions, such as:
Why is your class so big that it must be split up?
Are you sure your class is so big that it must be split up? (How big is 'big'?)
Are you sure you have your class properly abstracted?
Can you make the common functions into a new class that can be used by the main class you are working with? That will hide the functions behind a class interface barrier.
On the whole, if you can avoid it, do not split the class file up arbitrarily because of size constraints; keep together that which belongs together.
A Gruesome Possibility
Assuming that a split is necessary and an orthodox split (into various classes that work together) is not possible, the question becomes: how gruesome will you accept your code being? (It's already a bit gruesome since there's an awful lot of functionality in a single file; can you stand it becoming more gruesome?)
Assume your class is in 4 (or more) files.
class.h
class.c
class1.c
class2.c
The header, class.h, is orthodox - self-contained and idempotent. It is used by the outside world (meaning outside this collection of source code) to access the facilities provided by the class.
The files class1.c and class2.c contain implementations of the functions in the class. They could be given a separate, distinctive file suffix - there might be some advantages to doing so. The files are not designed to be compiled standalone; they are strictly a convenience that splits the source up because the class got too big.
The file class.c is what you compile. It contains:
#include "class.h"
Other definitions needed by the class internals.
#include "class1.c"
#include "class2.c"
Thus, although the source is split up, you actually compile a single file, class.c.
In your makefile or equivalent, you specify that class.o depends on the header and all three source files; if any of those changes, then you need to recompile the whole lot. One advantage of changing the suffix of the implementation files (class1.c and class2.c) is that they will not compile separately because the suffix is not recognized by the C (Objective-C) compiler. One downside of changing the suffix is that your syntax-aware editor won't be aware of the correct syntax highlighting for the separate files unless you tell it the file type. If you use an IDE, it may also be less than amused at this trickery.
If you work on a machine where the size of the source means it cannot all be compiled at once like this, then you are snookered. This technique does not help at all; you have to split the files up and compile them separately. In that case, really look hard at whether you can split the code cleanly into several classes which can be managed in an orthodox way.
By request, my comment on the OP as an answer:
There's no language support for this that I'm aware of... You could put all the support functions in a separate c file and only #import its header from the class implementation files? If they don't have to be C functions (for passing as callbacks to C APIs, for example) I'd reimplement them as methods on the class and declare the private interface in a separate header—each implementation file would then #import both the "public" and "private" header.
Prefix their names with output of a cryptographic RNG. Now you don't have to worry about unintentional name collisions. Problem solved. You can hide the renaming in preprocessor macros if you really like.

Xcode xcconfig: Configuring a dependency based on the target

In the quest to resolve the Objective-C namespace issue I'd like to experiment with prefixing a dependency's Objective-C classes based on the target being built.
As an example, suppose I have in my shared library (ObjCStaticLib) a class (CWindow). I have two plugins (A and B) that will use this CWindow. To avoid A's CWindow from colliding with B's CWindow, I want to prefix the CWindow class name at compile time, so A's CWindow becomes ACWindow and B's becomes BCWindow.
I'm looking for a way to communicate to ObjCStaticLib at compile time what prefix it should use to compile itself with. I'm thinking about using xcconfigs to specify a preprocessor macro that the leaf target customizes and that ObjCStaticLib uses. However, I'm not aware of a way for a target to "communicate" with a dependency like that.
I can modify all the sources/projects/etc involved as necessary to implement per-client namespace customization in a dependency.
Does anyone have a good solution for this?