aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2016-12-13 20:46:43 +0000
committerGravatar John Cater <jcater@google.com>2016-12-13 21:06:16 +0000
commitdf036962c94eeac0ccb6d1359d6f9681195b45ef (patch)
tree0f96bd9b3ab0a60cb9b736717408938c36f49864
parent44cf5606eb3e66dc315ffc325ce47f331e3a0741 (diff)
Extract swiftc argument generation from swift_library implementation
Make it possible to use compiler args that swift_library creates in other rules that do not depend on it. Also rename _module_name to swift_module_name and make it public because proper usage of swiftc_args requires a module name to be passed in. -- PiperOrigin-RevId: 141926959 MOS_MIGRATED_REVID=141926959
-rw-r--r--tools/build_defs/apple/swift.bzl203
1 files changed, 120 insertions, 83 deletions
diff --git a/tools/build_defs/apple/swift.bzl b/tools/build_defs/apple/swift.bzl
index c1cf96eb8c..5c1b662d65 100644
--- a/tools/build_defs/apple/swift.bzl
+++ b/tools/build_defs/apple/swift.bzl
@@ -78,9 +78,9 @@ def _swift_bitcode_flags(ctx):
return []
-def _module_name(ctx):
- """Returns a module name for the given rule context."""
- return ctx.label.package.lstrip("//").replace("/", "_") + "_" + ctx.label.name
+def swift_module_name(label):
+ """Returns a module name for the given label."""
+ return label.package.lstrip("//").replace("/", "_") + "_" + label.name
def _swift_lib_dir(ctx):
@@ -160,23 +160,35 @@ def _validate_rule_and_deps(ctx):
fail(name_error_str % dep.label)
-def _swift_library_impl(ctx):
- """Implementation for swift_library Skylark rule."""
+def swiftc_args(ctx):
+ """Returns an almost compelete array of arguments to be passed to swiftc.
- _validate_rule_and_deps(ctx)
+ This macro is intended to be used by the swift_library rule implementation
+ below but it also may be used by other rules outside this file. It has no
+ side effects and does not modify ctx. It expects ctx to contain the same
+ fragments and attributes as swift_library (you're encouraged to depend on
+ SWIFT_LIBRARY_ATTRS in your rule definition).
+
+ Args:
+ ctx: rule context
+
+ Returns:
+ A list of command line arguments for swiftc. The returned arguments
+ include everything except the arguments generation of which would require
+ adding new files or actions.
+ """
- # TODO(b/29772303): Assert xcode version.
apple_fragment = ctx.fragments.apple
cpu = apple_fragment.single_arch_cpu
platform = apple_fragment.single_arch_platform
- target_os = ctx.fragments.apple.minimum_os_for_platform_type(
+ target_os = apple_fragment.minimum_os_for_platform_type(
platform.platform_type)
target = _swift_target(cpu, platform, target_os)
apple_toolchain = apple_common.apple_toolchain()
- module_name = ctx.attr.module_name or _module_name(ctx)
+ module_name = ctx.attr.module_name or swift_module_name(ctx.label)
# A list of paths to pass with -F flag.
framework_dirs = set([
@@ -184,31 +196,22 @@ def _swift_library_impl(ctx):
# Collect transitive dependecies.
dep_modules = []
- dep_libs = []
swiftc_defines = ctx.attr.defines
swift_providers = [x.swift for x in ctx.attr.deps if hasattr(x, "swift")]
objc_providers = [x.objc for x in ctx.attr.deps if hasattr(x, "objc")]
for swift in swift_providers:
- dep_libs += swift.transitive_libs
dep_modules += swift.transitive_modules
swiftc_defines += swift.transitive_defines
objc_includes = set() # Everything that needs to be included with -I
- objc_files = set() # All inputs required for the compile action
objc_module_maps = set() # Module maps for dependent targets
objc_defines = set()
for objc in objc_providers:
objc_includes += objc.include
-
- objc_files += objc.header
- objc_files += objc.module_map
-
objc_module_maps += objc.module_map
- files = set(objc.static_framework_file) + set(objc.dynamic_framework_file)
- objc_files += files
framework_dirs += _parent_dirs(objc.framework_dir)
# TODO(cparsons): Remove getattr call once dynamic_framework_dir is stable.
framework_dirs += _parent_dirs(getattr(objc, "dynamic_framework_dir", []))
@@ -218,49 +221,11 @@ def _swift_library_impl(ctx):
# their module cannot be compiled by clang), but did not occur in practice.
objc_defines += objc.define
- # A unique path for rule's outputs.
- objs_outputs_path = label_scoped_path(ctx, "_objs/")
-
- output_lib = ctx.new_file(objs_outputs_path + module_name + ".a")
- output_module = ctx.new_file(objs_outputs_path + module_name + ".swiftmodule")
-
- # These filenames are guaranteed to be unique, no need to scope.
- output_header = ctx.new_file(ctx.label.name + "-Swift.h")
- swiftc_output_map_file = ctx.new_file(ctx.label.name + ".output_file_map.json")
-
- swiftc_output_map = struct() # Maps output types to paths.
- output_objs = [] # Object file outputs, used in archive action.
- swiftc_outputs = [] # Other swiftc outputs that aren't processed further.
- for source in ctx.files.srcs:
- basename = source.basename
- obj = ctx.new_file(objs_outputs_path + basename + ".o")
- partial_module = ctx.new_file(objs_outputs_path + basename +
- ".partial_swiftmodule")
- output_objs.append(obj)
- swiftc_outputs.append(partial_module)
-
- swiftc_output_map += struct(**{
- source.path: struct(object=obj.path, swiftmodule=partial_module.path)})
-
- # Write down the intermediate outputs map for this compilation, to be used
- # with -output-file-map flag.
- # It's a JSON file that maps each source input (.swift) to its outputs
- # (.o, .bc, .d, ...)
- # Example:
- # {'foo.swift':
- # {'object': 'foo.o', 'bitcode': 'foo.bc', 'dependencies': 'foo.d'}}
- # There's currently no documentation on this option, however all of the keys
- # are listed here https://github.com/apple/swift/blob/swift-2.2.1-RELEASE/include/swift/Driver/Types.def
- ctx.file_action(output=swiftc_output_map_file, content=swiftc_output_map.to_json())
-
srcs_args = [f.path for f in ctx.files.srcs]
# Include each swift module's parent directory for imports to work.
include_dirs = set([x.dirname for x in dep_modules])
- # Include the parent directory of the resulting module so LLDB can find it.
- include_dirs += set([output_module.dirname])
-
# Include the genfiles root so full-path imports can work for generated protos.
include_dirs += set([ctx.configuration.genfiles_dir.path])
@@ -268,15 +233,6 @@ def _swift_library_impl(ctx):
framework_args = ["-F%s" % x for x in framework_dirs]
define_args = ["-D%s" % x for x in swiftc_defines]
- # This tells the linker to write a reference to .swiftmodule as an AST symbol
- # in the final binary.
- # With dSYM enabled, this results in a __DWARF,__swift_ast section added to
- # the dSYM binary, from where LLDB is able deserialize module information.
- # Without dSYM, LLDB will follow the AST references, however there is a bug
- # where it follows only the first one https://bugs.swift.org/browse/SR-2637
- # This means that dSYM is required for debugging until that is resolved.
- extra_linker_args = ["-Xlinker -add_ast_path -Xlinker " + output_module.path]
-
clang_args = _intersperse(
"-Xcc",
@@ -296,23 +252,16 @@ def _swift_library_impl(ctx):
# https://llvm.org/bugs/show_bug.cgi?id=19501
+ ["-fmodule-map-file=%s" % x.path for x in objc_module_maps])
- args = _swift_xcrun_args(ctx) + [
- "swiftc",
+ args = [
"-emit-object",
- "-emit-module-path",
- output_module.path,
"-module-name",
module_name,
- "-emit-objc-header-path",
- output_header.path,
"-target",
target,
"-sdk",
apple_toolchain.sdk_dir(),
"-module-cache-path",
module_cache_path(ctx),
- "-output-file-map",
- swiftc_output_map_file.path,
]
if ctx.configuration.coverage_enabled:
@@ -328,6 +277,82 @@ def _swift_library_impl(ctx):
args.extend(define_args)
args.extend(ctx.attr.copts)
+ return args
+
+
+def _swift_library_impl(ctx):
+ """Implementation for swift_library Skylark rule."""
+
+ _validate_rule_and_deps(ctx)
+
+ # Collect transitive dependecies.
+ dep_modules = []
+ dep_libs = []
+ swiftc_defines = ctx.attr.defines
+
+ swift_providers = [x.swift for x in ctx.attr.deps if hasattr(x, "swift")]
+ objc_providers = [x.objc for x in ctx.attr.deps if hasattr(x, "objc")]
+
+ for swift in swift_providers:
+ dep_libs += swift.transitive_libs
+ dep_modules += swift.transitive_modules
+ swiftc_defines += swift.transitive_defines
+
+ objc_files = set() # All inputs required for the compile action
+ for objc in objc_providers:
+ objc_files += objc.header
+ objc_files += objc.module_map
+
+ files = set(objc.static_framework_file) + set(objc.dynamic_framework_file)
+ objc_files += files
+
+ # A unique path for rule's outputs.
+ objs_outputs_path = label_scoped_path(ctx, "_objs/")
+
+ module_name = ctx.attr.module_name or swift_module_name(ctx.label)
+ output_lib = ctx.new_file(objs_outputs_path + module_name + ".a")
+ output_module = ctx.new_file(objs_outputs_path + module_name + ".swiftmodule")
+
+ # These filenames are guaranteed to be unique, no need to scope.
+ output_header = ctx.new_file(ctx.label.name + "-Swift.h")
+ swiftc_output_map_file = ctx.new_file(ctx.label.name + ".output_file_map.json")
+
+ swiftc_output_map = struct() # Maps output types to paths.
+ output_objs = [] # Object file outputs, used in archive action.
+ swiftc_outputs = [] # Other swiftc outputs that aren't processed further.
+ for source in ctx.files.srcs:
+ basename = source.basename
+ obj = ctx.new_file(objs_outputs_path + basename + ".o")
+ partial_module = ctx.new_file(objs_outputs_path + basename +
+ ".partial_swiftmodule")
+ output_objs.append(obj)
+ swiftc_outputs.append(partial_module)
+
+ swiftc_output_map += struct(**{
+ source.path: struct(object=obj.path, swiftmodule=partial_module.path)})
+
+ # Write down the intermediate outputs map for this compilation, to be used
+ # with -output-file-map flag.
+ # It's a JSON file that maps each source input (.swift) to its outputs
+ # (.o, .bc, .d, ...)
+ # Example:
+ # {'foo.swift':
+ # {'object': 'foo.o', 'bitcode': 'foo.bc', 'dependencies': 'foo.d'}}
+ # There's currently no documentation on this option, however all of the keys
+ # are listed here https://github.com/apple/swift/blob/swift-2.2.1-RELEASE/include/swift/Driver/Types.def
+ ctx.file_action(output=swiftc_output_map_file, content=swiftc_output_map.to_json())
+
+ args = _swift_xcrun_args(ctx) + ["swiftc"] + swiftc_args(ctx)
+ args += [
+ "-I" + output_module.dirname,
+ "-emit-module-path",
+ output_module.path,
+ "-emit-objc-header-path",
+ output_header.path,
+ "-output-file-map",
+ swiftc_output_map_file.path,
+ ]
+
xcrun_action(
ctx,
inputs=ctx.files.srcs + dep_modules + list(objc_files) +
@@ -348,6 +373,15 @@ def _swift_library_impl(ctx):
] + [x.path for x in output_objs],
progress_message=("Archiving Swift objects %s" % ctx.label.name))
+ # This tells the linker to write a reference to .swiftmodule as an AST symbol
+ # in the final binary.
+ # With dSYM enabled, this results in a __DWARF,__swift_ast section added to
+ # the dSYM binary, from where LLDB is able deserialize module information.
+ # Without dSYM, LLDB will follow the AST references, however there is a bug
+ # where it follows only the first one https://bugs.swift.org/browse/SR-2637
+ # This means that dSYM is required for debugging until that is resolved.
+ extra_linker_args = ["-Xlinker -add_ast_path -Xlinker " + output_module.path]
+
objc_provider = apple_common.new_objc_provider(
library=set([output_lib] + dep_libs),
header=set([output_header]),
@@ -364,18 +398,21 @@ def _swift_library_impl(ctx):
objc=objc_provider,
files=set([output_lib, output_module, output_header]))
+SWIFT_LIBRARY_ATTRS = {
+ "srcs": attr.label_list(allow_files = [".swift"], allow_empty=False),
+ "deps": attr.label_list(providers=[["swift"], ["objc"]]),
+ "module_name": attr.string(mandatory=False),
+ "defines": attr.string_list(mandatory=False, allow_empty=True),
+ "copts": attr.string_list(mandatory=False, allow_empty=True),
+ "_xcrunwrapper": attr.label(
+ executable=True,
+ cfg="host",
+ default=Label(XCRUNWRAPPER_LABEL))
+}
+
swift_library = rule(
_swift_library_impl,
- attrs = {
- "srcs": attr.label_list(allow_files = [".swift"], allow_empty=False),
- "deps": attr.label_list(providers=[["swift"], ["objc"]]),
- "module_name": attr.string(mandatory=False),
- "defines": attr.string_list(mandatory=False, allow_empty=True),
- "copts": attr.string_list(mandatory=False, allow_empty=True),
- "_xcrunwrapper": attr.label(
- executable=True,
- cfg="host",
- default=Label(XCRUNWRAPPER_LABEL))},
+ attrs = SWIFT_LIBRARY_ATTRS,
fragments = ["apple", "objc"],
output_to_genfiles=True,
)