The handbook for every CMake user, providing structured learning, the latest best practices and real-world advice from one of the CMake co-maintainers.
Author(s): Craig Scott
Edition: 14
Publisher: Crascit Pty Ltd
Year: 2023
Language: English
Pages: 631
Professional CMake: A Practical Guide
Table of Contents
Preface
Acknowledgments
Part I: Fundamentals
Chapter 1. Introduction
Chapter 2. Setting Up A Project
2.1. In-source Builds
2.2. Out-of-source Builds
2.3. Generating Project Files
2.4. Running The Build Tool
2.5. Recommended Practices
Chapter 3. A Minimal Project
3.1. Managing CMake Versions
3.2. The project() Command
3.3. Building A Basic Executable
3.4. Commenting
3.5. Recommended Practices
Chapter 4. Building Simple Targets
4.1. Executables
4.2. Defining Libraries
4.3. Linking Targets
4.4. Linking Non-targets
4.5. Old-style CMake
4.6. Recommended Practices
Chapter 5. Variables
5.1. Variable Basics
5.2. Environment Variables
5.3. Cache Variables
5.4. Scope Blocks
5.5. Potentially Surprising Behavior Of Variables
5.6. Manipulating Cache Variables
5.6.1. Setting Cache Values On The Command Line
5.6.2. CMake GUI Tools
5.7. Printing Variable Values
5.8. String Handling
5.9. Lists
5.9.1. Problems With Unbalanced Square Brackets
5.10. Math
5.11. Recommended Practices
Chapter 6. Flow Control
6.1. The if() Command
6.1.1. Basic Expressions
6.1.2. Logic Operators
6.1.3. Comparison Tests
6.1.4. File System Tests
6.1.5. Existence Tests
6.1.6. Common Examples
6.2. Looping
6.2.1. foreach()
6.2.2. while()
6.2.3. Interrupting Loops
6.3. Recommended Practices
Chapter 7. Using Subdirectories
7.1. add_subdirectory()
7.1.1. Source And Binary Directory Variables
7.1.2. Scope
7.1.3. When To Call project()
7.2. include()
7.3. Project-relative Variables
7.4. Ending Processing Early
7.5. Recommended Practices
Chapter 8. Functions And Macros
8.1. The Basics
8.2. Argument Handling Essentials
8.3. Keyword Arguments
8.4. Returning Values
8.4.1. Returning Values From Functions
8.4.2. Returning Values From Macros
8.5. Overriding Commands
8.6. Special Variables For Functions
8.7. Other Ways Of Invoking CMake Code
8.8. Problems With Argument Handling
8.8.1. Parsing Arguments Robustly
8.8.2. Forwarding Command Arguments
8.8.3. Special Cases For Argument Expansion
8.9. Recommended Practices
Chapter 9. Properties
9.1. General Property Commands
9.2. Global Properties
9.3. Directory Properties
9.4. Target Properties
9.5. Source Properties
9.6. Cache Variable Properties
9.7. Other Property Types
9.8. Recommended Practices
Chapter 10. Generator Expressions
10.1. Simple Boolean Logic
10.2. Target Details
10.3. General Information
10.4. Path Expressions
10.5. Utility Expressions
10.6. Recommended Practices
Chapter 11. Modules
11.1. Checking Existence And Support
11.2. Other Modules
11.3. Recommended Practices
Chapter 12. Policies
12.1. Policy Control
12.2. Policy Scope
12.3. Recommended Practices
Chapter 13. Debugging And Diagnostics
13.1. Log Messages
13.1.1. Log Levels
13.1.2. Message Indenting
13.1.3. Message Contexts
13.1.4. Check Messages
13.2. Color Diagnostics
13.3. Print Helpers
13.4. Tracing Variable Access
13.5. Debugging Generator Expressions
13.6. Profiling CMake Calls
13.7. Discarding Previous Results
13.8. Recommended Practices
Part II: Builds In Depth
Chapter 14. Build Type
14.1. Build Type Basics
14.1.1. Single Configuration Generators
14.1.2. Multiple Configuration Generators
14.2. Common Errors
14.3. Custom Build Types
14.4. Recommended Practices
Chapter 15. Compiler And Linker Essentials
15.1. Target Properties
15.1.1. Compiler Flags
15.1.2. Linker Flags
15.1.3. Sources
15.2. Target Property Commands
15.2.1. Linking Libraries
15.2.2. Linker Options
15.2.3. Header Search Paths
15.2.4. Compiler Defines
15.2.5. Compiler Options
15.2.6. Source Files
15.3. Directory Properties And Commands
15.4. De-duplicating Options
15.5. Compiler And Linker Variables
15.5.1. Compiler And Linker Variables Are Single Strings, Not Lists
15.5.2. Distinguish Between Cache And Non-cache Variables
15.5.3. Prefer Appending Over Replacing Flags
15.5.4. Understand When Variable Values Are Used
15.6. Language-specific Compiler Flags
15.7. Compiler Option Abstractions
15.7.1. Warnings As Errors
15.7.2. System Header Search Paths
15.7.3. Runtime Library Selection
15.7.4. Debug Information Format Selection
15.8. Recommended Practices
Chapter 16. Advanced Linking
16.1. Require Targets For Linking
16.2. Customize How Libraries Are Linked
16.2.1. Link Group Features
16.2.2. Link Library Features
16.2.3. Custom Features
16.2.4. Feature Validity
16.3. Propagating Up Direct Link Dependencies
16.3.1. Link Seaming Example
16.3.2. Static Plugins
16.4. Recommended Practices
Chapter 17. Language Requirements
17.1. Setting The Language Standard Directly
17.2. Setting The Language Standard By Feature Requirements
17.2.1. Detection And Use Of Optional Language Features
17.3. Recommended Practices
Chapter 18. Target Types
18.1. Executables
18.2. Libraries
18.2.1. Basic Library Types
18.2.2. Object Libraries
18.2.3. Imported Libraries
18.2.4. Interface Libraries
18.2.5. Interface Imported Libraries
18.2.6. Library Aliases
18.3. Promoting Imported Targets
18.4. Recommended Practices
Chapter 19. Custom Tasks
19.1. Custom Targets
19.2. Adding Build Steps To An Existing Target
19.3. Commands That Generate Files
19.4. Configure Time Tasks
19.5. Platform Independent Commands
19.6. Combining The Different Approaches
19.7. Recommended Practices
Chapter 20. Working With Files
20.1. Manipulating Paths
20.1.1. cmake_path()
20.1.2. Older Commands
20.2. Copying Files
20.3. Reading And Writing Files Directly
20.4. File System Manipulation
20.5. File Globbing
20.6. Downloading And Uploading
20.7. Recommended Practices
Chapter 21. Specifying Version Details
21.1. Project Version
21.2. Source Code Access To Version Details
21.3. Source Control Commits
21.4. Recommended Practices
Chapter 22. Libraries
22.1. Build Basics
22.2. Linking Static Libraries
22.3. Shared Library Versioning
22.4. Interface Compatibility
22.5. Symbol Visibility
22.5.1. Specifying Default Visibility
22.5.2. Specifying Individual Symbol Visibilities
22.6. Mixing Static And Shared Libraries
22.7. Recommended Practices
Chapter 23. Toolchains And Cross Compiling
23.1. Toolchain Files
23.2. Defining The Target System
23.3. Tool Selection
23.4. System Roots
23.5. Compiler Checks
23.6. Examples
23.6.1. Raspberry Pi
23.6.2. GCC With 32-bit Target On 64-bit Host
23.7. Android
23.7.1. Historical Context
23.7.2. Using The NDK
23.7.3. Android Studio
23.7.4. ndk-build
23.7.5. Visual Studio Generators
23.8. Recommended Practices
Chapter 24. Apple Features
24.1. CMake Generator Selection
24.2. Application Bundles
24.2.1. Bundle Structure
24.2.2. Bundle Info.plist Files
24.2.3. Sources, Resources And Other Files
24.3. Frameworks
24.3.1. Framework Structure
24.3.2. Framework Info.plist Files
24.3.3. Headers
24.4. Loadable Bundles
24.5. Build Settings
24.5.1. SDK Selection
24.5.2. Deployment Target
24.5.3. Device Families
24.5.4. Compiler Test Workarounds
24.6. Code Signing
24.6.1. Signing Identity And Development Team
24.6.2. Provisioning Profiles
24.6.3. Entitlements
24.7. Creating And Exporting Archives
24.8. Universal Binaries
24.8.1. Device-only Bundles
24.8.2. Intel And Apple Silicon Binaries
24.8.3. Combined Device And Simulator Binaries
24.9. Linking Frameworks
24.10. Embedding Frameworks
24.11. Limitations
24.12. Recommended Practices
Part III: The Bigger Picture
Chapter 25. Finding Things
25.1. Finding Files And Paths
25.1.1. Apple-specific Behavior
25.1.2. Cross-compilation Controls
25.1.3. Validators
25.2. Finding Paths
25.3. Finding Programs
25.4. Finding Libraries
25.5. Finding Packages
25.5.1. Package Registries
25.5.2. FindPkgConfig
25.6. Ignoring Search Paths
25.7. Debugging find_…() Calls
25.8. Recommended Practices
Chapter 26. Testing
26.1. Defining And Executing A Simple Test
26.2. Test Environment
26.3. Pass / Fail Criteria And Other Result Types
26.4. Test Grouping And Selection
26.4.1. Regular Expressions
26.4.2. Test Numbers
26.4.3. Labels
26.4.4. Repeating Tests
26.5. Parallel Execution
26.6. Managing Test Resources
26.6.1. Defining Test Resource Requirements
26.6.2. Specifying Available System Resources
26.6.3. Using Resources Allocated To A Test
26.7. Test Dependencies
26.8. Cross-compiling And Emulators
26.9. Build And Test Mode
26.10. CDash Integration
26.10.1. Key CDash Concepts
26.10.2. Executing Pipelines And Actions
26.10.3. CTest Configuration
26.10.4. Test Measurements And Results
26.11. Output Control
26.12. GoogleTest
26.13. Recommended Practices
Chapter 27. Installing
27.1. Directory Layout
27.1.1. Relative Layout
27.1.2. Base Install Location
27.2. Installing Project Targets
27.2.1. Interface Properties
27.2.2. RPATH
27.2.3. Apple-specific Targets
27.3. Installing Exports
27.4. Installing Imported Targets
27.5. Installing Files
27.5.1. File Sets
27.5.2. Explicit Public And Private Headers
27.5.3. Simple Files And Programs
27.5.4. Whole Directories
27.6. Custom Install Logic
27.7. Installing Dependencies
27.7.1. Runtime Dependency Sets
27.7.2. InstallRequiredSystemLibraries Module
27.7.3. BundleUtilities And GetPrerequisites
27.8. Writing A Config Package File
27.8.1. Config Files For CMake Projects
27.8.2. Config Files For Non-CMake Projects
27.9. Executing An Install
27.10. Recommended Practices
Chapter 28. Packaging
28.1. Packaging Basics
28.2. Components
28.3. Multi Configuration Packages
28.3.1. Multiple Build Directories
28.3.2. Pass Multiple Configurations To cpack
28.4. Package Generators
28.4.1. Simple Archives
28.4.2. Qt Installer Framework (IFW)
28.4.3. WIX
28.4.4. NSIS
28.4.5. DragNDrop
28.4.6. productbuild
28.4.7. RPM
28.4.8. DEB
28.4.9. FreeBSD
28.4.10. Cygwin
28.4.11. NuGet
28.4.12. External
28.5. Recommended Practices
Chapter 29. ExternalProject
29.1. High Level Overview
29.2. Directory Layout
29.3. Built-in Steps
29.3.1. Archive Downloads
29.3.2. Repository Download Methods
29.3.3. Configuration Step
29.3.4. Build Step
29.3.5. Install Step
29.3.6. Test Step
29.4. Step Management
29.5. Miscellaneous Features
29.6. Common Issues
29.7. ExternalData
29.8. Recommended Practices
Chapter 30. FetchContent
30.1. Comparison With ExternalProject
30.2. Basic Usage
30.3. Resolving Dependencies
30.4. Integration With find_package()
30.4.1. Try find_package() Before FetchContent
30.4.2. Redirect find_package() To FetchContent
30.4.3. Redirections Directory
30.5. Developer Overrides
30.6. Other Uses For FetchContent
30.7. Restrictions
30.8. Recommended Practices
Chapter 31. Making Projects Consumable
31.1. Use Project-specific Names
31.2. Don’t Assume A Top Level Build
31.3. Avoid Hard-coding Developer Choices
31.4. Avoid Package Variables If Possible
31.5. Use Appropriate Methods To Obtain Dependencies
31.6. Recommended Practices
Chapter 32. Dependency Providers
32.1. Top Level Setup Injection Point
32.2. Dependency Provider Implementation
32.2.1. Accepting find_package() Requests
32.2.2. Accepting FetchContent_MakeAvailable() Requests
32.2.3. Accepting Multiple Request Methods
32.2.4. Wrapping The Built-in Implementations
32.2.5. Preserving Variable Values
32.2.6. Delegating Providers
32.3. Recommended Practices
Chapter 33. Presets
33.1. High Level Structure
33.2. Configure Presets
33.2.1. Essential Fields
33.2.2. Inheritance
33.2.3. Macros
33.2.4. Environment Variables
33.2.5. Toolchains
33.2.6. Conditions
33.3. Build Presets
33.4. Test Presets
33.5. Package Presets
33.6. Workflow Presets
33.7. Recommended Practices
Chapter 34. Project Organization
34.1. Superbuild Structure
34.2. Non-superbuild Structure
34.3. Common Top Level Subdirectories
34.4. IDE Projects
34.5. Defining Targets
34.5.1. Building Up A Target Across Directories
34.5.2. Target Output Locations
34.6. Windows-specific Issues
34.7. Cleaning Files
34.8. Re-running CMake On File Changes
34.9. Injecting Files Into Projects
34.10. Recommended Practices
Chapter 35. Build Performance
35.1. Unity Builds
35.1.1. BATCH Mode
35.1.2. GROUP Mode
35.2. Precompiled Headers
35.3. Build Parallelism
35.3.1. Makefiles Generators
35.3.2. Ninja Generators
35.3.3. Visual Studio Generators
35.3.4. Xcode Generator
35.3.5. Optimizing Build Dependencies
35.4. Compiler Caches
35.4.1. Ccache Configuration
35.4.2. Makefiles And Ninja Generators
35.4.3. Xcode Generator
35.4.4. Visual Studio Generators
35.4.5. Combined Generator Support
35.5. Debug-related Improvements
35.6. Alternative Linkers
35.7. Recommended Practices
Chapter 36. Working With Qt
36.1. Basic Setup
36.2. Build Details
36.2.1. Standard Library Implementation
36.2.2. Position Independent Code
36.2.3. Windows GUI Applications
36.3. Autogen
36.3.1. Moc
36.3.2. Widgets
36.3.3. Resources
36.4. Translations
36.5. Deployment
36.5.1. Qt Deployment Tools
36.5.2. Deploying Translation Files
36.5.3. Linux Considerations
36.6. Transition To Qt 6
36.7. Recommended Practices
Appendix A: Timer Dependency Provider
Appendix B: Full Compiler Cache Example
Index