aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorAlex Merry <kde@randomguy3.me.uk>2014-02-15 16:42:47 +0000
committerAlex Merry <kde@randomguy3.me.uk>2014-02-16 10:49:12 +0000
commit434c63acd090568147505ff1c31053dcb1b3863f (patch)
tree95ae83b51b2bc658d8eaf7113aed5a9cb0552afe /modules
parent3d931552b72972adb0cefe79cc4d9586671d5224 (diff)
downloadextra-cmake-modules-434c63acd090568147505ff1c31053dcb1b3863f.tar.gz
extra-cmake-modules-434c63acd090568147505ff1c31053dcb1b3863f.tar.bz2
Improve the ECMGenerateHeaders API with a variable for generated files
ecm_generate_headers() now allows/forces the caller to collect the paths of the generated headers, so that they can be passed to the install command. This avoids issues of unexpected files being in the CamelCase includes directory, both from previous builds and because of case-insensitive file systems. MODULE_NAME is removed, as it is no longer desirable or necessary. Instead, the headers are placed directly in the output directory (usually CMAKE_CURRENT_BUILD_DIR). Overall, this makes ecm_generate_headers() behave much more like other file generation macros (like the Qt ones). The old syntax is still supported for now, to make the porting effort easier. REVIEW: 115765
Diffstat (limited to 'modules')
-rw-r--r--modules/ECMGenerateHeaders.cmake173
1 files changed, 142 insertions, 31 deletions
diff --git a/modules/ECMGenerateHeaders.cmake b/modules/ECMGenerateHeaders.cmake
index e98a22e9..9d294d1e 100644
--- a/modules/ECMGenerateHeaders.cmake
+++ b/modules/ECMGenerateHeaders.cmake
@@ -10,31 +10,83 @@
# 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( ClassA ClassB ...
-# [MODULE_NAME name]
-# [OUTPUT_DIR path]
+# ECM_GENERATE_HEADERS(camelcase_headers_var
+# HEADER_NAMES ClassA [ClassB [...]]
+# [OUTPUT_DIR output_dir]
# [PREFIX prefix]
-# [REQUIRED_HEADERS variable])
+# [REQUIRED_HEADERS variable]
+# [RELATIVE relative_path])
#
-# The MODULE_NAME argument is used to provide information about where the
-# directories will be generated. By default, PROJECT_NAME will be used.
+# The paths to the generated CamelCase headers will be appended to
+# camelcase_headers_var.
#
-# The optional PREFIX will be prepended to the filenames, e.g. PREFIX KParts
-# will generate KParts/Part and kparts/part.h
+# 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 <kparts/part.h>" 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.
+# 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 "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>")
#
-# The REQUIRED_HEADERS argument will receive an output variable name where all
-# the required headers will be appended so that they can be installed together
-# with the generated ones.
+# 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)
#
-# The RELATIVE argument will specify where are the original headers from the
-# current directory.
+# 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 (c) 2013, Aleix Pol Gonzalez <aleixpol@blue-systems.com>
+# Copyright 2013 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
+# Copyright 2014 Alex Merry <alex.merry@kdemail.net>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
@@ -42,29 +94,16 @@
include(CMakeParseArguments)
-function(ECM_GENERATE_HEADERS)
- set(oneValueArgs MODULE_NAME OUTPUT_DIR PREFIX REQUIRED_HEADERS RELATIVE)
- cmake_parse_arguments(EGH "" "${oneValueArgs}" "" ${ARGN})
+# FIXME: remove when all the frameworks are ported to the new syntax
+macro(_ECM_GENERATE_HEADERS_OLD)
if(NOT EGH_MODULE_NAME)
set(EGH_MODULE_NAME ${PROJECT_NAME})
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 (NOT ${EGH_RELATIVE} MATCHES "^.*/$")
- set(EGH_RELATIVE "${EGH_RELATIVE}/")
- endif()
-
- if (EGH_PREFIX)
- string(TOLOWER "${EGH_PREFIX}/" lowercaseprefix)
- endif()
string(TOLOWER ${EGH_MODULE_NAME} lowercasemodule)
foreach(_CLASSNAME ${EGH_UNPARSED_ARGUMENTS})
string(TOLOWER ${_CLASSNAME} lowercaseclassname)
- set(FANCY_HEADER_NAME ${EGH_OUTPUT_DIR}/${EGH_MODULE_NAME}/${EGH_PREFIX}/${_CLASSNAME})
+ set(FANCY_HEADER_NAME ${EGH_OUTPUT_DIR}/${EGH_MODULE_NAME}/${EGH_PREFIX}${_CLASSNAME})
set(_actualheader "${CMAKE_CURRENT_SOURCE_DIR}/${EGH_RELATIVE}${lowercaseclassname}.h")
if (NOT EXISTS ${_actualheader})
message(FATAL_ERROR "Could not find \"${_actualheader}\"")
@@ -85,4 +124,76 @@ function(ECM_GENERATE_HEADERS)
if (NOT EGH_REQUIRED_HEADERS STREQUAL "")
set(${EGH_REQUIRED_HEADERS} ${${EGH_REQUIRED_HEADERS}} ${REQUIRED_HEADERS} PARENT_SCOPE)
endif ()
+endmacro()
+
+function(ECM_GENERATE_HEADERS)
+ set(options)
+ set(oneValueArgs OUTPUT_DIR PREFIX REQUIRED_HEADERS RELATIVE MODULE_NAME)
+ set(multiValueArgs HEADER_NAMES)
+ cmake_parse_arguments(EGH "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ 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()
+
+ if(NOT EGH_HEADER_NAMES)
+ message(AUTHOR_WARNING "Please update your usage of ECM_GENERATE_HEADERS to the new syntax")
+ _ecm_generate_headers_old()
+ return()
+ endif()
+
+ if (EGH_MODULE_NAME)
+ # this is not a valid argument in the new syntax
+ message(FATAL_ERROR "Unexpected MODULE_NAME argument for ECM_GENERATE_HEADERS")
+ endif()
+
+ if (NOT EGH_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Missing camelcase_headers_var argument to ECM_GENERATE_HEADERS")
+ else()
+ list(GET EGH_UNPARSED_ARGUMENTS 0 camelcase_headers_var)
+ list(REMOVE_AT EGH_UNPARSED_ARGUMENTS 0)
+ if (EGH_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unexpected arguments to ECM_GENERATE_HEADERS: ${EGH_UNPARSED_ARGUMENTS}")
+ endif()
+ 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()