default_output_dir = "{{root_out_dir}}/bin"
}
+ copy_command = "ln -f {{source}} {{output}} 2>/dev/null || (rm -rf {{output}} && cp -af {{source}} {{output}})"
tool("copy") {
- command = "ln -f {{source}} {{output}} 2>/dev/null || (rm -rf {{output}} && cp -af {{source}} {{output}})"
+ command = copy_command
description = "COPY {{source}} {{output}}"
}
+ if (current_os == "mac") {
+ tool("copy_bundle_data") {
+ # http://serverfault.com/q/209888/43689
+ _copydir = "mkdir -p {{output}} && cd {{source}} && " +
+ "pax -rwl . \"\$OLDPWD\"/{{output}}"
+ command = "rm -rf {{output}} && if [[ -d {{source}} ]]; then " +
+ _copydir + "; else " + copy_command + "; fi"
+ description = "COPY_BUNDLE_DATA {{source}} {{output}}"
+ }
+ tool("compile_xcassets") {
+ command = "false"
+ description = "The LLVM build doesn't use any xcasset files"
+ }
+ }
+
tool("stamp") {
command = "touch {{output}}"
description = "STAMP {{output}}"
--- /dev/null
+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" ]
+ }
+}
+import("//clang-tools-extra/clangd/xpc/enable.gni")
import("//clang/lib/StaticAnalyzer/Frontend/enable.gni")
import("//llvm/triples.gni")
import("//llvm/utils/gn/build/write_cmake_config.gni")
"LLVM_LIT_TOOLS_DIR=", # Intentionally empty, matches cmake build.
"LLVM_TOOLS_DIR=" + rebase_path("$root_out_dir/bin"),
"PYTHON_EXECUTABLE=$python_path",
- "CLANGD_BUILD_XPC_SUPPORT=0", # FIXME
]
+ if (clangd_build_xpc) {
+ extra_values += [ "CLANGD_BUILD_XPC_SUPPORT=1" ]
+ } else {
+ extra_values += [ "CLANGD_BUILD_XPC_SUPPORT=0" ]
+ }
+
if (clang_enable_static_analyzer) {
extra_values += [ "CLANG_ENABLE_STATIC_ANALYZER=1" ]
} else {
"//llvm/utils/llvm-lit",
"//llvm/utils/not",
]
+ if (clangd_build_xpc) {
+ deps +=
+ [ "//clang-tools-extra/clangd/xpc/test-client:clangd-xpc-test-client" ]
+ }
# FIXME: dep on dexp once it exist
testonly = true