SlideShare a Scribd company logo
Richard Thomson
Senior Software Engineer, NVIDIA
@LegalizeAdulthd
http://LegalizeAdulthood.wordpress.com
legalize@xmission.com
Outline
 Feature concerns
 Platform concerns
 Testing for C++ standard support
 Testing for C++ language features
 Testing for compiler option support
 Testing for specific headers
 Testing arbitrary code can compile
 Testing for specific functions
 Testing arbitrary code can run
 Using the results of the tests
Feature Concerns
 Does the compiler support the minimum
standard my code assumes?
 Does the compiler support the minimum
language features my code assumes?
Platform Concerns
 Does the compiler have headers my code
assumes to exist?
 Does the standard library have functions my
code assumes to exist?
 Is the compiler generating 32-bit or 64-bit
code?
 Does the compiler provide specific extensions?
C++ Standard Support
 If you need it, you need it...
 Usually you won't conditionally compile your
code for different versions of the standard
 Rely on older releases for older standards
 May want to explicitly state the assumed
standard to avoid future incompatibilities
 e.g. compile for C++11 with C++14/17/20/...
features disabled
Specifying C++ Standard for
Targets
 Target properties:
 <LANG>_STANDARD:STRING
 The requested standard version
 C: 90, 99 or 11
 CXX: 98, 11, 14, 17 (>= 3.8), or 20 (>= 3.12)
 CUDA: 98 or 11
 <LANG>_STANDARD_REQUIRED:BOOL
 Hard error if the standard is not supported
 <LANG>_EXTENSIONS:BOOL
 Enable compiler extensions
 Always set along with <LANG>_STANDARD
Specifying C++ Standard Globally
 Target properties initialized from global
properties:
 CMAKE_<LANG>_STANDARD
 CMAKE_<LANG>_STANDARD_REQUIRED
 CMAKE_<LANG>_EXTENSIONS
 Easiest way to ensure all targets are
compiled consistently
 Can override with target properties if a mix
is needed
C++ Language Features for
Targets
target_compile_features( <target>
<PRIVATE|PUBLIC|INTERFACE> feature1 [feature2...]
[<PRIVATE|PUBLIC|INTERFACE> feature3 [feature4....]]
... )
 Sets target properties COMPILE_FEATURES,
INTERFACE_COMPILE_FEATURES
 CMAKE_<LANG>_KNOWN_FEATURES contains all known
features for the compiler, e.g. cxx_alignas. Consult
documentation for supported list of language features.
 If you only use a few "modern" features, may be useful to require
specific features instead of full standard support
 The strongest requirement between standard versions and
compiler features wins, e.g. transitive compiler dependencies
Detecting and Using Optional
Features
 Use generator expressions
target_compile_features( foo PUBLIC $<$<COMPILE_FEATURES:cxx_override>:cxx_override> )
target_compile_definitions( foo PUBLIC
$<$<COMPILE_FEATURES:cxx_override>:-Dfoo_OVERRIDE=override>
$<NOT $<COMPILE_FEATURES:cxx_override>>:-Dfoo_OVERRIDE=>
)
 Use WriteCompilerDetectionHeader module:
include(WriteCompilerDetectionHeader)
write_compiler_detection_header(
FILE foo_compiler_detection.h
PREFIX foo
COMPILERS GNU Clang MSVC Intel
FEATURES cxx_override )
 Allows you to use CMAKE_CXX_STANDARD with
CMAKE_CXX_STANDARD_REQUIRED set to OFF
Check Modules
 CMake ships with a variety of check
modules
 Generally implemented by compiling a
piece of boiler plate code
 May also link and run the boiler plate
 Results are stored in cache variables
 Checks are only executed once during
initial configure
 Variables control the compilation and link
Useful Check Modules
 CheckCXXCompilerFlag
 CheckCXXSymbolExists
 CheckIncludeFileCXX
 CheckLibraryExists
 CheckPrototypeDefinition
 CheckStructHasMember
 CheckTypeSize
 CheckCXXSourceCompiles
 CheckCXXSourceRuns
Variables Affecting Check Modules
 Variables affecting the boiler plate:
 CMAKE_REQUIRED_FLAGS
 CMAKE_REQUIRED_DEFINITIONS
 CMAKE_REQUIRED_INCLUDES
 CMAKE_REQUIRED_LIBRARIES
 CMAKE_REQUIRED_QUIET
 Set the variables before calling the specific
check command
 CMake does not use these variables for
regular compilation
Testing for C++ Compiler Flags
 Maybe you want an Address Sanitizer
(ASan) build if the compiler supports it
 Support varies based on compiler version
 Testing compiler and version combinations
is tedious and fragile
 CheckCXXCompilerFlag module:
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-fsanitize=address
ASanSupported)
if(ASanSupported)
# ...
endif()
Testing for Specific Functions
 CheckCXXSymbolExists can find a symbol
that identifies a macro, variable or C style
function using the C++ compiler.
 CheckPrototypeDefinition can check that a
declared C function matches the expected
prototype
check_prototype_definition(getpwent_r
"struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)"
"NULL"
"unistd.h;pwd.h"
SOLARIS_GETPWENT_R)
 Use CheckCXXSourceCompiles for other
cases
Testing for Specific Headers
 CheckIncludeFileCXX validates that a
header can be included in C++
include(CheckIncludeFileCXX)
check_include_file_cxx("sstream" haveSStream)
 CheckIncludeFile, CheckIncludeFiles
provides similar functionality for C headers
Testing for Specific Libraries
 CheckLibraryExists can find a function in a
library
 CheckCXXSourceCompiles can be used to
attempt to call a function in a library and link
against it
Testing Code Compiles
 CheckCSourceCompiles for C
 CheckCXXSourceCompiles for C++
include(CheckCXXSourceCompiles)
check_cxx_source_compiles("
int main(int argc, char *argv[])
{
int myVar;
return 0;
}" noWarnUnused FAIL_REGEX "[Ww]arn")
if(noWarnUnused)
message("Unused variables don't warn")
endif()
Testing Code Runs
 CheckCSourceRuns for C
 CheckCXXSourceRuns for C++
include(CheckCXXSourceRuns)
check_cxx_source_runs("
int main()
{
return 1; // still runs OK
}" runsOK)
if(runsOK)
message("Code ran OK")
endif()
What To Do With The Results?
 Checks result in variables being set
 Use the variables in generator expressions
 Use the variables in target properties
 Use the variables to configure header files
Generator Expressions
 Used during build system generation to
produce information specific to a build
configuration
 Use for information that varies between debug
or release, for instance
target_compile_definitions(
foo PUBLIC <$<CONFIG:Debug>:DEBUG>)
 Be careful about sense of true/false
 CMake considers 1, ON, TRUE, YES to be truthy
 Generator expressions only consider 1 to be truthy
 Rich syntax, see documentation for full details
Common Generator
Expressions
 $<BOOL:...> Evaluate CMake truthy
 $<AND:?[,?]...> 1 if all ?s are 1
 $<OR:?[,?]...> 1 if any ?s are 1
 $<NOT:?> 1 if ? is 0, 0 if ? is 1
 $<TARGET_EXISTS:tgt> 1 if target tgt
exists
 $<CONFIG:cfg> 1 if cfg is config
 $<PLATFORM_ID:id> 1 if id is platform
 $<COMPILER_ID:id> 1 if id is compiler
Informational Generator
Expressions
 Return some kind of information instead of
0,1
 $<CONFIG> Configuration name
 $<PLATFORM_ID> Platform name
 $<COMPILER_ID> Compiler name
 $<TARGET_FILE:tgt> Full path to target
 $<TARGET_PROPERTY:tgt,prop> Value of
prop
Output Generator Expressions
 Combine inputs to produce an output
 $<0:?> Empty string (ignores ?)
 $<1:?> Content of ?
 $<JOIN:list,glue> Join items in list with
glue
 $<LOWER_CASE:?> ? converted to
lower case
 $<UPPER_CASE:?> ? converted to
upper case
 $<MAKE_C_IDENTIFIER:?> ? as C
identifier
Recommended Overall
Strategy
 Test for things you use
 Don't test for OS/version combinations
 Don't test for compiler/version combinations
 For things you need, fail if not found
 For optional things, write a configuration
header
Configuring Files
cmake_configure_file( <input> <output>
[COPYONLY] [ESCAPE_QUOTES] [@ONLY]
[NEWLINE_STYLE
[UNIX|DOS|WIN32|LF|CRLF] ]
)
 Writes an output file from an input file
template, substituting variable references in
the template.
 Template in the source tree, e.g. foo.h.in
 Output in the binary tree, e.g. foo.h
Common configure_file Constructs
 #cmakedefine VAR ...
Depending on truthiness of VAR, expands to
○ #define VAR ...
○ /* #undef VAR */
 #cmakedefine01 VAR
Depending on truthiness of VAR, expands to
○ #define VAR 1
○ #define VAR 0
 @VAR@ expands to value of VAR, without
@s
configure_file Example
Template
// foo_features.h
#pragma once
#cmakedefine01 HAVE_STD_MEMCMP
#cmakedefine01 HAVE_STD_STRCMP
#cmakedefine01 HAVE_C_MEMCMP
#cmakedefine01 HAVE_C_STRCMP
#cmakedefine01 HAVE_C_BCMP
configure_file Set Variables
include(CheckSymbolExists)
include(CheckCXXSourceCompiles)
check_cxx_source_compiles([=[
#include <cstring>
int main() { return std::memcmp("", "", 0); }
]=] HAVE_STD_MEMCMP)
check_cxx_source_compiles([=[
#include <cstring>
int main() { return std::strcmp("", ""); }
]=] HAVE_STD_STRCMP)
check_symbol_exists("memcmp" "string.h" HAVE_C_MEMCMP)
check_symbol_exists("strcmp" "string.h" HAVE_C_STRCMP)
check_symbol_exists("bcmp" "strings.h" HAVE_C_BCMP)
configure_file Example Usage
configure_file(foo_features.h.in foo_features.h)
add_executable(foo foo.cpp
"${CMAKE_CURRENT_BINARY_DIR}/foo_features.h")
target_include_directories(foo
PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
configure_file CMake Output
-- Performing Test HAVE_STD_MEMCMP
-- Performing Test HAVE_STD_MEMCMP - Success
-- Performing Test HAVE_STD_STRCMP
-- Performing Test HAVE_STD_STRCMP - Success
-- Looking for memcmp
-- Looking for memcmp - found
-- Looking for strcmp
-- Looking for strcmp - found
-- Looking for bcmp
-- Looking for bcmp - not found
-- Configuring done
-- Generating done
configure_file Resulting
Header
// foo_features.h
#pragma once
#define HAVE_STD_MEMCMP 1
#define HAVE_STD_STRCMP 1
#define HAVE_C_MEMCMP 1
#define HAVE_C_STRCMP 1
#define HAVE_C_BCMP 0
Using Configured Header
#include <foo_features.h>
#include <iostream>
#if HAVE_STD_MEMCMP || HAVE_STD_STRCMP
#include <cstring>
#endif
#if HAVE_C_MEMCMP || HAVE_C_STRCMP
#include <string.h>
#endif
#if HAVE_C_BCMP
#include <strings.h>
#endif
int main()
{
#if HAVE_STD_MEMCMP
std::cout << "Have std::memcmpn";
#endif
#if HAVE_STD_STRCMP
std::cout << "Have std::strcmpn";
#endif
#if HAVE_C_MEMCMP
std::cout << "Have C memcmpn";
#endif
#if HAVE_C_STRCMP
std::cout << "Have C strcmpn";
#endif
#if HAVE_C_BCMP
std::cout << "Have C bcmpn";
#endif
return 0;
}
Program Output
Have std::memcmp
Have std::strcmp
Have C memcmp
Have C strcmp

More Related Content

PDF
Last train to php 7
PDF
Continuous Quality Assurance
PPTX
PHP 7 Crash Course - php[world] 2015
PDF
CLI, the other SAPI
ODP
Mastering Namespaces in PHP
PPTX
C++ basics
PDF
PHP traits, treat or threat?
ODP
Best practices tekx
Last train to php 7
Continuous Quality Assurance
PHP 7 Crash Course - php[world] 2015
CLI, the other SAPI
Mastering Namespaces in PHP
C++ basics
PHP traits, treat or threat?
Best practices tekx

What's hot (20)

PDF
HHVM and Hack: A quick introduction
PPT
Php Debugger
PPTX
Why choose Hack/HHVM over PHP7
DOCX
Perl 20tips
PPTX
HipHop Virtual Machine
PDF
Android debug bridge android developers
PDF
6 preprocessor macro header
PDF
Perl Programming - 02 Regular Expression
PPTX
Hack and HHVM
PPTX
Hack Programming Language
KEY
groovy & grails - lecture 6
PDF
Unit 5 quesn b ans5
PPTX
C - ISRO
PDF
Intro to Hack Language
PPTX
Unit 1-introduction to perl
PDF
Nginx pres
PDF
Fighting Fear-Driven-Development With PHPUnit
PDF
Preparing for the next php version
DOCX
Unit 5 quesn b ans5
ODP
PHP Basic
HHVM and Hack: A quick introduction
Php Debugger
Why choose Hack/HHVM over PHP7
Perl 20tips
HipHop Virtual Machine
Android debug bridge android developers
6 preprocessor macro header
Perl Programming - 02 Regular Expression
Hack and HHVM
Hack Programming Language
groovy & grails - lecture 6
Unit 5 quesn b ans5
C - ISRO
Intro to Hack Language
Unit 1-introduction to perl
Nginx pres
Fighting Fear-Driven-Development With PHPUnit
Preparing for the next php version
Unit 5 quesn b ans5
PHP Basic
Ad

Similar to Feature and platform testing with CMake (20)

PDF
LOSS_C11- Programming Linux 20221006.pdf
PPT
Autoconf&Automake
ODP
Makefile Generation From Autotools
PPTX
GCC RTL and Machine Description
PPTX
cs262_intro_slides.pptx
PDF
Prog1-L1.pdf
DOCX
1 CMPS 12M Introduction to Data Structures Lab La.docx
PPTX
C++ AND CATEGORIES OF SOFTWARE
DOCX
BACKGROUND A shell provides a command-line interface for users. I.docx
PPT
Lec 04 intro assembly
PDF
The Hitchhiker's Guide to Faster Builds. Viktor Kirilov. CoreHard Spring 2019
PPTX
Chapter 2
PPTX
Visual Studio 2010 and .NET 4.0 Overview
KEY
Código Saudável => Programador Feliz - Rs on Rails 2010
PPTX
MSDN Presents: Visual Studio 2010, .NET 4, SharePoint 2010 for Developers
PPT
Introduction to Programming Lesson 01
RTF
Readme
PDF
Lecture 3 getting_started_with__c_
PDF
Working Effectively With Legacy Perl Code
PDF
Java fx tools
LOSS_C11- Programming Linux 20221006.pdf
Autoconf&Automake
Makefile Generation From Autotools
GCC RTL and Machine Description
cs262_intro_slides.pptx
Prog1-L1.pdf
1 CMPS 12M Introduction to Data Structures Lab La.docx
C++ AND CATEGORIES OF SOFTWARE
BACKGROUND A shell provides a command-line interface for users. I.docx
Lec 04 intro assembly
The Hitchhiker's Guide to Faster Builds. Viktor Kirilov. CoreHard Spring 2019
Chapter 2
Visual Studio 2010 and .NET 4.0 Overview
Código Saudável => Programador Feliz - Rs on Rails 2010
MSDN Presents: Visual Studio 2010, .NET 4, SharePoint 2010 for Developers
Introduction to Programming Lesson 01
Readme
Lecture 3 getting_started_with__c_
Working Effectively With Legacy Perl Code
Java fx tools
Ad

More from Richard Thomson (11)

PPTX
Why I Use Visual Studio & ReSharper for C++
PDF
Vintage Computing Festival Midwest 18 2023-09-09 What's In A Terminal.pdf
PPTX
Automated Testing with CMake, CTest and CDash
PPTX
Consuming Libraries with CMake
PPTX
PPTX
SIMD Processing Using Compiler Intrinsics
PPTX
Modern C++
PPTX
Cross Platform Mobile Development with Visual Studio 2015 and C++
PDF
Consuming and Creating Libraries in C++
PPTX
Web mashups with NodeJS
PPTX
C traps and pitfalls for C++ programmers
Why I Use Visual Studio & ReSharper for C++
Vintage Computing Festival Midwest 18 2023-09-09 What's In A Terminal.pdf
Automated Testing with CMake, CTest and CDash
Consuming Libraries with CMake
SIMD Processing Using Compiler Intrinsics
Modern C++
Cross Platform Mobile Development with Visual Studio 2015 and C++
Consuming and Creating Libraries in C++
Web mashups with NodeJS
C traps and pitfalls for C++ programmers

Recently uploaded (20)

PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
Nekopoi APK 2025 free lastest update
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PDF
AI in Product Development-omnex systems
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
Digital Strategies for Manufacturing Companies
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
How Creative Agencies Leverage Project Management Software.pdf
PPTX
Transform Your Business with a Software ERP System
PDF
System and Network Administraation Chapter 3
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Reimagine Home Health with the Power of Agentic AI​
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Which alternative to Crystal Reports is best for small or large businesses.pdf
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Nekopoi APK 2025 free lastest update
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
AI in Product Development-omnex systems
2025 Textile ERP Trends: SAP, Odoo & Oracle
Navsoft: AI-Powered Business Solutions & Custom Software Development
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
VVF-Customer-Presentation2025-Ver1.9.pptx
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Digital Strategies for Manufacturing Companies
Upgrade and Innovation Strategies for SAP ERP Customers
How to Migrate SBCGlobal Email to Yahoo Easily
Design an Analysis of Algorithms I-SECS-1021-03
How Creative Agencies Leverage Project Management Software.pdf
Transform Your Business with a Software ERP System
System and Network Administraation Chapter 3
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...

Feature and platform testing with CMake

  • 1. Richard Thomson Senior Software Engineer, NVIDIA @LegalizeAdulthd http://LegalizeAdulthood.wordpress.com legalize@xmission.com
  • 2. Outline  Feature concerns  Platform concerns  Testing for C++ standard support  Testing for C++ language features  Testing for compiler option support  Testing for specific headers  Testing arbitrary code can compile  Testing for specific functions  Testing arbitrary code can run  Using the results of the tests
  • 3. Feature Concerns  Does the compiler support the minimum standard my code assumes?  Does the compiler support the minimum language features my code assumes?
  • 4. Platform Concerns  Does the compiler have headers my code assumes to exist?  Does the standard library have functions my code assumes to exist?  Is the compiler generating 32-bit or 64-bit code?  Does the compiler provide specific extensions?
  • 5. C++ Standard Support  If you need it, you need it...  Usually you won't conditionally compile your code for different versions of the standard  Rely on older releases for older standards  May want to explicitly state the assumed standard to avoid future incompatibilities  e.g. compile for C++11 with C++14/17/20/... features disabled
  • 6. Specifying C++ Standard for Targets  Target properties:  <LANG>_STANDARD:STRING  The requested standard version  C: 90, 99 or 11  CXX: 98, 11, 14, 17 (>= 3.8), or 20 (>= 3.12)  CUDA: 98 or 11  <LANG>_STANDARD_REQUIRED:BOOL  Hard error if the standard is not supported  <LANG>_EXTENSIONS:BOOL  Enable compiler extensions  Always set along with <LANG>_STANDARD
  • 7. Specifying C++ Standard Globally  Target properties initialized from global properties:  CMAKE_<LANG>_STANDARD  CMAKE_<LANG>_STANDARD_REQUIRED  CMAKE_<LANG>_EXTENSIONS  Easiest way to ensure all targets are compiled consistently  Can override with target properties if a mix is needed
  • 8. C++ Language Features for Targets target_compile_features( <target> <PRIVATE|PUBLIC|INTERFACE> feature1 [feature2...] [<PRIVATE|PUBLIC|INTERFACE> feature3 [feature4....]] ... )  Sets target properties COMPILE_FEATURES, INTERFACE_COMPILE_FEATURES  CMAKE_<LANG>_KNOWN_FEATURES contains all known features for the compiler, e.g. cxx_alignas. Consult documentation for supported list of language features.  If you only use a few "modern" features, may be useful to require specific features instead of full standard support  The strongest requirement between standard versions and compiler features wins, e.g. transitive compiler dependencies
  • 9. Detecting and Using Optional Features  Use generator expressions target_compile_features( foo PUBLIC $<$<COMPILE_FEATURES:cxx_override>:cxx_override> ) target_compile_definitions( foo PUBLIC $<$<COMPILE_FEATURES:cxx_override>:-Dfoo_OVERRIDE=override> $<NOT $<COMPILE_FEATURES:cxx_override>>:-Dfoo_OVERRIDE=> )  Use WriteCompilerDetectionHeader module: include(WriteCompilerDetectionHeader) write_compiler_detection_header( FILE foo_compiler_detection.h PREFIX foo COMPILERS GNU Clang MSVC Intel FEATURES cxx_override )  Allows you to use CMAKE_CXX_STANDARD with CMAKE_CXX_STANDARD_REQUIRED set to OFF
  • 10. Check Modules  CMake ships with a variety of check modules  Generally implemented by compiling a piece of boiler plate code  May also link and run the boiler plate  Results are stored in cache variables  Checks are only executed once during initial configure  Variables control the compilation and link
  • 11. Useful Check Modules  CheckCXXCompilerFlag  CheckCXXSymbolExists  CheckIncludeFileCXX  CheckLibraryExists  CheckPrototypeDefinition  CheckStructHasMember  CheckTypeSize  CheckCXXSourceCompiles  CheckCXXSourceRuns
  • 12. Variables Affecting Check Modules  Variables affecting the boiler plate:  CMAKE_REQUIRED_FLAGS  CMAKE_REQUIRED_DEFINITIONS  CMAKE_REQUIRED_INCLUDES  CMAKE_REQUIRED_LIBRARIES  CMAKE_REQUIRED_QUIET  Set the variables before calling the specific check command  CMake does not use these variables for regular compilation
  • 13. Testing for C++ Compiler Flags  Maybe you want an Address Sanitizer (ASan) build if the compiler supports it  Support varies based on compiler version  Testing compiler and version combinations is tedious and fragile  CheckCXXCompilerFlag module: include(CheckCXXCompilerFlag) check_cxx_compiler_flag(-fsanitize=address ASanSupported) if(ASanSupported) # ... endif()
  • 14. Testing for Specific Functions  CheckCXXSymbolExists can find a symbol that identifies a macro, variable or C style function using the C++ compiler.  CheckPrototypeDefinition can check that a declared C function matches the expected prototype check_prototype_definition(getpwent_r "struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)" "NULL" "unistd.h;pwd.h" SOLARIS_GETPWENT_R)  Use CheckCXXSourceCompiles for other cases
  • 15. Testing for Specific Headers  CheckIncludeFileCXX validates that a header can be included in C++ include(CheckIncludeFileCXX) check_include_file_cxx("sstream" haveSStream)  CheckIncludeFile, CheckIncludeFiles provides similar functionality for C headers
  • 16. Testing for Specific Libraries  CheckLibraryExists can find a function in a library  CheckCXXSourceCompiles can be used to attempt to call a function in a library and link against it
  • 17. Testing Code Compiles  CheckCSourceCompiles for C  CheckCXXSourceCompiles for C++ include(CheckCXXSourceCompiles) check_cxx_source_compiles(" int main(int argc, char *argv[]) { int myVar; return 0; }" noWarnUnused FAIL_REGEX "[Ww]arn") if(noWarnUnused) message("Unused variables don't warn") endif()
  • 18. Testing Code Runs  CheckCSourceRuns for C  CheckCXXSourceRuns for C++ include(CheckCXXSourceRuns) check_cxx_source_runs(" int main() { return 1; // still runs OK }" runsOK) if(runsOK) message("Code ran OK") endif()
  • 19. What To Do With The Results?  Checks result in variables being set  Use the variables in generator expressions  Use the variables in target properties  Use the variables to configure header files
  • 20. Generator Expressions  Used during build system generation to produce information specific to a build configuration  Use for information that varies between debug or release, for instance target_compile_definitions( foo PUBLIC <$<CONFIG:Debug>:DEBUG>)  Be careful about sense of true/false  CMake considers 1, ON, TRUE, YES to be truthy  Generator expressions only consider 1 to be truthy  Rich syntax, see documentation for full details
  • 21. Common Generator Expressions  $<BOOL:...> Evaluate CMake truthy  $<AND:?[,?]...> 1 if all ?s are 1  $<OR:?[,?]...> 1 if any ?s are 1  $<NOT:?> 1 if ? is 0, 0 if ? is 1  $<TARGET_EXISTS:tgt> 1 if target tgt exists  $<CONFIG:cfg> 1 if cfg is config  $<PLATFORM_ID:id> 1 if id is platform  $<COMPILER_ID:id> 1 if id is compiler
  • 22. Informational Generator Expressions  Return some kind of information instead of 0,1  $<CONFIG> Configuration name  $<PLATFORM_ID> Platform name  $<COMPILER_ID> Compiler name  $<TARGET_FILE:tgt> Full path to target  $<TARGET_PROPERTY:tgt,prop> Value of prop
  • 23. Output Generator Expressions  Combine inputs to produce an output  $<0:?> Empty string (ignores ?)  $<1:?> Content of ?  $<JOIN:list,glue> Join items in list with glue  $<LOWER_CASE:?> ? converted to lower case  $<UPPER_CASE:?> ? converted to upper case  $<MAKE_C_IDENTIFIER:?> ? as C identifier
  • 24. Recommended Overall Strategy  Test for things you use  Don't test for OS/version combinations  Don't test for compiler/version combinations  For things you need, fail if not found  For optional things, write a configuration header
  • 25. Configuring Files cmake_configure_file( <input> <output> [COPYONLY] [ESCAPE_QUOTES] [@ONLY] [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ] )  Writes an output file from an input file template, substituting variable references in the template.  Template in the source tree, e.g. foo.h.in  Output in the binary tree, e.g. foo.h
  • 26. Common configure_file Constructs  #cmakedefine VAR ... Depending on truthiness of VAR, expands to ○ #define VAR ... ○ /* #undef VAR */  #cmakedefine01 VAR Depending on truthiness of VAR, expands to ○ #define VAR 1 ○ #define VAR 0  @VAR@ expands to value of VAR, without @s
  • 27. configure_file Example Template // foo_features.h #pragma once #cmakedefine01 HAVE_STD_MEMCMP #cmakedefine01 HAVE_STD_STRCMP #cmakedefine01 HAVE_C_MEMCMP #cmakedefine01 HAVE_C_STRCMP #cmakedefine01 HAVE_C_BCMP
  • 28. configure_file Set Variables include(CheckSymbolExists) include(CheckCXXSourceCompiles) check_cxx_source_compiles([=[ #include <cstring> int main() { return std::memcmp("", "", 0); } ]=] HAVE_STD_MEMCMP) check_cxx_source_compiles([=[ #include <cstring> int main() { return std::strcmp("", ""); } ]=] HAVE_STD_STRCMP) check_symbol_exists("memcmp" "string.h" HAVE_C_MEMCMP) check_symbol_exists("strcmp" "string.h" HAVE_C_STRCMP) check_symbol_exists("bcmp" "strings.h" HAVE_C_BCMP)
  • 29. configure_file Example Usage configure_file(foo_features.h.in foo_features.h) add_executable(foo foo.cpp "${CMAKE_CURRENT_BINARY_DIR}/foo_features.h") target_include_directories(foo PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
  • 30. configure_file CMake Output -- Performing Test HAVE_STD_MEMCMP -- Performing Test HAVE_STD_MEMCMP - Success -- Performing Test HAVE_STD_STRCMP -- Performing Test HAVE_STD_STRCMP - Success -- Looking for memcmp -- Looking for memcmp - found -- Looking for strcmp -- Looking for strcmp - found -- Looking for bcmp -- Looking for bcmp - not found -- Configuring done -- Generating done
  • 31. configure_file Resulting Header // foo_features.h #pragma once #define HAVE_STD_MEMCMP 1 #define HAVE_STD_STRCMP 1 #define HAVE_C_MEMCMP 1 #define HAVE_C_STRCMP 1 #define HAVE_C_BCMP 0
  • 32. Using Configured Header #include <foo_features.h> #include <iostream> #if HAVE_STD_MEMCMP || HAVE_STD_STRCMP #include <cstring> #endif #if HAVE_C_MEMCMP || HAVE_C_STRCMP #include <string.h> #endif #if HAVE_C_BCMP #include <strings.h> #endif int main() { #if HAVE_STD_MEMCMP std::cout << "Have std::memcmpn"; #endif #if HAVE_STD_STRCMP std::cout << "Have std::strcmpn"; #endif #if HAVE_C_MEMCMP std::cout << "Have C memcmpn"; #endif #if HAVE_C_STRCMP std::cout << "Have C strcmpn"; #endif #if HAVE_C_BCMP std::cout << "Have C bcmpn"; #endif return 0; }
  • 33. Program Output Have std::memcmp Have std::strcmp Have C memcmp Have C strcmp