# - Function to generate forward includes for your project # This module provides the function ECM_GENERATE_HEADERS # # The ECM_GENERATE_HEADERS function is used to generate C/C++ forwarding header # files for your project. # # To be more precise, there will be two kinds of headers being generated. Lowercase # and CamelCase, for convenience. That means that for a class named "ClassA" in a # module called "Module" we will get 2 different files: Module/ClassA and # module/classa.h. Both these files will be including a "classa.h" file that is # expected to be in the headers dir (see HEADERS_DIR argument below). # # ECM_GENERATE_HEADERS(camelcase_headers_var # HEADER_NAMES ClassA [ClassB [...]] # [OUTPUT_DIR output_dir] # [PREFIX prefix] # [REQUIRED_HEADERS variable] # [RELATIVE relative_path]) # # The paths to the generated CamelCase headers will be appended to # camelcase_headers_var. # # HEADER_NAMES lists the generated CamelCase header names. # # PREFIX places the headers in subdirectories. This should be a CamelCase name # like KParts, which will cause the CamelCase headers to be placed in the KParts # directory (eg: KParts/Part). It will also, for the convenience of code in the # source distribution, generate forwarding lowercase headers, like # kparts/part.h. This allows includes like "#include " to be # used before installation, as long as the include_directories are set # appropriately. # # The OUTPUT_DIR argument specifies where the files will be generated; this # should be within the build directory. By default, CMAKE_CURRENT_BINARY_DIR # will be used. This option can be used to avoid file conflicts. # # The REQUIRED_HEADERS argument specifies an output variable name where all the # required headers will be appended so that they can be installed together with # the generated ones. This is mostly intended as a convenience so that adding a # new header to a project only requires specifying the CamelCase variant in the # CMakeLists.txt file; the lowercase variant will then be added to this # variable. # # The RELATIVE argument indicates where the lowercase headers can be found # relative to CMAKE_CURRENT_SOURCE_DIR. It does not affect the generated # CamelCase files, but ECM_GENERATE_HEADERS uses it when checking that the # lowercase header exists, and to generate lowercase forwarding headers when # PREFIX is set. # # To allow other parts of the source distribution (eg: tests) to use the # generated headers before installation, it may be desirable to set the # INCLUDE_DIRECTORIES property for the library target to output_dir. For # example, if output_dir is CMAKE_CURRENT_BINARY_DIR (the default), you could do # target_include_directories(MyLib # PUBLIC "$") # # Example usage (without PREFIX): # ecm_generate_headers( # MyLib_FORWARDING_HEADERS # HEADERS # MLFoo # MLBar # # etc # REQUIRED_HEADERS MyLib_HEADERS # ) # install(FILES ${MyLib_FORWARDING_HEADERS} ${MyLib_HEADERS} # DESTINATION ${CMAKE_INSTALL_PREFIX}/include # COMPONENT Devel) # # Example usage (with PREFIX): # ecm_generate_headers( # MyLib_FORWARDING_HEADERS # HEADERS # Foo # Bar # # etc # PREFIX MyLib # REQUIRED_HEADERS MyLib_HEADERS # ) # install(FILES ${MyLib_FORWARDING_HEADERS} # DESTINATION ${CMAKE_INSTALL_PREFIX}/include/MyLib # COMPONENT Devel) # install(FILES ${MyLib_HEADERS} # DESTINATION ${CMAKE_INSTALL_PREFIX}/include/mylib # COMPONENT Devel) # # # Copyright 2013 Aleix Pol Gonzalez # Copyright 2014 Alex Merry # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # include(CMakeParseArguments) function(ECM_GENERATE_HEADERS camelcase_headers_var) set(options) set(oneValueArgs OUTPUT_DIR PREFIX REQUIRED_HEADERS RELATIVE) set(multiValueArgs HEADER_NAMES) cmake_parse_arguments(EGH "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if (EGH_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unexpected arguments to ECM_GENERATE_HEADERS: ${EGH_UNPARSED_ARGUMENTS}") endif() if(NOT EGH_HEADER_NAMES) message(FATAL_ERROR "Missing header_names argument to ECM_GENERATE_HEADERS") endif() if(NOT EGH_OUTPUT_DIR) set(EGH_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") endif() # Make sure EGH_RELATIVE is /-terminated when it's not empty if (EGH_RELATIVE AND NOT "${EGH_RELATIVE}" MATCHES "^.*/$") set(EGH_RELATIVE "${EGH_RELATIVE}/") endif() if (EGH_PREFIX) if (NOT "${EGH_PREFIX}" MATCHES "^.*/$") set(EGH_PREFIX "${EGH_PREFIX}/") endif() string(TOLOWER "${EGH_PREFIX}" lowercaseprefix) endif() foreach(_CLASSNAME ${EGH_HEADER_NAMES}) string(TOLOWER "${_CLASSNAME}" lowercaseclassname) set(FANCY_HEADER_FILE "${EGH_OUTPUT_DIR}/${EGH_PREFIX}${_CLASSNAME}") set(_actualheader "${CMAKE_CURRENT_SOURCE_DIR}/${EGH_RELATIVE}${lowercaseclassname}.h") if (NOT EXISTS ${_actualheader}) message(FATAL_ERROR "Could not find \"${_actualheader}\"") endif() if (NOT EXISTS ${FANCY_HEADER_FILE}) file(WRITE ${FANCY_HEADER_FILE} "#include \"${lowercaseprefix}${lowercaseclassname}.h\"\n") endif() list(APPEND ${camelcase_headers_var} "${FANCY_HEADER_FILE}") if (EGH_REQUIRED_HEADERS) list(APPEND ${EGH_REQUIRED_HEADERS} "${_actualheader}") endif() if (EGH_PREFIX) # Local forwarding header, for namespaced headers, e.g. kparts/part.h set(REGULAR_HEADER_NAME ${EGH_OUTPUT_DIR}/${lowercaseprefix}${lowercaseclassname}.h) if (NOT EXISTS ${REGULAR_HEADER_NAME}) file(WRITE ${REGULAR_HEADER_NAME} "#include \"${_actualheader}\"\n") endif() endif() endforeach() set(${camelcase_headers_var} ${${camelcase_headers_var}} PARENT_SCOPE) if (NOT EGH_REQUIRED_HEADERS STREQUAL "") set(${EGH_REQUIRED_HEADERS} ${${EGH_REQUIRED_HEADERS}} PARENT_SCOPE) endif () endfunction()