diff --git a/.gitignore b/.gitignore index 427409edc..7921c3584 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ bazel-* .idea -tests/macos/xcodeproj/**/xcuserdata \ No newline at end of file +tests/macos/xcodeproj/**/xcuserdata +**/*.xcodeproj/bazelinstallers/index-import diff --git a/rules/library.bzl b/rules/library.bzl index aeb2e9242..2f48bcb00 100644 --- a/rules/library.bzl +++ b/rules/library.bzl @@ -568,6 +568,8 @@ def apple_library(name, library_tools = {}, export_private_headers = True, names objc_library_data = library_tools["wrap_resources_in_filegroup"](name = objc_libname + "_data", srcs = data) objc_copts.append("-I.") + + objc_copts.extend(("-index-store-path", "$(GENDIR)/rules_ios_apple_library_objc.indexstore")) objc_library( name = objc_libname, srcs = objc_sources + objc_private_hdrs + objc_non_exported_hdrs, diff --git a/rules/repositories.bzl b/rules/repositories.bzl index 10c437f0f..fa6d072c9 100644 --- a/rules/repositories.bzl +++ b/rules/repositories.bzl @@ -59,6 +59,24 @@ def rules_ios_dependencies(): ], ) + _maybe( + http_archive, + name = "com_github_lyft_index_import", + build_file_content = """\ +load("@bazel_skylib//rules:native_binary.bzl", "native_binary") + +native_binary( + name = "index_import", + src = "index-import", + out = "index-import", + visibility = ["//visibility:public"], +) +""", + canonical_id = "index-import-5.1.1.3", + sha256 = "0946012f1557a72fcbc65bd3f2e9b2a99d5b1e57e6db43a5ad0c969bddd9e072", + urls = ["https://github.com/lyft/index-import/releases/download/5.1.1.3/index-import.zip"], + ) + _maybe( http_archive, name = "com_github_yonaskolb_xcodegen", diff --git a/rules/xcodeproj.bzl b/rules/xcodeproj.bzl index 0c997a640..3174121c4 100644 --- a/rules/xcodeproj.bzl +++ b/rules/xcodeproj.bzl @@ -185,7 +185,8 @@ def _xcodeproj_impl(ctx): "BAZEL_PATH": ctx.attr.bazel_path, "BAZEL_WORKSPACE_ROOT": "$SRCROOT/%s" % script_dot_dots, "BAZEL_STUBS_DIR": "$PROJECT_FILE_PATH/bazelstubs", - "BAZEL_INSTALLER": "$BAZEL_STUBS_DIR/%s" % ctx.executable.installer.short_path, + "BAZEL_INSTALLERS_DIR": "$PROJECT_FILE_PATH/bazelinstallers", + "BAZEL_INSTALLER": "$BAZEL_INSTALLERS_DIR/%s" % ctx.executable.installer.basename, "CC": "$BAZEL_STUBS_DIR/clang-stub", "CXX": "$CC", "CLANG_ANALYZER_EXEC": "$CC", @@ -227,6 +228,7 @@ def _xcodeproj_impl(ctx): "PRODUCT_NAME": target_info.name, "BAZEL_BIN_SUBDIR": target_info.bazel_bin_subdir, "MACH_O_TYPE": target_macho_type, + "CLANG_ENABLE_MODULES": "YES", } if target_info.product_type == "application": @@ -234,7 +236,6 @@ def _xcodeproj_impl(ctx): target_settings["PRODUCT_BUNDLE_IDENTIFIER"] = target_info.bundle_id if target_info.product_type == "bundle.unit-test": target_settings["SUPPORTS_MACCATALYST"] = False - target_dependencies = [] test_host_appname = getattr(target_info, "test_host_appname", None) if test_host_appname: @@ -315,15 +316,17 @@ $BAZEL_INSTALLER install_script = ctx.actions.declare_file( "%s-install-xcodeproj.sh" % ctx.attr.name, ) - + installer_runfile_paths = [i.short_path for i in ctx.attr.installer[DefaultInfo].default_runfiles.files.to_list()] ctx.actions.expand_template( template = ctx.file._xcodeproj_installer_template, output = install_script, substitutions = { "$(project_short_path)": project.short_path, "$(project_full_path)": project.path, + "$(installer_runfile_short_paths)": " ".join(installer_runfile_paths), "$(installer_short_path)": ctx.executable.installer.short_path, "$(clang_stub_short_path)": ctx.executable.clang_stub.short_path, + "$(index_import_short_path)": ctx.executable.index_import.short_path, "$(clang_stub_ld_path)": ctx.executable.ld_stub.short_path, "$(clang_stub_swiftc_path)": ctx.executable.swiftc_stub.short_path, "$(print_json_leaf_nodes_path)": ctx.executable.print_json_leaf_nodes.short_path, @@ -343,6 +346,7 @@ $BAZEL_INSTALLER direct = ctx.files.build_wrapper + ctx.files.installer + ctx.files.clang_stub + + ctx.files.index_import + ctx.files.ld_stub + ctx.files.swiftc_stub + ctx.files._infoplist_stub + @@ -367,6 +371,7 @@ xcodeproj = rule( "_workspace_xcsettings": attr.label(executable = False, default = Label("//tools/xcodeproj_shims:WorkspaceSettings.xcsettings"), allow_single_file = ["xcsettings"]), "output_processor": attr.label(executable = True, default = Label("//tools/xcodeproj_shims:output-processor.rb"), cfg = "host", allow_single_file = True), "_xcodegen": attr.label(executable = True, default = Label("@com_github_yonaskolb_xcodegen//:xcodegen"), cfg = "host"), + "index_import": attr.label(executable = True, default = Label("@com_github_lyft_index_import//:index_import"), cfg = "host"), "clang_stub": attr.label(executable = True, default = Label("//tools/xcodeproj_shims:clang-stub"), cfg = "host"), "ld_stub": attr.label(executable = True, default = Label("//tools/xcodeproj_shims:ld-stub"), cfg = "host"), "swiftc_stub": attr.label(executable = True, default = Label("//tools/xcodeproj_shims:swiftc-stub"), cfg = "host"), diff --git a/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/_indexstore.sh b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/_indexstore.sh new file mode 100755 index 000000000..36fe20ad3 --- /dev/null +++ b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/_indexstore.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +set -euo pipefail + +# Import Bazel built indexstores into Xcode. See https://github.com/lyft/index-import +# +# This makes use of a number of Xcode's provided environment variables. These +# file remappings are not specific to this project, the apply to all projects +# built with Bazel and rules_swift. + +# Example: /private/var/tmp/_bazel_//execroot/ +readonly bazel_root="^/private/var/tmp/_bazel_.+?/.+?/execroot/[^/]+" +readonly bazel_bin="^(?:$bazel_root/)?bazel-out/.+?/bin" + +# Object file paths are fundamental to how Xcode loads from the indexstore. If +# the `OutputFile` does not match what Xcode looks for, then those parts of the +# indexstore will not be found and used. +readonly bazel_swift_object="$bazel_bin/.*/(.+?)(?:_swift)?_objs/.*/(.+?)[.]swift[.]o$" +readonly bazel_objc_object="$bazel_bin/.*/_objs/(?:arc/|non_arc/)?(.+?)-(?:objc|cpp)/(.+?)[.]o$" +readonly xcode_object="$CONFIGURATION_TEMP_DIR/\$1.build/Objects-normal/$ARCHS/\$2.o" + +# Bazel built `.swiftmodule` files are copied to `DerivedData`. Since modules +# are referenced by indexstores, their paths are remapped. +readonly bazel_module="$bazel_bin/.*/(.+?)[.]swiftmodule$" +readonly xcode_module="$BUILT_PRODUCTS_DIR/\$1.swiftmodule/$ARCHS.swiftmodule" + +# External dependencies are available via the `bazel-` symlink. +# This remapping, in combination with `xcode-index-preferences.json`, enables +# index features for external dependencies, such as jump-to-definition. +readonly bazel_external="$bazel_root/external" +readonly xcode_external="$BAZEL_WORKSPACE_ROOT/bazel-$(basename "$SRCROOT")/external" + + +$BAZEL_INSTALLERS_DIR/index-import \ + -remap "$bazel_module=$xcode_module" \ + -remap "$bazel_swift_object=$xcode_object" \ + -remap "$bazel_objc_object=$xcode_object" \ + -remap "$bazel_external=$xcode_external" \ + -remap "$bazel_root=$BAZEL_WORKSPACE_ROOT" \ + -remap "^([^//])=$BAZEL_WORKSPACE_ROOT/\$1" \ + "$@" \ + "$BUILD_DIR"/../../Index/DataStore diff --git a/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/_swiftmodule.sh b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/_swiftmodule.sh new file mode 100755 index 000000000..c974cfb3e --- /dev/null +++ b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/_swiftmodule.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -euo pipefail + +for module in "$@"; do + doc="${module%.swiftmodule}.swiftdoc" + module_name=$(basename "$module") + module_bundle="$BUILT_PRODUCTS_DIR/$module_name" + mkdir -p "$module_bundle" + + cp "$module" "$module_bundle/$NATIVE_ARCH_ACTUAL.swiftmodule" + cp "$doc" "$module_bundle/$NATIVE_ARCH_ACTUAL.swiftdoc" + + ios_module_name="$NATIVE_ARCH_ACTUAL-$LLVM_TARGET_TRIPLE_VENDOR-$SWIFT_PLATFORM_TARGET_PREFIX$LLVM_TARGET_TRIPLE_SUFFIX" + cp "$module" "$module_bundle/$ios_module_name.swiftmodule" + cp "$doc" "$module_bundle/$ios_module_name.swiftdoc" + + chmod -R +w "$module_bundle" +done diff --git a/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/indexstores.sh b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/indexstores.sh new file mode 100755 index 000000000..ee2e1871f --- /dev/null +++ b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/indexstores.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -euo pipefail + +# See `_indexstore.sh` for full details. + +# Make sure add these to bazel build target copts for objective-c +find "$BAZEL_WORKSPACE_ROOT/bazel-out"/*/bin/ \ + -type d \ + -name "*.indexstore" \ + -print0 \ + | xargs -0 "$BAZEL_INSTALLERS_DIR/_indexstore.sh" + +echo "Finish remapping index files" \ No newline at end of file diff --git a/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/install.sh b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/install.sh new file mode 100755 index 000000000..5f5e1f43a --- /dev/null +++ b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/install.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Install the runnable products so that Xcode can run it. This includes `.app`s, +# `.xctest`s, and also command line binaries. + +# TODO: Lyft uses this script, because Xcode calls `ditto` on the `.swiftmodule`/`.swiftdoc` files of the top-level +# target. +# "$SRCROOT"/bazel/installers/xcode-artifacts.sh + +set -eux + + +diagnostics_dir="$TARGET_BUILD_DIR/../../../bazel-xcode-diagnostics/" +mkdir -p $diagnostics_dir + +# Delete all logfiles that are older than 7 days +find $diagnostics_dir -type f -atime +7d -delete +date_suffix="$(date +%Y%m%d.%H%M%S%L)" + +case ${PRODUCT_TYPE} in + com.apple.product-type.framework) + input="bazel-bin/$BAZEL_BIN_SUBDIR/${TARGET_NAME}/${FULL_PRODUCT_NAME}" + ;; + com.apple.product-type.bundle.unit-test) + input="bazel-bin/$BAZEL_BIN_SUBDIR/$TARGET_NAME.__internal__.__test_bundle_archive-root/$TARGET_NAME${WRAPPER_SUFFIX:-}" + ;; + com.apple.product-type.application) + input="bazel-bin/$BAZEL_BIN_SUBDIR/${TARGET_NAME}_archive-root/Payload/$TARGET_NAME${WRAPPER_SUFFIX:-}" + ;; + *) + echo "Error: Installing ${TARGET_NAME} of type ${PRODUCT_TYPE} is unsupported" >&2 + exit 1 + ;; +esac +output="$TARGET_BUILD_DIR/$FULL_PRODUCT_NAME" + +mkdir -p "$(dirname "$output")" + +if [[ -d $input ]]; then + # Copy bundle contents, into the destination bundle. + # This avoids self-nesting, like: Foo.app/Foo.app + input+="/" +fi + + +rsync \ + --recursive --chmod=u+w --delete \ + "$input" "$output" > $diagnostics_dir/rsync-stdout-$date_suffix.log 2> $diagnostics_dir/rsync-stderr-$date_suffix.log + + +# Part of the build intermediary output will be swiftmodule files +# which XCode will use for indexing. Let's keep those. +$BAZEL_INSTALLERS_DIR/swiftmodules.sh > $diagnostics_dir/swiftmodules-stdout-$date_suffix.log 2> $diagnostics_dir/swiftmodules-stderr-$date_suffix.log & +$BAZEL_INSTALLERS_DIR/indexstores.sh > $diagnostics_dir/indexstores-stdout-$date_suffix.log 2> $diagnostics_dir/indexstores-stderr-$date_suffix.log & +$BAZEL_INSTALLERS_DIR/lldb-settings.sh > $diagnostics_dir/lldb-stdout-$date_suffix.log 2> $diagnostics_dir/lldb-stderr-$date_suffix.log & + + diff --git a/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/installer b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/installer new file mode 100755 index 000000000..5f5e1f43a --- /dev/null +++ b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/installer @@ -0,0 +1,57 @@ +#!/bin/bash + +# Install the runnable products so that Xcode can run it. This includes `.app`s, +# `.xctest`s, and also command line binaries. + +# TODO: Lyft uses this script, because Xcode calls `ditto` on the `.swiftmodule`/`.swiftdoc` files of the top-level +# target. +# "$SRCROOT"/bazel/installers/xcode-artifacts.sh + +set -eux + + +diagnostics_dir="$TARGET_BUILD_DIR/../../../bazel-xcode-diagnostics/" +mkdir -p $diagnostics_dir + +# Delete all logfiles that are older than 7 days +find $diagnostics_dir -type f -atime +7d -delete +date_suffix="$(date +%Y%m%d.%H%M%S%L)" + +case ${PRODUCT_TYPE} in + com.apple.product-type.framework) + input="bazel-bin/$BAZEL_BIN_SUBDIR/${TARGET_NAME}/${FULL_PRODUCT_NAME}" + ;; + com.apple.product-type.bundle.unit-test) + input="bazel-bin/$BAZEL_BIN_SUBDIR/$TARGET_NAME.__internal__.__test_bundle_archive-root/$TARGET_NAME${WRAPPER_SUFFIX:-}" + ;; + com.apple.product-type.application) + input="bazel-bin/$BAZEL_BIN_SUBDIR/${TARGET_NAME}_archive-root/Payload/$TARGET_NAME${WRAPPER_SUFFIX:-}" + ;; + *) + echo "Error: Installing ${TARGET_NAME} of type ${PRODUCT_TYPE} is unsupported" >&2 + exit 1 + ;; +esac +output="$TARGET_BUILD_DIR/$FULL_PRODUCT_NAME" + +mkdir -p "$(dirname "$output")" + +if [[ -d $input ]]; then + # Copy bundle contents, into the destination bundle. + # This avoids self-nesting, like: Foo.app/Foo.app + input+="/" +fi + + +rsync \ + --recursive --chmod=u+w --delete \ + "$input" "$output" > $diagnostics_dir/rsync-stdout-$date_suffix.log 2> $diagnostics_dir/rsync-stderr-$date_suffix.log + + +# Part of the build intermediary output will be swiftmodule files +# which XCode will use for indexing. Let's keep those. +$BAZEL_INSTALLERS_DIR/swiftmodules.sh > $diagnostics_dir/swiftmodules-stdout-$date_suffix.log 2> $diagnostics_dir/swiftmodules-stderr-$date_suffix.log & +$BAZEL_INSTALLERS_DIR/indexstores.sh > $diagnostics_dir/indexstores-stdout-$date_suffix.log 2> $diagnostics_dir/indexstores-stderr-$date_suffix.log & +$BAZEL_INSTALLERS_DIR/lldb-settings.sh > $diagnostics_dir/lldb-stdout-$date_suffix.log 2> $diagnostics_dir/lldb-stderr-$date_suffix.log & + + diff --git a/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/lldb-settings.sh b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/lldb-settings.sh new file mode 100755 index 000000000..1039f3f17 --- /dev/null +++ b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/lldb-settings.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -euo pipefail + + +# Bazel uses `-debug-prefix-map` to strip the bazel build directory from the +# paths embedded in debug info. This means the debug info contains _project +# relative_ paths instead of Bazel absolute paths. +# +# However, Xcode sets breakpoints via _project absolute_ paths, which are not +# the paths in the debug info. This lldb setting ensures that _project relative_ +# paths are remapped to _project absolute_ paths. +# +# NOTE: In order to use this, add this line to `~/.lldbinit`: +# +# command source ~/.lldbinit-source-map +cat <<-END > ~/.lldbinit-source-map +settings set target.source-map ./ "$SRCROOT/" +END diff --git a/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/swiftmodules.sh b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/swiftmodules.sh new file mode 100755 index 000000000..0bb695905 --- /dev/null +++ b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/bazelinstallers/swiftmodules.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -euo pipefail + +# Copy Bazel build `.swiftmodule` files to `DerivedData`. This is used by Xcode +# and its indexing. +find "$BAZEL_WORKSPACE_ROOT/bazel-out"/*/bin/ \ + -name "*.swiftmodule" \ + -not -path "*/_swift_module_cache/*" \ + -print0 \ + | xargs -0 "$BAZEL_INSTALLERS_DIR/_swiftmodule.sh" diff --git a/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/project.pbxproj b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/project.pbxproj index 0b5a2fd41..36d97588d 100755 --- a/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/project.pbxproj +++ b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/project.pbxproj @@ -272,6 +272,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = /tests/macos/xcodeproj; + CLANG_ENABLE_MODULES = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; MACH_O_TYPE = "$(inherited)"; PRODUCT_NAME = "Single-Application-UnitTests"; @@ -284,6 +285,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = /rules/test_host_app; + CLANG_ENABLE_MODULES = YES; INFOPLIST_FILE = "$BAZEL_STUBS_DIR/Info-stub.plist"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACH_O_TYPE = "$(inherited)"; @@ -297,6 +299,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = /rules/test_host_app; + CLANG_ENABLE_MODULES = YES; INFOPLIST_FILE = "$BAZEL_STUBS_DIR/Info-stub.plist"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACH_O_TYPE = "$(inherited)"; @@ -310,7 +313,8 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BUILD_EXEC = "$BAZEL_STUBS_DIR/build-wrapper"; - BAZEL_INSTALLER = $BAZEL_STUBS_DIR/tools/xcodeproj_shims/installer; + BAZEL_INSTALLER = $BAZEL_INSTALLERS_DIR/installer; + BAZEL_INSTALLERS_DIR = $PROJECT_FILE_PATH/bazelinstallers; BAZEL_OUTPUT_PROCESSOR = "$BAZEL_STUBS_DIR/output-processor.rb"; BAZEL_PATH = bazelisk; BAZEL_STUBS_DIR = $PROJECT_FILE_PATH/bazelstubs; @@ -333,7 +337,8 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BUILD_EXEC = "$BAZEL_STUBS_DIR/build-wrapper"; - BAZEL_INSTALLER = $BAZEL_STUBS_DIR/tools/xcodeproj_shims/installer; + BAZEL_INSTALLER = $BAZEL_INSTALLERS_DIR/installer; + BAZEL_INSTALLERS_DIR = $PROJECT_FILE_PATH/bazelinstallers; BAZEL_OUTPUT_PROCESSOR = "$BAZEL_STUBS_DIR/output-processor.rb"; BAZEL_PATH = bazelisk; BAZEL_STUBS_DIR = $PROJECT_FILE_PATH/bazelstubs; @@ -356,6 +361,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = /tests/macos/xcodeproj; + CLANG_ENABLE_MODULES = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; MACH_O_TYPE = "$(inherited)"; PRODUCT_NAME = "Single-Application-RunnableTestSuite"; @@ -368,6 +374,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = /tests/macos/xcodeproj; + CLANG_ENABLE_MODULES = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; MACH_O_TYPE = "$(inherited)"; PRODUCT_NAME = "Single-Application-RunnableTestSuite"; @@ -380,6 +387,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = /tests/macos/xcodeproj; + CLANG_ENABLE_MODULES = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; MACH_O_TYPE = "$(inherited)"; PRODUCT_NAME = "Single-Application-UnitTests"; diff --git a/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003..000000000 --- a/tests/macos/xcodeproj/Single-Application-Project-AllTargets.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/_indexstore.sh b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/_indexstore.sh new file mode 100755 index 000000000..36fe20ad3 --- /dev/null +++ b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/_indexstore.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +set -euo pipefail + +# Import Bazel built indexstores into Xcode. See https://github.com/lyft/index-import +# +# This makes use of a number of Xcode's provided environment variables. These +# file remappings are not specific to this project, the apply to all projects +# built with Bazel and rules_swift. + +# Example: /private/var/tmp/_bazel_//execroot/ +readonly bazel_root="^/private/var/tmp/_bazel_.+?/.+?/execroot/[^/]+" +readonly bazel_bin="^(?:$bazel_root/)?bazel-out/.+?/bin" + +# Object file paths are fundamental to how Xcode loads from the indexstore. If +# the `OutputFile` does not match what Xcode looks for, then those parts of the +# indexstore will not be found and used. +readonly bazel_swift_object="$bazel_bin/.*/(.+?)(?:_swift)?_objs/.*/(.+?)[.]swift[.]o$" +readonly bazel_objc_object="$bazel_bin/.*/_objs/(?:arc/|non_arc/)?(.+?)-(?:objc|cpp)/(.+?)[.]o$" +readonly xcode_object="$CONFIGURATION_TEMP_DIR/\$1.build/Objects-normal/$ARCHS/\$2.o" + +# Bazel built `.swiftmodule` files are copied to `DerivedData`. Since modules +# are referenced by indexstores, their paths are remapped. +readonly bazel_module="$bazel_bin/.*/(.+?)[.]swiftmodule$" +readonly xcode_module="$BUILT_PRODUCTS_DIR/\$1.swiftmodule/$ARCHS.swiftmodule" + +# External dependencies are available via the `bazel-` symlink. +# This remapping, in combination with `xcode-index-preferences.json`, enables +# index features for external dependencies, such as jump-to-definition. +readonly bazel_external="$bazel_root/external" +readonly xcode_external="$BAZEL_WORKSPACE_ROOT/bazel-$(basename "$SRCROOT")/external" + + +$BAZEL_INSTALLERS_DIR/index-import \ + -remap "$bazel_module=$xcode_module" \ + -remap "$bazel_swift_object=$xcode_object" \ + -remap "$bazel_objc_object=$xcode_object" \ + -remap "$bazel_external=$xcode_external" \ + -remap "$bazel_root=$BAZEL_WORKSPACE_ROOT" \ + -remap "^([^//])=$BAZEL_WORKSPACE_ROOT/\$1" \ + "$@" \ + "$BUILD_DIR"/../../Index/DataStore diff --git a/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/_swiftmodule.sh b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/_swiftmodule.sh new file mode 100755 index 000000000..c974cfb3e --- /dev/null +++ b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/_swiftmodule.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -euo pipefail + +for module in "$@"; do + doc="${module%.swiftmodule}.swiftdoc" + module_name=$(basename "$module") + module_bundle="$BUILT_PRODUCTS_DIR/$module_name" + mkdir -p "$module_bundle" + + cp "$module" "$module_bundle/$NATIVE_ARCH_ACTUAL.swiftmodule" + cp "$doc" "$module_bundle/$NATIVE_ARCH_ACTUAL.swiftdoc" + + ios_module_name="$NATIVE_ARCH_ACTUAL-$LLVM_TARGET_TRIPLE_VENDOR-$SWIFT_PLATFORM_TARGET_PREFIX$LLVM_TARGET_TRIPLE_SUFFIX" + cp "$module" "$module_bundle/$ios_module_name.swiftmodule" + cp "$doc" "$module_bundle/$ios_module_name.swiftdoc" + + chmod -R +w "$module_bundle" +done diff --git a/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/indexstores.sh b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/indexstores.sh new file mode 100755 index 000000000..ee2e1871f --- /dev/null +++ b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/indexstores.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -euo pipefail + +# See `_indexstore.sh` for full details. + +# Make sure add these to bazel build target copts for objective-c +find "$BAZEL_WORKSPACE_ROOT/bazel-out"/*/bin/ \ + -type d \ + -name "*.indexstore" \ + -print0 \ + | xargs -0 "$BAZEL_INSTALLERS_DIR/_indexstore.sh" + +echo "Finish remapping index files" \ No newline at end of file diff --git a/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/install.sh b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/install.sh new file mode 100755 index 000000000..5f5e1f43a --- /dev/null +++ b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/install.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Install the runnable products so that Xcode can run it. This includes `.app`s, +# `.xctest`s, and also command line binaries. + +# TODO: Lyft uses this script, because Xcode calls `ditto` on the `.swiftmodule`/`.swiftdoc` files of the top-level +# target. +# "$SRCROOT"/bazel/installers/xcode-artifacts.sh + +set -eux + + +diagnostics_dir="$TARGET_BUILD_DIR/../../../bazel-xcode-diagnostics/" +mkdir -p $diagnostics_dir + +# Delete all logfiles that are older than 7 days +find $diagnostics_dir -type f -atime +7d -delete +date_suffix="$(date +%Y%m%d.%H%M%S%L)" + +case ${PRODUCT_TYPE} in + com.apple.product-type.framework) + input="bazel-bin/$BAZEL_BIN_SUBDIR/${TARGET_NAME}/${FULL_PRODUCT_NAME}" + ;; + com.apple.product-type.bundle.unit-test) + input="bazel-bin/$BAZEL_BIN_SUBDIR/$TARGET_NAME.__internal__.__test_bundle_archive-root/$TARGET_NAME${WRAPPER_SUFFIX:-}" + ;; + com.apple.product-type.application) + input="bazel-bin/$BAZEL_BIN_SUBDIR/${TARGET_NAME}_archive-root/Payload/$TARGET_NAME${WRAPPER_SUFFIX:-}" + ;; + *) + echo "Error: Installing ${TARGET_NAME} of type ${PRODUCT_TYPE} is unsupported" >&2 + exit 1 + ;; +esac +output="$TARGET_BUILD_DIR/$FULL_PRODUCT_NAME" + +mkdir -p "$(dirname "$output")" + +if [[ -d $input ]]; then + # Copy bundle contents, into the destination bundle. + # This avoids self-nesting, like: Foo.app/Foo.app + input+="/" +fi + + +rsync \ + --recursive --chmod=u+w --delete \ + "$input" "$output" > $diagnostics_dir/rsync-stdout-$date_suffix.log 2> $diagnostics_dir/rsync-stderr-$date_suffix.log + + +# Part of the build intermediary output will be swiftmodule files +# which XCode will use for indexing. Let's keep those. +$BAZEL_INSTALLERS_DIR/swiftmodules.sh > $diagnostics_dir/swiftmodules-stdout-$date_suffix.log 2> $diagnostics_dir/swiftmodules-stderr-$date_suffix.log & +$BAZEL_INSTALLERS_DIR/indexstores.sh > $diagnostics_dir/indexstores-stdout-$date_suffix.log 2> $diagnostics_dir/indexstores-stderr-$date_suffix.log & +$BAZEL_INSTALLERS_DIR/lldb-settings.sh > $diagnostics_dir/lldb-stdout-$date_suffix.log 2> $diagnostics_dir/lldb-stderr-$date_suffix.log & + + diff --git a/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/installer b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/installer new file mode 100755 index 000000000..5f5e1f43a --- /dev/null +++ b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/installer @@ -0,0 +1,57 @@ +#!/bin/bash + +# Install the runnable products so that Xcode can run it. This includes `.app`s, +# `.xctest`s, and also command line binaries. + +# TODO: Lyft uses this script, because Xcode calls `ditto` on the `.swiftmodule`/`.swiftdoc` files of the top-level +# target. +# "$SRCROOT"/bazel/installers/xcode-artifacts.sh + +set -eux + + +diagnostics_dir="$TARGET_BUILD_DIR/../../../bazel-xcode-diagnostics/" +mkdir -p $diagnostics_dir + +# Delete all logfiles that are older than 7 days +find $diagnostics_dir -type f -atime +7d -delete +date_suffix="$(date +%Y%m%d.%H%M%S%L)" + +case ${PRODUCT_TYPE} in + com.apple.product-type.framework) + input="bazel-bin/$BAZEL_BIN_SUBDIR/${TARGET_NAME}/${FULL_PRODUCT_NAME}" + ;; + com.apple.product-type.bundle.unit-test) + input="bazel-bin/$BAZEL_BIN_SUBDIR/$TARGET_NAME.__internal__.__test_bundle_archive-root/$TARGET_NAME${WRAPPER_SUFFIX:-}" + ;; + com.apple.product-type.application) + input="bazel-bin/$BAZEL_BIN_SUBDIR/${TARGET_NAME}_archive-root/Payload/$TARGET_NAME${WRAPPER_SUFFIX:-}" + ;; + *) + echo "Error: Installing ${TARGET_NAME} of type ${PRODUCT_TYPE} is unsupported" >&2 + exit 1 + ;; +esac +output="$TARGET_BUILD_DIR/$FULL_PRODUCT_NAME" + +mkdir -p "$(dirname "$output")" + +if [[ -d $input ]]; then + # Copy bundle contents, into the destination bundle. + # This avoids self-nesting, like: Foo.app/Foo.app + input+="/" +fi + + +rsync \ + --recursive --chmod=u+w --delete \ + "$input" "$output" > $diagnostics_dir/rsync-stdout-$date_suffix.log 2> $diagnostics_dir/rsync-stderr-$date_suffix.log + + +# Part of the build intermediary output will be swiftmodule files +# which XCode will use for indexing. Let's keep those. +$BAZEL_INSTALLERS_DIR/swiftmodules.sh > $diagnostics_dir/swiftmodules-stdout-$date_suffix.log 2> $diagnostics_dir/swiftmodules-stderr-$date_suffix.log & +$BAZEL_INSTALLERS_DIR/indexstores.sh > $diagnostics_dir/indexstores-stdout-$date_suffix.log 2> $diagnostics_dir/indexstores-stderr-$date_suffix.log & +$BAZEL_INSTALLERS_DIR/lldb-settings.sh > $diagnostics_dir/lldb-stdout-$date_suffix.log 2> $diagnostics_dir/lldb-stderr-$date_suffix.log & + + diff --git a/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/lldb-settings.sh b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/lldb-settings.sh new file mode 100755 index 000000000..1039f3f17 --- /dev/null +++ b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/lldb-settings.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -euo pipefail + + +# Bazel uses `-debug-prefix-map` to strip the bazel build directory from the +# paths embedded in debug info. This means the debug info contains _project +# relative_ paths instead of Bazel absolute paths. +# +# However, Xcode sets breakpoints via _project absolute_ paths, which are not +# the paths in the debug info. This lldb setting ensures that _project relative_ +# paths are remapped to _project absolute_ paths. +# +# NOTE: In order to use this, add this line to `~/.lldbinit`: +# +# command source ~/.lldbinit-source-map +cat <<-END > ~/.lldbinit-source-map +settings set target.source-map ./ "$SRCROOT/" +END diff --git a/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/swiftmodules.sh b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/swiftmodules.sh new file mode 100755 index 000000000..0bb695905 --- /dev/null +++ b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/bazelinstallers/swiftmodules.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -euo pipefail + +# Copy Bazel build `.swiftmodule` files to `DerivedData`. This is used by Xcode +# and its indexing. +find "$BAZEL_WORKSPACE_ROOT/bazel-out"/*/bin/ \ + -name "*.swiftmodule" \ + -not -path "*/_swift_module_cache/*" \ + -print0 \ + | xargs -0 "$BAZEL_INSTALLERS_DIR/_swiftmodule.sh" diff --git a/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/project.pbxproj b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/project.pbxproj index 9c6e58543..e1d73237c 100755 --- a/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/project.pbxproj +++ b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/project.pbxproj @@ -272,6 +272,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = /tests/macos/xcodeproj; + CLANG_ENABLE_MODULES = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; MACH_O_TYPE = "$(inherited)"; PRODUCT_NAME = "Single-Application-RunnableTestSuite"; @@ -284,6 +285,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = /tests/macos/xcodeproj; + CLANG_ENABLE_MODULES = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; MACH_O_TYPE = "$(inherited)"; PRODUCT_NAME = "Single-Application-UnitTests"; @@ -296,7 +298,8 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BUILD_EXEC = "$BAZEL_STUBS_DIR/build-wrapper"; - BAZEL_INSTALLER = $BAZEL_STUBS_DIR/tools/xcodeproj_shims/installer; + BAZEL_INSTALLER = $BAZEL_INSTALLERS_DIR/installer; + BAZEL_INSTALLERS_DIR = $PROJECT_FILE_PATH/bazelinstallers; BAZEL_OUTPUT_PROCESSOR = "$BAZEL_STUBS_DIR/output-processor.rb"; BAZEL_PATH = bazelisk; BAZEL_STUBS_DIR = $PROJECT_FILE_PATH/bazelstubs; @@ -319,6 +322,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = /rules/test_host_app; + CLANG_ENABLE_MODULES = YES; INFOPLIST_FILE = "$BAZEL_STUBS_DIR/Info-stub.plist"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACH_O_TYPE = "$(inherited)"; @@ -332,6 +336,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = /rules/test_host_app; + CLANG_ENABLE_MODULES = YES; INFOPLIST_FILE = "$BAZEL_STUBS_DIR/Info-stub.plist"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACH_O_TYPE = "$(inherited)"; @@ -345,6 +350,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = /tests/macos/xcodeproj; + CLANG_ENABLE_MODULES = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; MACH_O_TYPE = "$(inherited)"; PRODUCT_NAME = "Single-Application-RunnableTestSuite"; @@ -357,7 +363,8 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BUILD_EXEC = "$BAZEL_STUBS_DIR/build-wrapper"; - BAZEL_INSTALLER = $BAZEL_STUBS_DIR/tools/xcodeproj_shims/installer; + BAZEL_INSTALLER = $BAZEL_INSTALLERS_DIR/installer; + BAZEL_INSTALLERS_DIR = $PROJECT_FILE_PATH/bazelinstallers; BAZEL_OUTPUT_PROCESSOR = "$BAZEL_STUBS_DIR/output-processor.rb"; BAZEL_PATH = bazelisk; BAZEL_STUBS_DIR = $PROJECT_FILE_PATH/bazelstubs; @@ -380,6 +387,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = /tests/macos/xcodeproj; + CLANG_ENABLE_MODULES = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; MACH_O_TYPE = "$(inherited)"; PRODUCT_NAME = "Single-Application-UnitTests"; diff --git a/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003..000000000 --- a/tests/macos/xcodeproj/Single-Application-Project-DirectTargetsOnly.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/_indexstore.sh b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/_indexstore.sh new file mode 100755 index 000000000..36fe20ad3 --- /dev/null +++ b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/_indexstore.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +set -euo pipefail + +# Import Bazel built indexstores into Xcode. See https://github.com/lyft/index-import +# +# This makes use of a number of Xcode's provided environment variables. These +# file remappings are not specific to this project, the apply to all projects +# built with Bazel and rules_swift. + +# Example: /private/var/tmp/_bazel_//execroot/ +readonly bazel_root="^/private/var/tmp/_bazel_.+?/.+?/execroot/[^/]+" +readonly bazel_bin="^(?:$bazel_root/)?bazel-out/.+?/bin" + +# Object file paths are fundamental to how Xcode loads from the indexstore. If +# the `OutputFile` does not match what Xcode looks for, then those parts of the +# indexstore will not be found and used. +readonly bazel_swift_object="$bazel_bin/.*/(.+?)(?:_swift)?_objs/.*/(.+?)[.]swift[.]o$" +readonly bazel_objc_object="$bazel_bin/.*/_objs/(?:arc/|non_arc/)?(.+?)-(?:objc|cpp)/(.+?)[.]o$" +readonly xcode_object="$CONFIGURATION_TEMP_DIR/\$1.build/Objects-normal/$ARCHS/\$2.o" + +# Bazel built `.swiftmodule` files are copied to `DerivedData`. Since modules +# are referenced by indexstores, their paths are remapped. +readonly bazel_module="$bazel_bin/.*/(.+?)[.]swiftmodule$" +readonly xcode_module="$BUILT_PRODUCTS_DIR/\$1.swiftmodule/$ARCHS.swiftmodule" + +# External dependencies are available via the `bazel-` symlink. +# This remapping, in combination with `xcode-index-preferences.json`, enables +# index features for external dependencies, such as jump-to-definition. +readonly bazel_external="$bazel_root/external" +readonly xcode_external="$BAZEL_WORKSPACE_ROOT/bazel-$(basename "$SRCROOT")/external" + + +$BAZEL_INSTALLERS_DIR/index-import \ + -remap "$bazel_module=$xcode_module" \ + -remap "$bazel_swift_object=$xcode_object" \ + -remap "$bazel_objc_object=$xcode_object" \ + -remap "$bazel_external=$xcode_external" \ + -remap "$bazel_root=$BAZEL_WORKSPACE_ROOT" \ + -remap "^([^//])=$BAZEL_WORKSPACE_ROOT/\$1" \ + "$@" \ + "$BUILD_DIR"/../../Index/DataStore diff --git a/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/_swiftmodule.sh b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/_swiftmodule.sh new file mode 100755 index 000000000..c974cfb3e --- /dev/null +++ b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/_swiftmodule.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -euo pipefail + +for module in "$@"; do + doc="${module%.swiftmodule}.swiftdoc" + module_name=$(basename "$module") + module_bundle="$BUILT_PRODUCTS_DIR/$module_name" + mkdir -p "$module_bundle" + + cp "$module" "$module_bundle/$NATIVE_ARCH_ACTUAL.swiftmodule" + cp "$doc" "$module_bundle/$NATIVE_ARCH_ACTUAL.swiftdoc" + + ios_module_name="$NATIVE_ARCH_ACTUAL-$LLVM_TARGET_TRIPLE_VENDOR-$SWIFT_PLATFORM_TARGET_PREFIX$LLVM_TARGET_TRIPLE_SUFFIX" + cp "$module" "$module_bundle/$ios_module_name.swiftmodule" + cp "$doc" "$module_bundle/$ios_module_name.swiftdoc" + + chmod -R +w "$module_bundle" +done diff --git a/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/indexstores.sh b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/indexstores.sh new file mode 100755 index 000000000..ee2e1871f --- /dev/null +++ b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/indexstores.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -euo pipefail + +# See `_indexstore.sh` for full details. + +# Make sure add these to bazel build target copts for objective-c +find "$BAZEL_WORKSPACE_ROOT/bazel-out"/*/bin/ \ + -type d \ + -name "*.indexstore" \ + -print0 \ + | xargs -0 "$BAZEL_INSTALLERS_DIR/_indexstore.sh" + +echo "Finish remapping index files" \ No newline at end of file diff --git a/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/install.sh b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/install.sh new file mode 100755 index 000000000..5f5e1f43a --- /dev/null +++ b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/install.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Install the runnable products so that Xcode can run it. This includes `.app`s, +# `.xctest`s, and also command line binaries. + +# TODO: Lyft uses this script, because Xcode calls `ditto` on the `.swiftmodule`/`.swiftdoc` files of the top-level +# target. +# "$SRCROOT"/bazel/installers/xcode-artifacts.sh + +set -eux + + +diagnostics_dir="$TARGET_BUILD_DIR/../../../bazel-xcode-diagnostics/" +mkdir -p $diagnostics_dir + +# Delete all logfiles that are older than 7 days +find $diagnostics_dir -type f -atime +7d -delete +date_suffix="$(date +%Y%m%d.%H%M%S%L)" + +case ${PRODUCT_TYPE} in + com.apple.product-type.framework) + input="bazel-bin/$BAZEL_BIN_SUBDIR/${TARGET_NAME}/${FULL_PRODUCT_NAME}" + ;; + com.apple.product-type.bundle.unit-test) + input="bazel-bin/$BAZEL_BIN_SUBDIR/$TARGET_NAME.__internal__.__test_bundle_archive-root/$TARGET_NAME${WRAPPER_SUFFIX:-}" + ;; + com.apple.product-type.application) + input="bazel-bin/$BAZEL_BIN_SUBDIR/${TARGET_NAME}_archive-root/Payload/$TARGET_NAME${WRAPPER_SUFFIX:-}" + ;; + *) + echo "Error: Installing ${TARGET_NAME} of type ${PRODUCT_TYPE} is unsupported" >&2 + exit 1 + ;; +esac +output="$TARGET_BUILD_DIR/$FULL_PRODUCT_NAME" + +mkdir -p "$(dirname "$output")" + +if [[ -d $input ]]; then + # Copy bundle contents, into the destination bundle. + # This avoids self-nesting, like: Foo.app/Foo.app + input+="/" +fi + + +rsync \ + --recursive --chmod=u+w --delete \ + "$input" "$output" > $diagnostics_dir/rsync-stdout-$date_suffix.log 2> $diagnostics_dir/rsync-stderr-$date_suffix.log + + +# Part of the build intermediary output will be swiftmodule files +# which XCode will use for indexing. Let's keep those. +$BAZEL_INSTALLERS_DIR/swiftmodules.sh > $diagnostics_dir/swiftmodules-stdout-$date_suffix.log 2> $diagnostics_dir/swiftmodules-stderr-$date_suffix.log & +$BAZEL_INSTALLERS_DIR/indexstores.sh > $diagnostics_dir/indexstores-stdout-$date_suffix.log 2> $diagnostics_dir/indexstores-stderr-$date_suffix.log & +$BAZEL_INSTALLERS_DIR/lldb-settings.sh > $diagnostics_dir/lldb-stdout-$date_suffix.log 2> $diagnostics_dir/lldb-stderr-$date_suffix.log & + + diff --git a/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/installer b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/installer new file mode 100755 index 000000000..5f5e1f43a --- /dev/null +++ b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/installer @@ -0,0 +1,57 @@ +#!/bin/bash + +# Install the runnable products so that Xcode can run it. This includes `.app`s, +# `.xctest`s, and also command line binaries. + +# TODO: Lyft uses this script, because Xcode calls `ditto` on the `.swiftmodule`/`.swiftdoc` files of the top-level +# target. +# "$SRCROOT"/bazel/installers/xcode-artifacts.sh + +set -eux + + +diagnostics_dir="$TARGET_BUILD_DIR/../../../bazel-xcode-diagnostics/" +mkdir -p $diagnostics_dir + +# Delete all logfiles that are older than 7 days +find $diagnostics_dir -type f -atime +7d -delete +date_suffix="$(date +%Y%m%d.%H%M%S%L)" + +case ${PRODUCT_TYPE} in + com.apple.product-type.framework) + input="bazel-bin/$BAZEL_BIN_SUBDIR/${TARGET_NAME}/${FULL_PRODUCT_NAME}" + ;; + com.apple.product-type.bundle.unit-test) + input="bazel-bin/$BAZEL_BIN_SUBDIR/$TARGET_NAME.__internal__.__test_bundle_archive-root/$TARGET_NAME${WRAPPER_SUFFIX:-}" + ;; + com.apple.product-type.application) + input="bazel-bin/$BAZEL_BIN_SUBDIR/${TARGET_NAME}_archive-root/Payload/$TARGET_NAME${WRAPPER_SUFFIX:-}" + ;; + *) + echo "Error: Installing ${TARGET_NAME} of type ${PRODUCT_TYPE} is unsupported" >&2 + exit 1 + ;; +esac +output="$TARGET_BUILD_DIR/$FULL_PRODUCT_NAME" + +mkdir -p "$(dirname "$output")" + +if [[ -d $input ]]; then + # Copy bundle contents, into the destination bundle. + # This avoids self-nesting, like: Foo.app/Foo.app + input+="/" +fi + + +rsync \ + --recursive --chmod=u+w --delete \ + "$input" "$output" > $diagnostics_dir/rsync-stdout-$date_suffix.log 2> $diagnostics_dir/rsync-stderr-$date_suffix.log + + +# Part of the build intermediary output will be swiftmodule files +# which XCode will use for indexing. Let's keep those. +$BAZEL_INSTALLERS_DIR/swiftmodules.sh > $diagnostics_dir/swiftmodules-stdout-$date_suffix.log 2> $diagnostics_dir/swiftmodules-stderr-$date_suffix.log & +$BAZEL_INSTALLERS_DIR/indexstores.sh > $diagnostics_dir/indexstores-stdout-$date_suffix.log 2> $diagnostics_dir/indexstores-stderr-$date_suffix.log & +$BAZEL_INSTALLERS_DIR/lldb-settings.sh > $diagnostics_dir/lldb-stdout-$date_suffix.log 2> $diagnostics_dir/lldb-stderr-$date_suffix.log & + + diff --git a/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/lldb-settings.sh b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/lldb-settings.sh new file mode 100755 index 000000000..1039f3f17 --- /dev/null +++ b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/lldb-settings.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -euo pipefail + + +# Bazel uses `-debug-prefix-map` to strip the bazel build directory from the +# paths embedded in debug info. This means the debug info contains _project +# relative_ paths instead of Bazel absolute paths. +# +# However, Xcode sets breakpoints via _project absolute_ paths, which are not +# the paths in the debug info. This lldb setting ensures that _project relative_ +# paths are remapped to _project absolute_ paths. +# +# NOTE: In order to use this, add this line to `~/.lldbinit`: +# +# command source ~/.lldbinit-source-map +cat <<-END > ~/.lldbinit-source-map +settings set target.source-map ./ "$SRCROOT/" +END diff --git a/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/swiftmodules.sh b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/swiftmodules.sh new file mode 100755 index 000000000..0bb695905 --- /dev/null +++ b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/bazelinstallers/swiftmodules.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -euo pipefail + +# Copy Bazel build `.swiftmodule` files to `DerivedData`. This is used by Xcode +# and its indexing. +find "$BAZEL_WORKSPACE_ROOT/bazel-out"/*/bin/ \ + -name "*.swiftmodule" \ + -not -path "*/_swift_module_cache/*" \ + -print0 \ + | xargs -0 "$BAZEL_INSTALLERS_DIR/_swiftmodule.sh" diff --git a/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/project.pbxproj b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/project.pbxproj index ecc93c15c..659107ad1 100755 --- a/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/project.pbxproj +++ b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/project.pbxproj @@ -378,6 +378,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = "/tests/ios/unit-test/test-imports-app"; + CLANG_ENABLE_MODULES = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACH_O_TYPE = "$(inherited)"; PRODUCT_NAME = "TestImports-Unit-Tests"; @@ -391,6 +392,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = "/tests/ios/unit-test/test-imports-app"; + CLANG_ENABLE_MODULES = YES; INFOPLIST_FILE = "$BAZEL_STUBS_DIR/Info-stub.plist"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACH_O_TYPE = "$(inherited)"; @@ -404,6 +406,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = "/tests/ios/unit-test/test-imports-app"; + CLANG_ENABLE_MODULES = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACH_O_TYPE = "$(inherited)"; PRODUCT_NAME = "TestImports-Unit-Tests"; @@ -417,6 +420,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = "/tests/ios/unit-test"; + CLANG_ENABLE_MODULES = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.0; MACH_O_TYPE = "$(inherited)"; PRODUCT_NAME = DefaultHosted; @@ -430,6 +434,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = "/tests/ios/unit-test/test-imports-app"; + CLANG_ENABLE_MODULES = YES; INFOPLIST_FILE = "$BAZEL_STUBS_DIR/Info-stub.plist"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACH_O_TYPE = "$(inherited)"; @@ -443,7 +448,8 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BUILD_EXEC = "$BAZEL_STUBS_DIR/build-wrapper"; - BAZEL_INSTALLER = $BAZEL_STUBS_DIR/tools/xcodeproj_shims/installer; + BAZEL_INSTALLER = $BAZEL_INSTALLERS_DIR/installer; + BAZEL_INSTALLERS_DIR = $PROJECT_FILE_PATH/bazelinstallers; BAZEL_OUTPUT_PROCESSOR = "$BAZEL_STUBS_DIR/output-processor.rb"; BAZEL_PATH = bazelisk; BAZEL_STUBS_DIR = $PROJECT_FILE_PATH/bazelstubs; @@ -466,6 +472,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = /rules/test_host_app; + CLANG_ENABLE_MODULES = YES; INFOPLIST_FILE = "$BAZEL_STUBS_DIR/Info-stub.plist"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; MACH_O_TYPE = "$(inherited)"; @@ -479,6 +486,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = /rules/test_host_app; + CLANG_ENABLE_MODULES = YES; INFOPLIST_FILE = "$BAZEL_STUBS_DIR/Info-stub.plist"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; MACH_O_TYPE = "$(inherited)"; @@ -492,7 +500,8 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BUILD_EXEC = "$BAZEL_STUBS_DIR/build-wrapper"; - BAZEL_INSTALLER = $BAZEL_STUBS_DIR/tools/xcodeproj_shims/installer; + BAZEL_INSTALLER = $BAZEL_INSTALLERS_DIR/installer; + BAZEL_INSTALLERS_DIR = $PROJECT_FILE_PATH/bazelinstallers; BAZEL_OUTPUT_PROCESSOR = "$BAZEL_STUBS_DIR/output-processor.rb"; BAZEL_PATH = bazelisk; BAZEL_STUBS_DIR = $PROJECT_FILE_PATH/bazelstubs; @@ -515,6 +524,7 @@ isa = XCBuildConfiguration; buildSettings = { BAZEL_BIN_SUBDIR = "/tests/ios/unit-test"; + CLANG_ENABLE_MODULES = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.0; MACH_O_TYPE = "$(inherited)"; PRODUCT_NAME = DefaultHosted; diff --git a/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003..000000000 --- a/tests/macos/xcodeproj/Test-Target-With-Test-Host-Project.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/tools/xcodeproj_shims/BUILD.bazel b/tools/xcodeproj_shims/BUILD.bazel index 28b2f64f3..eacacddee 100644 --- a/tools/xcodeproj_shims/BUILD.bazel +++ b/tools/xcodeproj_shims/BUILD.bazel @@ -26,10 +26,16 @@ py_binary( visibility = STUB_VISIBILITY, ) +filegroup( + name = "installer_runfiles", + srcs = glob(["installers/*"]), + visibility = STUB_VISIBILITY, +) + sh_binary( name = "installer", srcs = ["install.sh"], - data = glob(["installers/*.sh"]), + data = [":installer_runfiles"], visibility = STUB_VISIBILITY, ) diff --git a/tools/xcodeproj_shims/install.sh b/tools/xcodeproj_shims/install.sh index 757ce4c70..5f5e1f43a 100755 --- a/tools/xcodeproj_shims/install.sh +++ b/tools/xcodeproj_shims/install.sh @@ -10,6 +10,12 @@ set -eux +diagnostics_dir="$TARGET_BUILD_DIR/../../../bazel-xcode-diagnostics/" +mkdir -p $diagnostics_dir + +# Delete all logfiles that are older than 7 days +find $diagnostics_dir -type f -atime +7d -delete +date_suffix="$(date +%Y%m%d.%H%M%S%L)" case ${PRODUCT_TYPE} in com.apple.product-type.framework) @@ -27,6 +33,7 @@ case ${PRODUCT_TYPE} in ;; esac output="$TARGET_BUILD_DIR/$FULL_PRODUCT_NAME" + mkdir -p "$(dirname "$output")" if [[ -d $input ]]; then @@ -35,19 +42,16 @@ if [[ -d $input ]]; then input+="/" fi -rsync --quiet \ + +rsync \ --recursive --chmod=u+w --delete \ - "$input" "$output" + "$input" "$output" > $diagnostics_dir/rsync-stdout-$date_suffix.log 2> $diagnostics_dir/rsync-stderr-$date_suffix.log # Part of the build intermediary output will be swiftmodule files # which XCode will use for indexing. Let's keep those. -"$BAZEL_WORKSPACE_ROOT"/tools/bazel-xcodeproj/installers/swiftmodules.sh >/dev/null 2>&1 & - -# This is more complicated, requires installing lyft/index-import, revisit. -# "$SRCROOT"/bazel/installers/indexstores.sh >/dev/null 2>&1 & - -"$BAZEL_WORKSPACE_ROOT"/tools/bazel-xcodeproj/installers/lldb-settings.sh >/dev/null 2>&1 & +$BAZEL_INSTALLERS_DIR/swiftmodules.sh > $diagnostics_dir/swiftmodules-stdout-$date_suffix.log 2> $diagnostics_dir/swiftmodules-stderr-$date_suffix.log & +$BAZEL_INSTALLERS_DIR/indexstores.sh > $diagnostics_dir/indexstores-stdout-$date_suffix.log 2> $diagnostics_dir/indexstores-stderr-$date_suffix.log & +$BAZEL_INSTALLERS_DIR/lldb-settings.sh > $diagnostics_dir/lldb-stdout-$date_suffix.log 2> $diagnostics_dir/lldb-stderr-$date_suffix.log & -wait diff --git a/tools/xcodeproj_shims/installers/_indexstore.sh b/tools/xcodeproj_shims/installers/_indexstore.sh new file mode 100755 index 000000000..36fe20ad3 --- /dev/null +++ b/tools/xcodeproj_shims/installers/_indexstore.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +set -euo pipefail + +# Import Bazel built indexstores into Xcode. See https://github.com/lyft/index-import +# +# This makes use of a number of Xcode's provided environment variables. These +# file remappings are not specific to this project, the apply to all projects +# built with Bazel and rules_swift. + +# Example: /private/var/tmp/_bazel_//execroot/ +readonly bazel_root="^/private/var/tmp/_bazel_.+?/.+?/execroot/[^/]+" +readonly bazel_bin="^(?:$bazel_root/)?bazel-out/.+?/bin" + +# Object file paths are fundamental to how Xcode loads from the indexstore. If +# the `OutputFile` does not match what Xcode looks for, then those parts of the +# indexstore will not be found and used. +readonly bazel_swift_object="$bazel_bin/.*/(.+?)(?:_swift)?_objs/.*/(.+?)[.]swift[.]o$" +readonly bazel_objc_object="$bazel_bin/.*/_objs/(?:arc/|non_arc/)?(.+?)-(?:objc|cpp)/(.+?)[.]o$" +readonly xcode_object="$CONFIGURATION_TEMP_DIR/\$1.build/Objects-normal/$ARCHS/\$2.o" + +# Bazel built `.swiftmodule` files are copied to `DerivedData`. Since modules +# are referenced by indexstores, their paths are remapped. +readonly bazel_module="$bazel_bin/.*/(.+?)[.]swiftmodule$" +readonly xcode_module="$BUILT_PRODUCTS_DIR/\$1.swiftmodule/$ARCHS.swiftmodule" + +# External dependencies are available via the `bazel-` symlink. +# This remapping, in combination with `xcode-index-preferences.json`, enables +# index features for external dependencies, such as jump-to-definition. +readonly bazel_external="$bazel_root/external" +readonly xcode_external="$BAZEL_WORKSPACE_ROOT/bazel-$(basename "$SRCROOT")/external" + + +$BAZEL_INSTALLERS_DIR/index-import \ + -remap "$bazel_module=$xcode_module" \ + -remap "$bazel_swift_object=$xcode_object" \ + -remap "$bazel_objc_object=$xcode_object" \ + -remap "$bazel_external=$xcode_external" \ + -remap "$bazel_root=$BAZEL_WORKSPACE_ROOT" \ + -remap "^([^//])=$BAZEL_WORKSPACE_ROOT/\$1" \ + "$@" \ + "$BUILD_DIR"/../../Index/DataStore diff --git a/tools/xcodeproj_shims/installers/_swiftmodule.sh b/tools/xcodeproj_shims/installers/_swiftmodule.sh index 06d6b6d7d..c974cfb3e 100755 --- a/tools/xcodeproj_shims/installers/_swiftmodule.sh +++ b/tools/xcodeproj_shims/installers/_swiftmodule.sh @@ -16,4 +16,4 @@ for module in "$@"; do cp "$doc" "$module_bundle/$ios_module_name.swiftdoc" chmod -R +w "$module_bundle" -done \ No newline at end of file +done diff --git a/tools/xcodeproj_shims/installers/indexstores.sh b/tools/xcodeproj_shims/installers/indexstores.sh new file mode 100755 index 000000000..ee2e1871f --- /dev/null +++ b/tools/xcodeproj_shims/installers/indexstores.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -euo pipefail + +# See `_indexstore.sh` for full details. + +# Make sure add these to bazel build target copts for objective-c +find "$BAZEL_WORKSPACE_ROOT/bazel-out"/*/bin/ \ + -type d \ + -name "*.indexstore" \ + -print0 \ + | xargs -0 "$BAZEL_INSTALLERS_DIR/_indexstore.sh" + +echo "Finish remapping index files" \ No newline at end of file diff --git a/tools/xcodeproj_shims/installers/swiftmodules.sh b/tools/xcodeproj_shims/installers/swiftmodules.sh index c2d0bc784..0bb695905 100755 --- a/tools/xcodeproj_shims/installers/swiftmodules.sh +++ b/tools/xcodeproj_shims/installers/swiftmodules.sh @@ -4,13 +4,8 @@ set -euo pipefail # Copy Bazel build `.swiftmodule` files to `DerivedData`. This is used by Xcode # and its indexing. - -# TODO: what should BAZEL_BIN be? -# something like this: -# readonly config=macos-x86_64-min10.13-applebin_macos-darwin_x86_64-dbg -# export BAZEL_BIN=bazel-out/$config/bin -find "$BAZEL_BIN" \ - -name "*.swiftmodule" \ +find "$BAZEL_WORKSPACE_ROOT/bazel-out"/*/bin/ \ + -name "*.swiftmodule" \ -not -path "*/_swift_module_cache/*" \ -print0 \ - | xargs -0 "$BAZEL_WORKSPACE_ROOT/tools/bazel-xcodeproj/installers/_swiftmodule.sh" \ No newline at end of file + | xargs -0 "$BAZEL_INSTALLERS_DIR/_swiftmodule.sh" diff --git a/tools/xcodeproj_shims/xcodeproj-installer.sh b/tools/xcodeproj_shims/xcodeproj-installer.sh index ab2e1d267..5f54cda6c 100755 --- a/tools/xcodeproj_shims/xcodeproj-installer.sh +++ b/tools/xcodeproj_shims/xcodeproj-installer.sh @@ -9,14 +9,19 @@ readonly tmp_dest=$(mktemp -d)/$(project_full_path)/ readonly stubs_dir="${dest}/bazelstubs" mkdir -p "${stubs_dir}" -readonly installer="$(installer_short_path)" +readonly installers_dir="${dest}/bazelinstallers" +mkdir -p "${installers_dir}" + +for INSTALLER_PATH in $(installer_runfile_short_paths) +do + cp "$INSTALLER_PATH" "${installers_dir}/" +done +cp "$(installer_short_path)" "${installers_dir}/" -installer_dir=$(dirname "${stubs_dir}/${installer}") -mkdir -p "${installer_dir}" -cp "${installer}" "${stubs_dir}/${installer}" cp "$(clang_stub_short_path)" "${stubs_dir}/clang-stub" cp "$(clang_stub_ld_path)" "${stubs_dir}/ld-stub" cp "$(clang_stub_swiftc_path)" "${stubs_dir}/swiftc-stub" +cp "$(index_import_short_path)" "${installers_dir}/index-import" cp "$(print_json_leaf_nodes_path)" "${stubs_dir}/print_json_leaf_nodes" cp "$(infoplist_stub)" "${stubs_dir}/Info-stub.plist" cp "$(build_wrapper_path)" "${stubs_dir}/build-wrapper" @@ -32,14 +37,9 @@ sed -i.bak -E -e 's|([ "])../../../|\1|g' "${tmp_dest}/project.pbxproj" rm "${tmp_dest}/project.pbxproj.bak" rsync --recursive --quiet --copy-links "${tmp_dest}" "${dest}" - # The new build system leaves a subdirectory called XCBuildData in the DerivedData directory which causes incremental build and test attempts to fail at launch time. # The error message says "Cannot attach to pid." This error seems to happen in the Xcode IDE, not when the project is tested from the xcodebuild command. # Therefore, we force xcode to use the legacy build system by adding the contents of WorkspaceSettings.xcsettings to the generated project. mkdir -p "$dest/project.xcworkspace/xcshareddata/" cp "$(workspacesettings_xcsettings_short_path)" "$dest/project.xcworkspace/xcshareddata/" - - -# -