mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 00:50:22 +00:00
Meta: Add a script and CMake function to generate a clang module map
In theory the clang module map should not have absolute paths for the headers. Other Swift projects seem to use the -ivfsoverlay feature of clang to work around this, but it seems difficult to get to work.
This commit is contained in:
parent
54c7bb1e9d
commit
cb55f65328
Notes:
github-actions[bot]
2024-08-07 00:29:06 +00:00
Author: https://github.com/ADKaster Commit: https://github.com/LadybirdBrowser/ladybird/commit/cb55f653284 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/965
4 changed files with 97 additions and 2 deletions
2
.github/actions/setup/action.yml
vendored
2
.github/actions/setup/action.yml
vendored
|
@ -53,7 +53,7 @@ runs:
|
||||||
set -e
|
set -e
|
||||||
sudo xcode-select --switch /Applications/Xcode_16.0.app
|
sudo xcode-select --switch /Applications/Xcode_16.0.app
|
||||||
brew update
|
brew update
|
||||||
brew install autoconf autoconf-archive automake bash ccache coreutils ffmpeg llvm@18 nasm ninja qt unzip wabt
|
brew install autoconf autoconf-archive automake bash ccache coreutils ffmpeg llvm@18 nasm ninja qt unzip wabt pyyaml
|
||||||
|
|
||||||
- name: 'Install vcpkg'
|
- name: 'Install vcpkg'
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
|
@ -23,7 +23,7 @@ function(_swift_generate_cxx_header target header)
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
cmake_parse_arguments(PARSE_ARGV 2 "ARG" "" "MODULE_NAME;CXX_STD_VERSION" "SEARCH_PATHS")
|
cmake_parse_arguments(PARSE_ARGV 2 "ARG" "" "MODULE_NAME;CXX_STD_VERSION" "SEARCH_PATHS;COMPILE_OPTIONS")
|
||||||
|
|
||||||
if(NOT ARG_MODULE_NAME)
|
if(NOT ARG_MODULE_NAME)
|
||||||
set(target_module_name $<TARGET_PROPERTY:${target},Swift_MODULE_NAME>)
|
set(target_module_name $<TARGET_PROPERTY:${target},Swift_MODULE_NAME>)
|
||||||
|
@ -70,6 +70,7 @@ function(_swift_generate_cxx_header target header)
|
||||||
${_SwiftSources}
|
${_SwiftSources}
|
||||||
${SDK_FLAGS}
|
${SDK_FLAGS}
|
||||||
${CXX_STD_FLAGS}
|
${CXX_STD_FLAGS}
|
||||||
|
${ARG_COMPILE_OPTIONS}
|
||||||
-Xcc -Wno-unqualified-std-cast-call
|
-Xcc -Wno-unqualified-std-cast-call
|
||||||
-Xcc -Wno-user-defined-literals
|
-Xcc -Wno-user-defined-literals
|
||||||
-Xcc -Wno-unknown-warning-option
|
-Xcc -Wno-unknown-warning-option
|
||||||
|
|
|
@ -23,6 +23,31 @@ function(embed_as_string_view name source_file output source_variable_name)
|
||||||
add_dependencies(all_generated "generate_${name}")
|
add_dependencies(all_generated "generate_${name}")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
function(generate_clang_module_map target_name)
|
||||||
|
cmake_parse_arguments(PARSE_ARGV 1 MODULE_MAP "" "DIRECTORY" "GENERATED_FILES")
|
||||||
|
if (NOT MODULE_MAP_DIRECTORY)
|
||||||
|
set(MODULE_MAP_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(module_map_file "${CMAKE_CURRENT_BINARY_DIR}/module/module.modulemap")
|
||||||
|
set(vfs_overlay_file "${CMAKE_CURRENT_BINARY_DIR}/vfs_overlay.yaml")
|
||||||
|
|
||||||
|
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
||||||
|
# FIXME: Make this depend on the public headers of the target
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT "${module_map_file}"
|
||||||
|
COMMAND "${Python3_EXECUTABLE}" "${SerenityOS_SOURCE_DIR}/Meta/generate_clang_module_map.py" "${MODULE_MAP_DIRECTORY}" --module-map "${module_map_file}" --vfs-map ${vfs_overlay_file} ${MODULE_MAP_GENERATED_FILES}
|
||||||
|
VERBATIM
|
||||||
|
DEPENDS "${SerenityOS_SOURCE_DIR}/Meta/generate_clang_module_map.py"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target("generate_${target_name}_module_map" DEPENDS "${module_map_file}")
|
||||||
|
add_dependencies(all_generated "generate_${target_name}_module_map")
|
||||||
|
add_dependencies("${target_name}" "generate_${target_name}_module_map")
|
||||||
|
|
||||||
|
target_compile_options(${target_name} PUBLIC "SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xcc -ivfsoverlay${vfs_overlay_file}>")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
function(compile_ipc source output)
|
function(compile_ipc source output)
|
||||||
if (NOT IS_ABSOLUTE ${source})
|
if (NOT IS_ABSOLUTE ${source})
|
||||||
set(source ${CMAKE_CURRENT_SOURCE_DIR}/${source})
|
set(source ${CMAKE_CURRENT_SOURCE_DIR}/${source})
|
||||||
|
|
69
Meta/generate_clang_module_map.py
Normal file
69
Meta/generate_clang_module_map.py
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generates a clang module map for a given directory
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import pathlib
|
||||||
|
import yaml
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def write_file_if_not_same(file_path, content):
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r') as f:
|
||||||
|
if f.read() == content:
|
||||||
|
return
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with open(file_path, 'w') as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
epilog=__doc__,
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
|
parser.add_argument('directory', help='source directory to generate module map for')
|
||||||
|
parser.add_argument('generated_files', nargs='+', help='extra files to include in the module map')
|
||||||
|
parser.add_argument('-m', '--module-map', required=True, help='output module map file')
|
||||||
|
parser.add_argument('-v', '--vfs-map', required=True, help='output VFS map file')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
root = pathlib.Path(args.directory)
|
||||||
|
if not root.is_dir():
|
||||||
|
print(f"Error: {args.directory} is not a directory", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
pathlib.Path(args.module_map).parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
header_files = [f for f in root.rglob('**/*.h') if f.is_file()]
|
||||||
|
module_name = root.name
|
||||||
|
|
||||||
|
module_map = f"module {module_name} {{\n"
|
||||||
|
for header_file in header_files:
|
||||||
|
module_map += f" header \"{header_file.relative_to(root)}\"\n"
|
||||||
|
for generated_file in args.generated_files:
|
||||||
|
module_map += f" header \"{generated_file}\"\n"
|
||||||
|
module_map += " requires cplusplus\n"
|
||||||
|
module_map += " export *\n"
|
||||||
|
module_map += "}\n"
|
||||||
|
|
||||||
|
vfs_map = {
|
||||||
|
"version": 0,
|
||||||
|
"use-external-names": False,
|
||||||
|
"roots": [
|
||||||
|
{
|
||||||
|
"name": f"{root}/module.modulemap",
|
||||||
|
"type": "file",
|
||||||
|
"external-contents": f"{args.module_map}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
write_file_if_not_same(args.module_map, module_map)
|
||||||
|
write_file_if_not_same(args.vfs_map, yaml.dump(vfs_map))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
Loading…
Reference in a new issue