efl/cmake/helpers/EflMacros.cmake

857 lines
28 KiB
CMake

# NOTE:
#
# - Use function() whenever possible, macro() doesn't start a new
# variable scope and needs careful handling to avoid left overs.
#
# - To 'export' values or lists, use the macros SET_GLOBAL() and
# LIST_APPEND_GLOBAL().
#
# LIST_APPEND_GLOBAL(Var Element)
#
# Append to a list in the global variable scope (cache internal)
function(LIST_APPEND_GLOBAL _var _element)
set(_local ${${_var}})
list(APPEND _local ${_element})
set(${_var} ${_local} CACHE INTERNAL "")
endfunction()
# SET_GLOBAL(Var Value [Help])
#
# Set a variable in the global variable scope (cache internal)
function(SET_GLOBAL _var _value)
set(${_var} "${_value}" CACHE INTERNAL "${ARGN}")
endfunction()
# EFL_OPTION(Name Help Default)
#
# Declare an option() that will be automatically printed by
# EFL_OPTIONS_SUMMARY()
#
# To extend the EFL_OPTIONS_SUMMARY() message, use
# EFL_OPTION_SET_MESSAGE(Name Message)
function(EFL_OPTION _name _help _defval)
set(_type)
set(_vartype)
set(_choices)
list(LENGTH ARGN _argc)
if(_argc LESS 1)
set(_type BOOL)
set(_vartype BOOL)
else()
list(GET ARGN 0 _type)
set(_vartype ${_type})
list(REMOVE_AT ARGN 0)
endif()
if(${_vartype} STREQUAL "CHOICE")
set(_type STRING)
SET_GLOBAL(EFL_OPTION_CHOICES_${_name} "${ARGN}" "Possible values for ${_name}")
set(_choices " (Choices: ${ARGN})")
endif()
LIST_APPEND_GLOBAL(EFL_ALL_OPTIONS ${_name})
SET_GLOBAL(EFL_OPTION_DEFAULT_${_name} "${_defval}" "Default value for ${_name}")
SET_GLOBAL(EFL_OPTION_TYPE_${_name} "${_vartype}" "Type of ${_name}")
set(${_name} ${_defval} CACHE ${_type} "${_help}${_choices}")
option(${_name} "${_help}${_choices}" ${_defval})
if(_choices)
list(FIND ARGN "${${_name}}" _ret)
if(${_ret} EQUAL -1)
message(FATAL_ERROR "Invalid choice ${_name}=${${_name}}${_choices}")
endif()
endif()
endfunction()
# EFL_OPTION_SET_MESSAGE(Name Message)
#
# Extends the summary line output by EFL_OPTIONS_SUMMARY()
# with more details.
function(EFL_OPTION_SET_MESSAGE _name _message)
SET_GLOBAL(EFL_OPTION_MESSAGE_${_name} "${_message}")
endfunction()
# EFL_OPTIONS_SUMMARY()
# Shows the summary of options, their values and related messages.
function(EFL_OPTIONS_SUMMARY)
message(STATUS "EFL Options Summary:")
message(STATUS " CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")
message(STATUS " CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
foreach(_o ${EFL_ALL_OPTIONS})
set(_v ${${_o}})
set(_d ${EFL_OPTION_DEFAULT_${_o}})
if("${_v}" STREQUAL "${_d}")
set(_i "default")
else()
set(_i "default: ${_d}")
endif()
if(EFL_OPTION_MESSAGE_${_o})
set(_m " [${EFL_OPTION_MESSAGE_${_o}}]")
else()
set(_m)
endif()
message(STATUS " ${_o}=${_v} (${_i})${_m}")
endforeach()
message(STATUS "EFL Libraries:")
foreach(_o ${EFL_ALL_LIBS})
message(STATUS " ${_o}${_mods}")
foreach(_m ${${_o}_MODULES})
string(REGEX REPLACE "^${_o}-module-" "" _m ${_m})
message(STATUS " dynamic: ${_m}")
endforeach()
foreach(_m ${${_o}_STATIC_MODULES})
string(REGEX REPLACE "^${_o}-module-" "" _m ${_m})
message(STATUS " static.: ${_m}")
endforeach()
unset(_m)
endforeach()
if(EFL_PKG_CONFIG_MISSING_OPTIONAL)
message(STATUS "The following pkg-config optional modules are missing:")
foreach(_m ${EFL_PKG_CONFIG_MISSING_OPTIONAL})
message(STATUS " ${_m}")
endforeach()
unset(_m)
endif()
endfunction()
set(EFL_ALL_LIBS)
set(EFL_ALL_TESTS)
# EFL_FINALIZE()
#
# Finalize EFL processing, adding extra targets.
function(EFL_FINALIZE)
add_custom_target(all-libs DEPENDS ${EFL_ALL_LIBS})
add_custom_target(all-tests DEPENDS ${EFL_ALL_TESTS})
endfunction()
# EFL_FILES_TO_ABSOLUTE(Var Source_Dir Binary_Dir [file1 ... fileN])
#
# Convert list of files to absolute path. If not absolute, then
# check inside Source_Dir and if it fails assumes it's inside Binary_Dir
function(EFL_FILES_TO_ABSOLUTE _var _srcdir _bindir)
set(_lst "")
foreach(f ${ARGN})
if(EXISTS "${f}")
list(APPEND _lst "${f}")
elseif(EXISTS "${_srcdir}/${f}")
list(APPEND _lst "${_srcdir}/${f}")
else()
list(APPEND _lst "${_bindir}/${f}")
endif()
endforeach()
set(${_var} "${_lst}" PARENT_SCOPE)
endfunction()
# EFL_PKG_CONFIG_EVAL_TO(Var Name [module1 ... moduleN])
#
# Evaluate the list of of pkg-config modules and assign to variable
# Var. If it's missing, abort with a message saying ${Name} is missing
# the list of modules.
#
# OPTIONAL keyword may be used to convert the remaining elements in optional
# packages.
function(EFL_PKG_CONFIG_EVAL_TO _var _name)
set(_found "")
set(_missing "")
set(_missing_optional "")
set(_optional OFF)
foreach(f ${ARGN})
if(${f} STREQUAL "OPTIONAL")
set(_optional ON)
else()
pkg_check_modules(PKG_CONFIG_DEP_${f} ${f})
if(PKG_CONFIG_DEP_${f}_FOUND)
list(APPEND _found ${f})
elseif(_optional)
list(APPEND _missing_optional ${f})
LIST_APPEND_GLOBAL(EFL_PKG_CONFIG_MISSING_OPTIONAL ${f})
else()
list(APPEND _missing ${f})
else()
endif()
endif()
endforeach()
if(NOT _missing)
SET_GLOBAL(${_var} "${_found}")
SET_GLOBAL(${_var}_MISSING "${_missing_optional}")
else()
message(FATAL_ERROR "${_name} missing required pkg-config modules: ${_missing}")
endif()
endfunction()
# EFL_PKG_CONFIG_EVAL(Name Private_List Public_List)
#
# Evaluates both lists and creates ${Name}_PKG_CONFIG_REQUIRES as well as
# ${Name}_PKG_CONFIG_REQUIRES_PRIVATE with found elements.
#
# OPTIONAL keyword may be used to convert the remaining elements in optional
# packages.
function(EFL_PKG_CONFIG_EVAL _target _private _public)
EFL_PKG_CONFIG_EVAL_TO(${_target}_PKG_CONFIG_REQUIRES ${_target} ${_public})
EFL_PKG_CONFIG_EVAL_TO(${_target}_PKG_CONFIG_REQUIRES_PRIVATE ${_target} ${_private})
set(_lst ${${_target}_PKG_CONFIG_REQUIRES_MISSING})
foreach(_e ${${_target}_PKG_CONFIG_REQUIRES_PRIVATE_MISSING})
list(APPEND _lst ${_e})
endforeach()
if(_lst)
message(STATUS "${_target} missing optional pkg-config: ${_lst}")
endif()
endfunction()
function(EFL_PKG_CONFIG_LIB_WRITE)
set(_pkg_config_requires)
set(_pkg_config_requires_private)
set(_libraries)
set(_public_libraries)
foreach(_e ${${EFL_LIB_CURRENT}_PKG_CONFIG_REQUIRES})
set(_pkg_config_requires "${_pkg_config_requires} ${_e}")
endforeach()
foreach(_e ${${EFL_LIB_CURRENT}_PKG_CONFIG_REQUIRES_PRIVATE})
set(_pkg_config_requires_private "${_pkg_config_requires_private} ${_e}")
endforeach()
foreach(_e ${LIBRARIES})
set(_libraries "${_libraries} -l${_e}")
endforeach()
foreach(_e ${PUBLIC_LIBRARIES})
set(_public_libraries "${_public_libraries} -l${_e}")
endforeach()
if(NOT ${EFL_LIB_CURRENT} STREQUAL "efl")
set(_cflags " -I\${includedir}/${EFL_LIB_CURRENT}-${PROJECT_VERSION_MAJOR}")
endif()
# TODO: handle eolian needs
set(_contents
"prefix=${CMAKE_INSTALL_PREFIX}
exec_prefix=\${prefix}
libdir=\${exec_prefix}/lib
includedir=\${prefix}/include
datarootdir=\${prefix}/share
datadir=\${datarootdir}
pkgdatadir=\${datadir}/${EFL_LIB_CURRENT}
modules=\${libdir}/${EFL_LIB_CURRENT}/modules
Name: ${EFL_LIB_CURRENT}
Description: ${DESCRIPTION}
Version: ${VERSION}
Requires:${_pkg_config_requires}
Requires.private:${_pkg_config_requires_private}
Libs: -L\${libdir} -l${EFL_LIB_CURRENT}${_public_libraries}
Libs.private:${_libraries}
Cflags: -I\${includedir}/efl-${PROJECT_VERSION_MAJOR}${_cflags}
")
file(WRITE "${CMAKE_BINARY_DIR}/lib/pkgconfig/${EFL_LIB_CURRENT}.pc" "${_contents}")
install(FILES "${CMAKE_BINARY_DIR}/lib/pkgconfig/${EFL_LIB_CURRENT}.pc"
DESTINATION "lib/pkgconfig")
endfunction()
# _EFL_INCLUDE_OR_DETECT(Name Source_Dir)
#
# Internal macro that will include(${Source_Dir}/CMakeLists.txt) if
# that exists, otherwise will check if there is a single source file,
# in that case it will automatically define SOURCES to that (including
# extras such as headers and .eo)
#
# Name is only used to print out messages when it's auto-detected.
macro(_EFL_INCLUDE_OR_DETECT _name _srcdir)
if(EXISTS ${_srcdir}/CMakeLists.txt)
include(${_srcdir}/CMakeLists.txt)
else()
# doc says it's not recommended because it can't know if more files
# were added, but we're doing this explicitly to handle one file.
file(GLOB _autodetect_files RELATIVE ${_srcdir}
${_srcdir}/*.c
${_srcdir}/*.h
${_srcdir}/*.hh
${_srcdir}/*.cxx
${_srcdir}/*.cpp
${_srcdir}/*.eo
)
list(LENGTH _autodetect_files _autodetect_files_count)
if(_autodetect_files_count GREATER 1)
message(WARNING "${_name}: ${_srcdir} contains no CMakeLists.txt and contains more than one source file. Don't know what to do, then ignored.")
elseif(_autodetect_files_count EQUAL 1)
file(GLOB SOURCES RELATIVE ${_srcdir}
${_srcdir}/*.c
${_srcdir}/*.h
${_srcdir}/*.hh
${_srcdir}/*.cxx
${_srcdir}/*.cpp
${_srcdir}/*.eo
)
message(STATUS "${_name} auto-detected as: ${SOURCES}")
else()
message(STATUS "${_name} contains no auto-detectable sources.")
endif()
unset(_autodetect_files_count)
unset(_autodetect_files)
endif()
endmacro()
# _EFL_LIB_PROCESS_MODULES_INTERNAL()
#
# Internal function to process modules of current EFL_LIB()
function(_EFL_LIB_PROCESS_MODULES_INTERNAL)
if(EXISTS ${EFL_MODULES_SOURCE_DIR}/CMakeLists.txt)
message(FATAL_ERROR "${EFL_MODULES_SOURCE_DIR}/CMakeLists.txt shouldn't exist. Modules are expected to be defined in their own directory.")
else()
file(GLOB modules RELATIVE ${EFL_MODULES_SOURCE_DIR} ${EFL_MODULES_SOURCE_DIR}/*)
foreach(module ${modules})
if(IS_DIRECTORY ${EFL_MODULES_SOURCE_DIR}/${module})
set(EFL_MODULE_SCOPE ${module})
file(GLOB submodules RELATIVE ${EFL_MODULES_SOURCE_DIR}/${EFL_MODULE_SCOPE} ${EFL_MODULES_SOURCE_DIR}/${EFL_MODULE_SCOPE}/*)
foreach(submodule ${submodules})
if(IS_DIRECTORY ${EFL_MODULES_SOURCE_DIR}/${EFL_MODULE_SCOPE}/${submodule})
EFL_MODULE(${submodule})
endif()
unset(submodule)
unset(submodules)
endforeach()
else()
set(EFL_MODULE_SCOPE)
EFL_MODULE(${module})
endif()
unset(EFL_MODULE_SCOPE)
endforeach()
endif()
if(${EFL_LIB_CURRENT}_MODULES)
add_custom_target(${EFL_LIB_CURRENT}-modules DEPENDS ${${EFL_LIB_CURRENT}_MODULES})
endif()
endfunction()
# _EFL_LIB_PROCESS_BINS_INTERNAL()
#
# Internal function to process bins of current EFL_LIB()
function(_EFL_LIB_PROCESS_BINS_INTERNAL)
if(EXISTS ${EFL_BIN_SOURCE_DIR}/CMakeLists.txt)
EFL_BIN(${EFL_LIB_CURRENT})
else()
file(GLOB bins RELATIVE ${EFL_BIN_SOURCE_DIR} ${EFL_BIN_SOURCE_DIR}/*)
foreach(bin ${bins})
if(IS_DIRECTORY ${EFL_BIN_SOURCE_DIR}/${bin})
EFL_BIN(${bin})
endif()
endforeach()
endif()
if(${EFL_LIB_CURRENT}_BINS)
add_custom_target(${EFL_LIB_CURRENT}-bins DEPENDS ${${EFL_LIB_CURRENT}_BINS})
endif()
endfunction()
# _EFL_LIB_PROCESS_TESTS_INTERNAL()
#
# Internal function to process tests of current EFL_LIB()
function(_EFL_LIB_PROCESS_TESTS_INTERNAL)
if(EXISTS ${EFL_TESTS_SOURCE_DIR}/CMakeLists.txt)
EFL_TEST(${EFL_LIB_CURRENT})
else()
file(GLOB tests RELATIVE ${EFL_TESTS_SOURCE_DIR} ${EFL_TESTS_SOURCE_DIR}/*)
foreach(test ${tests})
if(IS_DIRECTORY ${EFL_TESTS_SOURCE_DIR}/${test})
EFL_TEST(${test})
endif()
endforeach()
endif()
if(${EFL_LIB_CURRENT}_TESTS)
add_custom_target(${EFL_LIB_CURRENT}-tests DEPENDS ${${EFL_LIB_CURRENT}_TESTS})
LIST_APPEND_GLOBAL(EFL_ALL_TESTS ${EFL_LIB_CURRENT}-tests)
endif()
endfunction()
# EFL_LIB(Name)
#
# adds a library ${Name} automatically setting object/target
# properties based on script-modifiable variables:
# - DESCRIPTION: results in ${Name}_DESCRIPTION and fills pkg-config files.
# - PKG_CONFIG_REQUIRES: results in ${Name}_PKG_CONFIG_REQUIRES and
# fills pkg-config files. Elements after 'OPTIONAL' keyword are
# optional.
# - PKG_CONFIG_REQUIRES_PRIVATE: results in
# ${Name}_PKG_CONFIG_REQUIRES_PRIVATE and fills pkg-config
# files. Elements after 'OPTIONAL' keyword are optional.
# - INCLUDE_DIRECTORIES: results in target_include_directories
# - SYSTEM_INCLUDE_DIRECTORIES: results in target_include_directories(SYSTEM)
# - OUTPUT_NAME
# - SOURCES
# - PUBLIC_HEADERS
# - VERSION (defaults to project version)
# - SOVERSION (defaults to project major version)
# - LIBRARY_TYPE: SHARED or STATIC, defaults to SHARED
# - OBJECT_DEPENDS: say this object depends on other files (ie: includes)
# - DEPENDENCIES: results in add_dependencies()
# - LIBRARIES: results in target_link_libraries(LINK_PRIVATE)
# - PUBLIC_LIBRARIES: results in target_link_libraries(LINK_PUBLIC)
# - DEFINITIONS: target_compile_definitions()
#
# Defines the following variables that can be used within the included files:
# - EFL_LIB_CURRENT to ${Name}
# - EFL_LIB_SOURCE_DIR to source dir of ${Name} libraries
# - EFL_LIB_BINARY_DIR to binary dir of ${Name} libraries
# - EFL_BIN_SOURCE_DIR to source dir of ${Name} executables
# - EFL_BIN_BINARY_DIR to binary dir of ${Name} executables
# - EFL_MODULES_SOURCE_DIR to source dir of ${Name} modules
# - EFL_MODULES_BINARY_DIR to binary dir of ${Name} modules
# - EFL_TESTS_SOURCE_DIR to source dir of ${Name} tests
# - EFL_TESTS_BINARY_DIR to binary dir of ${Name} tests
#
# Modules are processed like:
# - loop for directories in src/modules/${EFL_LIB_CURRENT}:
# - if a src/modules/${EFL_LIB_CURRENT}/${Module}/CMakeLists.txt
# use variables as documented in EFL_MODULE()
# - otherwise loop for scoped-modules in
# src/modules/${EFL_LIB_CURRENT}/${EFL_MODULE_SCOPE}/CMakeLists.txt
# and use variables as documented in EFL_MODULE()
#
# EFL_MODULE() will handle MODULE_TYPE=ON;OFF;STATIC, handling
# dependencies and installation in the proper path, considering
# ${EFL_MODULE_SCOPE} whenever it's set.
#
# Binaries and tests are processed similarly:
# - if src/bin/${EFL_LIB_CURRENT}/CMakeLists.txt exist, then use
# variables as documented in EFL_BIN() or EFL_TEST(). The target
# will be called ${EFL_LIB_CURRENT}-bin or ${EFL_LIB_CURRENT}-test
# and the test OUTPUT_NAME defaults to ${EFL_LIB_CURRENT}_suite.
# - otherwise loop for directories in src/bin/${EFL_LIB_CURRENT} and
# for each src/bin/${EFL_LIB_CURRENT}/${Entry}/CMakeLists.txt use
# variables as documented in EFL_BIN() or EFL_TEST(). Binaries
# must provide an unique name that will be used as both target and
# OUTPUT_NAME. Tests will generate targets
# ${EFL_LIB_CURRENT}-test-${Entry}, while OUTPUT_NAME is ${Entry}.
#
# NOTE: src/modules/${EFL_LIB_CURRENT}/CMakeLists.txt is not
# allowed as it makes no sense to have a single module named
# after the library.
#
function(EFL_LIB _target)
set(EFL_LIB_CURRENT ${_target})
set(EFL_LIB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/lib/${_target})
set(EFL_LIB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/src/lib/${_target})
set(EFL_BIN_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/bin/${_target})
set(EFL_BIN_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/src/bin/${_target})
set(EFL_MODULES_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/modules/${_target})
set(EFL_MODULES_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/src/modules/${_target})
set(EFL_TESTS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/tests/${_target})
set(EFL_TESTS_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/src/tests/${_target})
set(DESCRIPTION)
set(PKG_CONFIG_REQUIRES)
set(PKG_CONFIG_REQUIRES_PRIVATE)
set(INCLUDE_DIRECTORIES)
set(SYSTEM_INCLUDE_DIRECTORIES)
set(OUTPUT_NAME)
set(SOURCES)
set(PUBLIC_HEADERS)
set(VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
set(SOVERSION ${PROJECT_VERSION_MAJOR})
set(LIBRARY_TYPE SHARED)
set(OBJECT_DEPENDS)
set(DEPENDENCIES)
set(LIBRARIES)
set(PUBLIC_LIBRARIES)
set(DEFINITIONS)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config/${_target}.cmake OPTIONAL)
include(${EFL_LIB_SOURCE_DIR}/CMakeLists.txt OPTIONAL)
if(LIBRARY_TYPE STREQUAL SHARED AND NOT PUBLIC_HEADERS)
message(FATAL_ERROR "Shared libraries must install public headers!")
endif()
EFL_FILES_TO_ABSOLUTE(_headers ${EFL_LIB_SOURCE_DIR} ${EFL_LIB_BINARY_DIR}
${PUBLIC_HEADERS})
EFL_FILES_TO_ABSOLUTE(_sources ${EFL_LIB_SOURCE_DIR} ${EFL_LIB_BINARY_DIR}
${SOURCES})
EFL_FILES_TO_ABSOLUTE(_obj_deps ${EFL_LIB_SOURCE_DIR} ${EFL_LIB_BINARY_DIR}
${OBJECT_DEPENDS})
EFL_PKG_CONFIG_EVAL(${_target} "${PKG_CONFIG_REQUIRES_PRIVATE}" "${PKG_CONFIG_REQUIRES}")
add_library(${_target} ${LIBRARY_TYPE} ${_sources} ${_headers})
set_target_properties(${_target} PROPERTIES
FRAMEWORK TRUE
PUBLIC_HEADER "${_headers}"
OBJECT_DEPENDS "${_obj_deps}"
COMPILE_FLAGS -DPACKAGE_DATA_DIR=\\"${CMAKE_INSTALL_FULL_DATADIR}/${_target}/\\")
if(DEPENDENCIES)
add_dependencies(${_target} ${DEPENDENCIES})
endif()
if(LIBRARIES)
target_link_libraries(${_target} LINK_PRIVATE ${LIBRARIES})
endif()
if(PUBLIC_LIBRARIES)
target_link_libraries(${_target} LINK_PRIVATE ${PUBLIC_LIBRARIES})
endif()
target_include_directories(${_target} PUBLIC
${INCLUDE_DIRECTORIES}
${EFL_LIB_SOURCE_DIR}
${EFL_LIB_BINARY_DIR}
)
if(SYSTEM_INCLUDE_DIRECTORIES)
target_include_directories(${_target} SYSTEM PUBLIC ${SYSTEM_INCLUDE_DIRECTORIES})
endif()
if(DEFINITIONS)
target_compile_definitions(${_target} PRIVATE ${DEFINITIONS})
endif()
if(OUTPUT_NAME)
set_target_properties(${_target} PROPERTIES OUTPUT_NAME ${OUTPUT_NAME})
endif()
if(VERSION AND SOVERSION)
set_target_properties(${_target} PROPERTIES
VERSION ${VERSION}
SOVERSION ${SOVERSION})
endif()
EFL_PKG_CONFIG_LIB_WRITE()
install(TARGETS ${_target}
PUBLIC_HEADER DESTINATION include/${_target}-${PROJECT_VERSION_MAJOR}
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib)
# do not leak those into binaries, modules or tests
unset(_sources)
unset(_headers)
unset(_obj_deps)
unset(INCLUDE_DIRECTORIES)
unset(SYSTEM_INCLUDE_DIRECTORIES)
unset(OUTPUT_NAME)
unset(SOURCES)
unset(PUBLIC_HEADERS)
unset(VERSION)
unset(SOVERSION)
unset(LIBRARY_TYPE)
unset(OBJECT_DEPENDS)
unset(DEPENDENCIES)
unset(LIBRARIES)
unset(PUBLIC_LIBRARIES)
unset(DEFINITIONS)
unset(DESCRIPTION)
unset(PKG_CONFIG_REQUIRES)
unset(PKG_CONFIG_REQUIRES_PRIVATE)
_EFL_LIB_PROCESS_BINS_INTERNAL()
_EFL_LIB_PROCESS_MODULES_INTERNAL()
_EFL_LIB_PROCESS_TESTS_INTERNAL()
LIST_APPEND_GLOBAL(EFL_ALL_LIBS ${_target})
endfunction()
# EFL_BIN(Name)
#
# Adds a binary (executable) for ${EFL_LIB_CURRENT} using
# ${EFL_BIN_SOURCE_DIR} and ${EFL_BIN_BINARY_DIR}
#
# Settings:
# - INCLUDE_DIRECTORIES: results in target_include_directories
# - SYSTEM_INCLUDE_DIRECTORIES: results in target_include_directories(SYSTEM)
# - OUTPUT_NAME
# - SOURCES
# - OBJECT_DEPENDS: say this object depends on other files (ie: includes)
# - DEPENDENCIES: results in add_dependencies(), defaults to
# ${EFL_LIB_CURRENT}-modules
# - LIBRARIES: results in target_link_libraries()
# - DEFINITIONS: target_compile_definitions()
# - INSTALL_DIR: defaults to bin. If empty, won't install.
#
# NOTE: it's meant to be called by files included by EFL_LIB() or similar,
# otherwise you need to prepare the environment yourself.
function(EFL_BIN _binname)
set(INCLUDE_DIRECTORIES)
set(SYSTEM_INCLUDE_DIRECTORIES)
set(OUTPUT_NAME ${_binname})
set(SOURCES)
set(OBJECT_DEPENDS)
if(TARGET ${EFL_LIB_CURRENT}-modules)
set(DEPENDENCIES ${EFL_LIB_CURRENT}-modules)
else()
set(DEPENDENCIES)
endif()
set(LIBRARIES)
set(DEFINITIONS)
set(INSTALL ON)
set(INSTALL_DIR bin)
if(_binname STREQUAL ${EFL_LIB_CURRENT})
set(_binsrcdir "${EFL_BIN_SOURCE_DIR}")
set(_binbindir "${EFL_BIN_BINARY_DIR}")
set(_bintarget "${EFL_LIB_CURRENT}-bin") # otherwise target would exist
else()
set(_binsrcdir "${EFL_BIN_SOURCE_DIR}/${_binname}")
set(_binbindir "${EFL_BIN_BINARY_DIR}/${_binname}")
set(_bintarget "${_binname}")
endif()
_EFL_INCLUDE_OR_DETECT("Binary ${_bintarget}" ${_binsrcdir})
if(NOT SOURCES)
message(WARNING "${_binsrcdir}/CMakeLists.txt defines no SOURCES")
return()
endif()
if(PUBLIC_HEADERS)
message(WARNING "${_binsrcdir}/CMakeLists.txt should not define PUBLIC_HEADERS, it's not to be installed.")
endif()
EFL_FILES_TO_ABSOLUTE(_sources ${_binsrcdir} ${_binbindir} ${SOURCES})
EFL_FILES_TO_ABSOLUTE(_obj_deps ${_binsrcdir} ${_binbindir} ${OBJECT_DEPENDS})
add_executable(${_bintarget} ${_sources})
if(_obj_deps)
set_target_properties(${_bintarget} PROPERTIES
OBJECT_DEPENDS "${_obj_deps}")
endif()
if(DEPENDENCIES)
add_dependencies(${_bintarget} ${DEPENDENCIES})
endif()
target_include_directories(${_bintarget} PRIVATE
${_binrcdir}
${_binbindir}
${INCLUDE_DIRECTORIES})
if(SYSTEM_INCLUDE_DIRECTORIES)
target_include_directories(${_bintarget} SYSTEM PRIVATE
${SYSTEM_INCLUDE_DIRECTORIES})
endif()
target_link_libraries(${_bintarget} LINK_PRIVATE
${EFL_LIB_CURRENT}
${LIBRARIES})
if(DEFINITIONS)
target_compile_definitions(${_bintarget} PRIVATE ${DEFINITIONS})
endif()
if(OUTPUT_NAME)
set_target_properties(${_bintarget} PROPERTIES OUTPUT_NAME ${OUTPUT_NAME})
endif()
if(INSTALL_DIR)
install(TARGETS ${_bintarget} RUNTIME DESTINATION ${INSTALL_DIR})
endif()
endfunction()
# EFL_TEST(Name)
#
# Adds a test for ${EFL_LIB_CURRENT} using
# ${EFL_TESTS_SOURCE_DIR} and ${EFL_TESTS_BINARY_DIR}
#
# Settings:
# - INCLUDE_DIRECTORIES: results in target_include_directories
# - SYSTEM_INCLUDE_DIRECTORIES: results in target_include_directories(SYSTEM)
# - OUTPUT_NAME
# - SOURCES
# - OBJECT_DEPENDS: say this object depends on other files (ie: includes)
# - DEPENDENCIES: results in add_dependencies(), defaults to
# ${EFL_LIB_CURRENT}-modules
# - LIBRARIES: results in target_link_libraries()
# - DEFINITIONS: target_compile_definitions()
#
# NOTE: it's meant to be called by files included by EFL_LIB() or similar,
# otherwise you need to prepare the environment yourself.
function(EFL_TEST _testname)
if(NOT CHECK_FOUND)
message(STATUS "${EFL_LIB_CURRENT} test ${_testname} ignored since no 'check' library was found.")
return()
endif()
set(INCLUDE_DIRECTORIES)
set(SYSTEM_INCLUDE_DIRECTORIES)
set(OUTPUT_NAME ${_testname})
set(SOURCES)
set(OBJECT_DEPENDS)
if(TARGET ${EFL_LIB_CURRENT}-modules)
set(DEPENDENCIES ${EFL_LIB_CURRENT}-modules)
else()
set(DEPENDENCIES)
endif()
set(LIBRARIES)
set(DEFINITIONS)
if(_testname STREQUAL ${EFL_LIB_CURRENT})
set(_testsrcdir "${EFL_TESTS_SOURCE_DIR}")
set(_testbindir "${EFL_TESTS_BINARY_DIR}")
set(_testtarget "${EFL_LIB_CURRENT}-test") # otherwise target would exist
set(OUTPUT_NAME "${EFL_LIB_CURRENT}_suite") # backward compatible
else()
set(_testsrcdir "${EFL_TESTS_SOURCE_DIR}/${_testname}")
set(_testbindir "${EFL_TESTS_BINARY_DIR}/${_testname}")
set(_testtarget "${EFL_LIB_CURRENT}-test-${_testname}")
endif()
_EFL_INCLUDE_OR_DETECT("Test ${_testtarget}" ${_testsrcdir})
if(NOT SOURCES)
message(WARNING "${_testsrcdir}/CMakeLists.txt defines no SOURCES")
return()
endif()
if(PUBLIC_HEADERS)
message(WARNING "${_testsrcdir}/CMakeLists.txt should not define PUBLIC_HEADERS, it's not to be installed.")
endif()
EFL_FILES_TO_ABSOLUTE(_sources ${_testsrcdir} ${_testbindir} ${SOURCES})
EFL_FILES_TO_ABSOLUTE(_obj_deps ${_testsrcdir} ${_testbindir} ${OBJECT_DEPENDS})
add_executable(${_testtarget} EXCLUDE_FROM_ALL ${_sources})
if(_obj_deps)
set_target_properties(${_testtarget} PROPERTIES
OBJECT_DEPENDS "${_obj_deps}")
endif()
if(DEPENDENCIES)
add_dependencies(${_testtarget} ${DEPENDENCIES})
endif()
target_include_directories(${_testtarget} PRIVATE
${_testrcdir}
${_testbindir}
${INCLUDE_DIRECTORIES})
target_include_directories(${_testtarget} SYSTEM PRIVATE
${SYSTEM_INCLUDE_DIRECTORIES}
${CHECK_INCLUDE_DIRS})
target_link_libraries(${_testtarget} LINK_PRIVATE
${EFL_LIB_CURRENT}
${LIBRARIES}
${CHECK_LIBRARIES})
target_compile_definitions(${_testtarget} PRIVATE
"-DTESTS_SRC_DIR=\"${_testrcdir}\""
"-DTESTS_BUILD_DIR=\"${_testbindir}\""
"-DTESTS_WD=\"${PROJECT_BINARY_DIR}\""
"-DPACKAGE_BUILD_DIR=\"1\""
${DEFINITIONS}
)
if(OUTPUT_NAME)
set_target_properties(${_testtarget} PROPERTIES OUTPUT_NAME ${OUTPUT_NAME})
endif()
set_target_properties(${_testtarget} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${_testbindir}"
RUNTIME_OUTPUT_DIRECTORY "${_testbindir}")
add_test(NAME ${_testname} COMMAND ${_testtarget})
LIST_APPEND_GLOBAL(${EFL_LIB_CURRENT}_TESTS ${_testtarget})
endfunction()
# EFL_MODULE(Name)
#
# Adds a module for ${EFL_LIB_CURRENT} using
# ${EFL_MODULES_SOURCE_DIR} and ${EFL_MODULES_BINARY_DIR}
# as well as ${EFL_MODULE_SCOPE} if it's contained into
# a subdir, such as eina's "mp" or evas "engines".
#
# To keep it simple to use, user is only expected to define variables:
# - SOURCES
# - OBJECT_DEPENDS
# - LIBRARIES
# - INCLUDE_DIRECTORIES
# - SYSTEM_INCLUDE_DIRECTORIES
# - DEFINITIONS
# - MODULE_TYPE: one of ON;OFF;STATIC, defaults to ON
# - INSTALL_DIR: defaults to
# lib/${EFL_LIB_CURRENT}/modules/${EFL_MODULE_SCOPE}/${Name}/v-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}/.
# If empty, won't install.
#
# NOTE: since the file will be included it shouldn't mess with global variables!
function(EFL_MODULE _modname)
if(EFL_MODULE_SCOPE)
set(_modsrcdir ${EFL_MODULES_SOURCE_DIR}/${EFL_MODULE_SCOPE}/${_modname})
set(_modoutdir lib/${EFL_LIB_CURRENT}/modules/${EFL_MODULE_SCOPE}/${_modname}/v-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR})
set(_modbindir ${EFL_MODULES_BINARY_DIR}/${EFL_MODULE_SCOPE}/${_modname})
set(_modtarget ${EFL_LIB_CURRENT}-module-${EFL_MODULE_SCOPE}-${_modname})
else()
set(_modsrcdir ${EFL_MODULES_SOURCE_DIR}/${_modname})
set(_modoutdir lib/${EFL_LIB_CURRENT}/modules/${_modname}/v-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR})
set(_modbindir ${EFL_MODULES_BINARY_DIR}/${_modname})
set(_modtarget ${EFL_LIB_CURRENT}-module-${_modname})
endif()
set(SOURCES)
set(OBJECT_DEPENDS)
set(LIBRARIES)
set(INCLUDE_DIRECTORIES)
set(SYSTEM_INCLUDE_DIRECTORIES)
set(DEFINITIONS)
set(MODULE_TYPE "ON")
set(INSTALL_DIR ${_modoutdir})
_EFL_INCLUDE_OR_DETECT("Module ${_modtarget}" ${_modsrcdir})
if(NOT SOURCES)
message(WARNING "${_modsrcdir}/CMakeLists.txt defines no SOURCES")
return()
endif()
if(PUBLIC_HEADERS)
message(WARNING "${_modsrcdir}/CMakeLists.txt should not define PUBLIC_HEADERS, it's not to be installed.")
endif()
if("${MODULE_TYPE}" STREQUAL "OFF")
return()
elseif("${MODULE_TYPE}" STREQUAL "STATIC")
set(_modtype STATIC)
else()
set(_modtype MODULE)
endif()
EFL_FILES_TO_ABSOLUTE(_sources ${_modsrcdir} ${_modbindir} ${SOURCES})
EFL_FILES_TO_ABSOLUTE(_obj_deps ${_modsrcdir} ${_modbindir} ${OBJECT_DEPENDS})
add_library(${_modtarget} ${_modtype} ${_sources})
set_target_properties(${_modtarget} PROPERTIES
OBJECT_DEPENDS "${_obj_deps}"
PREFIX ""
OUTPUT_NAME "module")
target_include_directories(${_modtarget} PRIVATE
${_modsrcdir}
${_modbindir}
${INCLUDE_DIRECTORIES})
target_include_directories(${_modtarget} SYSTEM PUBLIC
${SYSTEM_INCLUDE_DIRECTORIES})
target_link_libraries(${_modtarget} LINK_PRIVATE ${LIBRARIES})
target_compile_definitions(${_modtarget} PRIVATE ${DEFINITIONS})
set_target_properties(${_modtarget} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${_modoutdir}"
ARCHIVE_OUTPUT_DIRECTORY "${_modoutdir}"
RUNTIME_OUTPUT_DIRECTORY "${_modoutdir}")
if("${MODULE_TYPE}" STREQUAL "STATIC")
target_link_libraries(${EFL_LIB_CURRENT} LINK_PRIVATE ${_modtarget})
target_include_directories(${_modtarget} PRIVATE
${EFL_LIB_SOURCE_DIR}
${EFL_LIB_BINARY_DIR})
set_target_properties(${_modtarget} PROPERTIES
POSITION_INDEPENDENT_CODE TRUE)
LIST_APPEND_GLOBAL(${EFL_LIB_CURRENT}_STATIC_MODULES ${_modtarget})
else()
target_link_libraries(${_modtarget} LINK_PRIVATE ${EFL_LIB_CURRENT})
LIST_APPEND_GLOBAL(${EFL_LIB_CURRENT}_MODULES ${_modtarget})
if(INSTALL_DIR)
install(TARGETS ${_modtarget} LIBRARY DESTINATION "${INSTALL_DIR}")
endif()
endif()
endfunction()