diff --git a/README.md b/README.md index 4dcab4456..e18f2329b 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,9 @@ encountered first on your `PATH`. To make cacheable builds work correctly with debugging see [this doc](doc/debuggable_remote_swift.md). +For explicit module builds, see +[debugging with explicit modules](doc/explicit_modules.md#debugging). + ## Swift Package Manager Support To download, build, and reference external Swift packages as Bazel diff --git a/doc/explicit_modules.md b/doc/explicit_modules.md index 70a370e5b..ddd63e309 100644 --- a/doc/explicit_modules.md +++ b/doc/explicit_modules.md @@ -40,6 +40,22 @@ would still be embedded in the swiftmodule files. This means debugging in `lldb` with explicit modules would not work with cached swiftmodules and is therefore disabled. +### Module tracking in debug info + +With Swift 6.4 / Xcode 27 and newer, `swift.debug_module_path` is enabled by default +for Xcode toolchains. +In this mode the compiler writes the `.swiftmodule` path into each object file's +debug information using `-debug-module-path`. Each explicit module also +records its dependencies. LLDB uses these paths to find the module files +it needs for expression evaluation, replacing the previous `-add_ast_path` +or module-wrapping mechanism. See +[Module Tracking in Swift Debug Info](https://www.swift.org/blog/module-tracking-in-debug-info/) +for more details. + +Expression evaluation still requires the `.swiftmodule` and `.pcm` +files at their original or remapped locations. Your build or debugger +integration must make these files available locally. + ## Using explicit dependencies By default we implicitly add all possible precompiled modules to the diff --git a/swift/internal/debugging.bzl b/swift/internal/debugging.bzl index 0a59391c2..63d7bc159 100644 --- a/swift/internal/debugging.bzl +++ b/swift/internal/debugging.bzl @@ -25,8 +25,12 @@ load( load( ":feature_names.bzl", "SWIFT_FEATURE_DBG", + "SWIFT_FEATURE_DEBUG_MODULE_PATH", "SWIFT_FEATURE_FASTBUILD", + "SWIFT_FEATURE_FULL_DEBUG_INFO", "SWIFT_FEATURE_NO_EMBED_DEBUG_MODULE", + "SWIFT_FEATURE_USE_C_MODULES", + "SWIFT_FEATURE_USE_EXPLICIT_SWIFT_MODULE_MAP", ) load(":features.bzl", "is_feature_enabled") @@ -123,9 +127,36 @@ def should_embed_swiftmodule_for_debugging( not is_feature_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_NO_EMBED_DEBUG_MODULE, - ) + ) and + not uses_precise_debug_module_tracking(feature_configuration) ) +def uses_precise_debug_module_tracking(feature_configuration): + """Returns whether precise module tracking is enabled for this build. + + Args: + feature_configuration: The Swift feature configuration. + + Returns: + True for builds with debug info and all required module features enabled. + """ + + has_debug_info = _is_debugging(feature_configuration) or is_feature_enabled( + feature_configuration = feature_configuration, + feature_name = SWIFT_FEATURE_FULL_DEBUG_INFO, + ) + return has_debug_info and all([ + is_feature_enabled( + feature_configuration = feature_configuration, + feature_name = feature_name, + ) + for feature_name in [ + SWIFT_FEATURE_DEBUG_MODULE_PATH, + SWIFT_FEATURE_USE_C_MODULES, + SWIFT_FEATURE_USE_EXPLICIT_SWIFT_MODULE_MAP, + ] + ]) + def _is_debugging(feature_configuration): """Returns `True` if the current compilation mode produces debug info. diff --git a/swift/internal/feature_names.bzl b/swift/internal/feature_names.bzl index bf1aa1bee..550624037 100644 --- a/swift/internal/feature_names.bzl +++ b/swift/internal/feature_names.bzl @@ -224,6 +224,14 @@ SWIFT_FEATURE_ADD_DEFAULT_PRECOMPILED_MODULES = "swift.add_default_precompiled_m # using a JSON file instead of `-I` search paths. SWIFT_FEATURE_USE_EXPLICIT_SWIFT_MODULE_MAP = "swift.use_explicit_swift_module_map" +# If enabled together with explicit modules and debug info, object +# compilations record their own `.swiftmodule` path in debug info instead of +# embedding modules at link time. +# https://www.swift.org/blog/module-tracking-in-debug-info/ +# Requires Swift 6.4 or newer for the compiler and debugger support. +# Enabled by default for Xcode 27 and newer. +SWIFT_FEATURE_DEBUG_MODULE_PATH = "swift.debug_module_path" + # If enabled, Swift compilation actions will use the same global Clang module # cache used by Objective-C compilation actions. This can be disabled because # under some circumstances Clang module cache corruption can cause the Swift diff --git a/swift/toolchains/config/compile_config.bzl b/swift/toolchains/config/compile_config.bzl index 374f393aa..a203540b7 100644 --- a/swift/toolchains/config/compile_config.bzl +++ b/swift/toolchains/config/compile_config.bzl @@ -41,6 +41,7 @@ load( "SWIFT_FEATURE_COVERAGE", "SWIFT_FEATURE_COVERAGE_PREFIX_MAP", "SWIFT_FEATURE_DBG", + "SWIFT_FEATURE_DEBUG_MODULE_PATH", "SWIFT_FEATURE_DEBUG_PREFIX_MAP", "SWIFT_FEATURE_DECLARE_SWIFTSOURCEINFO", "SWIFT_FEATURE_DISABLE_AVAILABILITY_CHECKING", @@ -274,6 +275,21 @@ def compile_action_configs( configurators = [_constant_value_extraction_configurator], ), + # Record this object's own module path in debugging configurations. + ActionConfigInfo( + actions = [SWIFT_ACTION_COMPILE], + configurators = [lambda prerequisites, args: args.add( + "-debug-module-path", + prerequisites.swiftmodule_file, + )], + features = [[ + SWIFT_FEATURE_DEBUG_MODULE_PATH, + SWIFT_FEATURE_USE_C_MODULES, + SWIFT_FEATURE_USE_EXPLICIT_SWIFT_MODULE_MAP, + compilation_mode, + ] for compilation_mode in [SWIFT_FEATURE_DBG, SWIFT_FEATURE_FASTBUILD, SWIFT_FEATURE_FULL_DEBUG_INFO]], + ), + # Link Time Optimization (LTO). ActionConfigInfo( actions = all_compile_action_names(), diff --git a/swift/toolchains/xcode_swift_toolchain.bzl b/swift/toolchains/xcode_swift_toolchain.bzl index dadaa09b5..e0039b3e9 100644 --- a/swift/toolchains/xcode_swift_toolchain.bzl +++ b/swift/toolchains/xcode_swift_toolchain.bzl @@ -51,6 +51,7 @@ load( "SWIFT_FEATURE_ADD_DEFAULT_PRECOMPILED_MODULES", "SWIFT_FEATURE_COVERAGE", "SWIFT_FEATURE_COVERAGE_PREFIX_MAP", + "SWIFT_FEATURE_DEBUG_MODULE_PATH", "SWIFT_FEATURE_DEBUG_PREFIX_MAP", "SWIFT_FEATURE_DISABLE_SWIFT_SANDBOX", "SWIFT_FEATURE_FILE_PREFIX_MAP", @@ -864,6 +865,9 @@ def _xcode_swift_toolchain_impl(ctx): if _is_xcode_at_least_version(xcode_config, "26.4"): requested_features.append(SWIFT_FEATURE__SUPPORTS_HERMETIC_SWIFTMODULE) + if _is_xcode_at_least_version(xcode_config, "27.0"): + requested_features.append(SWIFT_FEATURE_DEBUG_MODULE_PATH) + # Xcode toolchains always support DEVELOPER_DIR requested_features.append(SWIFT_FEATURE__SUPPORTS_DEVELOPER_DIR) diff --git a/test/debug_settings_tests.bzl b/test/debug_settings_tests.bzl index c9ccefbef..f806cb3bb 100644 --- a/test/debug_settings_tests.bzl +++ b/test/debug_settings_tests.bzl @@ -14,10 +14,14 @@ """Tests for debugging-related command line flags under various configs.""" +load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") +load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") +load("//swift:providers.bzl", "SwiftInfo") load( "//test/rules:action_command_line_test.bzl", "make_action_command_line_test_rule", ) +load("//test/rules:action_inputs_test.bzl", "make_action_inputs_test_rule") DBG_CONFIG_SETTINGS = { "//command_line_option:compilation_mode": "dbg", @@ -108,6 +112,254 @@ unsupported_developer_dir_xcode_remap_command_line_test = make_action_command_li }, ) +def _debug_module_linking_test_impl(ctx): + env = analysistest.begin(ctx) + target = analysistest.target_under_test(env) + actions = analysistest.target_actions(env) + if ctx.attr.is_binary: + # swift_binary intentionally hides its module from SwiftInfo so that + # dependents cannot import it. Find the declared compilation output. + swiftmodules = [ + output + for action in actions + if action.mnemonic in ["SwiftCompile", "SwiftDeriveFiles"] + for output in action.outputs.to_list() + if output.extension == "swiftmodule" + ] + else: + swiftmodules = [ + module.swift.swiftmodule + for module in target[SwiftInfo].direct_modules + if module.swift and module.swift.swiftmodule + ] + asserts.equals(env, 1, len(swiftmodules), "Expected exactly one Swift module") + if len(swiftmodules) != 1: + return analysistest.end(env) + swiftmodule = swiftmodules[0] + + # Check the actual linker inputs propagated by the library. Darwin uses + # -add_ast_path; other platforms propagate a SwiftModuleWrap output. + if ctx.attr.is_binary: + link_actions = [a for a in actions if a.mnemonic == "CppLink"] + asserts.equals(env, 1, len(link_actions), "Expected exactly one CppLink action") + if len(link_actions) != 1: + return analysistest.end(env) + link_flags = link_actions[0].argv + additional_inputs = link_actions[0].inputs.to_list() + else: + linker_inputs = target[CcInfo].linking_context.linker_inputs.to_list() + link_flags = [flag for inputs in linker_inputs for flag in inputs.user_link_flags] + additional_inputs = [file for inputs in linker_inputs for file in inputs.additional_inputs] + modulewrap_actions = [a for a in actions if a.mnemonic == "SwiftModuleWrap"] + ast_flag = "-Wl,-add_ast_path,{}".format(swiftmodule.path) + if ctx.attr.expect_embedding: + if modulewrap_actions: + asserts.equals(env, 1, len(modulewrap_actions)) + wrapped_modules = modulewrap_actions[0].outputs.to_list() + asserts.equals(env, 1, len(wrapped_modules), "Expected exactly one wrapped module") + if len(wrapped_modules) != 1: + return analysistest.end(env) + wrapped_module = wrapped_modules[0] + asserts.true(env, wrapped_module.path in link_flags) + asserts.true(env, wrapped_module in additional_inputs) + else: + asserts.true(env, ast_flag in link_flags) + asserts.true(env, swiftmodule in additional_inputs) + else: + asserts.equals(env, [], modulewrap_actions) + asserts.false(env, ast_flag in link_flags) + asserts.false(env, swiftmodule in additional_inputs) + asserts.equals(env, [], [ + file.short_path + for file in additional_inputs + if file.extension in ["swiftmodule", "pcm"] or file.basename.endswith(".modulewrap.o") + ], "Debug modules must not be linker inputs") + + return analysistest.end(env) + +_EXPLICIT_DEBUG_MODULE_PATH_FEATURES = [ + "swift.debug_module_path", + "swift.emit_c_module", + "swift.use_c_modules", + "swift.use_explicit_swift_module_map", + "-swift.no_embed_debug_module", +] + +DEBUG_MODULE_PATH_CONFIG_SETTINGS = { + "//command_line_option:compilation_mode": "dbg", + "//command_line_option:features": _EXPLICIT_DEBUG_MODULE_PATH_FEATURES, +} + +debug_module_path_test = make_action_command_line_test_rule( + config_settings = DEBUG_MODULE_PATH_CONFIG_SETTINGS, +) + +debug_module_path_linking_test = analysistest.make( + _debug_module_linking_test_impl, + attrs = { + "expect_embedding": attr.bool(default = True), + "is_binary": attr.bool(default = False), + }, + config_settings = DEBUG_MODULE_PATH_CONFIG_SETTINGS, +) + +DEBUG_MODULE_PATH_DISABLED_CONFIG_SETTINGS = { + "//command_line_option:compilation_mode": "dbg", + "//command_line_option:features": [ + "-swift.debug_module_path", + "swift.emit_c_module", + "swift.use_c_modules", + "swift.use_explicit_swift_module_map", + "-swift.no_embed_debug_module", + ], +} + +debug_module_path_disabled_test = make_action_command_line_test_rule( + config_settings = DEBUG_MODULE_PATH_DISABLED_CONFIG_SETTINGS, +) + +debug_module_path_disabled_linking_test = analysistest.make( + _debug_module_linking_test_impl, + attrs = { + "expect_embedding": attr.bool(default = True), + "is_binary": attr.bool(default = False), + }, + config_settings = DEBUG_MODULE_PATH_DISABLED_CONFIG_SETTINGS, +) + +DEBUG_MODULE_PATH_SWIFT_MAP_ONLY_CONFIG_SETTINGS = { + "//command_line_option:compilation_mode": "dbg", + "//command_line_option:features": [ + "swift.debug_module_path", + "-swift.use_c_modules", + "swift.use_explicit_swift_module_map", + "-swift.no_embed_debug_module", + ], +} + +debug_module_path_swift_map_only_test = make_action_command_line_test_rule( + config_settings = DEBUG_MODULE_PATH_SWIFT_MAP_ONLY_CONFIG_SETTINGS, +) + +debug_module_path_swift_map_only_linking_test = analysistest.make( + _debug_module_linking_test_impl, + attrs = { + "expect_embedding": attr.bool(default = True), + "is_binary": attr.bool(default = False), + }, + config_settings = DEBUG_MODULE_PATH_SWIFT_MAP_ONLY_CONFIG_SETTINGS, +) + +DEBUG_MODULE_PATH_C_MODULES_ONLY_CONFIG_SETTINGS = { + "//command_line_option:compilation_mode": "dbg", + "//command_line_option:features": [ + "swift.debug_module_path", + "swift.emit_c_module", + "swift.use_c_modules", + "-swift.use_explicit_swift_module_map", + "-swift.no_embed_debug_module", + ], +} + +debug_module_path_c_modules_only_test = make_action_command_line_test_rule( + config_settings = DEBUG_MODULE_PATH_C_MODULES_ONLY_CONFIG_SETTINGS, +) + +debug_module_path_c_modules_only_linking_test = analysistest.make( + _debug_module_linking_test_impl, + attrs = { + "expect_embedding": attr.bool(default = True), + "is_binary": attr.bool(default = False), + }, + config_settings = DEBUG_MODULE_PATH_C_MODULES_ONLY_CONFIG_SETTINGS, +) + +DEBUG_MODULE_PATH_SPLIT_CONFIG_SETTINGS = { + "//command_line_option:compilation_mode": "dbg", + "//command_line_option:features": _EXPLICIT_DEBUG_MODULE_PATH_FEATURES + ["swift.split_derived_files_generation"], +} + +debug_module_path_split_test = make_action_command_line_test_rule( + config_settings = DEBUG_MODULE_PATH_SPLIT_CONFIG_SETTINGS, +) + +debug_module_path_split_inputs_test = make_action_inputs_test_rule( + config_settings = DEBUG_MODULE_PATH_SPLIT_CONFIG_SETTINGS, +) + +debug_module_path_split_linking_test = analysistest.make( + _debug_module_linking_test_impl, + attrs = { + "expect_embedding": attr.bool(default = True), + "is_binary": attr.bool(default = False), + }, + config_settings = DEBUG_MODULE_PATH_SPLIT_CONFIG_SETTINGS, +) + +DEBUG_MODULE_PATH_FASTBUILD_CONFIG_SETTINGS = { + "//command_line_option:compilation_mode": "fastbuild", + "//command_line_option:features": _EXPLICIT_DEBUG_MODULE_PATH_FEATURES, +} + +debug_module_path_fastbuild_test = make_action_command_line_test_rule( + config_settings = DEBUG_MODULE_PATH_FASTBUILD_CONFIG_SETTINGS, +) + +DEBUG_MODULE_PATH_OPT_CONFIG_SETTINGS = { + "//command_line_option:compilation_mode": "opt", + "//command_line_option:features": _EXPLICIT_DEBUG_MODULE_PATH_FEATURES, +} + +debug_module_path_opt_test = make_action_command_line_test_rule( + config_settings = DEBUG_MODULE_PATH_OPT_CONFIG_SETTINGS, +) + +debug_module_path_opt_linking_test = analysistest.make( + _debug_module_linking_test_impl, + attrs = { + "expect_embedding": attr.bool(default = True), + "is_binary": attr.bool(default = False), + }, + config_settings = DEBUG_MODULE_PATH_OPT_CONFIG_SETTINGS, +) + +DEBUG_MODULE_PATH_OPT_FULL_DI_CONFIG_SETTINGS = { + "//command_line_option:compilation_mode": "opt", + "//command_line_option:features": _EXPLICIT_DEBUG_MODULE_PATH_FEATURES + ["swift.full_debug_info"], +} + +debug_module_path_opt_full_di_test = make_action_command_line_test_rule( + config_settings = DEBUG_MODULE_PATH_OPT_FULL_DI_CONFIG_SETTINGS, +) + +debug_module_path_opt_full_di_linking_test = analysistest.make( + _debug_module_linking_test_impl, + attrs = { + "expect_embedding": attr.bool(default = True), + "is_binary": attr.bool(default = False), + }, + config_settings = DEBUG_MODULE_PATH_OPT_FULL_DI_CONFIG_SETTINGS, +) + +NO_EMBED_DEBUG_MODULE_CONFIG_SETTINGS = { + "//command_line_option:compilation_mode": "dbg", + "//command_line_option:features": [ + "-swift.debug_module_path", + "-swift.use_c_modules", + "-swift.use_explicit_swift_module_map", + "swift.no_embed_debug_module", + ], +} + +no_embed_debug_module_linking_test = analysistest.make( + _debug_module_linking_test_impl, + attrs = { + "expect_embedding": attr.bool(default = True), + "is_binary": attr.bool(default = False), + }, + config_settings = NO_EMBED_DEBUG_MODULE_CONFIG_SETTINGS, +) + def debug_settings_test_suite(name, tags = []): """Test suite for serializing debugging options. @@ -117,6 +369,173 @@ def debug_settings_test_suite(name, tags = []): """ all_tags = [name] + tags + # Record the module path without passing the module to the linker. + debug_module_path_test( + name = "{}_debug_module_path_explicit_modules".format(name), + expected_argv = [ + "-debug-module-path $(BIN_DIR)/test/fixtures/debug_settings/test_fixtures_debug_settings_simple.swiftmodule", + ], + mnemonic = "SwiftCompile", + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + debug_module_path_linking_test( + name = "{}_debug_module_path_explicit_modules_linking".format(name), + expect_embedding = False, + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + debug_module_path_fastbuild_test( + name = "{}_debug_module_path_fastbuild".format(name), + expected_argv = [ + "-debug-module-path $(BIN_DIR)/test/fixtures/debug_settings/test_fixtures_debug_settings_simple.swiftmodule", + ], + mnemonic = "SwiftCompile", + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + # Optimized builds without debug info do not request module tracking. + debug_module_path_opt_test( + name = "{}_debug_module_path_opt".format(name), + not_expected_argv = [ + "-debug-module-path", + ], + mnemonic = "SwiftCompile", + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + debug_module_path_opt_linking_test( + name = "{}_debug_module_path_opt_binary_linking".format(name), + expect_embedding = False, + is_binary = True, + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:binary", + ) + + # Explicit full debug info enables module tracking even in optimized builds. + debug_module_path_opt_full_di_test( + name = "{}_debug_module_path_opt_full_di".format(name), + expected_argv = [ + "-g", + "-debug-module-path $(BIN_DIR)/test/fixtures/debug_settings/test_fixtures_debug_settings_simple.swiftmodule", + ], + mnemonic = "SwiftCompile", + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + debug_module_path_opt_full_di_linking_test( + name = "{}_debug_module_path_opt_full_di_binary_linking".format(name), + expect_embedding = False, + is_binary = True, + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:module_path_binary", + ) + + # Disabling the feature or either explicit-module requirement retains + # legacy embedding. + debug_module_path_disabled_test( + name = "{}_debug_module_path_disabled".format(name), + not_expected_argv = [ + "-debug-module-path", + ], + mnemonic = "SwiftCompile", + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + debug_module_path_disabled_linking_test( + name = "{}_debug_module_path_disabled_linking".format(name), + expect_embedding = True, + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + debug_module_path_swift_map_only_test( + name = "{}_debug_module_path_swift_map_only".format(name), + not_expected_argv = [ + "-debug-module-path", + ], + mnemonic = "SwiftCompile", + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + debug_module_path_swift_map_only_linking_test( + name = "{}_debug_module_path_swift_map_only_linking".format(name), + expect_embedding = True, + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + debug_module_path_c_modules_only_test( + name = "{}_debug_module_path_c_modules_only".format(name), + not_expected_argv = [ + "-debug-module-path", + ], + mnemonic = "SwiftCompile", + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + debug_module_path_c_modules_only_linking_test( + name = "{}_debug_module_path_c_modules_only_linking".format(name), + expect_embedding = True, + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + no_embed_debug_module_linking_test( + name = "{}_no_embed_debug_module_linking".format(name), + expect_embedding = False, + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + # Split compilation records the path only in the object action, without + # making the module an input to its own compilation. + debug_module_path_split_test( + name = "{}_debug_module_path_dependency".format(name), + expected_argv = [ + "-debug-module-path $(BIN_DIR)/test/fixtures/debug_settings/test_fixtures_debug_settings_module_path_binary.swiftmodule", + ], + mnemonic = "SwiftCompile", + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:module_path_binary", + ) + + debug_module_path_split_inputs_test( + name = "{}_debug_module_path_dependency_inputs".format(name), + not_expected_inputs = [ + "test/fixtures/debug_settings/test_fixtures_debug_settings_module_path_binary.swiftmodule", + ], + mnemonic = "SwiftCompile", + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:module_path_binary", + ) + + debug_module_path_split_test( + name = "{}_debug_module_path_dependency_derive_files".format(name), + not_expected_argv = [ + "-debug-module-path", + ], + mnemonic = "SwiftDeriveFiles", + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:module_path_binary", + ) + + debug_module_path_split_linking_test( + name = "{}_debug_module_path_dependency_linking".format(name), + expect_embedding = False, + is_binary = True, + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:module_path_binary", + ) + # Verify that `-c dbg` builds serialize debugging options, remap paths, and # have other appropriate debug flags. dbg_action_command_line_test( diff --git a/test/fixtures/debug_settings/BUILD b/test/fixtures/debug_settings/BUILD index d42aee8e8..ef23ebb22 100644 --- a/test/fixtures/debug_settings/BUILD +++ b/test/fixtures/debug_settings/BUILD @@ -1,3 +1,4 @@ +load("//swift:swift_binary.bzl", "swift_binary") load( "//swift:swift_library.bzl", "swift_library", @@ -18,3 +19,16 @@ swift_library( srcs = ["Empty.swift"], tags = FIXTURE_TAGS, ) + +swift_binary( + name = "binary", + srcs = ["Empty.swift"], + tags = FIXTURE_TAGS, +) + +swift_binary( + name = "module_path_binary", + srcs = ["Empty.swift"], + tags = FIXTURE_TAGS, + deps = [":simple"], +)