efl/cmake/helpers/EflMacros.cmake

1104 lines
37 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()
unset(EFL_ALL_OPTIONS CACHE)
unset(EFL_ALL_LIBS CACHE)
unset(EFL_ALL_TESTS CACHE)
unset(EFL_PKG_CONFIG_MISSING_OPTIONAL CACHE)
# 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()
unset(HEADER_FILE_CONTENT CACHE)
# HEADER_CHECK(header [NAME variable] [INCLUDE_FILES extra1.h .. extraN.h])
#
# Check if the header file exists, in such case define variable
# in configuration file.
#
# Variable defaults to HAVE_${HEADER}, where HEADER is the uppercase
# representation of the first parameter. It can be overridden using
# NAME keyword.
#
# To include extra files, then use INCLUDE_FILES keyword.
function(HEADER_CHECK header)
string(TOUPPER HAVE_${header} var)
string(REGEX REPLACE "[^a-zA-Z0-9]" "_" var "${var}")
string(REGEX REPLACE "_{2,}" "_" var "${var}")
cmake_parse_arguments(PARAMS "" "NAME" "INCLUDE_FILES" ${ARGN})
if(PARAMS_NAME)
set(var ${PARAMS_NAME})
endif()
set(CMAKE_EXTRA_INCLUDE_FILES "${PARAMS_INCLUDE_FILES}")
CHECK_INCLUDE_FILE(${header} ${var})
if(${${var}})
SET_GLOBAL(HEADER_FILE_CONTENT "${HEADER_FILE_CONTENT}#define ${var} 1\n")
else()
SET_GLOBAL(HEADER_FILE_CONTENT "${HEADER_FILE_CONTENT}#undef ${var}\n")
endif()
endfunction()
# FUNC_CHECK(func [NAME variable]
# [INCLUDE_FILES header1.h .. headerN.h]
# [LIBRARIES lib1 ... libN]
# [DEFINITIONS -DA=1 .. -DN=123]
# [FLAGS -cmdlineparam1 .. -cmdlineparamN]
# [CXX])
#
# Check if the function exists, in such case define variable in
# configuration file.
#
# Variable defaults to HAVE_${FUNC}, where FUNC is the uppercase
# representation of the first parameter. It can be overridden using
# NAME keyword.
#
# To define include files use INCLUDE_FILES keyword.
#
# To use C++ compiler, use CXX keyword
function(FUNC_CHECK func)
string(TOUPPER HAVE_${func} var)
string(REGEX REPLACE "_{2,}" "_" var "${var}")
cmake_parse_arguments(PARAMS "CXX" "NAME" "INCLUDE_FILES;LIBRARIES;DEFINITIONS;FLAGS" ${ARGN})
set(CMAKE_REQUIRED_LIBRARIES "${PARAMS_LIBRARIES}")
set(CMAKE_REQUIRED_DEFINITIONS "${PARAMS_DEFINITIONS}")
set(CMAKE_REQUIRED_FLAGS "${PARAMS_FLAGS}")
if(PARAMS_CXX)
check_cxx_symbol_exists(${func} "${PARAMS_INCLUDE_FILES}" ${var})
else()
check_symbol_exists(${func} "${PARAMS_INCLUDE_FILES}" ${var})
endif()
if(${${var}} )
SET_GLOBAL(HEADER_FILE_CONTENT "${HEADER_FILE_CONTENT}#define ${var} 1\n")
else()
SET_GLOBAL(HEADER_FILE_CONTENT "${HEADER_FILE_CONTENT}#undef ${var}\n")
endif()
endfunction()
# TYPE_CHECK(type [NAME variable]
# [INCLUDE_FILES file1.h ... fileN.h]
# [LIBRARIES lib1 ... libN]
# [DEFINITIONS -DA=1 .. -DN=123]
# [FLAGS -cmdlineparam1 .. -cmdlineparamN]
# [CXX])
#
# Check if the type exists and its size, in such case define variable
# in configuration file.
#
# Variable defaults to HAVE_${TYPE}, where TYPE is the uppercase
# representation of the first parameter. It can be overridden using
# NAME keyword.
#
# To define include files use INCLUDE_FILES keyword.
#
# To use C++ compiler, use CXX keyword
function(TYPE_CHECK type)
string(TOUPPER HAVE_${type} var)
string(REGEX REPLACE "_{2,}" "_" var "${var}")
cmake_parse_arguments(PARAMS "CXX" "NAME" "INCLUDE_FILES;LIBRARIES;DEFINITIONS;FLAGS" ${ARGN})
set(CMAKE_REQUIRED_LIBRARIES "${PARAMS_LIBRARIES}")
set(CMAKE_REQUIRED_DEFINITIONS "${PARAMS_DEFINITIONS}")
set(CMAKE_REQUIRED_FLAGS "${PARAMS_FLAGS}")
set(CMAKE_EXTRA_INCLUDE_FILES "${PARAMS_INCLUDE_FILES}")
if(PARAMS_CXX)
set(lang CXX)
else()
set(lang C)
endif()
CHECK_TYPE_SIZE(${type} ${var} LANGUAGE ${lang})
if(HAVE_${var})
SET_GLOBAL(HEADER_FILE_CONTENT "${HEADER_FILE_CONTENT}#define ${var} 1\n")
else()
SET_GLOBAL(HEADER_FILE_CONTENT "${HEADER_FILE_CONTENT}#undef ${var}\n")
endif()
endfunction()
# EFL_HEADER_CHECKS_FINALIZE(file)
#
# Write the configuration gathered with HEADER_CHECK(), TYPE_CHECK()
# and FUNC_CHECK() to the given file.
function(EFL_HEADER_CHECKS_FINALIZE file)
file(WRITE ${file}.new ${HEADER_FILE_CONTENT})
if (NOT EXISTS ${file})
file(RENAME ${file}.new ${file})
message(STATUS "${file} was generated.")
else()
file(MD5 ${file}.new _new_md5)
file(MD5 ${file} _old_md5)
if(_new_md5 STREQUAL _old_md5)
message(STATUS "${file} is unchanged.")
else()
file(REMOVE ${file})
file(RENAME ${file}.new ${file})
message(STATUS "${file} was updated.")
endif()
endif()
unset(HEADER_FILE_CONTENT CACHE) # allow to reuse with an empty contents
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)
unset(${EFL_LIB_CURRENT}_MODULES CACHE)
unset(${EFL_LIB_CURRENT}_STATIC_MODULES CACHE)
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)
unset(${EFL_LIB_CURRENT}_TESTS CACHE)
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 source files that are needed, eo files can also be added here to be build
# - 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()
# - PUBLIC_EO_FILES: the eo files will be used to build that lib, and will be installed to the filesystem
#
# 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()
#merge public eo files into sources
set(SOURCES ${SOURCES} ${PUBLIC_EO_FILES})
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_FILES_TO_ABSOLUTE(_public_eo_files ${EFL_LIB_SOURCE_DIR} ${EFL_LIB_BINARY_DIR}
${PUBLIC_EO_FILES})
foreach(public_eo_file ${_public_eo_files})
get_filename_component(filename ${public_eo_file} NAME)
list(APPEND _headers ${EFL_LIB_BINARY_DIR}/${filename}.h)
endforeach()
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} PUBLIC ${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_CREATE_EO_RULES(${_target} ${EFL_LIB_BINARY_DIR})
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)
install(FILES
${_public_eo_files} DESTINATION share/eolian/include/${_target}-${PROJECT_VERSION_MAJOR}
)
# 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
"-DPACKAGE_DATA_DIR=\"${EFL_TESTS_SOURCE_DIR}\""
"-DTESTS_SRC_DIR=\"${_testrcdir}\""
"-DTESTS_BUILD_DIR=\"${_testbindir}\""
"-DTESTS_WD=\"${PROJECT_BINARY_DIR}\""
${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})
add_test(${_testname}-build "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target ${_testtarget})
set_tests_properties(${_testname} PROPERTIES DEPENDS ${_testname}-build)
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})
string(TOUPPER "${EFL_LIB_CURRENT}_MODULE_TYPE_${EFL_MODULE_SCOPE}_${_modname}" _modoptionname)
if(NOT ${_modoptionname}_DEFAULT)
set(${_modoptionname}_DEFAULT "ON")
endif()
EFL_OPTION(${_modoptionname} "Build ${EFL_LIB_CURRENT} module ${EFL_MODULE_SCOPE}/${_modname}" ${${_modoptionname}_DEFAULT} CHOICE ON;OFF;STATIC)
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})
string(TOUPPER "${EFL_LIB_CURRENT}_MODULE_TYPE_${_modname}" _modoptionname)
if(NOT ${_modoptionname}_DEFAULT)
set(${_modoptionname}_DEFAULT "ON")
endif()
EFL_OPTION(${_modoptionname} "Build ${EFL_LIB_CURRENT} module ${_modname}" ${${_modoptionname}_DEFAULT} CHOICE ON;OFF;STATIC)
endif()
set(SOURCES)
set(OBJECT_DEPENDS)
set(LIBRARIES)
set(INCLUDE_DIRECTORIES)
set(SYSTEM_INCLUDE_DIRECTORIES)
set(DEFINITIONS)
set(MODULE_TYPE "${${_modoptionname}}")
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_compile_definitions(${EFL_LIB_CURRENT} PRIVATE "-D${_modoptionname}_STATIC=1")
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})
target_compile_definitions(${EFL_LIB_CURRENT} PRIVATE "-D${_modoptionname}_DYNAMIC=1")
LIST_APPEND_GLOBAL(${EFL_LIB_CURRENT}_MODULES ${_modtarget})
if(INSTALL_DIR)
install(TARGETS ${_modtarget} LIBRARY DESTINATION "${INSTALL_DIR}")
endif()
endif()
endfunction()
macro(EFL_PROJECT version)
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
project(efl VERSION ${version})
else ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
execute_process(
COMMAND git rev-list --count HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
project(efl VERSION ${version}.${GIT_VERSION})
endif ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
message("VERSION ${PROJECT_VERSION}")
endmacro()
# Will use the source of the given target to create rules for creating
# the .eo.c and .eo.h files. The INCLUDE_DIRECTORIES of the target will be used
function(EFL_CREATE_EO_RULES target generation_dir)
get_target_property(build_files ${target} SOURCES)
get_target_property(_link_libraries ${target} LINK_LIBRARIES)
#build a list of targets we use to scan for all files
list(APPEND _include_targets ${target})
foreach(lib ${_link_libraries})
if (TARGET ${lib})
list(APPEND _include_targets ${lib})
endif()
endforeach()
#build a list of include directories
foreach(link_target ${_include_targets})
list(APPEND include_cmd -I${CMAKE_SOURCE_DIR}/src/lib/${link_target})
endforeach()
foreach(file ${build_files})
get_filename_component(ext ${file} EXT)
get_filename_component(filename ${file} NAME)
if (${ext} MATCHES "^\\.eo$")
set(build_files ${EFL_LIB_BINARY_DIR}/${filename}.c ${EFL_LIB_BINARY_DIR}/${filename}.h)
set(create_rule ON)
elseif (${ext} MATCHES "^\\.eot$")
set(build_files ${EFL_LIB_BINARY_DIR}/${filename}.h)
set(create_rule ON)
endif()
#add the custom rule
if (create_rule)
add_custom_command(
OUTPUT ${build_files}
COMMAND ${CMAKE_COMMAND} -E env "EFL_RUN_IN_TREE=1" ${EOLIAN_BIN} ${include_cmd} -o c:${EFL_LIB_BINARY_DIR}/${filename}.c -o h:${EFL_LIB_BINARY_DIR}/${filename}.h ${file}
DEPENDS ${file}
)
unset(create_rule)
list(APPEND eo_gen_files ${build_files})
endif()
endforeach()
if(eo_gen_files)
file(MAKE_DIRECTORY ${EFL_LIB_BINARY_DIR})
add_custom_target(${target}-eo
DEPENDS ${eo_gen_files}
)
add_dependencies(${target} ${target}-eo)
add_dependencies(${target} eolian-bin)
endif()
endfunction()