[Win][CMake] Use add_custom_command to copy each forwarding header files
[WebKit-https.git] / Source / cmake / WebKitMacros.cmake
1 # This file is for macros that are used by multiple projects. If your macro is
2 # exclusively needed in only one subdirectory of Source (e.g. only needed by
3 # WebCore), then put it there instead.
4
5 macro(WEBKIT_COMPUTE_SOURCES _framework)
6     foreach (_sourcesListFile IN LISTS ${_framework}_UNIFIED_SOURCE_LIST_FILES)
7       configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${_sourcesListFile}" "${DERIVED_SOURCES_DIR}/${_framework}/${_sourcesListFile}" COPYONLY)
8       message(STATUS "Using source list file: ${_sourcesListFile}")
9
10       list(APPEND _sourceListFileTruePaths "${CMAKE_CURRENT_SOURCE_DIR}/${_sourcesListFile}")
11     endforeach ()
12
13     if (WIN32 AND INTERNAL_BUILD)
14         set(WTF_SCRIPTS_DIR "${CMAKE_BINARY_DIR}/../include/private/WTF/Scripts")
15     else ()
16         set(WTF_SCRIPTS_DIR "${FORWARDING_HEADERS_DIR}/wtf/Scripts")
17     endif ()
18
19     execute_process(COMMAND ${RUBY_EXECUTABLE} ${WTF_SCRIPTS_DIR}/generate-unified-source-bundles.rb
20         "--derived-sources-path" "${DERIVED_SOURCES_DIR}/${_framework}"
21         "--source-tree-path" ${CMAKE_CURRENT_SOURCE_DIR}
22         "--print-bundled-sources"
23         "--feature-flags" "${UNIFIED_SOURCE_LIST_ENABLED_FEATURES}"
24         ${_sourceListFileTruePaths}
25         RESULT_VARIABLE _resultTmp
26         OUTPUT_VARIABLE _outputTmp)
27
28     if (${_resultTmp})
29          message(FATAL_ERROR "generate-unified-source-bundles.rb exited with non-zero status, exiting")
30     endif ()
31
32     foreach (_sourceFileTmp IN LISTS _outputTmp)
33         set_source_files_properties(${_sourceFileTmp} PROPERTIES HEADER_FILE_ONLY ON)
34         list(APPEND ${_framework}_HEADERS ${_sourceFileTmp})
35     endforeach ()
36     unset(_sourceFileTmp)
37
38     execute_process(COMMAND ${RUBY_EXECUTABLE} ${WTF_SCRIPTS_DIR}/generate-unified-source-bundles.rb
39         "--derived-sources-path" "${DERIVED_SOURCES_DIR}/${_framework}"
40         "--source-tree-path" ${CMAKE_CURRENT_SOURCE_DIR}
41         "--feature-flags" "${UNIFIED_SOURCE_LIST_ENABLED_FEATURES}"
42         ${_sourceListFileTruePaths}
43         RESULT_VARIABLE  _resultTmp
44         OUTPUT_VARIABLE _outputTmp)
45
46     if (${_resultTmp})
47         message(FATAL_ERROR "generate-unified-source-bundles.rb exited with non-zero status, exiting")
48     endif ()
49
50     list(APPEND ${_framework}_SOURCES ${_outputTmp})
51     unset(_platformSourcesFile)
52     unset(_resultTmp)
53     unset(_outputTmp)
54 endmacro()
55
56 macro(WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS)
57     set(_file ${CMAKE_CURRENT_SOURCE_DIR}/Platform${PORT}.cmake)
58     if (EXISTS ${_file})
59         message(STATUS "Using platform-specific CMakeLists: ${_file}")
60         include(${_file})
61     else ()
62         message(STATUS "Platform-specific CMakeLists not found: ${_file}")
63     endif ()
64 endmacro()
65
66 # Append the given dependencies to the source file
67 macro(WEBKIT_ADD_SOURCE_DEPENDENCIES _source _deps)
68     set(_tmp)
69     get_source_file_property(_tmp ${_source} OBJECT_DEPENDS)
70     if (NOT _tmp)
71         set(_tmp "")
72     endif ()
73
74     foreach (f ${_deps})
75         list(APPEND _tmp "${f}")
76     endforeach ()
77
78     set_source_files_properties(${_source} PROPERTIES OBJECT_DEPENDS "${_tmp}")
79     unset(_tmp)
80 endmacro()
81
82 macro(WEBKIT_ADD_PRECOMPILED_HEADER _header _cpp _source)
83     if (MSVC)
84         get_filename_component(PrecompiledBasename ${_cpp} NAME_WE)
85         file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_source}")
86         set(PrecompiledBinary "${CMAKE_CURRENT_BINARY_DIR}/${_source}/${PrecompiledBasename}.pch")
87         set(_sources ${${_source}})
88
89         # clang-cl requires /FI with /Yc
90         if (COMPILER_IS_CLANG_CL)
91             set_source_files_properties(${_cpp}
92                 PROPERTIES COMPILE_FLAGS "/Yc\"${_header}\" /Fp\"${PrecompiledBinary}\" /FI\"${_header}\""
93                 OBJECT_OUTPUTS "${PrecompiledBinary}")
94         else ()
95             set_source_files_properties(${_cpp}
96                 PROPERTIES COMPILE_FLAGS "/Yc\"${_header}\" /Fp\"${PrecompiledBinary}\""
97                 OBJECT_OUTPUTS "${PrecompiledBinary}")
98         endif ()
99         set_source_files_properties(${_sources}
100             PROPERTIES COMPILE_FLAGS "/Yu\"${_header}\" /FI\"${_header}\" /Fp\"${PrecompiledBinary}\"")
101
102         foreach (_src ${_sources})
103             WEBKIT_ADD_SOURCE_DEPENDENCIES(${_src} ${PrecompiledBinary})
104         endforeach ()
105
106         list(APPEND ${_source} ${_cpp})
107     endif ()
108     #FIXME: Add support for Xcode.
109 endmacro()
110
111 macro(WEBKIT_WRAP_SOURCELIST)
112     foreach (_file ${ARGN})
113         get_filename_component(_basename ${_file} NAME_WE)
114         get_filename_component(_path ${_file} PATH)
115
116         if (NOT _file MATCHES "${DERIVED_SOURCES_WEBCORE_DIR}")
117             string(REGEX REPLACE "/" "\\\\\\\\" _sourcegroup "${_path}")
118             source_group("${_sourcegroup}" FILES ${_file})
119         endif ()
120     endforeach ()
121
122     source_group("DerivedSources" REGULAR_EXPRESSION "${DERIVED_SOURCES_WEBCORE_DIR}")
123 endmacro()
124
125 macro(WEBKIT_FRAMEWORK_DECLARE _target)
126     # add_library() without any source files triggers CMake warning
127     # Addition of dummy "source" file does not result in any changes in generated build.ninja file
128     add_library(${_target} ${${_target}_LIBRARY_TYPE} "${CMAKE_BINARY_DIR}/cmakeconfig.h")
129 endmacro()
130
131 macro(WEBKIT_FRAMEWORK _target)
132     include_directories(SYSTEM ${${_target}_SYSTEM_INCLUDE_DIRECTORIES})
133     target_sources(${_target} PRIVATE
134         ${${_target}_HEADERS}
135         ${${_target}_SOURCES}
136     )
137     target_include_directories(${_target} PUBLIC "$<BUILD_INTERFACE:${${_target}_INCLUDE_DIRECTORIES}>")
138     target_include_directories(${_target} PRIVATE "$<BUILD_INTERFACE:${${_target}_PRIVATE_INCLUDE_DIRECTORIES}>")
139     target_link_libraries(${_target} ${${_target}_LIBRARIES})
140     set_target_properties(${_target} PROPERTIES COMPILE_DEFINITIONS "BUILDING_${_target}")
141
142     if (${_target}_OUTPUT_NAME)
143         set_target_properties(${_target} PROPERTIES OUTPUT_NAME ${${_target}_OUTPUT_NAME})
144     endif ()
145
146     if (${_target}_PRE_BUILD_COMMAND)
147         add_custom_target(_${_target}_PreBuild COMMAND ${${_target}_PRE_BUILD_COMMAND} VERBATIM)
148         add_dependencies(${_target} _${_target}_PreBuild)
149     endif ()
150
151     if (${_target}_POST_BUILD_COMMAND)
152         add_custom_command(TARGET ${_target} POST_BUILD COMMAND ${${_target}_POST_BUILD_COMMAND} VERBATIM)
153     endif ()
154
155     if (APPLE AND NOT PORT STREQUAL "GTK" AND NOT ${${_target}_LIBRARY_TYPE} MATCHES STATIC)
156         set_target_properties(${_target} PROPERTIES FRAMEWORK TRUE)
157         install(TARGETS ${_target} FRAMEWORK DESTINATION ${LIB_INSTALL_DIR})
158     endif ()
159 endmacro()
160
161 macro(WEBKIT_CREATE_FORWARDING_HEADER _target_directory _file)
162     get_filename_component(_source_path "${CMAKE_SOURCE_DIR}/Source/" ABSOLUTE)
163     get_filename_component(_absolute "${_file}" ABSOLUTE)
164     get_filename_component(_name "${_file}" NAME)
165     set(_target_filename "${_target_directory}/${_name}")
166
167     # Try to make the path in the forwarding header relative to the Source directory
168     # so that these forwarding headers are compatible with the ones created by the
169     # WebKit2 generate-forwarding-headers script.
170     string(REGEX REPLACE "${_source_path}/" "" _relative ${_absolute})
171
172     set(_content "#include \"${_relative}\"\n")
173
174     if (EXISTS "${_target_filename}")
175         file(READ "${_target_filename}" _old_content)
176     endif ()
177
178     if (NOT _old_content STREQUAL _content)
179         file(WRITE "${_target_filename}" "${_content}")
180     endif ()
181 endmacro()
182
183 macro(WEBKIT_CREATE_FORWARDING_HEADERS _framework)
184     # On Windows, we copy the entire contents of forwarding headers.
185     if (NOT WIN32)
186         set(_processing_directories 0)
187         set(_processing_files 0)
188         set(_target_directory "${FORWARDING_HEADERS_DIR}/${_framework}")
189
190         file(GLOB _files "${_target_directory}/*.h")
191         foreach (_file ${_files})
192             file(READ "${_file}" _content)
193             string(REGEX MATCH "^#include \"([^\"]*)\"" _matched ${_content})
194             if (_matched AND NOT EXISTS "${CMAKE_SOURCE_DIR}/Source/${CMAKE_MATCH_1}")
195                file(REMOVE "${_file}")
196             endif ()
197         endforeach ()
198
199         foreach (_currentArg ${ARGN})
200             if ("${_currentArg}" STREQUAL "DIRECTORIES")
201                 set(_processing_directories 1)
202                 set(_processing_files 0)
203             elseif ("${_currentArg}" STREQUAL "FILES")
204                 set(_processing_directories 0)
205                 set(_processing_files 1)
206             elseif (_processing_directories)
207                 file(GLOB _files "${_currentArg}/*.h")
208                 foreach (_file ${_files})
209                     WEBKIT_CREATE_FORWARDING_HEADER(${_target_directory} ${_file})
210                 endforeach ()
211             elseif (_processing_files)
212                 WEBKIT_CREATE_FORWARDING_HEADER(${_target_directory} ${_currentArg})
213             endif ()
214         endforeach ()
215     endif ()
216 endmacro()
217
218 function(WEBKIT_MAKE_FORWARDING_HEADERS framework)
219     set(options FLATTENED)
220     set(oneValueArgs DESTINATION)
221     set(multiValueArgs DIRECTORIES EXTRA_DIRECTORIES DERIVED_SOURCE_DIRECTORIES FILES)
222     cmake_parse_arguments(opt "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
223     set(headers ${opt_FILES})
224     if (opt_DESTINATION)
225         set(destination ${opt_DESTINATION})
226     else ()
227         set(destination ${FORWARDING_HEADERS_DIR}/${framework})
228     endif ()
229     file(MAKE_DIRECTORY ${destination})
230     foreach (dir IN LISTS opt_DIRECTORIES)
231         file(GLOB files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${dir}/*.h)
232         list(APPEND headers ${files})
233     endforeach ()
234     set(fwd_headers)
235     foreach (header IN LISTS headers)
236         if (opt_FLATTENED)
237             get_filename_component(header_filename ${header} NAME)
238             set(fwd_header ${destination}/${header_filename})
239         else ()
240             get_filename_component(header_dir ${header} DIRECTORY)
241             file(MAKE_DIRECTORY ${destination}/${header_dir})
242             set(fwd_header ${destination}/${header})
243         endif ()
244         add_custom_command(OUTPUT ${fwd_header}
245             COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${header} ${fwd_header}
246             MAIN_DEPENDENCY ${header}
247             VERBATIM
248         )
249         list(APPEND fwd_headers ${fwd_header})
250     endforeach ()
251     foreach (dir IN LISTS opt_EXTRA_DIRECTORIES)
252         set(dir ${CMAKE_CURRENT_SOURCE_DIR}/${dir})
253         file(GLOB_RECURSE files RELATIVE ${dir} ${dir}/*.h)
254         foreach (header IN LISTS files)
255             get_filename_component(header_dir ${header} DIRECTORY)
256             file(MAKE_DIRECTORY ${destination}/${header_dir})
257             set(fwd_header ${destination}/${header})
258             add_custom_command(OUTPUT ${fwd_header}
259                 COMMAND ${CMAKE_COMMAND} -E copy ${dir}/${header} ${fwd_header}
260                 MAIN_DEPENDENCY ${dir}/${header}
261                 VERBATIM
262             )
263             list(APPEND fwd_headers ${fwd_header})
264         endforeach ()
265     endforeach ()
266     add_custom_target(${framework}ForwardingHeaders DEPENDS ${fwd_headers})
267     add_dependencies(${framework} ${framework}ForwardingHeaders)
268     if (opt_DERIVED_SOURCE_DIRECTORIES)
269         set(script ${CMAKE_CURRENT_BINARY_DIR}/makeForwardingHeaders.cmake)
270         set(content "")
271         foreach (dir IN LISTS opt_DERIVED_SOURCE_DIRECTORIES)
272             string(CONCAT content ${content}
273                 "file(GLOB headers \"${dir}/*.h\")\n"
274                 "foreach (header IN LISTS headers)\n"
275                 "    get_filename_component(header_filename \${header} NAME)\n"
276                 "    execute_process(COMMAND \${CMAKE_COMMAND} -E copy \${header} ${destination}/\${header_filename} RESULT_VARIABLE result)\n"
277                 "    if (NOT \${result} EQUAL 0)\n"
278                 "        message(FATAL_ERROR \"Failed to copy \${header}: \${result}\")\n"
279                 "    endif ()\n"
280                 "endforeach ()\n"
281             )
282         endforeach ()
283         file(WRITE ${script} ${content})
284         add_custom_command(TARGET ${framework} POST_BUILD
285             COMMAND ${CMAKE_COMMAND} -P ${script}
286             VERBATIM
287         )
288     endif ()
289 endfunction()
290
291 # Helper macros for debugging CMake problems.
292 macro(WEBKIT_DEBUG_DUMP_COMMANDS)
293     set(CMAKE_VERBOSE_MAKEFILE ON)
294 endmacro()
295
296 macro(WEBKIT_DEBUG_DUMP_VARIABLES)
297     set_cmake_property(_variableNames VARIABLES)
298     foreach (_variableName ${_variableNames})
299        message(STATUS "${_variableName}=${${_variableName}}")
300     endforeach ()
301 endmacro()
302
303 # Append the given flag to the target property.
304 # Builds on top of get_target_property() and set_target_properties()
305 macro(WEBKIT_ADD_TARGET_PROPERTIES _target _property _flags)
306     get_target_property(_tmp ${_target} ${_property})
307     if (NOT _tmp)
308         set(_tmp "")
309     endif (NOT _tmp)
310
311     foreach (f ${_flags})
312         set(_tmp "${_tmp} ${f}")
313     endforeach (f ${_flags})
314
315     set_target_properties(${_target} PROPERTIES ${_property} ${_tmp})
316     unset(_tmp)
317 endmacro()
318
319 macro(WEBKIT_POPULATE_LIBRARY_VERSION library_name)
320     if (NOT DEFINED ${library_name}_VERSION_MAJOR)
321         set(${library_name}_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
322     endif ()
323     if (NOT DEFINED ${library_name}_VERSION_MINOR)
324         set(${library_name}_VERSION_MINOR ${PROJECT_VERSION_MINOR})
325     endif ()
326     if (NOT DEFINED ${library_name}_VERSION_MICRO)
327         set(${library_name}_VERSION_MICRO ${PROJECT_VERSION_MICRO})
328     endif ()
329     if (NOT DEFINED ${library_name}_VERSION)
330         set(${library_name}_VERSION ${PROJECT_VERSION})
331     endif ()
332 endmacro()
333
334 macro(WEBKIT_CREATE_SYMLINK target src dest)
335     add_custom_command(TARGET ${target} POST_BUILD
336         COMMAND ln -sf ${src} ${dest}
337         DEPENDS ${dest}
338         COMMENT "Create symlink from ${src} to ${dest}")
339 endmacro()