3535 "run_toolchain_shell_action" ,
3636 "run_toolchain_swift_action" ,
3737)
38- load (":archiving.bzl" , "register_static_archive_action" )
3938load (":attrs.bzl" , "swift_common_rule_attrs" )
4039load (
4140 ":compiling.bzl" ,
6968 "SWIFT_FEATURE_USE_GLOBAL_MODULE_CACHE" ,
7069 "SWIFT_FEATURE_USE_RESPONSE_FILES" ,
7170)
71+ load (":linking.bzl" , "register_libraries_to_link" )
7272load (
7373 ":providers.bzl" ,
7474 "SwiftClangModuleInfo" ,
@@ -413,6 +413,254 @@ def _cc_feature_configuration(feature_configuration):
413413 """
414414 return feature_configuration .cc_feature_configuration
415415
416+ def _compile (
417+ actions ,
418+ feature_configuration ,
419+ module_name ,
420+ srcs ,
421+ swift_toolchain ,
422+ target_name ,
423+ additional_inputs = [],
424+ bin_dir = None ,
425+ copts = [],
426+ defines = [],
427+ deps = [],
428+ genfiles_dir = None ):
429+ """Compiles a Swift module.
430+
431+ Args:
432+ actions: The context's `actions` object.
433+ feature_configuration: A feature configuration obtained from
434+ `swift_common.configure_features`.
435+ module_name: The name of the Swift module being compiled. This must be present and valid;
436+ use `swift_common.derive_module_name` to generate a default from the target's label if
437+ needed.
438+ srcs: The Swift source files to compile.
439+ swift_toolchain: The `SwiftToolchainInfo` provider of the toolchain.
440+ target_name: The name of the target for which the code is being compiled, which is used to
441+ determine unique file paths for the outputs.
442+ additional_inputs: A list of `File`s representing additional input files that need to be
443+ passed to the Swift compile action because they are referenced by compiler flags.
444+ bin_dir: The Bazel `*-bin` directory root. If provided, its path is used to store the cache
445+ for modules precompiled by Swift's ClangImporter.
446+ copts: A list of compiler flags that apply to the target being built. These flags, along
447+ with those from Bazel's Swift configuration fragment (i.e., `--swiftcopt` command line
448+ flags) are scanned to determine whether whole module optimization is being requested,
449+ which affects the nature of the output files.
450+ defines: Symbols that should be defined by passing `-D` to the compiler.
451+ deps: Dependencies of the target being compiled. These targets must propagate one of the
452+ following providers: `CcInfo`, `SwiftClangModuleInfo`, `SwiftInfo`, or
453+ `apple_common.Objc`.
454+ genfiles_dir: The Bazel `*-genfiles` directory root. If provided, its path is added to
455+ ClangImporter's header search paths for compatibility with Bazel's C++ and Objective-C
456+ rules which support inclusions of generated headers from that location.
457+
458+ Returns:
459+ A `struct` containing the following fields:
460+
461+ * `generated_header`: A `File` representing the Objective-C header that was generated for
462+ the compiled module. If no header was generated, this field will be None.
463+ * `generated_header_module_map`: A `File` representing the module map that was generated
464+ to correspond to the generated Objective-C header. If no module map was generated, this
465+ field will be None.
466+ * `indexstore`: A `File` representing the directory that contains the index store data
467+ generated by the compiler if index-while-building is enabled. May be None if no
468+ indexing was requested.
469+ * `linker_flags`: A list of strings representing additional flags that should be passed
470+ to the linker when linking these objects into a binary. If there are none, this field
471+ will always be an empty list, never None.
472+ * `linker_inputs`: A list of `File`s representing additional input files (such as those
473+ referenced in `linker_flags`) that need to be available to the link action when linking
474+ these objects into a binary. If there are none, this field will always be an empty
475+ list, never None.
476+ * `object_files`: A list of `.o` files that were produced by the compiler.
477+ * `swiftdoc`: The `.swiftdoc` file that was produced by the compiler.
478+ * `swiftmodule`: The `.swiftmodule` file that was produced by the compiler.
479+ """
480+
481+ # Force threaded mode for WMO builds, using the same number of cores that is
482+ # on a Mac Pro for historical reasons.
483+ # TODO(b/32571265): Generalize this based on platform and core count when an
484+ # API to obtain this is available.
485+ if _is_wmo (copts + swift_toolchain .command_line_copts , feature_configuration ):
486+ # We intentionally don't use `+=` or `extend` here to ensure that a
487+ # copy is made instead of extending the original.
488+ copts = copts + ["-num-threads" , "12" ]
489+
490+ compile_reqs = declare_compile_outputs (
491+ actions = actions ,
492+ copts = copts + swift_toolchain .command_line_copts ,
493+ srcs = srcs ,
494+ target_name = target_name ,
495+ index_while_building = swift_common .is_enabled (
496+ feature_configuration = feature_configuration ,
497+ feature_name = SWIFT_FEATURE_INDEX_WHILE_BUILDING ,
498+ ),
499+ )
500+ output_objects = compile_reqs .output_objects
501+
502+ swiftmodule = derived_files .swiftmodule (actions , module_name = module_name )
503+ swiftdoc = derived_files .swiftdoc (actions , module_name = module_name )
504+
505+ wrapper_args = actions .args ()
506+ if _is_enabled (
507+ feature_configuration = feature_configuration ,
508+ feature_name = SWIFT_FEATURE_USE_GLOBAL_MODULE_CACHE ,
509+ ):
510+ # If bin_dir is not provided, then we don't pass any special flags to the compiler,
511+ # letting it decide where the cache should live. This is usually somewhere in the system
512+ # temporary directory.
513+ if bin_dir :
514+ wrapper_args .add ("-module-cache-path" , _global_module_cache_path (bin_dir ))
515+ else :
516+ wrapper_args .add ("-Xwrapped-swift=-ephemeral-module-cache" )
517+
518+ if _is_enabled (
519+ feature_configuration = feature_configuration ,
520+ feature_name = SWIFT_FEATURE_DEBUG_PREFIX_MAP ,
521+ ):
522+ wrapper_args .add ("-Xwrapped-swift=-debug-prefix-pwd-is-dot" )
523+
524+ compile_args = actions .args ()
525+ if _is_enabled (
526+ feature_configuration = feature_configuration ,
527+ feature_name = SWIFT_FEATURE_USE_RESPONSE_FILES ,
528+ ):
529+ compile_args .use_param_file ("@%s" , use_always = True )
530+
531+ compile_args .add ("-emit-object" )
532+ compile_args .add_all (compile_reqs .args )
533+ compile_args .add ("-emit-module-path" )
534+ compile_args .add (swiftmodule )
535+
536+ # Add any command line arguments that do *not* have to do with emitting outputs.
537+ basic_inputs = _swiftc_command_line_and_inputs (
538+ # TODO(allevato): Make this argument a list of files instead.
539+ additional_input_depsets = [depset (additional_inputs )],
540+ args = compile_args ,
541+ copts = copts ,
542+ defines = defines ,
543+ deps = deps ,
544+ feature_configuration = feature_configuration ,
545+ genfiles_dir = genfiles_dir ,
546+ module_name = module_name ,
547+ srcs = srcs ,
548+ toolchain = swift_toolchain ,
549+ )
550+
551+ additional_outputs = []
552+
553+ # If the toolchain supports Objective-C interop, generate a Swift header for this library so
554+ # that it can be included by Objective-C code that depends on it.
555+ generates_header = not _is_enabled (
556+ feature_configuration = feature_configuration ,
557+ feature_name = SWIFT_FEATURE_NO_GENERATED_HEADER ,
558+ )
559+ if generates_header and swift_toolchain .supports_objc_interop :
560+ generated_header = derived_files .objc_header (actions = actions , target_name = target_name )
561+ compile_args .add ("-emit-objc-header-path" )
562+ compile_args .add (generated_header )
563+ additional_outputs .append (generated_header )
564+
565+ # Create a module map for the generated header file. This ensures that inclusions of it are
566+ # treated modularly, not textually.
567+ #
568+ # Caveat: Generated module maps are incompatible with the hack that some folks are using to
569+ # support mixed Objective-C and Swift modules. This trap door lets them escape the module
570+ # redefinition error, with the caveat that certain import scenarios could lead to incorrect
571+ # behavior because a header can be imported textually instead of modularly.
572+ if not _is_enabled (
573+ feature_configuration = feature_configuration ,
574+ feature_name = SWIFT_FEATURE_NO_GENERATED_MODULE_MAP ,
575+ ):
576+ generated_module_map = derived_files .module_map (
577+ actions = actions ,
578+ target_name = target_name ,
579+ )
580+ write_objc_header_module_map (
581+ actions = actions ,
582+ module_name = module_name ,
583+ objc_header = generated_header ,
584+ output = generated_module_map ,
585+ )
586+ else :
587+ generated_module_map = None
588+ else :
589+ generated_header = None
590+ generated_module_map = None
591+
592+ all_inputs = depset (
593+ transitive = [basic_inputs , depset (direct = compile_reqs .compile_inputs )],
594+ )
595+ compile_outputs = ([swiftmodule , swiftdoc ] + output_objects +
596+ compile_reqs .other_outputs ) + additional_outputs
597+
598+ if swift_toolchain .swift_worker :
599+ execution_requirements = {"supports-workers" : "1" }
600+ tools = [swift_toolchain .swift_worker ]
601+ else :
602+ execution_requirements = {}
603+ tools = []
604+
605+ run_toolchain_swift_action (
606+ actions = actions ,
607+ arguments = [wrapper_args , compile_args ],
608+ execution_requirements = execution_requirements ,
609+ inputs = all_inputs ,
610+ mnemonic = "SwiftCompile" ,
611+ outputs = compile_outputs ,
612+ progress_message = "Compiling Swift module {}" .format (module_name ),
613+ swift_tool = "swiftc" ,
614+ toolchain = swift_toolchain ,
615+ tools = tools ,
616+ )
617+
618+ linker_flags = []
619+ linker_inputs = []
620+
621+ # Ensure that the .swiftmodule file is embedded in the final library or binary
622+ # for debugging purposes.
623+ if _is_debugging (feature_configuration = feature_configuration ):
624+ module_embed_results = ensure_swiftmodule_is_embedded (
625+ actions = actions ,
626+ swiftmodule = swiftmodule ,
627+ target_name = target_name ,
628+ toolchain = swift_toolchain ,
629+ )
630+ linker_flags .extend (module_embed_results .linker_flags )
631+ linker_inputs .extend (module_embed_results .linker_inputs )
632+ output_objects .extend (module_embed_results .objects_to_link )
633+
634+ # Invoke an autolink-extract action for toolchains that require it.
635+ if swift_common .is_enabled (
636+ feature_configuration = feature_configuration ,
637+ feature_name = SWIFT_FEATURE_AUTOLINK_EXTRACT ,
638+ ):
639+ autolink_file = derived_files .autolink_flags (
640+ actions ,
641+ target_name = target_name ,
642+ )
643+ register_autolink_extract_action (
644+ actions = actions ,
645+ module_name = module_name ,
646+ objects = output_objects ,
647+ output = autolink_file ,
648+ toolchain = swift_toolchain ,
649+ )
650+ linker_flags .append ("@{}" .format (autolink_file .path ))
651+ linker_inputs .append (autolink_file )
652+
653+ return struct (
654+ generated_header = generated_header ,
655+ generated_module_map = generated_module_map ,
656+ indexstore = compile_reqs .indexstore ,
657+ linker_flags = linker_flags ,
658+ linker_inputs = linker_inputs ,
659+ object_files = output_objects ,
660+ swiftdoc = swiftdoc ,
661+ swiftmodule = swiftmodule ,
662+ )
663+
416664def _compile_as_objects (
417665 actions ,
418666 arguments ,
@@ -430,6 +678,8 @@ def _compile_as_objects(
430678 genfiles_dir = None ):
431679 """Compiles Swift source files into object files (and optionally a module).
432680
681+ NOTE: This API is deprecated. Use `swift_common.compile` instead.
682+
433683 Args:
434684 actions: The context's `actions` object.
435685 arguments: A list of `Args` objects that provide additional arguments to the
@@ -641,6 +891,8 @@ def _compile_as_library(
641891 linkopts = []):
642892 """Compiles Swift source files into static and/or shared libraries.
643893
894+ NOTE: This API is deprecated. Use `swift_common.compile` instead.
895+
644896 This is a high-level API that wraps the compilation and library creation steps
645897 based on the provided input arguments, and is likely suitable for most common
646898 purposes.
@@ -713,11 +965,6 @@ def _compile_as_library(
713965
714966 if not library_name :
715967 library_name = label .name
716- out_archive = derived_files .static_archive (
717- actions ,
718- alwayslink = alwayslink ,
719- link_name = library_name ,
720- )
721968
722969 # Register the compilation actions to get an object file (.o) for the Swift
723970 # code, along with its swiftmodule and swiftdoc.
@@ -800,17 +1047,19 @@ def _compile_as_library(
8001047 )
8011048
8021049 # Create an archive that contains the compiled .o files.
803- register_static_archive_action (
1050+ library_to_link = register_libraries_to_link (
8041051 actions = actions ,
1052+ alwayslink = alwayslink ,
8051053 cc_feature_configuration = _cc_feature_configuration (
8061054 feature_configuration = feature_configuration ,
8071055 ),
808- mnemonic = "SwiftArchive" ,
1056+ is_dynamic = False ,
1057+ is_static = True ,
1058+ library_name = library_name ,
8091059 objects = compile_results .output_objects ,
810- output = out_archive ,
811- progress_message = "Linking {}" .format (out_archive .short_path ),
8121060 swift_toolchain = toolchain ,
8131061 )
1062+ out_archive = library_to_link .pic_static_library
8141063
8151064 # TODO(b/130741225): Move this logic out of the API and have the rules themselves manipulate
8161065 # providers.
@@ -1265,6 +1514,7 @@ def _toolchain_attrs(toolchain_attr_name = "_toolchain"):
12651514swift_common = struct (
12661515 cc_feature_configuration = _cc_feature_configuration ,
12671516 compilation_attrs = _compilation_attrs ,
1517+ compile = _compile ,
12681518 compile_as_library = _compile_as_library ,
12691519 compile_as_objects = _compile_as_objects ,
12701520 configure_features = _configure_features ,
0 commit comments