| # This file is for macros that are used by multiple projects. If your macro is |
| # exclusively needed in only one subdirectory of Source (e.g. only needed by |
| # WebCore), then put it there instead. |
| |
| set(SWIFT_FATAL_DIAGNOSTIC_FLAGS "-Werror ExistentialAny -Werror StrictMemorySafety -Werror ForeignReferenceType -Werror NoUseUnstructuredThrowingTask -Werror NoUsage") |
| |
| macro(WEBKIT_COMPUTE_SOURCES _framework) |
| set(_derivedSourcesPath ${${_framework}_DERIVED_SOURCES_DIR}) |
| |
| foreach (_sourcesListFile IN LISTS ${_framework}_UNIFIED_SOURCE_LIST_FILES) |
| if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_sourcesListFile}") |
| set(_sourcesListInput "${CMAKE_CURRENT_SOURCE_DIR}/${_sourcesListFile}") |
| set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${_sourcesListInput}") |
| else () |
| set(_sourcesListInput "${_derivedSourcesPath}/${_sourcesListFile}") |
| endif () |
| if (${_framework}_UNIFIED_SOURCE_EXCLUDES) |
| file(STRINGS "${_sourcesListInput}" _allLines) |
| set(_filtered "") |
| foreach (_line IN LISTS _allLines) |
| set(_skip FALSE) |
| foreach (_pattern IN LISTS ${_framework}_UNIFIED_SOURCE_EXCLUDES) |
| if (_line MATCHES "${_pattern}") |
| set(_skip TRUE) |
| break () |
| endif () |
| endforeach () |
| if (NOT _skip) |
| string(APPEND _filtered "${_line}\n") |
| endif () |
| endforeach () |
| file(WRITE "${_derivedSourcesPath}/${_sourcesListFile}" "${_filtered}") |
| else () |
| configure_file("${_sourcesListInput}" "${_derivedSourcesPath}/${_sourcesListFile}" COPYONLY) |
| endif () |
| message(STATUS "Using source list file: ${_sourcesListFile}") |
| |
| list(APPEND _sourceListFileTruePaths "${_derivedSourcesPath}/${_sourcesListFile}") |
| endforeach () |
| |
| set(gusb_args --derived-sources-path ${_derivedSourcesPath} --source-tree-path ${CMAKE_CURRENT_SOURCE_DIR}) |
| list(APPEND gusb_args --ignore-header-groups) |
| # Windows needs a larger bundle size because that helps keep WebCore.lib's size below the 4GB maximum in debug builds. |
| if (MSVC AND ${_framework} STREQUAL "WebCore" AND ${_framework}_LIBRARY_TYPE STREQUAL "STATIC") |
| list(APPEND gusb_args --max-bundle-size 16) |
| endif () |
| if (${_framework} STREQUAL "WebCore") |
| list(APPEND gusb_args --dense-bundle-filter "JS*=JSBindings" --dense-bundle-filter "bindings/*=JSBindings") |
| endif () |
| if (DEFINED WEBKIT_MAX_BUNDLE_SIZE) |
| list(APPEND gusb_args --max-bundle-size ${WEBKIT_MAX_BUNDLE_SIZE} --enforce-cost) |
| endif () |
| |
| if (ENABLE_UNIFIED_BUILDS) |
| # One pass generates the bundles (stdout = files to compile) and writes the |
| # bundled member list to a side file via --print-bundled-sources. |
| set(_bundledSourcesFile "${CMAKE_CURRENT_BINARY_DIR}/${_framework}BundledSources.txt") |
| execute_process(COMMAND ${Python_EXECUTABLE} ${WTF_SCRIPTS_DIR}/generate-unified-source-bundles.py |
| ${gusb_args} |
| --print-bundled-sources "${_bundledSourcesFile}" |
| ${_sourceListFileTruePaths} |
| RESULT_VARIABLE _resultTmp |
| OUTPUT_VARIABLE _outputTmp) |
| |
| if (${_resultTmp}) |
| message(FATAL_ERROR "generate-unified-source-bundles.py exited with non-zero status, exiting") |
| endif () |
| |
| # Member sources folded into bundles: compiled via the bundle, so mark header-only. |
| file(STRINGS "${_bundledSourcesFile}" _bundledSources) |
| foreach (_sourceFileTmp IN LISTS _bundledSources) |
| set_source_files_properties(${_sourceFileTmp} PROPERTIES HEADER_FILE_ONLY ON) |
| list(APPEND ${_framework}_HEADERS ${_sourceFileTmp}) |
| endforeach () |
| unset(_sourceFileTmp) |
| |
| foreach (_file IN LISTS _outputTmp) |
| # Disambiguate top-level generated sources in DerivedSources vs top-level regular sources. |
| get_filename_component(_fileDir "${_file}" DIRECTORY) |
| if (NOT _fileDir AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_file}") |
| set(_file "${_derivedSourcesPath}/${_file}") |
| endif () |
| if (_file MATCHES "\\.c$") |
| list(APPEND ${_framework}_C_SOURCES ${_file}) |
| elseif (_file MATCHES "-ARC\\.mm$") |
| # generate-unified-source-bundles.rb emits *-ARC.mm and *-nonARC.mm bundles based |
| # on @nonARC annotations in Sources*.txt. The ARC bundles compile in a separate |
| # OBJECT library so the OBJCXX precompiled header agrees on -fobjc-arc. |
| list(APPEND ${_framework}_ARC_SOURCES ${_file}) |
| else () |
| list(APPEND ${_framework}_SOURCES ${_file}) |
| endif () |
| endforeach () |
| |
| unset(_resultTmp) |
| unset(_outputTmp) |
| else () |
| execute_process(COMMAND ${Python_EXECUTABLE} ${WTF_SCRIPTS_DIR}/generate-unified-source-bundles.py |
| ${gusb_args} |
| "--print-all-sources" |
| ${_sourceListFileTruePaths} |
| RESULT_VARIABLE _resultTmp |
| OUTPUT_VARIABLE _outputTmp) |
| |
| if (${_resultTmp}) |
| message(FATAL_ERROR "generate-unified-source-bundles.py exited with non-zero status, exiting") |
| endif () |
| |
| list(APPEND ${_framework}_SOURCES ${_outputTmp}) |
| unset(_resultTmp) |
| unset(_outputTmp) |
| endif () |
| endmacro() |
| |
| macro(WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS) |
| set(_file ${CMAKE_CURRENT_SOURCE_DIR}/Platform${PORT}.cmake) |
| if (EXISTS ${_file}) |
| message(STATUS "Using platform-specific CMakeLists: ${_file}") |
| include(${_file}) |
| else () |
| message(STATUS "Platform-specific CMakeLists not found: ${_file}") |
| endif () |
| endmacro() |
| |
| # Append the given dependencies to the source file |
| macro(WEBKIT_ADD_SOURCE_DEPENDENCIES _source _deps) |
| set(_tmp) |
| get_source_file_property(_tmp ${_source} OBJECT_DEPENDS) |
| if (NOT _tmp) |
| set(_tmp "") |
| endif () |
| |
| foreach (f ${_deps}) |
| list(APPEND _tmp "${f}") |
| endforeach () |
| |
| set_source_files_properties(${_source} PROPERTIES OBJECT_DEPENDS "${_tmp}") |
| unset(_tmp) |
| endmacro() |
| |
| # Wrapper around target_precompile_headers(). |
| # |
| # Swift sources are unaffected: with CMP0157 NEW (set in the top-level |
| # CMakeLists.txt) the Swift link rule receives only object files, so the |
| # .pch is never passed to swiftc. |
| # |
| # Targets that mix ARC and non-ARC .mm split the ARC sources into a separate |
| # OBJECT library (see ${_framework}_ARC_SOURCES) so each gets a matching PCH. |
| # |
| # On ports where OBJC/OBJCXX are not enabled languages those clauses are no-ops. |
| function(WEBKIT_ADD_PREFIX_HEADER _target _header) |
| cmake_parse_arguments(PARSE_ARGV 2 _PCH "PREFIX_NO_CODEGEN" "" "PREFIX_LANGUAGES") |
| if (NOT _PCH_PREFIX_LANGUAGES) |
| message(FATAL_ERROR "WEBKIT_ADD_PREFIX_HEADER(${_target}): PREFIX_LANGUAGES is required") |
| endif () |
| string(JOIN "," _pch_genex_langs ${_PCH_PREFIX_LANGUAGES}) |
| target_precompile_headers(${_target} PRIVATE |
| "$<$<COMPILE_LANGUAGE:${_pch_genex_langs}>:${CMAKE_CURRENT_SOURCE_DIR}/${_header}>") |
| _WEBKIT_PCH_STUB_NO_TIMESTAMP(${_target} ${_PCH_PREFIX_LANGUAGES}) |
| _WEBKIT_ADD_PCH_OBJECT(${_target} ${ARGN}) |
| endfunction() |
| |
| # REUSE_FROM is only safe where producer and consumer compile flags match exactly. |
| # That fails on GCC (per-target BUILDING_* define -> -Werror=invalid-pch) and on |
| # ELF clang when an executable reuses a library PCH (-fPIE vs -fPIC). Fall back |
| # to a per-target prefix header on those ports. |
| function(WEBKIT_REUSE_PREFIX_HEADER _target _from _header) |
| if (COMPILER_IS_CLANG AND APPLE) |
| target_precompile_headers(${_target} REUSE_FROM ${_from}) |
| else () |
| WEBKIT_ADD_PREFIX_HEADER(${_target} ${_header} PREFIX_NO_CODEGEN ${ARGN}) |
| endif () |
| endfunction() |
| |
| function(_WEBKIT_ADD_PCH_OBJECT _target) |
| if (NOT (COMPILER_IS_CLANG AND APPLE)) |
| return() |
| endif () |
| cmake_parse_arguments(PARSE_ARGV 1 _PO "PREFIX_NO_CODEGEN" "" "PREFIX_LANGUAGES") |
| set(_stub_flags "-fpch-debuginfo;-Xclang;-building-pch-with-obj") |
| if (NOT _PO_PREFIX_NO_CODEGEN) |
| list(PREPEND _stub_flags "-fpch-codegen") |
| endif () |
| get_target_property(_pch_bin_dir ${_target} BINARY_DIR) |
| list(FILTER _PO_PREFIX_LANGUAGES INCLUDE REGEX "^(CXX|OBJCXX)$") |
| foreach (_pch_lang IN LISTS _PO_PREFIX_LANGUAGES) |
| _WEBKIT_PCH_PATHS_FOR_LANGUAGE(${_pch_lang} _pch_src_ext _pch_stub_ext _pch_stem) |
| set_property(SOURCE "${_pch_bin_dir}/CMakeFiles/${_target}.dir/${_pch_stem}.${_pch_stub_ext}" |
| APPEND PROPERTY COMPILE_OPTIONS "${_stub_flags}") |
| set(_pch_obj_src "${CMAKE_CURRENT_BINARY_DIR}/${_target}_pch_obj.${_pch_src_ext}") |
| if (NOT EXISTS "${_pch_obj_src}") |
| file(WRITE "${_pch_obj_src}" "// PCH object for ${_target} (${_pch_lang})\n") |
| endif () |
| target_sources(${_target} PRIVATE "${_pch_obj_src}") |
| set_source_files_properties("${_pch_obj_src}" PROPERTIES |
| COMPILE_OPTIONS "-Xclang;-building-pch-with-obj;-fvisibility-inlines-hidden" |
| SKIP_UNITY_BUILD_INCLUSION ON) |
| endforeach () |
| endfunction() |
| |
| function(_WEBKIT_PCH_STUB_NO_TIMESTAMP _target) |
| if (NOT COMPILER_IS_CLANG) |
| return() |
| endif () |
| get_target_property(_pch_bin_dir ${_target} BINARY_DIR) |
| foreach (_lang ${ARGN}) |
| _WEBKIT_PCH_PATHS_FOR_LANGUAGE(${_lang} _src_ext _stub_ext _pch_stem) |
| set_property(SOURCE "${_pch_bin_dir}/CMakeFiles/${_target}.dir/${_pch_stem}.${_stub_ext}" |
| APPEND PROPERTY COMPILE_OPTIONS "-Xclang;-fno-pch-timestamp") |
| endforeach () |
| endfunction() |
| |
| macro(_WEBKIT_PCH_PATHS_FOR_LANGUAGE _lang _out_src_ext _out_stub_ext _out_pch_stem) |
| if (${_lang} STREQUAL "OBJCXX") |
| set(${_out_src_ext} "mm") |
| set(${_out_stub_ext} "mm") |
| set(${_out_pch_stem} "cmake_pch.objcxx.hxx") |
| elseif (${_lang} STREQUAL "OBJC") |
| set(${_out_src_ext} "m") |
| set(${_out_stub_ext} "m") |
| set(${_out_pch_stem} "cmake_pch.objc.h") |
| elseif (${_lang} STREQUAL "C") |
| set(${_out_src_ext} "c") |
| set(${_out_stub_ext} "c") |
| set(${_out_pch_stem} "cmake_pch.h") |
| else () |
| set(${_out_src_ext} "cpp") |
| set(${_out_stub_ext} "cxx") |
| set(${_out_pch_stem} "cmake_pch.hxx") |
| endif () |
| endmacro() |
| |
| function(WEBKIT_ADD_PREFIX_HEADER_WITH_PARENT _target _base_target _header _parent_header) |
| if (COMPILER_IS_CLANG) |
| string(JOIN "," _lang_genex ${ARGN}) |
| target_precompile_headers(${_target} PRIVATE |
| "$<$<COMPILE_LANGUAGE:${_lang_genex}>:${CMAKE_CURRENT_SOURCE_DIR}/${_header}>") |
| if (APPLE) |
| # FIXME: Upstream clang does not appear to propagate parent-PCH state to consumers |
| # of the child PCH (webkit.org/b/314763). Until that is root-caused, build the child |
| # prefix as a standalone PCH on non-Apple clang; the child header #includes its parent. |
| get_target_property(_chain_bin_dir ${_target} BINARY_DIR) |
| foreach (_lang ${ARGN}) |
| _WEBKIT_PCH_PATHS_FOR_LANGUAGE(${_lang} _src_ext _stub_ext _pch_stem) |
| set(_base_pch "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_base_target}.dir/${_pch_stem}.pch") |
| set(_chain_stub "${_chain_bin_dir}/CMakeFiles/${_target}.dir/${_pch_stem}.${_stub_ext}") |
| set_source_files_properties(${_chain_stub} PROPERTIES |
| COMPILE_OPTIONS "-Xclang;-include-pch;-Xclang;${_base_pch}" |
| OBJECT_DEPENDS "${_base_pch}") |
| endforeach () |
| endif () |
| _WEBKIT_PCH_STUB_NO_TIMESTAMP(${_target} ${ARGN}) |
| _WEBKIT_ADD_PCH_OBJECT(${_target} PREFIX_NO_CODEGEN PREFIX_LANGUAGES ${ARGN}) |
| else () |
| WEBKIT_ADD_PREFIX_HEADER(${_target} ${_parent_header} PREFIX_LANGUAGES ${ARGN}) |
| endif () |
| endfunction() |
| |
| function(WEBKIT_DEFINE_SUBTARGET _target _parent) |
| add_library(${_target} OBJECT) |
| target_sources(${_target} PRIVATE ${${_parent}_HEADERS} ${ARGN}) |
| target_include_directories(${_target} PRIVATE $<TARGET_PROPERTY:${_parent},INCLUDE_DIRECTORIES>) |
| target_include_directories(${_target} SYSTEM PRIVATE ${${_parent}_SYSTEM_INCLUDE_DIRECTORIES}) |
| target_compile_definitions(${_target} PRIVATE ${_parent}_EXPORTS $<TARGET_PROPERTY:${_parent},COMPILE_DEFINITIONS>) |
| target_compile_options(${_target} PRIVATE $<TARGET_PROPERTY:${_parent},COMPILE_OPTIONS>) |
| target_link_libraries(${_target} PRIVATE $<TARGET_PROPERTY:${_parent},LINK_LIBRARIES>) |
| if (${_parent}_DEPENDENCIES) |
| add_dependencies(${_target} ${${_parent}_DEPENDENCIES}) |
| endif () |
| endfunction() |
| |
| macro(WEBKIT_DEFINE_SUBTARGET_WITH_PREFIX _target _subtarget) |
| # Subtargets claim sources first-match-wins, so define HEADER_GROUPS subtargets |
| # before any DIRS subtarget whose directories overlap. |
| cmake_parse_arguments(_arg "" "PREFIX;CHAIN_PARENT" "PREFIX_LANGUAGES;DIRS;HEADER_GROUPS" ${ARGN}) |
| if (${_target}_FINALIZED) |
| message(FATAL_ERROR "WEBKIT_DEFINE_SUBTARGET_WITH_PREFIX(${_target} ${_subtarget}) must be called before WEBKIT_FRAMEWORK(${_target})") |
| endif () |
| if (NOT _arg_CHAIN_PARENT) |
| set(_arg_CHAIN_PARENT ${_target}) |
| endif () |
| if (COMPILER_IS_CLANG AND NOT MSVC AND NOT CMAKE_DISABLE_PRECOMPILE_HEADERS) |
| set(_src_exts) |
| foreach (_lang IN LISTS _arg_PREFIX_LANGUAGES) |
| _WEBKIT_PCH_PATHS_FOR_LANGUAGE(${_lang} _src_ext _stub_ext _pch_stem) |
| list(APPEND _src_exts ${_src_ext}) |
| endforeach () |
| string(JOIN "|" _src_exts ${_src_exts}) |
| set(${_subtarget}_SOURCES ${${_target}_SOURCES}) |
| list(FILTER ${_subtarget}_SOURCES INCLUDE REGEX "\\.(${_src_exts})$") |
| if (_arg_DIRS) |
| string(JOIN "|" _dirs ${_arg_DIRS}) |
| list(FILTER ${_subtarget}_SOURCES INCLUDE REGEX "(^|[-/])(${_dirs})[-/]") |
| endif () |
| if (_arg_HEADER_GROUPS) |
| string(JOIN "|" _groups ${_arg_HEADER_GROUPS}) |
| list(FILTER ${_subtarget}_SOURCES INCLUDE REGEX "-header-(${_groups})\\.") |
| endif () |
| if (${_subtarget}_SOURCES) |
| list(REMOVE_ITEM ${_target}_SOURCES ${${_subtarget}_SOURCES}) |
| WEBKIT_DEFINE_SUBTARGET(${_subtarget} ${_target} ${${_subtarget}_SOURCES}) |
| set(_subobjects "$<FILTER:$<TARGET_OBJECTS:${_subtarget}>,EXCLUDE,\\.(g|p)ch$>") |
| if (${_target}_LIBRARY_TYPE STREQUAL "SHARED" OR ${_target}_LIBRARY_TYPE STREQUAL "MODULE") |
| set(_rsp "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_subtarget}.dir/$<CONFIG>/objects.rsp") |
| file(GENERATE OUTPUT "${_rsp}" CONTENT "$<JOIN:${_subobjects},\n>") |
| target_link_options(${_target} PRIVATE "@${_rsp}") |
| set_property(TARGET ${_target} APPEND PROPERTY LINK_DEPENDS "${_subobjects};${_rsp}") |
| else () |
| target_link_libraries(${_target} INTERFACE "${_subobjects}") |
| endif () |
| WEBKIT_ADD_PREFIX_HEADER_WITH_PARENT(${_subtarget} ${_arg_CHAIN_PARENT} ${_arg_PREFIX} "" ${_arg_PREFIX_LANGUAGES}) |
| endif () |
| endif () |
| unset(_arg_CHAIN_PARENT) |
| unset(_arg_PREFIX) |
| unset(_arg_PREFIX_LANGUAGES) |
| unset(_arg_DIRS) |
| unset(_arg_HEADER_GROUPS) |
| endmacro() |
| |
| macro(WEBKIT_FRAMEWORK_DECLARE _target) |
| # add_library() without any source files triggers CMake warning |
| # Addition of dummy "source" file does not result in any changes in generated build.ninja file |
| add_library(${_target} ${${_target}_LIBRARY_TYPE} "${CMAKE_BINARY_DIR}/cmakeconfig.h") |
| endmacro() |
| |
| macro(WEBKIT_LIBRARY_DECLARE _target) |
| # add_library() without any source files triggers CMake warning |
| # Addition of dummy "source" file does not result in any changes in generated build.ninja file |
| add_library(${_target} ${${_target}_LIBRARY_TYPE} "${CMAKE_BINARY_DIR}/cmakeconfig.h") |
| |
| if (${_target}_LIBRARY_TYPE STREQUAL "OBJECT") |
| list(APPEND ${_target}_INTERFACE_LIBRARIES "$<FILTER:$<TARGET_OBJECTS:${_target}>,EXCLUDE,\\.(g|p)ch$>") |
| if (TARGET ${_target}_c) |
| list(APPEND ${_target}_INTERFACE_LIBRARIES "$<FILTER:$<TARGET_OBJECTS:${_target}_c>,EXCLUDE,\\.(g|p)ch$>") |
| endif () |
| endif () |
| endmacro() |
| |
| macro(WEBKIT_EXECUTABLE_DECLARE _target) |
| add_executable(${_target} "${CMAKE_BINARY_DIR}/cmakeconfig.h") |
| endmacro() |
| |
| # Private macro for setting the properties of a target. |
| macro(_WEBKIT_TARGET_SETUP _target _logical_name) |
| if (USE_HEADER_MAPS) |
| WEBKIT_WRITE_HEADER_MAP(${_target} |
| DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/${_target}-project-headers.hmap |
| FILES ${${_target}_PROJECT_HEADERS} |
| QUOTED BRACKETED |
| ) |
| WEBKIT_WRITE_HEADER_MAP(${_target} |
| DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/${_target}-framework-headers.hmap |
| FILES |
| ${${_target}_PUBLIC_FRAMEWORK_HEADERS} ${${_target}_PUBLIC_HEADERS} |
| ${${_target}_PRIVATE_FRAMEWORK_HEADERS} ${${_target}_PRIVATE_HEADERS} |
| QUOTED BRACKETED |
| ) |
| include_directories(BEFORE |
| ${CMAKE_CURRENT_BINARY_DIR}/${_target}-project-headers.hmap |
| ${CMAKE_CURRENT_BINARY_DIR}/${_target}-framework-headers.hmap |
| ) |
| target_include_directories(${_target} BEFORE PUBLIC |
| ${CMAKE_CURRENT_BINARY_DIR}/${_target}-framework-headers.hmap |
| ) |
| endif () |
| target_include_directories(${_target} PUBLIC "$<BUILD_INTERFACE:${${_logical_name}_INCLUDE_DIRECTORIES}>") |
| target_include_directories(${_target} SYSTEM PRIVATE "$<BUILD_INTERFACE:${${_logical_name}_SYSTEM_INCLUDE_DIRECTORIES}>") |
| target_include_directories(${_target} PRIVATE "$<BUILD_INTERFACE:${${_logical_name}_PRIVATE_INCLUDE_DIRECTORIES}>") |
| |
| if (DEVELOPER_MODE_CXX_FLAGS) |
| target_compile_options(${_target} PRIVATE |
| "$<$<NOT:$<COMPILE_LANGUAGE:Swift>>:${DEVELOPER_MODE_CXX_FLAGS}>") |
| target_compile_options(${_target} PRIVATE |
| "$<$<COMPILE_LANGUAGE:Swift>:SHELL:${SWIFT_FATAL_DIAGNOSTIC_FLAGS}>") |
| endif () |
| |
| target_compile_definitions(${_target} PRIVATE "BUILDING_${_logical_name}") |
| if (${_logical_name}_DEFINITIONS) |
| target_compile_definitions(${_target} PUBLIC ${${_logical_name}_DEFINITIONS}) |
| endif () |
| if (${_logical_name}_PRIVATE_DEFINITIONS) |
| target_compile_definitions(${_target} PRIVATE ${${_logical_name}_PRIVATE_DEFINITIONS}) |
| endif () |
| |
| if (${_logical_name}_COMPILE_OPTIONS) |
| target_compile_options(${_target} PRIVATE ${${_logical_name}_COMPILE_OPTIONS}) |
| endif () |
| |
| if (${_logical_name}_LIBRARIES) |
| target_link_libraries(${_target} PUBLIC ${${_logical_name}_LIBRARIES}) |
| endif () |
| if (${_logical_name}_PRIVATE_LIBRARIES) |
| target_link_libraries(${_target} PRIVATE ${${_logical_name}_PRIVATE_LIBRARIES}) |
| endif () |
| |
| if (${_logical_name}_DEPENDENCIES) |
| add_dependencies(${_target} ${${_logical_name}_DEPENDENCIES}) |
| endif () |
| endmacro() |
| |
| macro(_WEBKIT_TARGET _target) |
| set(${_target}_FINALIZED TRUE) |
| if (CMAKE_GENERATOR MATCHES "Visual Studio") |
| if (${_target}_C_SOURCES) |
| add_library(${_target}_c OBJECT) |
| target_sources(${_target}_c PRIVATE ${${_target}_C_SOURCES}) |
| |
| _WEBKIT_TARGET_SETUP(${_target}_c ${_target}) |
| |
| set_target_properties(${_target}_c PROPERTIES C_STANDARD 17) |
| list(APPEND ${_target}_PRIVATE_LIBRARIES ${_target}_c) |
| endif () |
| |
| target_sources(${_target} PRIVATE |
| ${${_target}_HEADERS} |
| ${${_target}_SOURCES} |
| ) |
| |
| _WEBKIT_TARGET_SETUP(${_target} ${_target}) |
| else () |
| target_sources(${_target} PRIVATE |
| ${${_target}_HEADERS} |
| ${${_target}_SOURCES} |
| ${${_target}_C_SOURCES} |
| ) |
| |
| _WEBKIT_TARGET_SETUP(${_target} ${_target}) |
| endif () |
| endmacro() |
| |
| macro(_WEBKIT_TARGET_ANALYZE _target) |
| if (ClangTidy_EXE) |
| set(_clang_path_and_options |
| ${ClangTidy_EXE} |
| # Include all non system headers |
| --header-filter=.* |
| ) |
| set_target_properties(${_target} PROPERTIES |
| C_CLANG_TIDY "${_clang_path_and_options}" |
| CXX_CLANG_TIDY "${_clang_path_and_options}" |
| ) |
| endif () |
| |
| if (IWYU_EXE) |
| set(_iwyu_path_and_options |
| ${IWYU_EXE} |
| # Suggests the more concise syntax introduced in C++17 |
| -Xiwyu --cxx17ns |
| # Tells iwyu to always keep these includes |
| -Xiwyu --keep=**/config.h |
| ) |
| if (MSVC) |
| list(APPEND _iwyu_path_and_options --driver-mode=cl) |
| endif () |
| set_target_properties(${_target} PROPERTIES |
| CXX_INCLUDE_WHAT_YOU_USE "${_iwyu_path_and_options}" |
| ) |
| endif () |
| endmacro() |
| |
| function(_WEBKIT_TARGET_LINK_FRAMEWORK_INTO target_name framework _public_frameworks_var _private_frameworks_var) |
| set_property(GLOBAL PROPERTY ${framework}_LINKED_INTO ${target_name}) |
| |
| get_property(_framework_public_frameworks GLOBAL PROPERTY ${framework}_FRAMEWORKS) |
| foreach (dependency IN LISTS ${_framework_public_frameworks}) |
| set(${_public_frameworks_var} "${${_public_frameworks_var}};${dependency}" PARENT_SCOPE) |
| endforeach () |
| |
| get_property(_framework_private_frameworks GLOBAL PROPERTY ${framework}_PRIVATE_FRAMEWORKS) |
| foreach (dependency IN LISTS _framework_private_frameworks) |
| set(${_private_frameworks_var} "${${_private_frameworks_var}};${dependency}" PARENT_SCOPE) |
| _WEBKIT_TARGET_LINK_FRAMEWORK_INTO(${target_name} ${dependency} ${_public_frameworks_var} ${_private_frameworks_var}) |
| endforeach () |
| endfunction() |
| |
| macro(_WEBKIT_FRAMEWORK_LINK_FRAMEWORK _target_name) |
| # Set the public libraries before modifying them when determining visibility. |
| set_property(GLOBAL PROPERTY ${_target_name}_PUBLIC_LIBRARIES ${${_target_name}_LIBRARIES}) |
| |
| set(_public_frameworks) |
| set(_private_frameworks) |
| |
| foreach (framework IN LISTS ${_target_name}_FRAMEWORKS) |
| get_property(_linked_into GLOBAL PROPERTY ${framework}_LINKED_INTO) |
| if (_linked_into) |
| list(APPEND _public_frameworks ${_linked_into}) |
| elseif (${framework}_LIBRARY_TYPE STREQUAL "SHARED") |
| list(APPEND _public_frameworks ${framework}) |
| else () |
| list(APPEND _private_frameworks ${framework}) |
| endif () |
| endforeach () |
| |
| # Recurse into the dependent frameworks |
| if (_private_frameworks) |
| list(REMOVE_DUPLICATES _private_frameworks) |
| endif () |
| if (${_target_name}_LIBRARY_TYPE STREQUAL "SHARED") |
| set_property(GLOBAL PROPERTY ${_target_name}_LINKED_INTO ${_target_name}) |
| foreach (framework IN LISTS _private_frameworks) |
| _WEBKIT_TARGET_LINK_FRAMEWORK_INTO(${_target_name} ${framework} _public_frameworks _private_frameworks) |
| endforeach () |
| endif () |
| |
| # Add to the ${target_name}_LIBRARIES |
| if (_public_frameworks) |
| list(REMOVE_DUPLICATES _public_frameworks) |
| endif () |
| foreach (framework IN LISTS _public_frameworks) |
| # FIXME: https://bugs.webkit.org/show_bug.cgi?id=231774 |
| if (APPLE) |
| list(APPEND ${_target_name}_PRIVATE_LIBRARIES WebKit::${framework}) |
| else () |
| list(APPEND ${_target_name}_LIBRARIES WebKit::${framework}) |
| endif () |
| endforeach () |
| |
| # Add to the ${target_name}_PRIVATE_LIBRARIES |
| if (_private_frameworks) |
| list(REMOVE_DUPLICATES _private_frameworks) |
| endif () |
| foreach (framework IN LISTS _private_frameworks) |
| if (${_target_name}_LIBRARY_TYPE STREQUAL "SHARED") |
| get_property(_linked_libraries GLOBAL PROPERTY ${framework}_PUBLIC_LIBRARIES) |
| list(APPEND ${_target_name}_INTERFACE_LIBRARIES |
| ${_linked_libraries} |
| ) |
| list(APPEND ${_target_name}_INTERFACE_INCLUDE_DIRECTORIES |
| ${${framework}_FRAMEWORK_HEADERS_DIR} |
| ${${framework}_PRIVATE_FRAMEWORK_HEADERS_DIR} |
| ) |
| list(APPEND ${_target_name}_PRIVATE_LIBRARIES WebKit::${framework}) |
| if (${framework}_LIBRARY_TYPE STREQUAL "OBJECT") |
| list(APPEND ${_target_name}_PRIVATE_LIBRARIES "$<FILTER:$<TARGET_OBJECTS:${framework}>,EXCLUDE,\\.(g|p)ch$>") |
| if (TARGET ${framework}_c) |
| list(APPEND ${_target_name}_PRIVATE_LIBRARIES "$<FILTER:$<TARGET_OBJECTS:${framework}_c>,EXCLUDE,\\.(g|p)ch$>") |
| endif () |
| endif () |
| else () |
| list(APPEND ${_target_name}_LIBRARIES WebKit::${framework}) |
| endif () |
| endforeach () |
| |
| set_property(GLOBAL PROPERTY ${_target_name}_FRAMEWORKS ${_public_frameworks}) |
| set_property(GLOBAL PROPERTY ${_target_name}_PRIVATE_FRAMEWORKS ${_private_frameworks}) |
| endmacro() |
| |
| macro(_WEBKIT_TARGET_LINK_FRAMEWORK _target) |
| foreach (framework IN LISTS ${_target}_FRAMEWORKS) |
| get_property(_linked_into GLOBAL PROPERTY ${framework}_LINKED_INTO) |
| |
| # See if the target is linking a framework that the specified framework is already linked into |
| if ((NOT _linked_into) OR (framework STREQUAL _linked_into) OR (NOT _linked_into IN_LIST ${_target}_FRAMEWORKS)) |
| list(APPEND ${_target}_PRIVATE_LIBRARIES WebKit::${framework}) |
| |
| # The WebKit:: alias targets do not propagate OBJECT libraries so the |
| # underyling library's objects are explicitly added to link properly |
| if (TARGET ${framework} AND ${framework}_LIBRARY_TYPE STREQUAL "OBJECT") |
| list(APPEND ${_target}_PRIVATE_LIBRARIES "$<FILTER:$<TARGET_OBJECTS:${framework}>,EXCLUDE,\\.(g|p)ch$>") |
| if (TARGET ${framework}_c) |
| list(APPEND ${_target}_PRIVATE_LIBRARIES "$<FILTER:$<TARGET_OBJECTS:${framework}_c>,EXCLUDE,\\.(g|p)ch$>") |
| endif () |
| endif () |
| endif () |
| endforeach () |
| endmacro() |
| |
| macro(_WEBKIT_LIBRARY_LINK_FRAMEWORK _target) |
| # See if the library is SHARED and if so just link frameworks the same as executables |
| if (${_target}_LIBRARY_TYPE STREQUAL SHARED) |
| _WEBKIT_TARGET_LINK_FRAMEWORK(${_target}) |
| else () |
| # Include the framework headers but don't try and link the frameworks |
| foreach (framework IN LISTS ${_target}_FRAMEWORKS) |
| get_target_property(_is_framework ${framework} FRAMEWORK) |
| if (_is_framework) |
| target_compile_options(${_target} PRIVATE -F${CMAKE_BINARY_DIR}) |
| else () |
| list(APPEND ${_target}_INCLUDE_DIRECTORIES |
| ${${framework}_FRAMEWORK_HEADERS_DIR} |
| ${${framework}_PRIVATE_FRAMEWORK_HEADERS_DIR} |
| ) |
| endif () |
| endforeach () |
| endif () |
| endmacro() |
| |
| function(_WEBKIT_ADD_CODE_SIGN _target) |
| get_target_property(_skip_codesign ${_target} SKIP_CODESIGN) |
| if (_skip_codesign) |
| return() |
| endif () |
| set(_identity ${WEBKIT_CODE_SIGN_IDENTITY}) |
| if (NOT _identity) |
| set(_identity "-") |
| endif () |
| cmake_parse_arguments(_arg "" "" "DEPENDS" ${ARGN}) |
| get_target_property(_is_framework ${_target} FRAMEWORK) |
| if (_is_framework) |
| set(_sign_path "$<TARGET_BUNDLE_DIR:${_target}>") |
| if (PORT STREQUAL Mac) |
| set(_cstemp_path "${_sign_path}/Versions/A/$<TARGET_FILE_BASE_NAME:${_target}>.cstemp") |
| else () |
| set(_cstemp_path "${_sign_path}/$<TARGET_FILE_BASE_NAME:${_target}>.cstemp") |
| endif () |
| else () |
| set(_sign_path "$<TARGET_FILE:${_target}>") |
| set(_cstemp_path "${_sign_path}.cstemp") |
| endif () |
| if (${_target}_CODE_SIGN_ENTITLEMENTS) |
| set(_entitlements --entitlements ${${_target}_CODE_SIGN_ENTITLEMENTS}) |
| endif () |
| set(_stamp "${CMAKE_CURRENT_BINARY_DIR}/${_target}-codesign.stamp") |
| add_custom_command( |
| OUTPUT ${_stamp} |
| DEPENDS $<TARGET_FILE:${_target}> ${_arg_DEPENDS} |
| # Work around rdar://145010536 when a previous codesign task was interrupted. |
| COMMAND rm -f ${_cstemp_path} |
| COMMAND set -o pipefail && |
| ${WEBKITADDITIONS_CODESIGN_PRELUDE} |
| /usr/bin/codesign --force --sign ${_identity} ${_entitlements} ${_sign_path} 2>&1 | |
| sed "/replacing existing signature/d" |
| COMMAND ${CMAKE_COMMAND} -E touch ${_stamp} |
| VERBATIM |
| COMMENT "Code signing ${_target}") |
| add_custom_target(${_target}_CodeSign ALL DEPENDS ${_stamp}) |
| add_dependencies(${_target}_CodeSign ${_target}) |
| endfunction() |
| |
| macro(_WEBKIT_TARGET_INTERFACE _target) |
| add_library(${_target}_PostBuild INTERFACE) |
| target_link_libraries(${_target}_PostBuild INTERFACE ${${_target}_INTERFACE_LIBRARIES}) |
| target_include_directories(${_target}_PostBuild INTERFACE ${${_target}_INTERFACE_INCLUDE_DIRECTORIES}) |
| if (${_target}_INTERFACE_DEPENDENCIES) |
| add_dependencies(${_target}_PostBuild ${${_target}_INTERFACE_DEPENDENCIES}) |
| endif () |
| if (${_target}_INTERFACE_LINK_DEPENDS) |
| set_property(TARGET ${_target}_PostBuild PROPERTY |
| INTERFACE_LINK_DEPENDS ${${_target}_INTERFACE_LINK_DEPENDS}) |
| endif () |
| if (NOT ${_target}_LIBRARY_TYPE STREQUAL "SHARED") |
| target_compile_definitions(${_target}_PostBuild INTERFACE "STATICALLY_LINKED_WITH_${_target}") |
| endif () |
| if (TARGET ${_target}_CodeSign) |
| add_dependencies(${_target}_PostBuild ${_target}_CodeSign) |
| endif () |
| add_library(WebKit::${_target} ALIAS ${_target}_PostBuild) |
| endmacro() |
| |
| macro(WEBKIT_FRAMEWORK _target) |
| _WEBKIT_FRAMEWORK_LINK_FRAMEWORK(${_target}) |
| _WEBKIT_TARGET(${_target}) |
| _WEBKIT_TARGET_ANALYZE(${_target}) |
| |
| # Apply PGO compile flags only to library targets (not executables) to avoid duplicate symbol errors |
| # Link flags are applied globally via CMAKE_SHARED_LINKER_FLAGS for LTO compatibility |
| if (PGO_COMPILE_OPTIONS) |
| target_compile_options(${_target} PRIVATE ${PGO_COMPILE_OPTIONS}) |
| endif () |
| |
| if (${_target}_OUTPUT_NAME) |
| set_target_properties(${_target} PROPERTIES OUTPUT_NAME ${${_target}_OUTPUT_NAME}) |
| endif () |
| |
| if (${_target}_PRE_BUILD_COMMAND) |
| add_custom_target(_${_target}_PreBuild COMMAND ${${_target}_PRE_BUILD_COMMAND} VERBATIM) |
| add_dependencies(${_target} _${_target}_PreBuild) |
| endif () |
| |
| if (${_target}_POST_BUILD_COMMAND) |
| add_custom_command(TARGET ${_target} POST_BUILD COMMAND ${${_target}_POST_BUILD_COMMAND} VERBATIM) |
| endif () |
| |
| if (APPLE AND NOT PORT STREQUAL "GTK" AND ${${_target}_LIBRARY_TYPE} MATCHES SHARED) |
| set_target_properties(${_target} PROPERTIES FRAMEWORK TRUE) |
| target_compile_options(${_target} BEFORE PUBLIC -F${CMAKE_BINARY_DIR}) |
| install(TARGETS ${_target} FRAMEWORK DESTINATION ${LIB_INSTALL_DIR}) |
| _WEBKIT_CREATE_FRAMEWORK_BUNDLE_STRUCTURE(${_target}) |
| _WEBKIT_ADD_CODE_SIGN(${_target} DEPENDS ${${_target}_CODE_SIGN_INPUTS}) |
| endif () |
| |
| _WEBKIT_TARGET_INTERFACE(${_target}) |
| endmacro() |
| |
| macro(WEBKIT_LIBRARY _target) |
| _WEBKIT_LIBRARY_LINK_FRAMEWORK(${_target}) |
| _WEBKIT_TARGET(${_target}) |
| _WEBKIT_TARGET_ANALYZE(${_target}) |
| |
| # Apply PGO compile flags only to library targets (not executables) to avoid duplicate symbol errors |
| # Link flags are applied globally via CMAKE_SHARED_LINKER_FLAGS for LTO compatibility |
| if (PGO_COMPILE_OPTIONS) |
| target_compile_options(${_target} PRIVATE ${PGO_COMPILE_OPTIONS}) |
| endif () |
| |
| if (${_target}_OUTPUT_NAME) |
| set_target_properties(${_target} PROPERTIES OUTPUT_NAME ${${_target}_OUTPUT_NAME}) |
| endif () |
| |
| if (APPLE AND ${${_target}_LIBRARY_TYPE} MATCHES SHARED) |
| _WEBKIT_ADD_CODE_SIGN(${_target} DEPENDS ${${_target}_CODE_SIGN_INPUTS}) |
| endif () |
| |
| _WEBKIT_TARGET_INTERFACE(${_target}) |
| endmacro() |
| |
| macro(WEBKIT_EXECUTABLE _target) |
| _WEBKIT_TARGET_LINK_FRAMEWORK(${_target}) |
| _WEBKIT_TARGET(${_target}) |
| _WEBKIT_TARGET_ANALYZE(${_target}) |
| |
| if (${_target}_OUTPUT_NAME) |
| set_target_properties(${_target} PROPERTIES OUTPUT_NAME ${${_target}_OUTPUT_NAME}) |
| endif () |
| |
| if (APPLE) |
| _WEBKIT_ADD_CODE_SIGN(${_target} DEPENDS ${${_target}_CODE_SIGN_INPUTS}) |
| endif () |
| endmacro() |
| |
| # Delete staged files not in FILES, so a renamed or removed header drops its old |
| # copy instead of lingering and colliding as a duplicate in a Clang umbrella |
| # module. Only safe when the calling step owns the destination exclusively. |
| # `flattened` matches by basename when TRUE, by relative path otherwise. |
| function(WEBKIT_PRUNE_STALE_DESTINATION destination flattened) |
| set(_expected) |
| foreach (file IN LISTS ARGN) |
| if (flattened) |
| get_filename_component(_rel ${file} NAME) |
| else () |
| set(_rel ${file}) |
| endif () |
| list(APPEND _expected ${_rel}) |
| endforeach () |
| file(GLOB_RECURSE _existing RELATIVE ${destination} ${destination}/*) |
| foreach (_entry IN LISTS _existing) |
| if (NOT _entry IN_LIST _expected) |
| file(REMOVE ${destination}/${_entry}) |
| endif () |
| endforeach () |
| endfunction() |
| |
| function(_WEBKIT_CREATE_FRAMEWORK_BUNDLE_STRUCTURE _target) |
| if (PORT STREQUAL Mac) |
| set(_version "Versions/A/") |
| file(MAKE_DIRECTORY |
| "${CMAKE_BINARY_DIR}/${_target}.framework/Versions/A") |
| file(CREATE_LINK "A" |
| "${CMAKE_BINARY_DIR}/${_target}.framework/Versions/Current" SYMBOLIC) |
| endif () |
| |
| foreach (_name Headers Modules PrivateHeaders) |
| file(MAKE_DIRECTORY |
| "${CMAKE_BINARY_DIR}/${_target}.framework/${_version}${_name}") |
| if (PORT STREQUAL Mac) |
| file(CREATE_LINK "Versions/Current/${_name}" |
| "${CMAKE_BINARY_DIR}/${_target}.framework/${_name}" SYMBOLIC) |
| endif () |
| endforeach () |
| endfunction() |
| |
| function(WEBKIT_COPY_FILES target_name) |
| set(options FLATTENED NO_SYMLINK PRUNE_STALE) |
| set(oneValueArgs DESTINATION) |
| set(multiValueArgs FILES COMMAND) |
| cmake_parse_arguments(opt "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) |
| set(files ${opt_FILES}) |
| set(dst_files) |
| |
| if (opt_PRUNE_STALE) |
| WEBKIT_PRUNE_STALE_DESTINATION(${opt_DESTINATION} "${opt_FLATTENED}" ${files}) |
| endif () |
| |
| foreach (file IN LISTS files) |
| if (IS_ABSOLUTE ${file}) |
| set(src_file ${file}) |
| else () |
| set(src_file ${CMAKE_CURRENT_SOURCE_DIR}/${file}) |
| endif () |
| if (opt_FLATTENED) |
| get_filename_component(filename ${file} NAME) |
| set(dst_file ${opt_DESTINATION}/${filename}) |
| else () |
| get_filename_component(file_dir ${file} DIRECTORY) |
| file(MAKE_DIRECTORY ${opt_DESTINATION}/${file_dir}) |
| set(dst_file ${opt_DESTINATION}/${file}) |
| endif () |
| # On macOS, symlink instead of copy so #import deduplicates headers reachable |
| # via both forwarded (<WebKit/X.h>) and source-tree paths. |
| # NO_SYMLINK for destinations post-processed in-place (e.g. ANGLE headers). |
| if (opt_COMMAND) |
| set(command ${opt_COMMAND}) |
| elseif (APPLE AND NOT opt_NO_SYMLINK) |
| set(command ${CMAKE_COMMAND} -E create_symlink) |
| else () |
| set(command ${CMAKE_COMMAND} -E copy_if_different) |
| endif () |
| add_custom_command(OUTPUT ${dst_file} |
| COMMAND ${command} ${src_file} ${dst_file} |
| MAIN_DEPENDENCY ${src_file} |
| VERBATIM |
| ) |
| list(APPEND dst_files ${dst_file}) |
| endforeach () |
| add_custom_target(${target_name} ALL DEPENDS ${dst_files}) |
| endfunction() |
| |
| function(WEBKIT_SYMLINK_FILES target_name) |
| set(options FLATTENED PRUNE_STALE) |
| set(oneValueArgs DESTINATION) |
| set(multiValueArgs FILES) |
| cmake_parse_arguments(opt "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) |
| set(files ${opt_FILES}) |
| set(dst_files) |
| file(MAKE_DIRECTORY ${opt_DESTINATION}) |
| |
| if (opt_PRUNE_STALE) |
| WEBKIT_PRUNE_STALE_DESTINATION(${opt_DESTINATION} "${opt_FLATTENED}" ${files}) |
| endif () |
| |
| foreach (file IN LISTS files) |
| if (IS_ABSOLUTE ${file}) |
| set(src_file ${file}) |
| else () |
| set(src_file ${CMAKE_CURRENT_SOURCE_DIR}/${file}) |
| endif () |
| if (opt_FLATTENED) |
| get_filename_component(filename ${file} NAME) |
| set(dst_file ${opt_DESTINATION}/${filename}) |
| else () |
| get_filename_component(file_dir ${file} DIRECTORY) |
| file(MAKE_DIRECTORY ${opt_DESTINATION}/${file_dir}) |
| set(dst_file ${opt_DESTINATION}/${file}) |
| endif () |
| add_custom_command(OUTPUT ${dst_file} |
| COMMAND ${CMAKE_COMMAND} -E create_symlink ${src_file} ${dst_file} |
| MAIN_DEPENDENCY ${src_file} |
| VERBATIM |
| ) |
| list(APPEND dst_files ${dst_file}) |
| endforeach () |
| add_custom_target(${target_name} ALL DEPENDS ${dst_files}) |
| endfunction() |
| |
| # Helper macros for debugging CMake problems. |
| macro(WEBKIT_DEBUG_DUMP_COMMANDS) |
| set(CMAKE_VERBOSE_MAKEFILE ON) |
| endmacro() |
| |
| macro(WEBKIT_DEBUG_DUMP_VARIABLES) |
| set_cmake_property(_variableNames VARIABLES) |
| foreach (_variableName ${_variableNames}) |
| message(STATUS "${_variableName}=${${_variableName}}") |
| endforeach () |
| endmacro() |
| |
| # Append the given flag to the target property. |
| # Builds on top of get_target_property() and set_target_properties() |
| macro(WEBKIT_ADD_TARGET_PROPERTIES _target _property _flags) |
| get_target_property(_tmp ${_target} ${_property}) |
| if (NOT _tmp) |
| set(_tmp "") |
| endif (NOT _tmp) |
| |
| foreach (f ${_flags}) |
| set(_tmp "${_tmp} ${f}") |
| endforeach (f ${_flags}) |
| |
| set_target_properties(${_target} PROPERTIES ${_property} ${_tmp}) |
| unset(_tmp) |
| endmacro() |
| |
| function(WEBKIT_ADD_TARGET_UNSAFE_BUFFER_WARNINGS _target) |
| if (ENABLE_UNSAFE_BUFFER_USAGE_WARNING AND WEBKIT_UNSAFE_BUFFER_WARNING_FLAGS) |
| WEBKIT_ADD_TARGET_CXX_FLAGS(${_target} ${WEBKIT_UNSAFE_BUFFER_WARNING_FLAGS}) |
| endif () |
| endfunction() |
| |
| macro(WEBKIT_POPULATE_LIBRARY_VERSION library_name) |
| if (NOT DEFINED ${library_name}_VERSION_MAJOR) |
| set(${library_name}_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) |
| endif () |
| if (NOT DEFINED ${library_name}_VERSION_MINOR) |
| set(${library_name}_VERSION_MINOR ${PROJECT_VERSION_MINOR}) |
| endif () |
| if (NOT DEFINED ${library_name}_VERSION_MICRO) |
| set(${library_name}_VERSION_MICRO ${PROJECT_VERSION_MICRO}) |
| endif () |
| if (NOT DEFINED ${library_name}_VERSION) |
| set(${library_name}_VERSION ${PROJECT_VERSION}) |
| endif () |
| endmacro() |
| |
| macro(WEBKIT_CREATE_SYMLINK target src dest) |
| add_custom_command(TARGET ${target} POST_BUILD |
| COMMAND ln -sf ${src} ${dest} |
| DEPENDS ${dest} |
| COMMENT "Create symlink from ${src} to ${dest}") |
| endmacro() |
| |
| function(_WEBKIT_COMPUTE_SWIFT_SHARED_CLANG_FLAGS _outvar) |
| # All Swift C++-interop targets pass the same -Xcc -D set so the clang |
| # importer's module-cache hash matches and bmalloc/wtf/SDK PCMs build once. |
| # -I/-isystem/-fmodule-map-file/-fvisibility are not in the hash and stay |
| # per-target. Per-target target_compile_definitions are intentionally NOT |
| # forwarded here; the wrapper no longer mirrors plain -D to -Xcc. |
| set(_flags |
| -DENABLE_WEBGPU_SWIFT=1 |
| -DJS_EXPORT_PRIVATE= |
| -DNODELETE= |
| -DPAL_EXPORT= |
| -DUCHAR_TYPE=char16_t |
| -DWEBCORE_EXPORT= |
| -DWEBCORE_TESTSUPPORT_EXPORT= |
| -DWK_EXPORT= |
| -DWTF_EXPORT_PRIVATE= |
| -D__WEBGPU__ |
| ) |
| # iOS WebKit_Internal headers gate textual #imports behind this macro that |
| # trip strict cross-module-import-visibility checks (bug 312083). |
| if (NOT CMAKE_SYSTEM_NAME STREQUAL "iOS") |
| list(APPEND _flags -DWK_SUPPORTS_SWIFT_OBJCXX_INTEROP=1) |
| endif () |
| if (APPLE) |
| # Normalize the LangOpt that WebGPU's SafeInteropWrappers enables |
| # implicitly so PAL/WebKit hash to the same module-cache dir. |
| list(APPEND _flags -fexperimental-bounds-safety-attributes) |
| endif () |
| string(TOUPPER "${CMAKE_BUILD_TYPE}" _bt) |
| if (CMAKE_CXX_FLAGS_${_bt} MATCHES "NDEBUG" OR CMAKE_CXX_FLAGS MATCHES "NDEBUG") |
| list(APPEND _flags -DNDEBUG -DRELEASE_WITHOUT_OPTIMIZATIONS) |
| endif () |
| # Globals from add_definitions() (BUILDING_WEBKIT=1, PAS_BMALLOC=1, |
| # _LIBCPP_HARDENING_MODE=...). Read from a fixed directory so every caller |
| # sees the same set regardless of its own add_definitions(). |
| get_directory_property(_dir_defs DIRECTORY "${CMAKE_SOURCE_DIR}/Source" COMPILE_DEFINITIONS) |
| foreach (_d IN LISTS _dir_defs) |
| if (NOT _d MATCHES "^(BUILDING_WITH_CMAKE|HAVE_CONFIG_H)($|=)") |
| list(APPEND _flags "-D${_d}") |
| endif () |
| endforeach () |
| # cmakeconfig.h's ENABLE_/HAVE_/USE_ values are NOT enumerated here. They |
| # come in via the per-target @-response file generated by |
| # _webkit_generate_platform_swift_args, which preprocesses wtf/Platform.h |
| # so the importer sees the same effective definitions C++ TUs do |
| # (including Platform.h-derived flags like HAVE_MATERIAL_HOSTING that |
| # cmakeconfig.h doesn't track). |
| set(${_outvar} ${_flags} PARENT_SCOPE) |
| endfunction() |
| |
| # Generates ${_resp_path}, a swiftc @-response file with the platform-derived |
| # flags. Mirrors the Xcode "Generate Swift platform args" build phase. |
| # Format (one token per line): -DNAME for truthy HAVE_/USE_/ENABLE_/ |
| # WTF_PLATFORM_/ASSERT_ macros from wtf/Platform.h, plus -Xcc -DNAME=VALUE |
| # for every cmakeconfig.h entry. DEPFILE re-runs it on Platform header changes. |
| function(_webkit_generate_platform_swift_args _target _resp_path _ordering_dep) |
| set(_depfile "${_resp_path}.d") |
| # Stable empty file; /dev/null's mtime is "now" and would always look dirty. |
| set(_empty_input "${CMAKE_BINARY_DIR}/DerivedSources/empty.cpp") |
| file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/DerivedSources") |
| if (NOT EXISTS "${_empty_input}") |
| file(WRITE "${_empty_input}" "") |
| endif () |
| set(_clang_cmd ${CMAKE_CXX_COMPILER}) |
| if (COMPILER_IS_CLANG_CL) |
| # clang-cl defaults to the MSVC (cl) driver, which silently ignores the |
| # GCC-style preprocess flags below (-std=, -dM, -MF, -include ...) and |
| # then treats their operands as input files, failing with "no such file |
| # or directory: cmakeconfig.h". Flip it to the GCC driver so the flags |
| # are honored. Must precede the flags it governs. |
| list(APPEND _clang_cmd --driver-mode=gcc) |
| endif () |
| list(APPEND _clang_cmd |
| -x c++ -std=c++2b |
| -E -P -dM |
| -MD -MF "${_depfile}" -MT "${_resp_path}" |
| -D __WK_GENERATING_PLATFORM_ARGS__ |
| # Mirrors Xcode's generate-platform-args: avoids wtf/Compiler.h's |
| # #error in non-Debug since the preprocessor never sets __OPTIMIZE__. |
| -D RELEASE_WITHOUT_OPTIMIZATIONS |
| -I "${WTF_FRAMEWORK_HEADERS_DIR}" |
| -I "${CMAKE_BINARY_DIR}" |
| -include cmakeconfig.h |
| -include wtf/Platform.h |
| ) |
| if (CMAKE_OSX_SYSROOT) |
| list(APPEND _clang_cmd "-isysroot" "${CMAKE_OSX_SYSROOT}") |
| endif () |
| if (CMAKE_Swift_COMPILER_TARGET) |
| list(APPEND _clang_cmd "-target" "${CMAKE_Swift_COMPILER_TARGET}") |
| endif () |
| if (WEBKIT_ADDITIONS_INCLUDE_PATH) |
| list(APPEND _clang_cmd "-I" "${WEBKIT_ADDITIONS_INCLUDE_PATH}") |
| endif () |
| # Custom commands don't inherit add_compile_options, so mirror the -isystem |
| # stub OptionsCocoa.cmake feeds C-family compiles: an empty AppleFeatures.h |
| # for SDKs lacking it, which Platform.h's preprocessing needs. |
| if (EXISTS "${CMAKE_BINARY_DIR}/generated-stubs") |
| list(APPEND _clang_cmd "-isystem" "${CMAKE_BINARY_DIR}/generated-stubs") |
| endif () |
| # NDEBUG affects ASSERT_ENABLED -> ENABLE_SECURITY_ASSERTIONS -> struct layouts. |
| string(TOUPPER "${CMAKE_BUILD_TYPE}" _build_type_upper) |
| if (CMAKE_CXX_FLAGS_${_build_type_upper} MATCHES "NDEBUG" OR CMAKE_CXX_FLAGS MATCHES "NDEBUG") |
| list(APPEND _clang_cmd "-DNDEBUG") |
| endif () |
| # -fsanitize=* drives ASAN_ENABLED etc; keep this preprocess in sync with C++. |
| list(APPEND _clang_cmd ${ENABLED_COMPILER_SANITIZERS}) |
| list(APPEND _clang_cmd "${_empty_input}") |
| |
| # Order resp generation after the framework's headers are staged: the |
| # clang preprocess -include's wtf/Platform.h from WTF_FRAMEWORK_HEADERS_DIR. |
| # Targets declared after this macro call are skipped (not yet visible to |
| # if(TARGET ...)); for current callers WTF_CopyHeaders is already created. |
| set(_header_deps "") |
| foreach (_lib IN ITEMS WTF "${_target}" ${${_target}_FRAMEWORKS}) |
| foreach (_suffix IN ITEMS _CopyHeaders _CopyPrivateHeaders) |
| if (TARGET "${_lib}${_suffix}") |
| list(APPEND _header_deps "${_lib}${_suffix}") |
| endif () |
| endforeach () |
| endforeach () |
| list(REMOVE_DUPLICATES _header_deps) |
| |
| set(_script "${CMAKE_SOURCE_DIR}/Source/WTF/Scripts/generate-platform-args") |
| add_custom_command( |
| OUTPUT "${_resp_path}" |
| COMMAND ${Python_EXECUTABLE} |
| "${_script}" |
| --cmake |
| --output "${_resp_path}" |
| --cmakeconfig "${CMAKE_BINARY_DIR}/cmakeconfig.h" |
| -- |
| ${_clang_cmd} |
| DEPFILE "${_depfile}" |
| DEPENDS |
| "${_script}" |
| "${CMAKE_BINARY_DIR}/cmakeconfig.h" |
| ${_ordering_dep} |
| ${_header_deps} |
| COMMENT "Generating ${_target} platform-swift-args.resp" |
| VERBATIM |
| ) |
| endfunction() |
| |
| function(_webkit_setup_swift_header_deps _target _stamp _header _resp) |
| # Discover _CopyHeaders/_CopyPrivateHeaders targets for this target and its |
| # direct framework dependencies. Called via cmake_language(DEFER CALL ...) |
| # so targets declared after WEBKIT_SETUP_SWIFT_AND_GENERATE_SWIFT_CPP_INTEROP_HEADER |
| # (e.g. ${_target}_CopyHeaders itself) are visible to if(TARGET ...). |
| set(_candidates "${_target}") |
| if (DEFINED ${_target}_FRAMEWORKS) |
| list(APPEND _candidates ${${_target}_FRAMEWORKS}) |
| endif () |
| set(_deps "") |
| foreach (_lib IN LISTS _candidates) |
| foreach (_suffix IN ITEMS _CopyHeaders _CopyPrivateHeaders) |
| if (TARGET "${_lib}${_suffix}") |
| list(APPEND _deps "${_lib}${_suffix}") |
| endif () |
| endforeach () |
| endforeach () |
| list(REMOVE_DUPLICATES _deps) |
| |
| # Collect all generated (binary-dir) headers/sources that Swift may import. |
| # ${_target}_HEADERS and ${_target}_DERIVED_SOURCES are fully populated by |
| # the time this deferred function runs. We find those that live under |
| # CMAKE_BINARY_DIR (i.e., produced by add_custom_command) and wire them into |
| # the ${_target}_SwiftGeneratedDeps placeholder target created at macro time. |
| # This covers both the header-emission add_custom_command and the main Swift |
| # compilation |
| set(_generated_files "") |
| foreach (_f IN LISTS ${_target}_HEADERS ${_target}_DERIVED_SOURCES) |
| cmake_path(IS_PREFIX CMAKE_BINARY_DIR "${_f}" NORMALIZE _in_build) |
| if (_in_build) |
| list(APPEND _generated_files "${_f}") |
| endif () |
| endforeach () |
| if (_generated_files) |
| # File-level DEPENDS must be fixed at target-creation time, so create a |
| # separate inner target and chain it into the placeholder. |
| add_custom_target(${_target}_SwiftGenFileOrderDeps DEPENDS ${_generated_files}) |
| add_dependencies(${_target}_SwiftGeneratedDeps ${_target}_SwiftGenFileOrderDeps) |
| endif () |
| # Ensure the main Swift compilation also waits for all generated files. |
| add_dependencies(${_target} ${_target}_SwiftGeneratedDeps) |
| |
| add_custom_target(${_target}_SwiftCxxHeaderStamp DEPENDS ${_stamp}) |
| add_dependencies(${_target}_SwiftCxxHeader ${_target}_SwiftCxxHeaderStamp) |
| if (_deps) |
| add_dependencies(${_target}_SwiftCxxHeader ${_deps}) |
| add_dependencies(${_target}_SwiftGeneratedDeps ${_deps}) |
| endif () |
| |
| # Pre-CMP0157 CMake compiles .swift files inside ${_target}'s link rule, which is a |
| # circular dependency. This workaround retains the old "compile twice" behavior, |
| # with the first compilation producing a throw-away .a file for the purpose of |
| # generating the C++ interop header. |
| if (NOT POLICY CMP0157) |
| get_target_property(_swift_srcs ${_target} SOURCES) |
| list(FILTER _swift_srcs INCLUDE REGEX "\\.swift$") |
| if (_swift_srcs) |
| get_target_property(_module_name ${_target} Swift_MODULE_NAME) |
| add_library(${_target}_SwiftCompile STATIC EXCLUDE_FROM_ALL ${_swift_srcs}) |
| set_target_properties(${_target}_SwiftCompile PROPERTIES Swift_MODULE_NAME ${_module_name}) |
| target_compile_options(${_target}_SwiftCompile PRIVATE $<TARGET_PROPERTY:${_target},COMPILE_OPTIONS>) |
| target_compile_definitions(${_target}_SwiftCompile PRIVATE $<TARGET_PROPERTY:${_target},COMPILE_DEFINITIONS>) |
| target_include_directories(${_target}_SwiftCompile PRIVATE $<TARGET_PROPERTY:${_target},INCLUDE_DIRECTORIES>) |
| # Emit the interop header from the helper only: it is the sole writer |
| # of WebKit-Swift-Generated.h.tmp in the legacy path and produces the |
| # swiftmodule the copy depends on, so the copy is ordered after the |
| # single write. ${_target} deliberately does not emit it here. |
| if (DEFINED ${_target}_SWIFT_EMIT_HEADER_FLAGS) |
| target_compile_options(${_target}_SwiftCompile PRIVATE ${${_target}_SWIFT_EMIT_HEADER_FLAGS}) |
| endif () |
| add_dependencies(${_target}_SwiftCompile ${_target}_SwiftGeneratedDeps) |
| file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/swift-link) |
| set_target_properties(${_target} PROPERTIES Swift_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/swift-link) |
| endif () |
| endif () |
| |
| add_dependencies(${_target}_SwiftInterop ${_target}_SwiftCxxHeader) |
| endfunction() |
| |
| macro(WEBKIT_SETUP_SWIFT_AND_GENERATE_SWIFT_CPP_INTEROP_HEADER _target _module_name _interop_module_path _output_header) |
| if (SWIFT_REQUIRED) |
| set_target_properties(${_target} PROPERTIES Swift_MODULE_NAME ${_module_name}) |
| # Ask swiftc where to find the header files which support C/C++ builds |
| # Right now this macro is used only once; if it's used more often then |
| # we should abstract this so it's executed only once. |
| execute_process( |
| COMMAND ${ORIGINAL_Swift_COMPILER} -print-target-info |
| OUTPUT_VARIABLE _swift_target_info |
| ) |
| string(JSON _swift_target_paths GET ${_swift_target_info} "paths") |
| string(JSON _swift_runtime_resource_path GET ${_swift_target_paths} "runtimeResourcePath") |
| target_include_directories(${_target} SYSTEM AFTER PRIVATE "${_swift_runtime_resource_path}") |
| # Swift C++-interop objects auto-link swiftCxx/swiftCxxStdlib; consumers |
| # linked by clang++ need this search path to satisfy those directives. |
| string(JSON _swift_runtime_library_path GET ${_swift_target_paths} "runtimeLibraryPaths" 0) |
| target_link_directories(${_target} INTERFACE "${_swift_runtime_library_path}") |
| # Expose the path as a compile definition so the bubblewrap sandbox |
| # (BubblewrapLauncher.cpp) can bind-mount it into the child process filesystem. |
| target_compile_definitions(${_target} PRIVATE "WEBKIT_SWIFT_STDLIB_LIBRARY_PATH=\"${_swift_runtime_library_path}\"") |
| |
| # Assemble arguments which need to be passed to swiftc. |
| # The platform-derived feature flags (HAVE_/USE_/ENABLE_/WTF_PLATFORM_/ |
| # ASSERT_) plus the cmakeconfig.h seed defines for the clang importer |
| # are produced as a build-time @-response file. The custom command that |
| # writes it is created later (after the SwiftGeneratedDeps placeholder |
| # exists); we just thread the @-flag here so it ends up in the swiftc |
| # invocation that CMake assembles from target_compile_options. |
| set(_resp_path "${CMAKE_CURRENT_BINARY_DIR}/${_target}.platform-swift-args.resp") |
| set(_swift_options "@${_resp_path}") |
| # Other options needed by Swift for C++ interop, including the location |
| # of the modulemap and hader for WebKit's internal "APIs" which we |
| # make available from C++ to Swift. |
| # By default the interop module dir goes on Clang's include search path |
| # (-Xcc -I) so the C++ interop importer can find module.modulemap there. |
| # Targets where the modulemap must remain Swift-only (e.g. WebKit, whose |
| # WebKit_Internal would otherwise be loaded twice and conflict with the |
| # WebKit_Private framework module — matches Xcode's SWIFT_INCLUDE_PATHS |
| # which is also Swift-only) can set |
| # ${_target}_SWIFT_INTEROP_MODULE_PATH_SWIFT_ONLY to TRUE. |
| list(APPEND _swift_options "-cxx-interoperability-mode=default" "-Xcc" "-std=c++2b") |
| _WEBKIT_COMPUTE_SWIFT_SHARED_CLANG_FLAGS(_shared_cc_flags) |
| foreach (_f IN LISTS _shared_cc_flags) |
| list(APPEND _swift_options "-Xcc" "${_f}") |
| endforeach () |
| # Match Xcode's CommonBase.xcconfig SWIFT_VERSION = 6.0. The importer's |
| # apinotes version is keyed off the effective Swift language mode, so |
| # this also keeps PAL/WebGPU/WebKit on the same module-cache hash. |
| list(APPEND _swift_options "-swift-version" "6") |
| if (APPLE) |
| # Swift modules extend their underlying ObjC++ module. |
| list(APPEND _swift_options "-import-underlying-module") |
| # Don't fire the module's own cross-import overlay while compiling it. |
| list(APPEND _swift_options "-Xfrontend" "-disable-cross-import-overlays") |
| endif () |
| if (${_target}_SWIFT_INTEROP_MODULE_PATH_SWIFT_ONLY) |
| list(APPEND _swift_options "-I${_interop_module_path}") |
| else () |
| list(APPEND _swift_options "-Xcc" "-I${_interop_module_path}") |
| endif () |
| # InternalImportsByDefault keeps unqualified `import Foo` from re-exporting Foo's |
| # types through the module's public interface. WebGPU/PAL want this; WebKit has |
| # public APIs whose signatures use Foundation/UIKit types via plain `import`, |
| # so callers can opt out by setting ${_target}_SWIFT_NO_INTERNAL_IMPORTS_BY_DEFAULT. |
| if (NOT ${_target}_SWIFT_NO_INTERNAL_IMPORTS_BY_DEFAULT) |
| list(APPEND _swift_options "-enable-upcoming-feature" "InternalImportsByDefault") |
| endif () |
| # On non-Apple platforms, Swift's embedded clang doesn't automatically search |
| # the compiler's C++ standard library headers (e.g. <coroutine> lives in /usr/include/c++/15/). |
| # Pass them explicitly so the wtf umbrella module can include them. |
| # Exclude GCC's architecture-specific lib directory (e.g. /usr/lib/gcc/aarch64-linux-gnu/15/include): |
| # it contains GCC-specific intrinsic headers (arm_neon.h, etc.) that use GCC builtins |
| # unknown to Swift's embedded Clang. Clang provides its own compatible versions in its |
| # resource directory and will find them automatically without an explicit -I path. |
| # Also exclude libstdc++ version-specific dirs (/usr/include/c++/N, |
| # /usr/include/<arch>/c++/N, /usr/include/c++/N/backward) when those come from |
| # CMAKE_CXX (which may be GCC of a different version than Swift's embedded clang |
| # uses). Pinning the cmake-detected libstdc++ version forces both copies into |
| # Swift's clang importer and triggers "different definitions in different modules" |
| # errors for std::* types. Swift's clang finds its own libstdc++ on Linux. |
| # Likewise exclude the host clang's resource directory (e.g. |
| # /usr/lib/llvm-18/lib/clang/18/include): it ships its own builtin |
| # module.modulemap, and Swift's embedded clang already loads the one from |
| # /opt/swift/usr/lib/swift/clang/include. Forwarding both makes every |
| # _Builtin_* / opencl_c module get defined twice and aborts -emit-module. |
| if (NOT APPLE) |
| foreach (_dir IN LISTS CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES) |
| if (_dir MATCHES "^/usr/lib/gcc/") |
| continue () |
| endif () |
| if (_dir MATCHES "/c\\+\\+/[0-9]+(/|$)") |
| continue () |
| endif () |
| if (_dir MATCHES "/clang/[0-9]+/include(/|$)") |
| continue () |
| endif () |
| list(APPEND _swift_options "-Xcc" "-I${_dir}") |
| endforeach () |
| endif () |
| # The clang importer must agree with C++ TUs on every layout-affecting |
| # feature check; sanitizers gate ASAN_ENABLED → ENABLE_SECURITY_ASSERTIONS |
| # → RefCountDebuggerImpl members. Without this, Swift's inline `new` of a |
| # RefCounted C++ type undersizes the allocation and the C++ ctor overflows |
| # it. -sanitize= instruments Swift codegen; the importer ignores -Xcc |
| # -fsanitize= for __has_feature(), so define __SANITIZE_*__ directly so |
| # Compiler.h's #ifdef path sets ASAN_ENABLED/TSAN_ENABLED. |
| foreach (_sanitizer IN LISTS ENABLE_SANITIZERS) |
| list(APPEND _swift_options "-sanitize=${_sanitizer}") |
| if (_sanitizer STREQUAL "address") |
| list(APPEND _swift_options "-Xcc" "-D__SANITIZE_ADDRESS__") |
| elseif (_sanitizer STREQUAL "thread") |
| list(APPEND _swift_options "-Xcc" "-D__SANITIZE_THREAD__") |
| endif () |
| endforeach () |
| # swiftc spawns swift-plugin-server under sandbox-exec to expand macros |
| # (e.g. SwiftUI @State). When the cmake build itself runs inside an |
| # outer sandbox that disallows nested sandbox_apply, macro expansion |
| # fails with "external macro implementation type ... could not be |
| # found". -disable-sandbox skips the inner sandbox; the macros are |
| # WebKit's own, so the isolation it provides isn't load-bearing here. |
| list(APPEND _swift_options "-disable-sandbox") |
| # Explicit module builds (EMB) pre-build all Clang PCMs once via |
| # libSwiftScan, so each swift-frontend process reuses them rather than |
| # rebuilding from scratch. This is faster when many Swift source files |
| # import the same C++ interop modules. Targets opt in by setting |
| # ${_target}_SWIFT_EXPLICIT_MODULE_BUILD before the macro call. |
| # All Apple targets (PAL/WebGPU/WebKit on iOS and Mac) use EMB; |
| # non-Apple builds rely on -module-cache-path for implicit sharing. |
| if (${_target}_SWIFT_EXPLICIT_MODULE_BUILD) |
| list(APPEND _swift_options "-explicit-module-build") |
| # Force experimental clang attributes ON to match cached SwiftShims |
| # PCM content. SDK swiftinterfaces carry -strict-memory-safety in |
| # their swift-module-flags-ignorable, which on older swift-driver |
| # paths implicitly enables late-parse-attributes and |
| # bounds-safety-attributes when building SwiftShims PCM. Without |
| # the explicit flags here, our consumer's clang has them OFF and |
| # rejects the cached PCM with |
| # "experimental late parsing of attributes was enabled in |
| # precompiled file but is currently disabled" (or the |
| # equivalent for bounds-safety). |
| # https://bugs.webkit.org/show_bug.cgi?id=312083 |
| list(APPEND _swift_options |
| "-Xcc" "-fexperimental-bounds-safety-attributes" |
| "-Xcc" "-fexperimental-late-parse-attributes" |
| ) |
| endif () |
| list(APPEND _swift_options "-module-cache-path" "${CMAKE_BINARY_DIR}/SwiftModuleCache") |
| set_property(DIRECTORY "${CMAKE_BINARY_DIR}" APPEND PROPERTY ADDITIONAL_CLEAN_FILES "${CMAKE_BINARY_DIR}/SwiftModuleCache") |
| list(APPEND _swift_options "-track-system-dependencies") |
| # We'll use these options both for mainstream cmake invocations of swiftc (here) |
| # and for our own invocation to output an interoperability .h file (later). |
| # target_compile_options deduplicates repeated tokens, so collapse each |
| # -Xcc <arg> into a single SHELL: entry to keep the pair together. |
| # https://bugs.webkit.org/show_bug.cgi?id=312105 |
| set(_swift_only_options "") |
| set(_pending_xcc FALSE) |
| foreach (_opt IN LISTS _swift_options) |
| if (_pending_xcc) |
| list(APPEND _swift_only_options "$<$<COMPILE_LANGUAGE:Swift>:SHELL:-Xcc ${_opt}>") |
| set(_pending_xcc FALSE) |
| elseif (_opt STREQUAL "-Xcc") |
| set(_pending_xcc TRUE) |
| else () |
| list(APPEND _swift_only_options "$<$<COMPILE_LANGUAGE:Swift>:${_opt}>") |
| endif () |
| endforeach () |
| target_compile_options(${_target} PRIVATE ${_swift_only_options}) |
| |
| if (CMAKE_SYSTEM_NAME STREQUAL "iOS" AND CMAKE_OSX_SYSROOT) |
| target_compile_options(${_target} PRIVATE |
| # Our just-built frameworks must come before the SDK's |
| # PrivateFrameworks so `<WebCore/X.h>` etc. resolve to cmake-built |
| # copies. Mirrors Xcode's BUILT_PRODUCTS_DIR precedence over SDK. |
| "$<$<COMPILE_LANGUAGE:Swift>:SHELL:-Xcc -F${CMAKE_LIBRARY_OUTPUT_DIRECTORY}>" |
| "$<$<COMPILE_LANGUAGE:Swift>:SHELL:-F ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}>" |
| "$<$<COMPILE_LANGUAGE:Swift>:SHELL:-Xcc -iframework${CMAKE_OSX_SYSROOT}/System/Library/PrivateFrameworks>") |
| if (EXISTS "${CMAKE_OSX_SYSROOT}/usr/local/include/unicode_private.modulemap") |
| target_compile_options(${_target} PRIVATE |
| "$<$<COMPILE_LANGUAGE:Swift>:SHELL:-Xcc -isystem${CMAKE_OSX_SYSROOT}/usr/local/include>" |
| "$<$<COMPILE_LANGUAGE:Swift>:SHELL:-Xcc -fmodule-map-file=${CMAKE_OSX_SYSROOT}/usr/local/include/unicode_private.modulemap>") |
| endif () |
| endif () |
| if (WEBKIT_ADDITIONS_COMPILE_PATH) |
| target_compile_options(${_target} PRIVATE |
| "$<$<COMPILE_LANGUAGE:Swift>:SHELL:-Xcc -isystem${WEBKIT_ADDITIONS_COMPILE_PATH}>") |
| elseif (WEBKIT_ADDITIONS_INCLUDE_PATH) |
| target_compile_options(${_target} PRIVATE |
| "$<$<COMPILE_LANGUAGE:Swift>:SHELL:-Xcc -isystem${WEBKIT_ADDITIONS_INCLUDE_PATH}>") |
| endif () |
| |
| # cmake's Swift interop does not respect CMAKE_SHARED_LINKER_FLAGS, so let's pass |
| # on those that we can. |
| # rdar://155519819 |
| string(REPLACE " " ";" CMAKE_SHARED_LINKER_FLAGS_SPLIT "${CMAKE_SHARED_LINKER_FLAGS}") |
| foreach (_flag IN ITEMS ${CMAKE_SHARED_LINKER_FLAGS_SPLIT}) |
| # We can only pass on -Wl flags. |
| string(SUBSTRING ${_flag} 0 4 _prefix) |
| if (${_prefix} STREQUAL "-Wl,") |
| string(SUBSTRING ${_flag} 4 -1 _shorter_flag) |
| # SHELL: keeps the -Xlinker/argument pair together; without it |
| # CMake deduplicates the repeated -Xlinker tokens. |
| # https://bugs.webkit.org/show_bug.cgi?id=312105 |
| target_compile_options(${_target} PUBLIC "$<$<COMPILE_LANGUAGE:Swift>:SHELL:-Xlinker ${_shorter_flag}>") |
| endif () |
| endforeach () |
| |
| # Empty list means: skip Swift C++ interop header generation entirely. |
| # Useful for iOS where some Swift files transitively import broken |
| # umbrella modules. https://bugs.webkit.org/show_bug.cgi?id=312083 |
| set(_skip_swift_cxx_header FALSE) |
| if (DEFINED ${_target}_SWIFT_TYPECHECK_SOURCES AND "${${_target}_SWIFT_TYPECHECK_SOURCES}" STREQUAL "") |
| set(_skip_swift_cxx_header TRUE) |
| endif () |
| |
| cmake_path(APPEND CMAKE_CURRENT_BINARY_DIR include OUTPUT_VARIABLE _header_base_path) |
| cmake_path(APPEND _header_base_path ${_output_header} OUTPUT_VARIABLE _header_path) |
| |
| cmake_path(GET _header_path FILENAME _header_filename) |
| cmake_path(APPEND CMAKE_CURRENT_BINARY_DIR "${_header_filename}.tmp" OUTPUT_VARIABLE _header_tmp_path) |
| set(_header_stamp_path "${_header_path}.stamp") |
| if (NOT DEFINED ${_target}_SWIFT_EMIT_CLANG_HEADER_MIN_ACCESS) |
| set(${_target}_SWIFT_EMIT_CLANG_HEADER_MIN_ACCESS internal) |
| endif () |
| # -emit-clang-header-min-access was added in Swift 6.3. Please simplify |
| # this once that becomes mandatory. |
| if (CMAKE_Swift_COMPILER_VERSION VERSION_GREATER_EQUAL 6.3) |
| set(CAN_USE_EMIT_CLANG_HEADER_MIN_ACCESS TRUE) |
| endif () |
| # Always create the SwiftCxxHeader placeholder so external callers |
| # (e.g. Source/WebKit/CMakeLists.txt's deferred add_dependencies) can |
| # reference it even when ${_target}_SWIFT_TYPECHECK_SOURCES is empty |
| # and we skip the C++-interop header emission entirely. |
| add_custom_target(${_target}_SwiftCxxHeader) |
| # Placeholder ordering target. The deferred _webkit_setup_swift_header_deps |
| # call populates it with all generated (binary-dir) headers for this target |
| # once ${_target}_HEADERS and ${_target}_DERIVED_SOURCES are fully known. |
| add_custom_target(${_target}_SwiftGeneratedDeps) |
| # Generate the @-response file with platform-derived -D flags. The |
| # @-flag itself is already in _swift_options above, which gets fed to |
| # target_compile_options via _swift_only_options earlier in the macro. |
| _webkit_generate_platform_swift_args(${_target} "${_resp_path}" ${_target}_SwiftGeneratedDeps) |
| |
| # Trigger source whose mtime tracks the resp (and the emit-clang-header |
| # stamp / INTEROP_HEADERS when applicable). target_sources is how we |
| # plumb file-level deps in since CMake's Swift compile ignores |
| # OBJECT_DEPENDS. Created eagerly so the resp's add_custom_command |
| # has an in-graph consumer even when the typecheck path is skipped. |
| set(_trigger_path "${CMAKE_CURRENT_BINARY_DIR}/${_target}_SwiftRebuildTrigger.swift") |
| if (NOT EXISTS "${_trigger_path}") |
| file(WRITE "${_trigger_path}" "// Auto-generated; mtime tracks ${_target}'s Swift inputs.\n") |
| endif () |
| set(_trigger_deps "${_resp_path}") |
| if (DEFINED ${_target}_SWIFT_INTEROP_SOURCES) |
| list(APPEND _trigger_deps ${${_target}_SWIFT_INTEROP_HEADERS}) |
| elseif (NOT _skip_swift_cxx_header) |
| list(APPEND _trigger_deps "${_header_stamp_path}") |
| endif () |
| add_custom_command( |
| OUTPUT "${_trigger_path}" |
| DEPENDS ${_trigger_deps} |
| COMMAND ${CMAKE_COMMAND} -E touch "${_trigger_path}" |
| COMMENT "Refreshing ${_target} Swift rebuild trigger" |
| ) |
| target_sources(${_target} PRIVATE "${_trigger_path}") |
| add_custom_target(${_target}_SwiftRebuildTrigger DEPENDS "${_trigger_path}") |
| |
| if (NOT _skip_swift_cxx_header) |
| # WebKit-Swift-Generated.h.tmp must be written by exactly one target: the one |
| # whose ${_module_name}.swiftmodule the copy command below depends on. A |
| # second writer races the copy and fails it sporadically. |
| # https://bugs.webkit.org/show_bug.cgi?id=316000 |
| set(_swift_emit_header_flags |
| "$<$<COMPILE_LANGUAGE:Swift>:SHELL:-emit-clang-header-path ${_header_tmp_path}>") |
| if (CAN_USE_EMIT_CLANG_HEADER_MIN_ACCESS) |
| list(APPEND _swift_emit_header_flags |
| "$<$<COMPILE_LANGUAGE:Swift>:SHELL:-Xfrontend -emit-clang-header-min-access -Xfrontend ${${_target}_SWIFT_EMIT_CLANG_HEADER_MIN_ACCESS}>") |
| endif () |
| if (POLICY CMP0157) |
| # New Swift support: ${_target} is the only Swift compile, so emit here. |
| target_compile_options(${_target} PRIVATE ${_swift_emit_header_flags}) |
| else () |
| # Legacy support compiles the Swift sources twice: in the throw-away |
| # ${_target}_SwiftCompile helper (which produces the swiftmodule the |
| # copy depends on) and again in ${_target}'s link rule. Emit only from |
| # the helper; emitting from ${_target} too would make its link rule |
| # write the same temp unordered against the copy and race it. Stashed |
| # here, applied to the helper by _webkit_setup_swift_header_deps. |
| set(${_target}_SWIFT_EMIT_HEADER_FLAGS "${_swift_emit_header_flags}") |
| endif () |
| add_custom_command( |
| OUTPUT ${_header_stamp_path} |
| BYPRODUCTS ${_header_path} |
| DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${_module_name}.swiftmodule |
| COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_header_tmp_path} ${_header_path} |
| COMMAND ${CMAKE_COMMAND} -E touch ${_header_stamp_path} |
| COMMENT "Generating ${_target} Swift-C++ header" |
| VERBATIM) |
| |
| target_include_directories(${_target} PUBLIC ${_header_base_path}) |
| # Defer dependency wiring until end-of-directory so if(TARGET ...) inside |
| # _webkit_setup_swift_header_deps sees targets declared after this macro |
| # call (e.g. ${_target}_CopyHeaders is often created later in the same file). |
| cmake_language(DEFER CALL _webkit_setup_swift_header_deps |
| "${_target}" "${_header_stamp_path}" "${_header_path}" "${_resp_path}") |
| endif () |
| endif () |
| endmacro() |