2017-10-24 01:00:40 +02:00
cmake_minimum_required ( VERSION 3.3.0 FATAL_ERROR )
# prevent multiple inclusion
if ( DEFINED REFLECTION_GENERATOR_MODULE_LOADED )
return ( )
endif ( )
set ( REFLECTION_GENERATOR_MODULE_LOADED YES )
# find code generator
2017-11-03 22:41:51 +01:00
set ( DEFAULT_REFLECTION_GENERATOR_EXECUTABLE "reflective_rapidjson_generator" )
2018-01-20 18:10:58 +01:00
set ( REFLECTION_GENERATOR_EXECUTABLE "" CACHE FILEPATH "path to executable of reflection generator" )
if ( REFLECTION_GENERATOR_EXECUTABLE )
2017-11-03 22:41:51 +01:00
# use custom generator executable
2018-01-20 18:10:58 +01:00
if ( NOT EXISTS "${REFLECTION_GENERATOR_EXECUTABLE}" OR IS_DIRECTORY "${REFLECTION_GENERATOR_EXECUTABLE}" )
message ( FATAL_ERROR "The specified code generator executable \" ${ REFLECTION_GENERATOR_EXECUTABLE } \" is not a file. " )
2017-11-03 22:41:51 +01:00
endif ( )
elseif ( CMAKE_CROSSCOMPILING OR NOT TARGET "${DEFAULT_REFLECTION_GENERATOR_EXECUTABLE}" )
# find native/external "reflective_rapidjson_generator"
2018-01-20 21:15:14 +01:00
find_program ( REFLECTION_GENERATOR_EXECUTABLE
" $ { D E F A U L T _ R E F L E C T I O N _ G E N E R A T O R _ E X E C U T A B L E } "
P A T H S " / u s r / b i n " " / b i n "
)
2017-11-03 22:41:51 +01:00
else ( )
# use "reflective_rapidjson_generator" target
set ( REFLECTION_GENERATOR_EXECUTABLE "${DEFAULT_REFLECTION_GENERATOR_EXECUTABLE}" )
2017-10-24 01:00:40 +02:00
endif ( )
if ( NOT REFLECTION_GENERATOR_EXECUTABLE )
2018-01-20 18:10:58 +01:00
message ( FATAL_ERROR "Unable to find executable of generator for reflection code. Set REFLECTION_GENERATOR_EXECUTABLE to specify the path." )
2017-10-24 01:00:40 +02:00
endif ( )
2018-02-03 15:44:10 +01:00
# determine Clang's resource directory
set ( REFLECTION_GENERATOR_CLANG_RESOURCE_DIR "" CACHE PATH "directory containing Clang's builtin headers, usually /usr/lib/clang/version" )
if ( NOT REFLECTION_GENERATOR_CLANG_RESOURCE_DIR )
if ( NOT REFLECTION_GENERATOR_CLANG_BIN )
find_program ( REFLECTION_GENERATOR_CLANG_BIN clang
N A M E S c l a n g + +
P A T H S " / u s r / b i n " " / b i n "
)
if ( NOT REFLECTION_GENERATOR_CLANG_BIN )
message ( FATAL_ERROR "Unable to find the clang executable to determine Clang's resource directory" )
endif ( )
endif ( )
exec_program ( ${ REFLECTION_GENERATOR_CLANG_BIN } ARGS -print-resource-dir OUTPUT_VARIABLE REFLECTION_GENERATOR_CLANG_RESOURCE_DIR )
endif ( )
if ( NOT REFLECTION_GENERATOR_CLANG_RESOURCE_DIR OR NOT IS_DIRECTORY "${REFLECTION_GENERATOR_CLANG_RESOURCE_DIR}" )
message ( FATAL_ERROR "Unable to find Clang's resource directory. Set REFLECTION_GENERATOR_CLANG_RESOURCE_DIR manually to the corresponding path (usually /usr/lib/clang/\$version)." )
endif ( )
message ( STATUS "Using ${REFLECTION_GENERATOR_CLANG_RESOURCE_DIR} as Clang's resource directory for Reflective RapidJSON" )
# allow to specify a custom include paths (useful for cross-compilation when header files are under custom prefix)
set ( REFLECTION_GENERATOR_INCLUDE_DIRECTORIES "" CACHE FILEPATH "include directories for code generator" )
# allow to specify a custom platform tiple (useful for cross-compilation to specify the target platform)
set ( REFLECTION_GENERATOR_TRIPLE "" CACHE STRING "platform triple for code generator" )
2018-01-20 18:10:58 +01:00
2017-11-17 21:42:49 +01:00
# define helper function to add a reflection generator invocation for a specified list of source files
2017-10-24 01:00:40 +02:00
include ( CMakeParseArguments )
function ( add_reflection_generator_invocation )
# parse arguments
2017-11-17 21:42:49 +01:00
set ( OPTIONAL_ARGS
)
set ( ONE_VALUE_ARGS
O U T P U T _ D I R E C T O R Y
J S O N _ V I S I B I L I T Y
)
set ( MULTI_VALUE_ARGS
I N P U T _ F I L E S
G E N E R A T O R S
O U T P U T _ L I S T S
C L A N G _ O P T I O N S
C L A N G _ O P T I O N S _ F R O M _ T A R G E T S
J S O N _ C L A S S E S )
2017-10-24 01:00:40 +02:00
cmake_parse_arguments ( ARGS "${OPTIONAL_ARGS}" "${ONE_VALUE_ARGS}" "${MULTI_VALUE_ARGS}" ${ ARGN } )
# determine file name or file path if none specified
2017-10-25 17:32:03 +02:00
if ( NOT ARGS_OUTPUT_DIRECTORY )
set ( ARGS_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/reflection" )
file ( MAKE_DIRECTORY "${ARGS_OUTPUT_DIRECTORY}" )
2017-10-24 01:00:40 +02:00
endif ( )
2018-02-03 15:44:10 +01:00
# specify Clang's resource directory
list ( APPEND ARGS_CLANG_OPTIONS -resource-dir "${REFLECTION_GENERATOR_CLANG_RESOURCE_DIR}" )
# apply specified REFLECTION_GENERATOR_TRIPLET
if ( REFLECTION_GENERATOR_TRIPLE )
list ( APPEND ARGS_CLANG_OPTIONS
- X c l a n g - t r i p l e
- X c l a n g " $ { R E F L E C T I O N _ G E N E R A T O R _ T R I P L E } "
)
endif ( )
2018-01-20 18:10:58 +01:00
# apply specified REFLECTION_GENERATOR_INCLUDE_DIRECTORIES
foreach ( INCLUDE_DIR ${ REFLECTION_GENERATOR_INCLUDE_DIRECTORIES } )
2018-02-03 15:44:10 +01:00
list ( APPEND ARGS_CLANG_OPTIONS -I "${INCLUDE_DIR}" )
2018-01-20 18:10:58 +01:00
endforeach ( )
2018-02-03 15:44:10 +01:00
# add workaround for cross compiling with mingw-w64 to prevent host stdlib.h being included
# (not sure why specifying REFLECTION_GENERATOR_INCLUDE_DIRECTORIES is not enough to let it find this particular header file)
2018-01-20 18:10:58 +01:00
if ( MINGW )
2018-02-03 15:44:10 +01:00
# find MinGW version of stdlib.h
2018-01-20 18:10:58 +01:00
find_file ( MINGW_W64_STDLIB_H stdlib.h ${ REFLECTION_GENERATOR_INCLUDE_DIRECTORIES } )
if ( NOT EXISTS "${MINGW_W64_STDLIB_H}" )
message ( FATAL_ERROR "Unable to locate MinGW version of stdlib.h. Ensure it is in REFLECTION_GENERATOR_INCLUDE_DIRECTORIES." )
endif ( )
2018-02-03 15:44:10 +01:00
# ensure libtooling includes the MinGW version of stdlib.h rather than the host version
2018-01-20 18:10:58 +01:00
list ( APPEND ARGS_CLANG_OPTIONS
2018-02-03 15:44:10 +01:00
- i n c l u d e " $ { M I N G W _ W 6 4 _ S T D L I B _ H } "
- D _ S T D L I B _ H # prevent processing of host stdlib.h
2018-01-20 18:10:58 +01:00
)
endif ( )
2017-11-17 21:42:49 +01:00
# add options to be passed to clang from the specified targets
if ( ARGS_CLANG_OPTIONS_FROM_TARGETS )
foreach ( TARGET_NAME ${ ARGS_CLANG_OPTIONS_FROM_TARGETS } )
# add compile flags
set ( PROP "$<TARGET_PROPERTY:${TARGET_NAME},COMPILE_FLAGS>" )
list ( APPEND ARGS_CLANG_OPTIONS "$<$<BOOL:${PROP}>:$<JOIN:${PROP},$<SEMICOLON>>>" )
# add compile definitions
set ( PROP "$<TARGET_PROPERTY:${TARGET_NAME},COMPILE_DEFINITIONS>" )
list ( APPEND ARGS_CLANG_OPTIONS "$<$<BOOL:${PROP}>:-D$<JOIN:${PROP},$<SEMICOLON>-D>>" )
# add include directories
set ( PROP "$<TARGET_PROPERTY:${TARGET_NAME},INCLUDE_DIRECTORIES>" )
list ( APPEND ARGS_CLANG_OPTIONS "$<$<BOOL:${PROP}>:-I$<JOIN:${PROP},$<SEMICOLON>-I>>" )
endforeach ( )
endif ( )
# create a custom command for each input file
2017-10-25 17:32:03 +02:00
foreach ( INPUT_FILE ${ ARGS_INPUT_FILES } )
2017-11-17 21:42:49 +01:00
# determine the output file
2017-10-25 17:32:03 +02:00
get_filename_component ( OUTPUT_NAME "${INPUT_FILE}" NAME_WE )
set ( OUTPUT_FILE "${ARGS_OUTPUT_DIRECTORY}/${OUTPUT_NAME}.h" )
message ( STATUS "Adding generator command for ${INPUT_FILE} producing ${OUTPUT_FILE}" )
2017-11-17 21:42:49 +01:00
# compose the CLI arguments and actually add the custom command
2017-11-11 12:37:24 +01:00
set ( CLI_ARGUMENTS
- - o u t p u t - f i l e " $ { O U T P U T _ F I L E } "
- - i n p u t - f i l e " $ { I N P U T _ F I L E } "
- - g e n e r a t o r s $ { A R G S _ G E N E R A T O R S }
- - c l a n g - o p t $ { A R G S _ C L A N G _ O P T I O N S }
- - j s o n - c l a s s e s $ { A R G S _ J S O N _ C L A S S E S }
)
if ( ARGS_JSON_VISIBILITY )
list ( APPEND CLI_ARGUMENTS --json-visibility "${ARGS_JSON_VISIBILITY}" )
endif ( )
2017-10-25 17:32:03 +02:00
add_custom_command (
O U T P U T " $ { O U T P U T _ F I L E } "
C O M M A N D " $ { R E F L E C T I O N _ G E N E R A T O R _ E X E C U T A B L E } "
2017-11-11 12:37:24 +01:00
A R G S $ { C L I _ A R G U M E N T S }
2017-10-25 17:32:03 +02:00
D E P E N D S " $ { I N P U T _ F I L E } "
W O R K I N G _ D I R E C T O R Y " $ { C M A K E _ C U R R E N T _ S O U R C E _ D I R } "
C O M M E N T " G e n e r a t i n g r e f l e c t i o n c o d e f o r $ { I N P U T _ F I L E } "
2017-11-17 21:42:49 +01:00
V E R B A T I M
2017-10-25 17:32:03 +02:00
)
2017-10-24 01:00:40 +02:00
2017-10-25 17:32:03 +02:00
# append the output file to lists specified via OUTPUT_LISTS
if ( ARGS_OUTPUT_LISTS )
foreach ( OUTPUT_LIST ${ ARGS_OUTPUT_LISTS } )
list ( APPEND "${OUTPUT_LIST}" "${OUTPUT_FILE}" )
set ( "${OUTPUT_LIST}" "${${OUTPUT_LIST}}" PARENT_SCOPE )
endforeach ( )
endif ( )
endforeach ( )
2017-10-24 01:00:40 +02:00
endfunction ( )