874e56630bbe896e3120d957a7d42f26847dc08c
[WebKit-https.git] / Source / cmake / WebKitMacros.cmake
1 include(CMakeParseArguments)
2 include(ProcessorCount)
3 ProcessorCount(PROCESSOR_COUNT)
4
5 macro(WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS)
6     set(_file ${CMAKE_CURRENT_SOURCE_DIR}/Platform${PORT}.cmake)
7     if (EXISTS ${_file})
8         message(STATUS "Using platform-specific CMakeLists: ${_file}")
9         include(${_file})
10     else ()
11         message(STATUS "Platform-specific CMakeLists not found: ${_file}")
12     endif ()
13 endmacro()
14
15 # Append the given dependencies to the source file
16 macro(ADD_SOURCE_DEPENDENCIES _source _deps)
17     set(_tmp)
18     get_source_file_property(_tmp ${_source} OBJECT_DEPENDS)
19     if (NOT _tmp)
20         set(_tmp "")
21     endif ()
22
23     foreach (f ${_deps})
24         list(APPEND _tmp "${f}")
25     endforeach ()
26
27     set_source_files_properties(${_source} PROPERTIES OBJECT_DEPENDS "${_tmp}")
28 endmacro()
29
30 macro(ADD_PRECOMPILED_HEADER _header _cpp _source)
31     if (MSVC)
32         get_filename_component(PrecompiledBasename ${_cpp} NAME_WE)
33         file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_source}")
34         set(PrecompiledBinary "${CMAKE_CURRENT_BINARY_DIR}/${_source}/${PrecompiledBasename}.pch")
35         set(_sources ${${_source}})
36
37         set_source_files_properties(${_cpp}
38             PROPERTIES COMPILE_FLAGS "/Yc\"${_header}\" /Fp\"${PrecompiledBinary}\""
39             OBJECT_OUTPUTS "${PrecompiledBinary}")
40         set_source_files_properties(${_sources}
41             PROPERTIES COMPILE_FLAGS "/Yu\"${_header}\" /FI\"${_header}\" /Fp\"${PrecompiledBinary}\""
42             OBJECT_DEPENDS "${PrecompiledBinary}")
43         list(APPEND ${_source} ${_cpp})
44     endif ()
45     #FIXME: Add support for Xcode.
46 endmacro()
47
48 option(SHOW_BINDINGS_GENERATION_PROGRESS "Show progress of generating bindings" OFF)
49
50 # Helper macro which wraps generate-bindings-all.pl script.
51 #   target is a new target name to be added
52 #   OUTPUT_SOURCE is a list name which will contain generated sources.(eg. WebCore_SOURCES)
53 #   INPUT_FILES are IDL files to generate.
54 #   BASE_DIR is base directory where script is called.
55 #   IDL_INCLUDES is value of --include argument. (eg. ${WEBCORE_DIR}/bindings/js)
56 #   FEATURES is a value of --defines argument.
57 #   DESTINATION is a value of --outputDir argument.
58 #   GENERATOR is a value of --generator argument.
59 #   SUPPLEMENTAL_DEPFILE is a value of --supplementalDependencyFile. (optional)
60 #   PP_EXTRA_OUTPUT is extra outputs of preprocess-idls.pl. (optional)
61 #   PP_EXTRA_ARGS is extra arguments for preprocess-idls.pl. (optional)
62 function(GENERATE_BINDINGS target)
63     set(options)
64     set(oneValueArgs OUTPUT_SOURCE BASE_DIR FEATURES DESTINATION GENERATOR SUPPLEMENTAL_DEPFILE)
65     set(multiValueArgs INPUT_FILES IDL_INCLUDES PP_EXTRA_OUTPUT PP_EXTRA_ARGS)
66     cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
67     set(binding_generator ${WEBCORE_DIR}/bindings/scripts/generate-bindings-all.pl)
68     set(idl_attributes_file ${WEBCORE_DIR}/bindings/scripts/IDLAttributes.txt)
69     set(idl_files_list ${CMAKE_CURRENT_BINARY_DIR}/idl_files_${target}.tmp)
70     set(_supplemental_dependency)
71
72     set(content)
73     foreach (f ${arg_INPUT_FILES})
74         if (NOT IS_ABSOLUTE ${f})
75             set(f ${CMAKE_CURRENT_SOURCE_DIR}/${f})
76         endif ()
77         set(content "${content}${f}\n")
78     endforeach ()
79     file(WRITE ${idl_files_list} ${content})
80
81     set(args
82         --defines ${arg_FEATURES}
83         --generator ${arg_GENERATOR}
84         --outputDir ${arg_DESTINATION}
85         --idlFilesList ${idl_files_list}
86         --preprocessor "${CODE_GENERATOR_PREPROCESSOR}"
87         --idlAttributesFile ${idl_attributes_file})
88     if (arg_SUPPLEMENTAL_DEPFILE)
89         list(APPEND args --supplementalDependencyFile ${arg_SUPPLEMENTAL_DEPFILE})
90     endif ()
91     if (PROCESSOR_COUNT)
92         list(APPEND args --numOfJobs ${PROCESSOR_COUNT})
93     endif ()
94     foreach (i IN LISTS arg_IDL_INCLUDES)
95         if (IS_ABSOLUTE ${i})
96             list(APPEND args --include ${i})
97         else ()
98             list(APPEND args --include ${CMAKE_CURRENT_SOURCE_DIR}/${i})
99         endif ()
100     endforeach ()
101     foreach (i IN LISTS arg_PP_EXTRA_OUTPUT)
102         list(APPEND args --ppExtraOutput ${i})
103     endforeach ()
104     foreach (i IN LISTS arg_PP_EXTRA_ARGS)
105         list(APPEND args --ppExtraArgs ${i})
106     endforeach ()
107
108     set(common_generator_dependencies
109         ${WEBCORE_DIR}/bindings/scripts/generate-bindings.pl
110         ${SCRIPTS_BINDINGS}
111         # Changing enabled features should trigger recompiling all IDL files
112         # because some of them use #if.
113         ${CMAKE_BINARY_DIR}/cmakeconfig.h
114     )
115     if (EXISTS ${WEBCORE_DIR}/bindings/scripts/CodeGenerator${arg_GENERATOR}.pm)
116         list(APPEND common_generator_dependencies ${WEBCORE_DIR}/bindings/scripts/CodeGenerator${arg_GENERATOR}.pm)
117     endif ()
118     if (EXISTS ${arg_BASE_DIR}/CodeGenerator${arg_GENERATOR}.pm)
119         list(APPEND common_generator_dependencies ${arg_BASE_DIR}/CodeGenerator${arg_GENERATOR}.pm)
120     endif ()
121     foreach (i IN LISTS common_generator_dependencies)
122         list(APPEND args --generatorDependency ${i})
123     endforeach ()
124
125     set(gen_sources)
126     set(gen_headers)
127     foreach (_file ${arg_INPUT_FILES})
128         get_filename_component(_name ${_file} NAME_WE)
129         list(APPEND gen_sources ${arg_DESTINATION}/JS${_name}.cpp)
130         list(APPEND gen_headers ${arg_DESTINATION}/JS${_name}.h)
131     endforeach ()
132     set(${arg_OUTPUT_SOURCE} ${${arg_OUTPUT_SOURCE}} ${gen_sources} PARENT_SCOPE)
133     set(act_args)
134     if (SHOW_BINDINGS_GENERATION_PROGRESS)
135         list(APPEND args --showProgress)
136     endif ()
137     if (${CMAKE_VERSION} VERSION_LESS 3.2)
138         set_source_files_properties(${gen_sources} ${gen_headers} PROPERTIES GENERATED 1)
139     else ()
140         list(APPEND act_args BYPRODUCTS ${gen_sources} ${gen_headers})
141         if (SHOW_BINDINGS_GENERATION_PROGRESS)
142             list(APPEND act_args USES_TERMINAL)
143         endif ()
144     endif ()
145     add_custom_target(${target}
146         COMMAND ${PERL_EXECUTABLE} ${binding_generator} ${args}
147         WORKING_DIRECTORY ${arg_BASE_DIR}
148         COMMENT "Generate bindings (${target})"
149         VERBATIM ${act_args})
150 endfunction()
151
152 macro(GENERATE_FONT_NAMES _infile)
153     set(NAMES_GENERATOR ${WEBCORE_DIR}/dom/make_names.pl)
154     set(_arguments  --fonts ${_infile})
155     set(_outputfiles ${DERIVED_SOURCES_WEBCORE_DIR}/WebKitFontFamilyNames.cpp ${DERIVED_SOURCES_WEBCORE_DIR}/WebKitFontFamilyNames.h)
156
157     add_custom_command(
158         OUTPUT  ${_outputfiles}
159         MAIN_DEPENDENCY ${_infile}
160         DEPENDS ${MAKE_NAMES_DEPENDENCIES} ${NAMES_GENERATOR} ${SCRIPTS_BINDINGS}
161         COMMAND ${PERL_EXECUTABLE} ${NAMES_GENERATOR} --outputDir ${DERIVED_SOURCES_WEBCORE_DIR} ${_arguments}
162         VERBATIM)
163 endmacro()
164
165
166 macro(GENERATE_EVENT_FACTORY _infile _outfile)
167     set(NAMES_GENERATOR ${WEBCORE_DIR}/dom/make_event_factory.pl)
168
169     add_custom_command(
170         OUTPUT  ${DERIVED_SOURCES_WEBCORE_DIR}/${_outfile}
171         MAIN_DEPENDENCY ${_infile}
172         DEPENDS ${NAMES_GENERATOR} ${SCRIPTS_BINDINGS}
173         COMMAND ${PERL_EXECUTABLE} ${NAMES_GENERATOR} --input ${_infile} --outputDir ${DERIVED_SOURCES_WEBCORE_DIR}
174         VERBATIM)
175 endmacro()
176
177
178 macro(GENERATE_EXCEPTION_CODE_DESCRIPTION _infile _outfile)
179     set(NAMES_GENERATOR ${WEBCORE_DIR}/dom/make_dom_exceptions.pl)
180
181     add_custom_command(
182         OUTPUT  ${DERIVED_SOURCES_WEBCORE_DIR}/${_outfile}
183         MAIN_DEPENDENCY ${_infile}
184         DEPENDS ${NAMES_GENERATOR} ${SCRIPTS_BINDINGS}
185         COMMAND ${PERL_EXECUTABLE} ${NAMES_GENERATOR} --input ${_infile} --outputDir ${DERIVED_SOURCES_WEBCORE_DIR}
186         VERBATIM)
187 endmacro()
188
189
190 macro(GENERATE_SETTINGS_MACROS _infile _outfile)
191     set(NAMES_GENERATOR ${WEBCORE_DIR}/page/make_settings.pl)
192
193     # Do not list the output in more than one independent target that may
194     # build in parallel or the two instances of the rule may conflict.
195     # <https://cmake.org/cmake/help/v3.0/command/add_custom_command.html>
196     set(_extra_output
197         ${DERIVED_SOURCES_WEBCORE_DIR}/InternalSettingsGenerated.h
198         ${DERIVED_SOURCES_WEBCORE_DIR}/InternalSettingsGenerated.cpp
199         ${DERIVED_SOURCES_WEBCORE_DIR}/InternalSettingsGenerated.idl
200     )
201     set(_args BYPRODUCTS ${_extra_output})
202     if (${CMAKE_VERSION} VERSION_LESS 3.2)
203         set_source_files_properties(${_extra_output} PROPERTIES GENERATED 1)
204         set(_args)
205     endif ()
206     add_custom_command(
207         OUTPUT ${DERIVED_SOURCES_WEBCORE_DIR}/${_outfile}
208         MAIN_DEPENDENCY ${_infile}
209         DEPENDS ${NAMES_GENERATOR} ${SCRIPTS_BINDINGS}
210         COMMAND ${PERL_EXECUTABLE} ${NAMES_GENERATOR} --input ${_infile} --outputDir ${DERIVED_SOURCES_WEBCORE_DIR}
211         VERBATIM ${_args})
212 endmacro()
213
214
215 macro(GENERATE_DOM_NAMES _namespace _attrs)
216     set(NAMES_GENERATOR ${WEBCORE_DIR}/dom/make_names.pl)
217     set(_arguments  --attrs ${_attrs})
218     set(_outputfiles ${DERIVED_SOURCES_WEBCORE_DIR}/${_namespace}Names.cpp ${DERIVED_SOURCES_WEBCORE_DIR}/${_namespace}Names.h)
219     set(_extradef)
220     set(_tags)
221
222     foreach (f ${ARGN})
223         if (_tags)
224             set(_extradef "${_extradef} ${f}")
225         else ()
226             set(_tags ${f})
227         endif ()
228     endforeach ()
229
230     if (_tags)
231         set(_arguments "${_arguments}" --tags ${_tags} --factory --wrapperFactory)
232         set(_outputfiles "${_outputfiles}" ${DERIVED_SOURCES_WEBCORE_DIR}/${_namespace}ElementFactory.cpp ${DERIVED_SOURCES_WEBCORE_DIR}/${_namespace}ElementFactory.h ${DERIVED_SOURCES_WEBCORE_DIR}/JS${_namespace}ElementWrapperFactory.cpp ${DERIVED_SOURCES_WEBCORE_DIR}/JS${_namespace}ElementWrapperFactory.h)
233     endif ()
234
235     if (_extradef)
236         set(_additionArguments "${_additionArguments}" --extraDefines=${_extradef})
237     endif ()
238
239     add_custom_command(
240         OUTPUT  ${_outputfiles}
241         DEPENDS ${MAKE_NAMES_DEPENDENCIES} ${NAMES_GENERATOR} ${SCRIPTS_BINDINGS} ${_attrs} ${_tags}
242         COMMAND ${PERL_EXECUTABLE} ${NAMES_GENERATOR} --preprocessor "${CODE_GENERATOR_PREPROCESSOR_WITH_LINEMARKERS}" --outputDir ${DERIVED_SOURCES_WEBCORE_DIR} ${_arguments} ${_additionArguments}
243         VERBATIM)
244 endmacro()
245
246 macro(MAKE_HASH_TOOLS _source)
247     get_filename_component(_name ${_source} NAME_WE)
248
249     if (${_source} STREQUAL "DocTypeStrings")
250         set(_hash_tools_h "${DERIVED_SOURCES_WEBCORE_DIR}/HashTools.h")
251     else ()
252         set(_hash_tools_h "")
253     endif ()
254
255     add_custom_command(
256         OUTPUT ${DERIVED_SOURCES_WEBCORE_DIR}/${_name}.cpp ${_hash_tools_h}
257         MAIN_DEPENDENCY ${_source}.gperf
258         COMMAND ${PERL_EXECUTABLE} ${WEBCORE_DIR}/make-hash-tools.pl ${DERIVED_SOURCES_WEBCORE_DIR} ${_source}.gperf ${GPERF_EXECUTABLE}
259         VERBATIM)
260
261     unset(_name)
262     unset(_hash_tools_h)
263 endmacro()
264
265 macro(WEBKIT_WRAP_SOURCELIST)
266     foreach (_file ${ARGN})
267         get_filename_component(_basename ${_file} NAME_WE)
268         get_filename_component(_path ${_file} PATH)
269
270         if (NOT _file MATCHES "${DERIVED_SOURCES_WEBCORE_DIR}")
271             string(REGEX REPLACE "/" "\\\\\\\\" _sourcegroup "${_path}")
272             source_group("${_sourcegroup}" FILES ${_file})
273         endif ()
274     endforeach ()
275
276     source_group("DerivedSources" REGULAR_EXPRESSION "${DERIVED_SOURCES_WEBCORE_DIR}")
277 endmacro()
278
279 macro(WEBKIT_FRAMEWORK _target)
280     include_directories(SYSTEM ${${_target}_SYSTEM_INCLUDE_DIRECTORIES})
281     add_library(${_target} ${${_target}_LIBRARY_TYPE}
282         ${${_target}_HEADERS}
283         ${${_target}_SOURCES}
284     )
285     target_include_directories(${_target} PUBLIC "$<BUILD_INTERFACE:${${_target}_INCLUDE_DIRECTORIES}>")
286     target_link_libraries(${_target} ${${_target}_LIBRARIES})
287     set_target_properties(${_target} PROPERTIES COMPILE_DEFINITIONS "BUILDING_${_target}")
288
289     if (${_target}_OUTPUT_NAME)
290         set_target_properties(${_target} PROPERTIES OUTPUT_NAME ${${_target}_OUTPUT_NAME})
291     endif ()
292
293     if (${_target}_PRE_BUILD_COMMAND)
294         add_custom_target(_${_target}_PreBuild COMMAND ${${_target}_PRE_BUILD_COMMAND} VERBATIM)
295         add_dependencies(${_target} _${_target}_PreBuild)
296     endif ()
297
298     if (${_target}_POST_BUILD_COMMAND)
299         add_custom_command(TARGET ${_target} POST_BUILD COMMAND ${${_target}_POST_BUILD_COMMAND} VERBATIM)
300     endif ()
301
302     if (APPLE AND NOT PORT STREQUAL "GTK" AND NOT ${${_target}_LIBRARY_TYPE} MATCHES STATIC)
303         set_target_properties(${_target} PROPERTIES FRAMEWORK TRUE)
304         install(TARGETS ${_target} FRAMEWORK DESTINATION ${LIB_INSTALL_DIR})
305     endif ()
306 endmacro()
307
308 macro(WEBKIT_CREATE_FORWARDING_HEADER _target_directory _file)
309     get_filename_component(_source_path "${CMAKE_SOURCE_DIR}/Source/" ABSOLUTE)
310     get_filename_component(_absolute "${_file}" ABSOLUTE)
311     get_filename_component(_name "${_file}" NAME)
312     set(_target_filename "${_target_directory}/${_name}")
313
314     # Try to make the path in the forwarding header relative to the Source directory
315     # so that these forwarding headers are compatible with the ones created by the
316     # WebKit2 generate-forwarding-headers script.
317     string(REGEX REPLACE "${_source_path}/" "" _relative ${_absolute})
318
319     set(_content "#include \"${_relative}\"\n")
320
321     if (EXISTS "${_target_filename}")
322         file(READ "${_target_filename}" _old_content)
323     endif ()
324
325     if (NOT _old_content STREQUAL _content)
326         file(WRITE "${_target_filename}" "${_content}")
327     endif ()
328 endmacro()
329
330 macro(WEBKIT_CREATE_FORWARDING_HEADERS _framework)
331     # On Windows, we copy the entire contents of forwarding headers.
332     if (NOT WIN32)
333         set(_processing_directories 0)
334         set(_processing_files 0)
335         set(_target_directory "${DERIVED_SOURCES_DIR}/ForwardingHeaders/${_framework}")
336
337         file(GLOB _files "${_target_directory}/*.h")
338         foreach (_file ${_files})
339             file(READ "${_file}" _content)
340             string(REGEX MATCH "^#include \"([^\"]*)\"" _matched ${_content})
341             if (_matched AND NOT EXISTS "${CMAKE_SOURCE_DIR}/Source/${CMAKE_MATCH_1}")
342                file(REMOVE "${_file}")
343             endif ()
344         endforeach ()
345
346         foreach (_currentArg ${ARGN})
347             if ("${_currentArg}" STREQUAL "DIRECTORIES")
348                 set(_processing_directories 1)
349                 set(_processing_files 0)
350             elseif ("${_currentArg}" STREQUAL "FILES")
351                 set(_processing_directories 0)
352                 set(_processing_files 1)
353             elseif (_processing_directories)
354                 file(GLOB _files "${_currentArg}/*.h")
355                 foreach (_file ${_files})
356                     WEBKIT_CREATE_FORWARDING_HEADER(${_target_directory} ${_file})
357                 endforeach ()
358             elseif (_processing_files)
359                 WEBKIT_CREATE_FORWARDING_HEADER(${_target_directory} ${_currentArg})
360             endif ()
361         endforeach ()
362     endif ()
363 endmacro()
364
365 # Helper macro which wraps generate-message-receiver.py and generate-message-header.py scripts
366 #   _output_source is a list name which will contain generated sources.(eg. WebKit2_SOURCES)
367 #   _input_files are messages.in files to generate.
368 macro(GENERATE_WEBKIT2_MESSAGE_SOURCES _output_source _input_files)
369     foreach (_file ${_input_files})
370         get_filename_component(_name ${_file} NAME_WE)
371         add_custom_command(
372             OUTPUT ${DERIVED_SOURCES_WEBKIT2_DIR}/${_name}MessageReceiver.cpp ${DERIVED_SOURCES_WEBKIT2_DIR}/${_name}Messages.h
373             MAIN_DEPENDENCY ${_file}
374             DEPENDS ${WEBKIT2_DIR}/Scripts/webkit/__init__.py
375                     ${WEBKIT2_DIR}/Scripts/webkit/messages.py
376                     ${WEBKIT2_DIR}/Scripts/webkit/model.py
377                     ${WEBKIT2_DIR}/Scripts/webkit/parser.py
378             COMMAND ${PYTHON_EXECUTABLE} ${WEBKIT2_DIR}/Scripts/generate-message-receiver.py ${_file} > ${DERIVED_SOURCES_WEBKIT2_DIR}/${_name}MessageReceiver.cpp
379             COMMAND ${PYTHON_EXECUTABLE} ${WEBKIT2_DIR}/Scripts/generate-messages-header.py ${_file} > ${DERIVED_SOURCES_WEBKIT2_DIR}/${_name}Messages.h
380             WORKING_DIRECTORY ${WEBKIT2_DIR}
381             VERBATIM)
382
383         list(APPEND ${_output_source} ${DERIVED_SOURCES_WEBKIT2_DIR}/${_name}MessageReceiver.cpp)
384     endforeach ()
385 endmacro()
386
387 macro(MAKE_JS_FILE_ARRAYS _output_cpp _output_h _scripts _scripts_dependencies)
388     if (WIN32)
389         set(_python_path set "PYTHONPATH=${JavaScriptCore_SCRIPTS_DIR}" COMMAND)
390     else ()
391         set(_python_path "PYTHONPATH=${JavaScriptCore_SCRIPTS_DIR}")
392     endif ()
393
394     add_custom_command(
395         OUTPUT ${_output_h} ${_output_cpp}
396         MAIN_DEPENDENCY ${WEBCORE_DIR}/Scripts/make-js-file-arrays.py
397         DEPENDS ${${_scripts}}
398         COMMAND ${_python_path} ${PYTHON_EXECUTABLE} ${WEBCORE_DIR}/Scripts/make-js-file-arrays.py ${_output_h} ${_output_cpp} ${${_scripts}}
399         VERBATIM)
400     list(APPEND WebCore_DERIVED_SOURCES ${_output_cpp})
401     ADD_SOURCE_DEPENDENCIES(${${_scripts_dependencies}} ${_output_h} ${_output_cpp})
402 endmacro()
403
404 # Helper macro for using all-in-one builds
405 # This macro removes the sources included in the _all_in_one_file from the input _file_list.
406 # _file_list is a list of source files
407 # _all_in_one_file is an all-in-one cpp file includes other cpp files
408 # _result_file_list is the output file list
409 macro(PROCESS_ALLINONE_FILE _file_list _all_in_one_file _result_file_list _no_compile)
410     file(STRINGS ${_all_in_one_file} _all_in_one_file_content)
411     set(${_result_file_list} ${_file_list})
412     set(_allins "")
413     foreach (_line ${_all_in_one_file_content})
414         string(REGEX MATCH "^#include [\"<](.*)[\">]" _found ${_line})
415         if (_found)
416             list(APPEND _allins ${CMAKE_MATCH_1})
417         endif ()
418     endforeach ()
419
420     foreach (_allin ${_allins})
421         if (${_no_compile})
422             # For DerivedSources.cpp, we still need the derived sources to be generated, but we do not want them to be compiled
423             # individually. We add the header to the result file list so that CMake knows to keep generating the files.
424             string(REGEX REPLACE "(.*)\\.cpp" "\\1" _allin_no_ext ${_allin})
425             string(REGEX REPLACE ";([^;]*/)${_allin_no_ext}\\.cpp;" ";\\1${_allin_no_ext}.h;" _new_result "${${_result_file_list}};")
426         else ()
427             string(REGEX REPLACE ";[^;]*/${_allin};" ";" _new_result "${${_result_file_list}};")
428         endif ()
429         set(${_result_file_list} ${_new_result})
430     endforeach ()
431
432 endmacro()