import("//llvm/utils/gn/build/symlink_or_copy.gni")
import("//llvm/utils/gn/build/write_cmake_config.gni")
# create_clangd_xpc_framework() in cmake creates both the ClangdXPC.framework
# bundle and the clangd.xpc bundle within it in a single action.
# Since GN has some native support for macOS bundles, it's more natural
# to have one create_bundle() each for both ClangdXPC.framework and clangd.xpc.
# See `llvm/utils/gn/gn.py help create_bundle` and ../cmake/modules.
######################################################################
# clangd.xpc bundle
write_cmake_config("XPCServiceInfo.plist") {
input = "../cmake/XPCServiceInfo.plist.in"
output = "$target_gen_dir/XPCServiceInfo.plist"
service_name = "clangd"
values = [
"CLANGD_XPC_SERVICE_NAME=$service_name",
"CLANGD_XPC_SERVICE_BUNDLE_NAME=org.llvm.$service_name",
]
}
bundle_data("clangxpc_bundle_xpc_service_info_plist") {
public_deps = [ ":XPCServiceInfo.plist" ]
sources = [ "$target_gen_dir/XPCServiceInfo.plist" ]
outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
}
bundle_data("clangxpc_bundle_xpc_service_executable") {
public_deps = [ "//clang-tools-extra/clangd/tool:clangd" ]
sources = [ "$root_out_dir/bin/clangd" ]
outputs = [ "{{bundle_executable_dir}}/{{source_file_part}}" ]
}
create_bundle("clangd.xpc") {
# .app directory structure.
# Since this target only exists to be copied into ClangdXPC.framework,
# put it in $target_gen_dir, not $root_out_dir.
bundle_root_dir = "$target_gen_dir/$target_name"
bundle_contents_dir = "$bundle_root_dir/Contents"
bundle_executable_dir = "$bundle_contents_dir/MacOS"
deps = [
":clangxpc_bundle_xpc_service_executable",
":clangxpc_bundle_xpc_service_info_plist",
]
}
######################################################################
# ClangdXPC.framework
write_cmake_config("Info.plist") {
input = "../cmake/Info.plist.in"
output = "$target_gen_dir/Info.plist"
values = [ "CLANGD_XPC_FRAMEWORK_NAME=ClangdXPC" ]
}
bundle_data("clangdxpc_bundle_info_plist") {
public_deps = [ ":Info.plist" ]
sources = [ "$target_gen_dir/Info.plist" ]
outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
}
shared_library("ClangdXPCLib") {
deps = [ "//clang-tools-extra/clangd/tool:clangd" ]
sources = [ "ClangdXPC.cpp" ]
}
bundle_data("clangdxpc_bundle_executable") {
public_deps = [ ":ClangdXPCLib" ]
sources = [ "$root_out_dir/lib/libClangdXPCLib.dylib" ]
outputs = [ "{{bundle_executable_dir}}/ClangdXPC" ]
}
bundle_data("clangdxpc_bundle_xpc") {
public_deps = [ ":clangd.xpc" ]
sources = [ "$target_gen_dir/clangd.xpc" ]
outputs = [ "{{bundle_contents_dir}}/XPCServices/{{source_file_part}}" ]
}
# .framework bundle symlinks:
# - ./ClangdXPC -> Versions/Current/ClangdXPC
# - ./Resources -> Versions/Current/Resources
# - ./XPCServices -> Versions/Current/XPCServices
# - ./Versions/Current -> Versions/A
# Since bundles are a mac thing, we know that symlink_or_copy() will symlink
# and not copy, and hence creating the symlink before the target exists is safe.
symlinks = [
"ClangdXPC",
"Resources",
"XPCServices",
]
foreach(target, symlinks) {
symlink_or_copy("clangdxpc_symlink_$target") {
source = "Versions/Current/$target"
output = "$root_out_dir/lib/ClangdXPC.framework/$target"
}
}
symlink_or_copy("clangdxpc_symlink_Versions_Current") {
source = "A"
output = "$root_out_dir/lib/ClangdXPC.framework/Versions/Current"
}
create_bundle("ClangdXPC.framework") {
# .framework directory structure.
bundle_root_dir = "$root_out_dir/lib/$target_name"
bundle_contents_dir = "$bundle_root_dir/Versions/A"
bundle_executable_dir = "$bundle_contents_dir"
bundle_resources_dir = "$bundle_contents_dir/Resources"
deps = [
":clangdxpc_bundle_executable",
":clangdxpc_bundle_info_plist",
":clangdxpc_bundle_xpc",
":clangdxpc_symlink_Versions_Current",
]
foreach(target, symlinks) {
deps += [ ":clangdxpc_symlink_$target" ]
}
}