Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add macro to assist in checking if code snippets compile #600

Merged
merged 5 commits into from
Oct 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The project release numbers follow [Semantic Versioning](http://semver.org/spec/

### Added
- Added `blt_convert_to_system_includes` macro to convert existing interface includes to system interface includes.
- `blt_check_code_compiles` which compiles a C++ code snippet and returns the result.

### Changed
- Added three extra options to `blt_print_target_properties` macro to print properties of
Expand Down
7 changes: 7 additions & 0 deletions SetupBLT.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ if (NOT BLT_LOADED)
cmake_policy(SET CMP0057 NEW)
endif()

# Make `check_cxx_source_compiles` honor `CMAKE_CXX_STANDARD`
# NOTE: This only works on a few CMake versions even though it was
# added in CMake 3.14. (for example, 3.20.2, 3.21.1, and 3.23.1 did not work)
if(POLICY CMP0067)
cmake_policy(SET CMP0067 NEW)
endif()

# Policy to use <PackageName>_ROOT variable in find_<Package> commands
# Policy added in 3.12+
if(POLICY CMP0074)
Expand Down
72 changes: 72 additions & 0 deletions cmake/BLTMacros.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -1425,3 +1425,75 @@ macro(blt_convert_to_system_includes)
unset(_include_dirs)
endmacro()


##------------------------------------------------------------------------------
## blt_check_code_compiles(CODE_COMPILES <variable>
## VERBOSE_OUTPUT <ON|OFF (default OFF)>
## SOURCE_STRING <quoted C++ program>)
##
## This macro checks if a snippet of C++ code compiles.
##
## SOURCE_STRING The source snippet to compile.
## Must be a valid C++ program with a main() function.
## Note: This parameter should be passed in as a quoted string variable. Otherwise,
## cmake will convert the string into a list and lose the semicolons.
## E.g. blt_check_code_compiles(SOURCE_STRING "${str_var}" ...)
##
## CODE_COMPILES A boolean variable the contains the compilation result.
##
## VERBOSE_OUTPUT Optional parameter to output debug information (Default: off)
##------------------------------------------------------------------------------
macro(blt_check_code_compiles)

set(options)
set(singleValueArgs CODE_COMPILES VERBOSE_OUTPUT )
# NOTE: SOURCE_STRING must be a multiValueArg otherwise CMake removes all semi-colons
set(multiValueArgs SOURCE_STRING)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does SOURCE_STRING need to be a multiValueArg because it can have embedded semicolons?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i bet it shouldn't actually.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried changing this to a single value arg and it removed all the semi-colons.


# Parse the arguments to the macro
cmake_parse_arguments(arg
"${options}" "${singleValueArgs}" "${multiValueArgs}" ${ARGN})

# Check the arguments
if(NOT DEFINED arg_SOURCE_STRING)
message(FATAL_ERROR "blt_check_code_compiles() requires SOURCE_STRING to be specified")
endif()

if(NOT DEFINED arg_CODE_COMPILES)
message(FATAL_ERROR "blt_check_code_compiles() requires CODE_COMPILES to be specified")
endif()

if(NOT DEFINED arg_VERBOSE_OUTPUT)
set(arg_VERBOSE_OUTPUT FALSE)
endif()

if(${arg_VERBOSE_OUTPUT})
message(STATUS "[blt_check_code_compiles] Attempting to compile source string: \n${arg_SOURCE_STRING}")
endif()

# Write string as temp file, try to compile it and then remove file
string(RANDOM LENGTH 5 _rand)
set(_fname ${CMAKE_CURRENT_BINARY_DIR}/_bltCheckCompiles${_rand}.cpp)
file(WRITE ${_fname} "${arg_SOURCE_STRING}")
try_compile(${arg_CODE_COMPILES}
${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp
SOURCES ${_fname}
CXX_STANDARD ${CMAKE_CXX_STANDARD}
OUTPUT_VARIABLE _res)
file(REMOVE ${_fname})

if(${arg_VERBOSE_OUTPUT})
message(STATUS "[blt_check_code_compiles] Compiler output: \n${_res}\n")

if(${arg_CODE_COMPILES})
message(STATUS "[blt_check_code_compiles] The code snippet successfully compiled")
else()
message(STATUS "[blt_check_code_compiles] The code snippet failed to compile")
endif()
endif()

# clear the variables set within the macro
unset(_fname)
unset(_res)

endmacro(blt_check_code_compiles)
48 changes: 48 additions & 0 deletions docs/api/utility.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,54 @@ When using the Intel toolchain within Visual Studio, we use the
``MSVC_INTEL`` flag, when provided, with a fallback to the ``MSVC`` flag.


.. blt_check_code_compiles:

blt_check_code_compiles
~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: cmake

blt_check_code_compiles(CODE_COMPILES <variable>
VERBOSE_OUTPUT <ON|OFF (default OFF)>
SOURCE_STRING <quoted C++ program>)

This macro checks if a snippet of C++ code compiles.

CODE_COMPILES
The boolean variable that will be filled with the compilation result.

VERBOSE_OUTPUT
Optional parameter to output debug information (Default: OFF)

SOURCE_STRING
The source snippet to compile.

``SOURCE_STRING`` must be a valid C++ program with a main() function and
must be passed in as a quoted string variable. Otherwise, CMake will convert
the string into a list and lose the semicolons. You can use any CMake method
of sending a string, but we recommend the
`bracket argument method <https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#bracket-argument>`_
shown below so you do not have to escape your quotes:

.. code-block:: cmake

blt_check_code_compiles(CODE_COMPILES hello_world_compiled
SOURCE_STRING
[=[
#include <iostream>

int main(int, char**)
{

std::cout << "Hello World!" << std::endl;

return 0;
}
]=])




.. _blt_find_libraries:

blt_find_libraries
Expand Down
22 changes: 22 additions & 0 deletions tests/internal/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,25 @@ message(
"Tests passed for `blt_split_source_list_by_language`.\n"
"*****************************************************")

message(STATUS "Checking for blt_check_code_compiles")

blt_check_code_compiles(CODE_COMPILES _hello_world_compiled
VERBOSE_OUTPUT ON
SOURCE_STRING
[=[
#include <iostream>

int main(int, char**)
{

std::cout << "Hello World!" << std::endl;

return 0;
}
]=])

if(_hello_world_compiled)
message(STATUS "... passed")
else()
message(FATAL_ERROR "... failed to compile.")
endif()