Then there’s an issue of granularity – specifying different sets of flags for different targets. It’s easy to make the mistake of overwriting any flags specified on the command line or set previously (as shown in the example above). The problem with modifying the CMAKE_FLAGS variables directly is that there’s many pitfalls awaiting the user. # Append - better, but still - don't to it One way to do it, that’s often described in older CMake guides is to directly alter CMAKE_CXX_FLAGS # Bad - discards flags specified on the command line This of course comes out of necessity – either adjusting the optimization level, warnings, linker flags, target architecture, or what have you. But first… Compiler flagsĪ common question everyone getting started with CMake has is “How do I set the compiler flags?”. This promotes encapsulation and allows for a much more fine-grained control over the compilation process. Instead of setting the compiler and linker flags and options globally, or on a per-directory basis, the configuration could be gathered into an interface target, that is then “linked” into other targets as needed. One major example that comes to mind is encapsulating compiler and linker configuration. They may carry any information useful during the build process. Those properties may describe a library, but certainly don’t have to. What are the other use cases then? The key thing to notice is that a target is just a set of properties. I honestly wouldn’t mind seeing add_target being introduced as a command alternative to add_library. Targets may represent libraries, but the uses are much broader than that, especially for INTERFACE targets. As a matter of fact all of the CMake-level entities declared with add_library or add_executable (plus some other commands I have not introduced yet) ARE targets. Instead of “interface library” I like to use the term “interface target” to remove the limiting suggestion that the feature is applicable only to libraries. While that is an important and common use case of INTERFACE libraries it is far from being the only one. In that use case, the INTERFACE library encapsulates a set of properties that describe the library headers – most importantly the include paths, but also possibly compiler defines and flags/switches, and whatever else is necessary. I had given one of the use cases for INTERFACE libraries there – modularizing header-only libraries. I already discussed OBJECT “libraries” in part 2 of the series, but only mentioned INTERFACE libraries briefly in the previous post. Quite the opposite, the add_library command name may actually be a little misleading, or at least suggesting limited use. However, the remaining “library” types – OBJECT and INTERFACE may not be as obvious. When dealing with static or shared libraries this makes sense and is totally intuitive – it immediately brings into mind the correlation between the declared target and the resulting binary library file. Interface targetsĬMake uses the command add_library to define all kinds of library-related targets. In this post I present a concrete use case for INTERFACE targets, discuss how to handle compiler and linker flags and introduce the include command. The INTERFACE keyword was mentioned, but left without a fully fleshed out exmaple. While we were at it I described how properties work and gave examples of using the PRIVATE and PUBLIC transitivity keywords. In part 4 of the series we’ve had a first look at modular design.
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |