We will use both try_compile and check_cxx_source_compiles and compare how the two commands work:
- We first create a C++11 project:
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
project(recipe-06 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
- We find OpenMP support for the compiler:
find_package(OpenMP)
if(OpenMP_FOUND)
# ... <- the steps below will be placed here
else()
message(STATUS "OpenMP not found: no test for taskloop is run")
endif()
- If OpenMP was found, we move forward and probe whether the desired feature is available. To this end, we set a scratch directory. This will be used by try_compile to generate its intermediate files. We place this inside the if-clause introduced in the previous step:
set(_scratch_dir ${CMAKE_CURRENT_BINARY_DIR}/omp_try_compile)
- We call try_compile to generate a small project to attempt compiling the source file taskloop.cpp. Success or failure will be saved into the omp_taskloop_test_1 variable. We need to set appropriate compiler flags, include directories, and link libraries for this small sample compilation. Since we are using the imported target OpenMP::OpenMP_CXX, this is simply done by setting the LINK_LIBRARIES option to try_compile. If compilation succeeds, then the task loop feature is available and we print a message for the user:
try_compile(
omp_taskloop_test_1
${_scratch_dir}
SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/taskloop.cpp
LINK_LIBRARIES
OpenMP::OpenMP_CXX
)
message(STATUS "Result of try_compile: ${omp_taskloop_test_1}")
- To use the check_cxx_source_compiles function, we need to include the CheckCXXSourceCompiles.cmake module file. This is distributed with CMake, alongside similar files for C (CheckCSourceCompiles.cmake) and Fortran (CheckFortranSourceCompiles.cmake):
include(CheckCXXSourceCompiles)
- We copy the contents of the source file we are attempting to compile and link into a CMake variable by reading its contents with the file(READ ...) command:
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/taskloop.cpp _snippet)
- We set CMAKE_REQUIRED_LIBRARIES. This is needed for the correct invocation of the compiler in the next step. Note the use of the imported OpenMP::OpenMP_CXX target, which will set also the proper compiler flags and include directories:
set(CMAKE_REQUIRED_LIBRARIES OpenMP::OpenMP_CXX)
- We invoke the check_cxx_source_compiles function with our code snippet. The result of the check will be saved into the omp_taskloop_test_2 variable:
check_cxx_source_compiles("${_snippet}" omp_taskloop_test_2)
- We unset the variables defined before calling check_cxx_source_compiles and print a message to the user:
unset(CMAKE_REQUIRED_LIBRARIES)
message(STATUS "Result of check_cxx_source_compiles: ${omp_taskloop_test_2}"
- Finally, we test the recipe:
$ mkdir -p build
$ cd build
$ cmake ..
-- ...
-- Found OpenMP_CXX: -fopenmp (found version "4.5")
-- Found OpenMP: TRUE (found version "4.5")
-- Result of try_compile: TRUE
-- Performing Test omp_taskloop_test_2
-- Performing Test omp_taskloop_test_2 - Success
-- Result of check_cxx_source_compiles: 1