2018-10-24 13:20:27 +00:00
function ( qt_feature_module_begin )
qt_parse_all_arguments ( _arg "qt_feature_module_begin"
" " " L I B R A R Y ; P R I V A T E _ F I L E ; P U B L I C _ F I L E " " P U B L I C _ D E P E N D E N C I E S ; P R I V A T E _ D E P E N D E N C I E S " $ { A R G N } )
if ( "${_arg_LIBRARY}" STREQUAL "" )
message ( FATAL_ERROR "qt_feature_begin_module needs a LIBRARY name!" )
endif ( )
if ( "${_arg_PUBLIC_FILE}" STREQUAL "" )
message ( FATAL_ERROR "qt_feature_begin_module needs a PUBLIC_FILE name!" )
endif ( )
if ( "${_arg_PRIVATE_FILE}" STREQUAL "" )
message ( FATAL_ERROR "qt_feature_begin_module needs a PRIVATE_FILE name!" )
endif ( )
set ( __QtFeature_library "${_arg_LIBRARY}" PARENT_SCOPE )
set ( __QtFeature_private_features "" PARENT_SCOPE )
set ( __QtFeature_public_features "" PARENT_SCOPE )
set ( __QtFeature_private_file "${_arg_PRIVATE_FILE}" PARENT_SCOPE )
set ( __QtFeature_public_file "${_arg_PUBLIC_FILE}" PARENT_SCOPE )
set ( __QtFeature_private_extra "" PARENT_SCOPE )
set ( __QtFeature_public_extra "" PARENT_SCOPE )
2018-11-02 10:42:58 +00:00
qt_push_features_into_parent_scope ( )
2018-10-24 13:20:27 +00:00
endfunction ( )
function ( qt_feature _feature )
qt_parse_all_arguments ( _arg "qt_feature"
" P R I V A T E ; P U B L I C "
" L A B E L ; P U R P O S E ; S E C T I O N ; " " A U T O D E T E C T ; C O N D I T I O N ; E N A B L E ; D I S A B L E ; E M I T _ I F " $ { A R G N } )
2018-10-25 12:28:06 +00:00
set ( _QT_FEATURE_DEFINITION_ ${ _feature } ${ ARGN } PARENT_SCOPE )
2018-10-25 11:16:42 +00:00
# Register feature for future use:
if ( _arg_PUBLIC )
list ( APPEND __QtFeature_public_features "${_feature}" )
2018-10-24 13:20:27 +00:00
endif ( )
2018-10-25 11:16:42 +00:00
if ( _arg_PRIVATE )
list ( APPEND __QtFeature_private_features "${_feature}" )
2018-10-24 13:20:27 +00:00
endif ( )
2018-10-25 11:16:42 +00:00
2018-10-24 13:20:27 +00:00
set ( __QtFeature_public_features ${ __QtFeature_public_features } PARENT_SCOPE )
set ( __QtFeature_private_features ${ __QtFeature_private_features } PARENT_SCOPE )
endfunction ( )
function ( qt_evaluate_to_boolean expressionVar )
if ( ${ ${expressionVar } } )
set ( ${ expressionVar } ON PARENT_SCOPE )
else ( )
set ( ${ expressionVar } OFF PARENT_SCOPE )
endif ( )
endfunction ( )
function ( qt_evaluate_config_expression resultVar )
set ( result "" )
set ( nestingLevel 0 )
set ( skipNext OFF )
set ( expression "${ARGN}" )
list ( LENGTH expression length )
math ( EXPR length "${length}-1" )
foreach ( memberIdx RANGE ${ length } )
if ( ${ skipNext } )
set ( skipNext OFF )
continue ( )
endif ( )
list ( GET expression ${ memberIdx } member )
if ( "${member}" STREQUAL "(" )
if ( ${ nestingLevel } GREATER 0 )
list ( APPEND result ${ member } )
endif ( )
math ( EXPR nestingLevel "${nestingLevel} + 1" )
continue ( )
elseif ( "${member}" STREQUAL ")" )
math ( EXPR nestingLevel "${nestingLevel} - 1" )
if ( nestingLevel LESS 0 )
break ( )
endif ( )
if ( ${ nestingLevel } EQUAL 0 )
qt_evaluate_config_expression ( result ${ result } )
else ( )
list ( APPEND result ${ member } )
endif ( )
continue ( )
elseif ( ${ nestingLevel } GREATER 0 )
list ( APPEND result ${ member } )
continue ( )
elseif ( "${member}" STREQUAL "NOT" )
list ( APPEND result ${ member } )
continue ( )
elseif ( "${member}" STREQUAL "AND" )
qt_evaluate_to_boolean ( result )
if ( NOT ${ result } )
break ( )
endif ( )
set ( result "" )
elseif ( "${member}" STREQUAL "OR" )
qt_evaluate_to_boolean ( result )
if ( ${ result } )
break ( )
endif ( )
set ( result "" )
elseif ( "${member}" STREQUAL "STREQUAL" AND memberIdx LESS ${ length } )
# Unfortunately the semantics for STREQUAL in if() are broken when the
# RHS is an empty string and the parameters to if are coming through a variable.
2018-10-25 11:16:42 +00:00
# So we expect people to write the empty string with single quotes and then we
2018-10-24 13:20:27 +00:00
# do the comparison manually here.
list ( LENGTH result lhsIndex )
math ( EXPR lhsIndex "${lhsIndex}-1" )
list ( GET result ${ lhsIndex } lhs )
list ( REMOVE_AT result ${ lhsIndex } )
set ( lhs "${${lhs}}" )
math ( EXPR rhsIndex "${memberIdx}+1" )
set ( skipNext ON )
list ( GET expression ${ rhsIndex } rhs )
# We can't pass through an empty string with double quotes through various
# stages of substitution, so instead it is represented using single quotes
# and resolve here.
string ( REGEX REPLACE "'(.*)'" "\\1" rhs "${rhs}" )
string ( COMPARE EQUAL "${lhs}" "${rhs}" stringCompareResult )
list ( APPEND result ${ stringCompareResult } )
else ( )
string ( FIND "${member}" "QT_FEATURE_" idx )
if ( idx EQUAL 0 )
# Remove the QT_FEATURE_ prefix
string ( SUBSTRING "${member}" 11 -1 feature )
qt_evaluate_feature ( ${ feature } )
endif ( )
list ( APPEND result ${ member } )
endif ( )
endforeach ( )
if ( "${result}" STREQUAL "" )
set ( result ON )
else ( )
qt_evaluate_to_boolean ( result )
endif ( )
set ( ${ resultVar } ${ result } PARENT_SCOPE )
endfunction ( )
2018-10-26 09:49:58 +00:00
function ( qt_feature_set_cache_value resultVar feature emit_if calculated label )
if ( DEFINED "FEATURE_${feature}" )
# Must set up the cache
if ( NOT ( emit_if ) )
message ( FATAL_ERROR "Sanity check failed: FEATURE_${feature} that was not emitted was found in the CMakeCache." )
endif ( )
# Revisit value:
set ( cache "${FEATURE_${feature}}" )
if ( ( cache STREQUAL "ON" ) OR ( cache STREQUAL "OFF" ) )
set ( result "${cache}" )
else ( )
message ( FATAL_ERROR "Sanity check failed: FEATURE_${feature} has invalid value \" ${ cache } \"!")
endif ( )
# Fix-up user-provided values
set ( "FEATURE_${feature}" "${cache}" CACHE BOOL "${label}" )
else ( )
# Initial setup:
if ( emit_if )
set ( "FEATURE_${feature}" "${calculated}" CACHE BOOL "${label}" )
endif ( )
set ( result "${calculated}" )
endif ( )
set ( "${resultVar}" "${result}" PARENT_SCOPE )
endfunction ( )
macro ( qt_feature_set_value feature cache condition label )
set ( result "${cache}" )
if ( NOT ( condition ) AND ( cache ) )
message ( SEND_ERROR "Feature \" ${ feature } \": Forcing to \"${cache}\" breaks its condition. " )
endif ( )
set ( QT_FEATURE_ ${ feature } "${result}" PARENT_SCOPE )
endmacro ( )
2018-10-24 13:20:27 +00:00
function ( qt_evaluate_feature _feature )
# If the feature was set explicitly by the user to be on or off, in the cache, then
# there's nothing for us to do.
2018-10-25 11:16:42 +00:00
if ( DEFINED "QT_FEATURE_${_feature}" )
2018-10-24 13:20:27 +00:00
return ( )
endif ( )
2018-10-25 12:28:06 +00:00
if ( NOT DEFINED _QT_FEATURE_DEFINITION_ ${ _feature } )
2018-11-02 10:42:58 +00:00
qt_debug_print_variables ( DEDUP MATCH "^QT_FEATURE" )
2018-10-24 13:20:27 +00:00
message ( FATAL_ERROR "Attempting to evaluate feature ${_feature} but its definition is missing. Either the feature does not exist or a dependency to the module that defines it is missing" )
endif ( )
cmake_parse_arguments ( _arg
" P R I V A T E ; P U B L I C "
2018-10-25 12:28:06 +00:00
" L A B E L ; P U R P O S E ; S E C T I O N ; " " A U T O D E T E C T ; C O N D I T I O N ; E N A B L E ; D I S A B L E ; E M I T _ I F " $ { _ Q T _ F E A T U R E _ D E F I N I T I O N _ $ { _ f e a t u r e } } )
2018-10-24 13:20:27 +00:00
2018-11-02 10:42:58 +00:00
if ( DEFINED QT_FEATURE_ ${ _feature } )
2018-10-24 13:20:27 +00:00
return ( )
endif ( )
if ( "${_arg_ENABLE}" STREQUAL "" )
set ( _arg_ENABLE OFF )
endif ( )
if ( "${_arg_DISABLE}" STREQUAL "" )
set ( _arg_DISABLE OFF )
endif ( )
if ( "${_arg_AUTODETECT}" STREQUAL "" )
set ( _arg_AUTODETECT ON )
endif ( )
if ( "${_arg_CONDITION}" STREQUAL "" )
2018-10-25 12:28:06 +00:00
set ( condition ON )
else ( )
qt_evaluate_config_expression ( condition ${ _arg_CONDITION } )
2018-10-24 13:20:27 +00:00
endif ( )
if ( ${ _arg_DISABLE } )
set ( result OFF )
elseif ( ( ${ _arg_ENABLE } ) OR ( ${ _arg_AUTODETECT } ) )
2018-10-25 12:28:06 +00:00
set ( result ${ condition } )
2018-10-24 13:20:27 +00:00
else ( )
# feature not auto-detected and not explicitly enabled
set ( result OFF )
endif ( )
2018-10-25 11:16:42 +00:00
if ( "${_arg_EMIT_IF}" STREQUAL "" )
2018-10-25 12:28:06 +00:00
set ( emit_if ON )
else ( )
qt_evaluate_config_expression ( emit_if ${ _arg_EMIT_IF } )
2018-10-25 11:16:42 +00:00
endif ( )
2018-10-26 09:49:58 +00:00
if ( NOT ( condition ) AND ( calculated ) )
message ( FATAL_ERROR "Sanity check failed: Feature ${_feature} is enabled but condition does not hold true." )
2018-10-25 11:16:42 +00:00
endif ( )
2018-10-25 12:28:06 +00:00
2018-10-26 09:49:58 +00:00
qt_feature_set_cache_value ( cache "${_feature}" "${emit_if}" "${result}" "${_arg_LABEL}" )
qt_feature_set_value ( "${_feature}" "${cache}" "${condition}" "${_arg_LABEL}" )
2018-10-24 13:20:27 +00:00
endfunction ( )
function ( qt_feature_definition _feature _name )
qt_parse_all_arguments ( _arg "qt_feature_definition" "NEGATE" "VALUE" "" ${ ARGN } )
# Generate code:
set ( _expected 1 )
if ( _arg_NEGATE )
set ( _expected -1 )
endif ( )
set ( _msg "\n#if defined(QT_FEATURE_${_feature}) && QT_FEATURE_${_feature} == ${_expected}\n" )
if ( _arg_VALUE )
string ( APPEND _msg "# define ${_name} ${_arg_VALUE}\n" )
else ( )
string ( APPEND _msg "# define ${_name}\n" )
endif ( )
string ( APPEND _msg "#endif\n" )
# Store for later use:
list ( FIND __QtFeature_public_features "${_feature}" _public_index )
if ( _public_index GREATER -1 )
string ( APPEND __QtFeature_public_extra "${_msg}" )
endif ( )
list ( FIND __QtFeature_private_features "${_feature}" _private_index )
if ( _private_index GREATER -1 )
string ( APPEND __QtFeature_private_extra "${_msg}" )
endif ( )
set ( __QtFeature_public_extra ${ __QtFeature_public_extra } PARENT_SCOPE )
set ( __QtFeature_private_extra ${ __QtFeature_private_extra } PARENT_SCOPE )
endfunction ( )
function ( qt_extra_definition _name _value )
qt_parse_all_arguments ( _arg "qt_extra_definition" "PUBLIC;PRIVATE" "" "" ${ ARGN } )
if ( _arg_PUBLIC )
string ( APPEND __QtFeature_public_extra "\n#define ${_name} ${_value}\n" )
elseif ( _arg_PRIVATE )
string ( APPEND __QtFeature_private_extra "\n#define ${_name} ${_value}\n" )
endif ( )
set ( __QtFeature_public_extra ${ __QtFeature_public_extra } PARENT_SCOPE )
set ( __QtFeature_private_extra ${ __QtFeature_private_extra } PARENT_SCOPE )
endfunction ( )
function ( _qt_generate_feature_line _line _feature )
set ( _line "" )
if ( QT_FEATURE_ ${ _feature } STREQUAL "ON" )
set ( _line "#define QT_FEATURE_${_feature} 1\n\n" PARENT_SCOPE )
elseif ( QT_FEATURE_ ${ _feature } STREQUAL "OFF" )
set ( _line "#define QT_FEATURE_${_feature} -1\n\n" PARENT_SCOPE )
elseif ( QT_FEATURE_ ${ _feature } STREQUAL "UNSET" )
set ( _line "#define QT_FEATURE_${_feature} 0\n\n" PARENT_SCOPE )
else ( )
message ( FATAL_ERROR "${_feature} has unexpected value \" ${ QT_FEATURE_${_feature } }\ "!" )
endif ( )
endfunction ( )
function ( _qt_feature_write_file _file _features _extra )
message ( "Generating file ${_file}." )
set ( _contents "" )
foreach ( _it ${ _features } )
_qt_generate_feature_line ( _line "${_it}" )
string ( APPEND _contents "${_line}" )
endforeach ( )
string ( APPEND _contents "${_extra}" )
file ( GENERATE OUTPUT "${_file}" CONTENT "${_contents}" )
endfunction ( )
function ( qt_feature_module_end target )
set ( all_features ${ __QtFeature_public_features } ${ __QtFeature_private_features } )
list ( REMOVE_DUPLICATES all_features )
foreach ( feature ${ all_features } )
qt_evaluate_feature ( ${ feature } )
endforeach ( )
set ( enabled_public_features "" )
set ( disabled_public_features "" )
set ( enabled_private_features "" )
set ( disabled_private_features "" )
foreach ( feature ${ __QtFeature_public_features } )
if ( QT_FEATURE_ ${ feature } )
list ( APPEND enabled_public_features ${ feature } )
else ( )
list ( APPEND disabled_public_features ${ feature } )
endif ( )
endforeach ( )
foreach ( feature ${ __QtFeature_private_features } )
if ( QT_FEATURE_ ${ feature } )
list ( APPEND enabled_private_features ${ feature } )
else ( )
list ( APPEND disabled_private_features ${ feature } )
endif ( )
endforeach ( )
foreach ( feature ${ all_features } )
2018-11-02 10:42:58 +00:00
unset ( _QT_FEATURE_DEFINITION_ ${ feature } PARENT_SCOPE )
2018-10-24 13:20:27 +00:00
endforeach ( )
_qt_feature_write_file ( "${CMAKE_CURRENT_BINARY_DIR}/${__QtFeature_private_file}"
" $ { _ _ Q t F e a t u r e _ p r i v a t e _ f e a t u r e s } " " $ { _ _ Q t F e a t u r e _ p r i v a t e _ e x t r a } "
)
qt_generate_forwarding_headers ( "${__QtFeature_library}" SOURCE "${__QtFeature_private_file}" PRIVATE )
_qt_feature_write_file ( "${CMAKE_CURRENT_BINARY_DIR}/${__QtFeature_public_file}"
" $ { _ _ Q t F e a t u r e _ p u b l i c _ f e a t u r e s } " " $ { _ _ Q t F e a t u r e _ p u b l i c _ e x t r a } "
)
qt_generate_forwarding_headers ( "${__QtFeature_library}" SOURCE "${__QtFeature_public_file}" )
get_target_property ( targetType "${target}" TYPE )
if ( "${targetType}" STREQUAL "INTERFACE_LIBRARY" )
set ( propertyPrefix "INTERFACE_" )
else ( )
set ( propertyPrefix "" )
set_target_properties ( "${target}" PROPERTIES EXPORT_PROPERTIES "QT_ENABLED_PUBLIC_FEATURES;QT_DISABLED_PUBLIC_FEATURES;QT_ENABLED_PRIVATE_FEATURES;QT_DISABLED_PRIVATE_FEATURES" )
endif ( )
foreach ( visibility public private )
string ( TOUPPER "${visibility}" capitalVisibility )
foreach ( state enabled disabled )
string ( TOUPPER "${state}" capitalState )
set_property ( TARGET "${target}" PROPERTY ${ propertyPrefix } QT_ ${ capitalState } _ ${ capitalVisibility } _FEATURES "${${state}_${visibility}_features}" )
endforeach ( )
endforeach ( )
unset ( __QtFeature_library PARENT_SCOPE )
unset ( __QtFeature_private_features PARENT_SCOPE )
unset ( __QtFeature_public_features PARENT_SCOPE )
unset ( __QtFeature_private_file PARENT_SCOPE )
unset ( __QtFeature_public_file PARENT_SCOPE )
unset ( __QtFeature_private_extra PARENT_SCOPE )
unset ( __QtFeature_public_extra PARENT_SCOPE )
2018-11-02 10:42:58 +00:00
qt_push_features_into_parent_scope ( )
2018-10-24 13:20:27 +00:00
endfunction ( )
function ( qt_config_compile_test name )
cmake_parse_arguments ( _arg "" "LABEL" "" ${ ARGN } )
check_cxx_source_compiles ( "${_arg_UNPARSED_ARGUMENTS}" HAVE_ ${ name } )
set ( TEST_ ${ name } "${HAVE_${name}}" CACHE INTERNAL "${_arg_LABEL}" )
endfunction ( )
function ( qt_config_compile_test_x86simd extension label )
string ( TOUPPER ${ extension } extension_uppercase )
try_compile ( TEST_X86SIMD_ ${ extension } "${CMAKE_CURRENT_BINARY_DIR}"
" $ { C M A K E _ C U R R E N T _ S O U R C E _ D I R } / c o n f i g . t e s t s / x 8 6 _ s i m d / m a i n . c p p "
C O M P I L E _ D E F I N I T I O N S - D Q T _ C O M P I L E R _ S U P P O R T S _ $ { e x t e n s i o n _ u p p e r c a s e }
O U T P U T _ V A R I A B L E f o o
)
set ( TEST_subarch_ ${ extension } "${TEST_X86SIMD_${extension}}" CACHE INTERNAL "${label}" )
endfunction ( )
function ( qt_pull_features_into_current_scope )
cmake_parse_arguments ( __arg "PUBLIC_FEATURES;PRIVATE_FEATURES" "FEATURE_PROPERTY_INFIX" "" ${ ARGN } )
foreach ( __target IN ITEMS ${ __arg_UNPARSED_ARGUMENTS } )
if ( NOT TARGET ${ __target } )
continue ( )
endif ( )
get_target_property ( __target_type "${__target}" TYPE )
if ( "${__target_type}" STREQUAL "INTERFACE_LIBRARY" )
set ( __property_prefix "INTERFACE_" )
else ( )
set ( __property_prefix "" )
endif ( )
foreach ( __visibility PUBLIC PRIVATE )
set ( __value ON )
foreach ( __state ENABLED DISABLED )
if ( NOT ${ __arg_${__visibility } _FEATURES} )
continue ( )
endif ( )
get_target_property ( __features "${__target}" ${ __property_prefix } QT_ ${ __arg_FEATURE_PROPERTY_INFIX } ${ __state } _ ${ __visibility } _FEATURES )
if ( "${__features}" STREQUAL "__features-NOTFOUND" )
continue ( )
endif ( )
foreach ( __feature ${ __features } )
set ( QT_FEATURE_ ${ __feature } ${ __value } PARENT_SCOPE )
endforeach ( )
set ( __value OFF )
endforeach ( )
endforeach ( )
endforeach ( )
endfunction ( )
macro ( qt_push_features_into_parent_scope )
2018-11-02 10:42:58 +00:00
get_cmake_property ( __variableNames VARIABLES )
list ( SORT __variableNames )
list ( REMOVE_DUPLICATES __variableNames )
foreach ( __var ${ __variableNames } )
if ( __var MATCHES "^QT_FEATURE_[a-z][a-z0-9_]*$" )
set ( "${__var}" "${${__var}}" PARENT_SCOPE )
2018-10-24 13:20:27 +00:00
endif ( )
endforeach ( )
endmacro ( )
macro ( qt_load_global_features )
if ( NOT TARGET Qt::Core )
find_package ( Qt ${ PROJECT_VERSION_MAJOR } Core QUIET )
endif ( )
qt_pull_features_into_current_scope ( PUBLIC_FEATURES PRIVATE_FEATURES FEATURE_PROPERTY_INFIX "GLOBAL_" Qt::Core )
endmacro ( )