Add "tulsi_deps" to "_TULSI_COMPILE_DEPS". Add a new special attribute, "tulsi_deps", to the list of rule attributes that Tulsi aspects propagate along. The new attribute name is an escape hatch intended for custom rule creators who use non-standard attribute names for rule dependencies and want those dependencies to show up in Xcode. PiperOrigin-RevId: 195271410
diff --git a/src/TulsiGenerator/Bazel/tulsi/tulsi_aspects.bzl b/src/TulsiGenerator/Bazel/tulsi/tulsi_aspects.bzl index 6950d09..950e916 100644 --- a/src/TulsiGenerator/Bazel/tulsi/tulsi_aspects.bzl +++ b/src/TulsiGenerator/Bazel/tulsi/tulsi_aspects.bzl
@@ -44,6 +44,10 @@ "_implicit_tests", # test_suites without a `tests` attr have an '$implicit_tests' attr instead. "test_bundle", "test_host", + # Special attribute name which serves as an escape hatch intended for custom + # rule creators who use non-standard attribute names for rule dependencies + # and want those dependencies to show up in Xcode. + "tulsi_deps", "watch_application", "xctest_app", ] @@ -115,20 +119,15 @@ ] def _dict_omitting_none(**kwargs): - """Creates a dict from the args, dropping keys with None or [] values.""" - return {name: kwargs[name] - for name in kwargs - # Skylark doesn't support "is"; comparison is explicit for correctness. - # pylint: disable=g-equals-none,g-explicit-bool-comparison - if kwargs[name] != None and kwargs[name] != [] - } + """Creates a dict from the args, dropping keys with None or [] values.""" + return {name: kwargs[name] for name in kwargs if kwargs[name] != None and kwargs[name] != []} def _struct_omitting_none(**kwargs): - """Creates a struct from the args, dropping keys with None or [] values.""" - return struct(**_dict_omitting_none(**kwargs)) + """Creates a struct from the args, dropping keys with None or [] values.""" + return struct(**_dict_omitting_none(**kwargs)) def _convert_outpath_to_symlink_path(path): - """Converts full output paths to their tulsi-symlink equivalents. + """Converts full output paths to their tulsi-symlink equivalents. Bazel output paths are unstable, prone to change with architecture, platform or flag changes. Therefore we can't rely on them to supply to Xcode. @@ -161,171 +160,181 @@ Returns: A string that is the original path modified according to the rules. """ - # Transform paths of the form: - # bazel-[whatever]/[platform-config]/symlink[/.*] - # to: - # _tulsi-includes/x/x/symlink[/.*] - first_dash = path.find('-') - components = path.split('/') - if (len(components) > 2 and - first_dash >= 0 and - first_dash < len(components[0])): - return '_tulsi-includes/x/x/' + '/'.join(components[3:]) - return path + + # Transform paths of the form: + # bazel-[whatever]/[platform-config]/symlink[/.*] + # to: + # _tulsi-includes/x/x/symlink[/.*] + first_dash = path.find("-") + components = path.split("/") + if (len(components) > 2 and + first_dash >= 0 and + first_dash < len(components[0])): + return ("_tulsi-includes/x/x/" + "/".join(components[3:])) + return path def _is_bazel_external_file(f): - """Returns True if the given file is a Bazel external file.""" - return f.path.startswith('external/') + """Returns True if the given file is a Bazel external file.""" + return f.path.startswith("external/") def _file_metadata(f): - """Returns metadata about a given File.""" - if not f: - return None + """Returns metadata about a given File.""" + if not f: + return None - # Special case handling for Bazel external files which have a path that starts - # with 'external/' but their short_path and root.path have no mention of being - # external. - out_path = f.path if _is_bazel_external_file(f) else f.short_path - if not f.is_source: - root_path = f.root.path - symlink_path = _convert_outpath_to_symlink_path(root_path) - if symlink_path == root_path: - # The root path should always be bazel-out/... and thus is expected to be - # updated. - print('Unexpected root path "%s". Please report.' % root_path) - root_execution_path_fragment = root_path + # Special case handling for Bazel external files which have a path that starts + # with 'external/' but their short_path and root.path have no mention of being + # external. + + out_path = f.path if _is_bazel_external_file(f) else f.short_path + if not f.is_source: + root_path = f.root.path + symlink_path = _convert_outpath_to_symlink_path(root_path) + if symlink_path == root_path: + # The root path should always be bazel-out/... and thus is expected to be + # updated. + print("Unexpected root path \"%s\". Please report." % root_path) + root_execution_path_fragment = root_path + else: + root_execution_path_fragment = symlink_path else: - root_execution_path_fragment = symlink_path - else: - root_execution_path_fragment = None + root_execution_path_fragment = None - # At the moment (Oct. 2016), Bazel disallows most files without extensions. - # As a temporary hack, Tulsi treats File instances pointing at extension-less - # paths as directories. This is extremely fragile and must be replaced with - # logic properly homed in Bazel. - is_dir = (f.basename.find('.') == -1) + # At the moment (Oct. 2016), Bazel disallows most files without extensions. + # As a temporary hack, Tulsi treats File instances pointing at extension-less + # paths as directories. This is extremely fragile and must be replaced with + # logic properly homed in Bazel. - return _struct_omitting_none( - path=out_path, - src=f.is_source, - root=root_execution_path_fragment, - is_dir=is_dir - ) + is_dir = (f.basename.find(".") == -1) -def _file_metadata_by_replacing_path(f, new_path, new_is_dir=None): - """Returns a copy of the f _file_metadata struct with the given path.""" - root_path = _get_opt_attr(f, 'rootPath') - if new_is_dir == None: - new_is_dir = f.is_dir + return _struct_omitting_none( + path = out_path, + src = f.is_source, + root = root_execution_path_fragment, + is_dir = is_dir, + ) - return _struct_omitting_none( - path=new_path, - src=f.src, - root=root_path, - is_dir=new_is_dir - ) +def _file_metadata_by_replacing_path(f, new_path, new_is_dir = None): + """Returns a copy of the f _file_metadata struct with the given path.""" + root_path = _get_opt_attr(f, "rootPath") + if new_is_dir == None: + new_is_dir = f.is_dir + + return _struct_omitting_none( + path = new_path, + src = f.src, + root = root_path, + is_dir = new_is_dir, + ) def _depset_to_file_metadata_list(a_depset): - """"Converts a depset of files into a list of _file_metadata structs.""" - return [_file_metadata(f) for f in a_depset.to_list()] + """"Converts a depset of files into a list of _file_metadata structs.""" + return [_file_metadata(f) for f in a_depset.to_list()] def _collect_artifacts(obj, attr_path): - """Returns a list of Artifact objects for the attr_path in obj.""" - return [f for src in _getattr_as_list(obj, attr_path) - for f in _get_opt_attr(src, 'files')] + """Returns a list of Artifact objects for the attr_path in obj.""" + return [f for src in _getattr_as_list(obj, attr_path) for f in _get_opt_attr(src, "files")] -def _collect_files(obj, attr_path, convert_to_metadata=True): - """Returns a list of artifact_location's for the attr_path in obj.""" - if convert_to_metadata: - return [_file_metadata(f) for f in _collect_artifacts(obj, attr_path)] - else: - return _collect_artifacts(obj, attr_path) +def _collect_files(obj, attr_path, convert_to_metadata = True): + """Returns a list of artifact_location's for the attr_path in obj.""" + if convert_to_metadata: + return [_file_metadata(f) for f in _collect_artifacts(obj, attr_path)] + else: + return _collect_artifacts(obj, attr_path) def _collect_first_file(obj, attr_path): - """Returns a the first artifact_location for the attr_path in obj.""" - files = _collect_files(obj, attr_path) - if not files: - return None - return files[0] + """Returns a the first artifact_location for the attr_path in obj.""" + files = _collect_files(obj, attr_path) + if not files: + return None + return files[0] -def _collect_supporting_files(rule_attr, convert_to_metadata=True): - """Extracts 'supporting' files from the given rule attributes.""" - all_files = [] - for attr in _SUPPORTING_FILE_ATTRIBUTES: - all_files += _collect_files(rule_attr, attr, - convert_to_metadata=convert_to_metadata) - return all_files +def _collect_supporting_files(rule_attr, convert_to_metadata = True): + """Extracts 'supporting' files from the given rule attributes.""" + all_files = [] + for attr in _SUPPORTING_FILE_ATTRIBUTES: + all_files += _collect_files( + rule_attr, + attr, + convert_to_metadata = convert_to_metadata, + ) + return all_files def _collect_bundle_paths(rule_attr, bundle_attributes, bundle_ext): - """Extracts subpaths with the given bundle_ext for the given attributes.""" - discovered_paths = depset() - bundles = [] - if not bundle_ext.endswith('/'): - bundle_ext += '/' - bundle_ext_len = len(bundle_ext) - 1 + """Extracts subpaths with the given bundle_ext for the given attributes.""" + discovered_paths = depset() + bundles = [] + if not bundle_ext.endswith("/"): + bundle_ext += "/" + bundle_ext_len = len(bundle_ext) - 1 - for attr in bundle_attributes: - for f in _collect_files(rule_attr, attr): - end = f.path.find(bundle_ext) - if end < 0: - continue - end += bundle_ext_len + for attr in bundle_attributes: + for f in _collect_files(rule_attr, attr): + end = f.path.find(bundle_ext) + if end < 0: + continue + end += bundle_ext_len - path = f.path[:end] - root_path = _get_opt_attr(f, 'rootPath') - full_path = str(root_path) + ':' + path - if full_path in discovered_paths: - continue - discovered_paths += [full_path] - # Generally Xcode treats bundles as special files so they should not be - # flagged as directories. - bundles.append(_file_metadata_by_replacing_path(f, path, False)) - return bundles + path = f.path[:end] + root_path = _get_opt_attr(f, "rootPath") + full_path = str(root_path) + ":" + path + if full_path in discovered_paths: + continue + discovered_paths += [full_path] + + # Generally Xcode treats bundles as special files so they should not be + # flagged as directories. + bundles.append(_file_metadata_by_replacing_path(f, path, False)) + return bundles def _collect_asset_catalogs(rule_attr): - """Extracts xcassets directories from the given rule attributes.""" - attrs = ['app_asset_catalogs', 'asset_catalogs'] - bundles = _collect_bundle_paths(rule_attr, attrs, '.xcassets') - bundles.extend(_collect_bundle_paths(rule_attr, attrs, '.xcstickers')) + """Extracts xcassets directories from the given rule attributes.""" + attrs = ["app_asset_catalogs", "asset_catalogs"] + bundles = _collect_bundle_paths(rule_attr, attrs, ".xcassets") + bundles.extend(_collect_bundle_paths(rule_attr, attrs, ".xcstickers")) - return bundles + return bundles def _collect_bundle_imports(rule_attr): - """Extracts bundle directories from the given rule attributes.""" - return _collect_bundle_paths(rule_attr, - ['bundle_imports', 'settings_bundle'], - '.bundle') + """Extracts bundle directories from the given rule attributes.""" + return _collect_bundle_paths( + rule_attr, + ["bundle_imports", "settings_bundle"], + ".bundle", + ) def _collect_framework_imports(rule_attr): - """Extracts framework directories from the given rule attributes.""" - return _collect_bundle_paths(rule_attr, - ['framework_imports'], - '.framework') + """Extracts framework directories from the given rule attributes.""" + return _collect_bundle_paths( + rule_attr, + ["framework_imports"], + ".framework", + ) def _collect_xcdatamodeld_files(obj, attr_path): - """Returns artifact_location's for xcdatamodeld's for attr_path in obj.""" - files = _collect_files(obj, attr_path) - if not files: - return [] - discovered_paths = depset() - datamodelds = [] - for f in files: - end = f.path.find('.xcdatamodel/') - if end < 0: - continue - end += 12 + """Returns artifact_location's for xcdatamodeld's for attr_path in obj.""" + files = _collect_files(obj, attr_path) + if not files: + return [] + discovered_paths = depset() + datamodelds = [] + for f in files: + end = f.path.find(".xcdatamodel/") + if end < 0: + continue + end += 12 - path = f.path[:end] - root_path = _get_opt_attr(f, 'rootPath') - full_path = str(root_path) + ':' + path - if full_path in discovered_paths: - continue - discovered_paths += [full_path] - datamodelds.append(_file_metadata_by_replacing_path(f, path, False)) - return datamodelds + path = f.path[:end] + root_path = _get_opt_attr(f, "rootPath") + full_path = str(root_path) + ":" + path + if full_path in discovered_paths: + continue + discovered_paths += [full_path] + datamodelds.append(_file_metadata_by_replacing_path(f, path, False)) + return datamodelds def _collect_dependency_labels(rule, filter, attr_list): - """Collects Bazel labels for a list of dependency attributes. + """Collects Bazel labels for a list of dependency attributes. Args: rule: The Bazel rule whose dependencies should be collected. @@ -336,28 +345,26 @@ Returns: A list of the Bazel labels of dependencies of the given rule. """ - attr = rule.attr - deps = [dep - for attribute in attr_list - for dep in _filter_deps(filter, _getattr_as_list(attr, attribute))] - return [dep.label for dep in deps if hasattr(dep, 'label')] + attr = rule.attr + deps = [dep for attribute in attr_list for dep in _filter_deps(filter, _getattr_as_list(attr, attribute))] + return [dep.label for dep in deps if hasattr(dep, "label")] def _get_opt_attr(obj, attr_path): - """Returns the value at attr_path on the given object if it is set.""" - attr_path = attr_path.split('.') - for a in attr_path: - if not obj or not hasattr(obj, a): - return None - obj = getattr(obj, a) - return obj + """Returns the value at attr_path on the given object if it is set.""" + attr_path = attr_path.split(".") + for a in attr_path: + if not obj or not hasattr(obj, a): + return None + obj = getattr(obj, a) + return obj def _get_label_attr(obj, attr_path): - """Returns the value at attr_path as a label string if it is set.""" - label = _get_opt_attr(obj, attr_path) - return str(label) if label else None + """Returns the value at attr_path as a label string if it is set.""" + label = _get_opt_attr(obj, attr_path) + return str(label) if label else None def _getattr_as_list(obj, attr_path): - """Returns the value at attr_path as a list. + """Returns the value at attr_path as a list. This handles normalization of attributes containing a single value for use in methods expecting a list of values. @@ -371,374 +378,376 @@ A list of values for obj at attr_path or [] if the struct has no such attribute. """ - val = _get_opt_attr(obj, attr_path) - if not val: - return [] + val = _get_opt_attr(obj, attr_path) + if not val: + return [] - if type(val) == 'list': - return val - return [val] + if type(val) == "list": + return val + return [val] def _extract_defines_from_option_list(lst): - """Extracts preprocessor defines from a list of -D strings.""" - defines = [] - for item in lst: - if item.startswith('-D'): - defines.append(item[2:]) - return defines + """Extracts preprocessor defines from a list of -D strings.""" + defines = [] + for item in lst: + if item.startswith("-D"): + defines.append(item[2:]) + return defines def _extract_compiler_defines(ctx): - """Extracts preprocessor defines from compiler fragments.""" - defines = [] + """Extracts preprocessor defines from compiler fragments.""" + defines = [] - cpp_fragment = _get_opt_attr(ctx.fragments, 'cpp') - if cpp_fragment: - c_options = _get_opt_attr(cpp_fragment, 'c_options') - defines += _extract_defines_from_option_list(c_options) + cpp_fragment = _get_opt_attr(ctx.fragments, "cpp") + if cpp_fragment: + c_options = _get_opt_attr(cpp_fragment, "c_options") + defines += _extract_defines_from_option_list(c_options) - compiler_options = cpp_fragment.compiler_options([]) - defines += _extract_defines_from_option_list(compiler_options) + compiler_options = cpp_fragment.compiler_options([]) + defines += _extract_defines_from_option_list(compiler_options) - unfiltered = cpp_fragment.unfiltered_compiler_options([]) - defines += _extract_defines_from_option_list(unfiltered) + unfiltered = cpp_fragment.unfiltered_compiler_options([]) + defines += _extract_defines_from_option_list(unfiltered) - cxx = cpp_fragment.cxx_options([]) - defines += _extract_defines_from_option_list(cxx) + cxx = cpp_fragment.cxx_options([]) + defines += _extract_defines_from_option_list(cxx) - objc_fragment = _get_opt_attr(ctx.fragments, 'objc') - if objc_fragment: - objc_copts = _get_opt_attr(objc_fragment, 'copts') - defines += _extract_defines_from_option_list(objc_copts) + objc_fragment = _get_opt_attr(ctx.fragments, "objc") + if objc_fragment: + objc_copts = _get_opt_attr(objc_fragment, "copts") + defines += _extract_defines_from_option_list(objc_copts) - return defines + return defines def _collect_secondary_artifacts(target, ctx): - """Returns a list of file metadatas for implicit outputs of 'rule'.""" - artifacts = [] - rule = ctx.rule - if rule.kind in _MERGEDINFOPLIST_GENERATING_RULES: - bin_dir = _convert_outpath_to_symlink_path(ctx.bin_dir.path) - package = target.label.package - basename = target.label.name - artifacts.append(_struct_omitting_none( - path='%s/%s-MergedInfo.plist' % (package, basename), - src=False, - root=bin_dir - )) + """Returns a list of file metadatas for implicit outputs of 'rule'.""" + artifacts = [] + rule = ctx.rule + if rule.kind in _MERGEDINFOPLIST_GENERATING_RULES: + bin_dir = _convert_outpath_to_symlink_path(ctx.bin_dir.path) + package = target.label.package + basename = target.label.name + artifacts.append(_struct_omitting_none( + path = "%s/%s-MergedInfo.plist" % (package, basename), + src = False, + root = bin_dir, + )) - return artifacts + return artifacts def _extract_generated_sources(target): - """Returns (source_metadatas, includes) generated by the given target.""" - file_metadatas = [] - objc_provider = _get_opt_attr(target, 'objc') - if hasattr(objc_provider, 'source') and hasattr(objc_provider, 'header'): - all_files = depset(objc_provider.source) - all_files += objc_provider.header - file_metadatas = [_file_metadata(f) for f in all_files] + """Returns (source_metadatas, includes) generated by the given target.""" + file_metadatas = [] + objc_provider = _get_opt_attr(target, "objc") + if hasattr(objc_provider, "source") and hasattr(objc_provider, "header"): + all_files = depset(objc_provider.source) + all_files += objc_provider.header + file_metadatas = [_file_metadata(f) for f in all_files] - return file_metadatas + return file_metadatas def _get_deployment_info(target, ctx): - """Returns (platform_type, minimum_os_version) for the given target.""" - platform_type = _get_platform_type(ctx) + """Returns (platform_type, minimum_os_version) for the given target.""" + platform_type = _get_platform_type(ctx) - if AppleBundleInfo in target: - apple_bundle_provider = target[AppleBundleInfo] - minimum_os_version = apple_bundle_provider.minimum_os_version - return (platform_type, minimum_os_version) - return (platform_type, _minimum_os_for_platform(ctx, platform_type)) + if AppleBundleInfo in target: + apple_bundle_provider = target[AppleBundleInfo] + minimum_os_version = apple_bundle_provider.minimum_os_version + return (platform_type, minimum_os_version) + return (platform_type, _minimum_os_for_platform(ctx, platform_type)) def _get_platform_type(ctx): - """Return the current apple_common.platform_type as a string.""" - current_platform = (_get_opt_attr(ctx, 'rule.attr.platform_type') - or _get_opt_attr(ctx, 'rule.attr._platform_type')) - if not current_platform: - apple_frag = _get_opt_attr(ctx.fragments, 'apple') - current_platform = str(apple_frag.single_arch_platform.platform_type) - return current_platform + """Return the current apple_common.platform_type as a string.""" + current_platform = (_get_opt_attr(ctx, "rule.attr.platform_type") or + _get_opt_attr(ctx, "rule.attr._platform_type")) + if not current_platform: + apple_frag = _get_opt_attr(ctx.fragments, "apple") + current_platform = str(apple_frag.single_arch_platform.platform_type) + return current_platform def _minimum_os_for_platform(ctx, platform_type_str): - """Extracts the minimum OS version for the given apple_common.platform.""" - min_os = _get_opt_attr(ctx, 'rule.attr.minimum_os_version') - if min_os: - return min_os + """Extracts the minimum OS version for the given apple_common.platform.""" + min_os = _get_opt_attr(ctx, "rule.attr.minimum_os_version") + if min_os: + return min_os - platform_type = getattr(apple_common.platform_type, platform_type_str) - min_os = (ctx.attr._tulsi_xcode_config[apple_common.XcodeVersionConfig] - .minimum_os_for_platform_type(platform_type)) + platform_type = getattr(apple_common.platform_type, platform_type_str) + min_os = (ctx.attr._tulsi_xcode_config[apple_common.XcodeVersionConfig].minimum_os_for_platform_type(platform_type)) - if not min_os: - return None + if not min_os: + return None - # Convert the DottedVersion to a string suitable for inclusion in a struct. - return str(min_os) + # Convert the DottedVersion to a string suitable for inclusion in a struct. + return str(min_os) def _collect_swift_modules(target): - """Returns a depset of Swift modules found on the given target.""" - swift_modules = depset() - if SwiftInfo in target: - swift_info = target[SwiftInfo] - for modules in _getattr_as_list(swift_info, 'transitive_modules'): - swift_modules += modules - return swift_modules + """Returns a depset of Swift modules found on the given target.""" + swift_modules = depset() + if SwiftInfo in target: + swift_info = target[SwiftInfo] + for modules in _getattr_as_list(swift_info, "transitive_modules"): + swift_modules += modules + return swift_modules def _collect_module_maps(target): - """Returns a depset of Clang module maps found on the given target.""" - maps = depset() - if SwiftInfo in target: - for module_maps in _getattr_as_list(target, 'objc.module_map'): - maps += module_maps - return maps + """Returns a depset of Clang module maps found on the given target.""" + maps = depset() + if SwiftInfo in target: + for module_maps in _getattr_as_list(target, "objc.module_map"): + maps += module_maps + return maps -# TODO(b/64490743): Add these files to the Xcode project. + # TODO(b/64490743): Add these files to the Xcode project. + def _collect_swift_header(target): - """Returns a depset of Swift generated headers found on the given target.""" - headers = depset() - # swift_* targets put the generated header into their objc provider HEADER - # field. - if SwiftInfo in target and hasattr(target, 'objc'): - headers += target.objc.header - return headers + """Returns a depset of Swift generated headers found on the given target.""" + headers = depset() + + # swift_* targets put the generated header into their objc provider HEADER + # field. + if SwiftInfo in target and hasattr(target, "objc"): + headers += target.objc.header + return headers def _target_filtering_info(ctx): - """Returns filtering information for test rules.""" - rule = ctx.rule + """Returns filtering information for test rules.""" + rule = ctx.rule - # TODO(b/72406542): Clean this up to use a test provider if possible. - if rule.kind.endswith('_test'): - # Note that a test's size is considered a tag for filtering purposes. - size = _getattr_as_list(rule, 'attr.size') - tags = _getattr_as_list(rule, 'attr.tags') - return struct(tags=tags + size) - else: - return None + # TODO(b/72406542): Clean this up to use a test provider if possible. + if rule.kind.endswith("_test"): + # Note that a test's size is considered a tag for filtering purposes. + size = _getattr_as_list(rule, "attr.size") + tags = _getattr_as_list(rule, "attr.tags") + return struct(tags = tags + size) + else: + return None def _tulsi_sources_aspect(target, ctx): - """Extracts information from a given rule, emitting it as a JSON struct.""" - rule = ctx.rule - target_kind = rule.kind - rule_attr = _get_opt_attr(rule, 'attr') - filter = _filter_for_rule(rule) + """Extracts information from a given rule, emitting it as a JSON struct.""" + rule = ctx.rule + target_kind = rule.kind + rule_attr = _get_opt_attr(rule, "attr") + filter = _filter_for_rule(rule) - tulsi_info_files = depset() - transitive_attributes = dict() - for attr_name in _TULSI_COMPILE_DEPS: - deps = _getattr_as_list(rule_attr, attr_name) - for dep in _filter_deps(filter, deps): - if hasattr(dep, 'tulsi_info_files'): - tulsi_info_files += dep.tulsi_info_files - if hasattr(dep, 'transitive_attributes'): - transitive_attributes += dep.transitive_attributes + tulsi_info_files = depset() + transitive_attributes = dict() + for attr_name in _TULSI_COMPILE_DEPS: + deps = _getattr_as_list(rule_attr, attr_name) + for dep in _filter_deps(filter, deps): + if hasattr(dep, "tulsi_info_files"): + tulsi_info_files += dep.tulsi_info_files + if hasattr(dep, "transitive_attributes"): + transitive_attributes += dep.transitive_attributes - artifacts = _get_opt_attr(target, 'files') - if artifacts: - # Ignore any generated Xcode projects as they are not useful to Tulsi. - artifacts = [_file_metadata(f) - for f in artifacts - if not f.short_path.endswith('project.pbxproj')] - else: - # artifacts may be an empty set type, in which case it must be explicitly - # set to None to allow Skylark's serialization to work. - artifacts = None + artifacts = _get_opt_attr(target, "files") + if artifacts: + # Ignore any generated Xcode projects as they are not useful to Tulsi. + artifacts = [_file_metadata(f) for f in artifacts if not f.short_path.endswith("project.pbxproj")] + else: + # artifacts may be an empty set type, in which case it must be explicitly + # set to None to allow Skylark's serialization to work. + artifacts = None - srcs = (_collect_files(rule, 'attr.srcs') + - _collect_files(rule, 'attr.hdrs') + - _collect_files(rule, 'attr.textual_hdrs')) - generated_files = [] - generated_non_arc_files = [] - if target_kind in _SOURCE_GENERATING_RULES: - generated_files = _extract_generated_sources(target) - elif target_kind in _NON_ARC_SOURCE_GENERATING_RULES: - generated_non_arc_files = _extract_generated_sources(target) + srcs = (_collect_files(rule, "attr.srcs") + + _collect_files(rule, "attr.hdrs") + + _collect_files(rule, "attr.textual_hdrs")) + generated_files = [] + generated_non_arc_files = [] + if target_kind in _SOURCE_GENERATING_RULES: + generated_files = _extract_generated_sources(target) + elif target_kind in _NON_ARC_SOURCE_GENERATING_RULES: + generated_non_arc_files = _extract_generated_sources(target) - swift_transitive_modules = depset( - [_file_metadata(f) - for f in _collect_swift_modules(target)]) + swift_transitive_modules = depset( + [_file_metadata(f) for f in _collect_swift_modules(target)], + ) - # Collect ObjC module maps dependencies for Swift targets. - objc_module_maps = depset( - [_file_metadata(f) - for f in _collect_module_maps(target)]) + # Collect ObjC module maps dependencies for Swift targets. + objc_module_maps = depset( + [_file_metadata(f) for f in _collect_module_maps(target)], + ) - # Collect the dependencies of this rule, dropping any .jar files (which may be - # created as artifacts of java/j2objc rules). - dep_labels = _collect_dependency_labels(rule, filter, _TULSI_COMPILE_DEPS) - compile_deps = [str(d) for d in dep_labels if not d.name.endswith('.jar')] + # Collect the dependencies of this rule, dropping any .jar files (which may be + # created as artifacts of java/j2objc rules). + dep_labels = _collect_dependency_labels(rule, filter, _TULSI_COMPILE_DEPS) + compile_deps = [str(d) for d in dep_labels if not d.name.endswith(".jar")] - binary_rule = _get_opt_attr(rule_attr, 'binary') - if binary_rule and type(binary_rule) == 'list': - binary_rule = binary_rule[0] + binary_rule = _get_opt_attr(rule_attr, "binary") + if binary_rule and type(binary_rule) == "list": + binary_rule = binary_rule[0] - supporting_files = (_collect_supporting_files(rule_attr) + - _collect_asset_catalogs(rule_attr) + - _collect_bundle_imports(rule_attr)) + supporting_files = (_collect_supporting_files(rule_attr) + + _collect_asset_catalogs(rule_attr) + + _collect_bundle_imports(rule_attr)) - copts_attr = _get_opt_attr(rule_attr, 'copts') - is_swift_library = target_kind == 'swift_library' + copts_attr = _get_opt_attr(rule_attr, "copts") + is_swift_library = target_kind == "swift_library" - # Keys for attribute and inheritable_attributes keys must be kept in sync - # with defines in Tulsi's RuleEntry. - attributes = _dict_omitting_none( - binary=_get_label_attr(binary_rule, 'label'), - copts=None if is_swift_library else copts_attr, - swiftc_opts=copts_attr if is_swift_library else None, - datamodels=_collect_xcdatamodeld_files(rule_attr, 'datamodels'), - supporting_files=supporting_files, - xctest_app=_get_label_attr(rule_attr, 'xctest_app.label'), - test_host=_get_label_attr(rule_attr, 'test_host.label'), - test_bundle=_get_label_attr(rule_attr, 'test_bundle.label'), - ) + # Keys for attribute and inheritable_attributes keys must be kept in sync + # with defines in Tulsi's RuleEntry. + attributes = _dict_omitting_none( + binary = _get_label_attr(binary_rule, "label"), + copts = None if is_swift_library else copts_attr, + swiftc_opts = copts_attr if is_swift_library else None, + datamodels = _collect_xcdatamodeld_files(rule_attr, "datamodels"), + supporting_files = supporting_files, + xctest_app = _get_label_attr(rule_attr, "xctest_app.label"), + test_host = _get_label_attr(rule_attr, "test_host.label"), + test_bundle = _get_label_attr(rule_attr, "test_bundle.label"), + ) - # Inheritable attributes are pulled up through dependencies of type 'binary' - # to simplify handling in Tulsi (so it appears as though bridging_header is - # defined on an ios_application rather than its associated objc_binary, for - # example). - inheritable_attributes = _dict_omitting_none( - bridging_header=_collect_first_file(rule_attr, 'bridging_header'), - compiler_defines=_extract_compiler_defines(ctx), - enable_modules=_get_opt_attr(rule_attr, 'enable_modules'), - launch_storyboard=_collect_first_file(rule_attr, 'launch_storyboard'), - pch=_collect_first_file(rule_attr, 'pch'), - ) + # Inheritable attributes are pulled up through dependencies of type 'binary' + # to simplify handling in Tulsi (so it appears as though bridging_header is + # defined on an ios_application rather than its associated objc_binary, for + # example). + inheritable_attributes = _dict_omitting_none( + bridging_header = _collect_first_file(rule_attr, "bridging_header"), + compiler_defines = _extract_compiler_defines(ctx), + enable_modules = _get_opt_attr(rule_attr, "enable_modules"), + launch_storyboard = _collect_first_file(rule_attr, "launch_storyboard"), + pch = _collect_first_file(rule_attr, "pch"), + ) - # Merge any attributes on the "binary" dependency into this container rule. - binary_attributes = _get_opt_attr(binary_rule, 'inheritable_attributes') - if binary_attributes: - inheritable_attributes = binary_attributes + inheritable_attributes + # Merge any attributes on the "binary" dependency into this container rule. + binary_attributes = _get_opt_attr(binary_rule, "inheritable_attributes") + if binary_attributes: + inheritable_attributes = binary_attributes + inheritable_attributes - extensions = [str(t.label) for t in _getattr_as_list(rule_attr, 'extensions')] - # Tulsi considers WatchOS apps and extensions as an "extension" - if target_kind == 'watchos_application': - watch_ext = _get_label_attr(rule_attr, 'extension.label') - extensions.append(watch_ext) - if target_kind == 'ios_application': - watch_app = _get_label_attr(rule_attr, 'watch_application.label') - if watch_app: - extensions.append(watch_app) + extensions = [str(t.label) for t in _getattr_as_list(rule_attr, "extensions")] - # Collect bundle related information. - if AppleBundleInfo in target: - apple_bundle_provider = target[AppleBundleInfo] + # Tulsi considers WatchOS apps and extensions as an "extension" + if target_kind == "watchos_application": + watch_ext = _get_label_attr(rule_attr, "extension.label") + extensions.append(watch_ext) + if target_kind == "ios_application": + watch_app = _get_label_attr(rule_attr, "watch_application.label") + if watch_app: + extensions.append(watch_app) - bundle_name = apple_bundle_provider.bundle_name - bundle_id = apple_bundle_provider.bundle_id - product_type = apple_bundle_provider.product_type + # Collect bundle related information. + if AppleBundleInfo in target: + apple_bundle_provider = target[AppleBundleInfo] - # We only need the infoplist from iOS extension targets. - infoplist = apple_bundle_provider.infoplist if IosExtensionBundleInfo in target else None - else: - bundle_name = None - # For macos_command_line_application, which does not have a AppleBundleInfo - # provider but does have a bundle_id attribute for use in the Info.plist. - bundle_id = _get_opt_attr(rule_attr, 'bundle_id') - product_type = None - infoplist = None + bundle_name = apple_bundle_provider.bundle_name + bundle_id = apple_bundle_provider.bundle_id + product_type = apple_bundle_provider.product_type - # Collect Swift related attributes. - if SwiftInfo in target: - attributes['has_swift_info'] = True - transitive_attributes['swift_language_version'] = target[SwiftInfo].swift_version - transitive_attributes['has_swift_dependency'] = True + # We only need the infoplist from iOS extension targets. + infoplist = apple_bundle_provider.infoplist if IosExtensionBundleInfo in target else None + else: + bundle_name = None - all_attributes = attributes + inheritable_attributes + transitive_attributes + # For macos_command_line_application, which does not have a AppleBundleInfo + # provider but does have a bundle_id attribute for use in the Info.plist. + bundle_id = _get_opt_attr(rule_attr, "bundle_id") + product_type = None + infoplist = None - objc_provider = _get_opt_attr(target, 'objc') - target_includes = [] - target_defines = [] - if objc_provider: - target_includes = [_convert_outpath_to_symlink_path(x) - for x in objc_provider.include] - target_defines = objc_provider.define.to_list() + # Collect Swift related attributes. + if SwiftInfo in target: + attributes["has_swift_info"] = True + transitive_attributes["swift_language_version"] = target[SwiftInfo].swift_version + transitive_attributes["has_swift_dependency"] = True - platform_type, os_deployment_target = _get_deployment_info(target, ctx) - non_arc_srcs = _collect_files(rule, 'attr.non_arc_srcs') + all_attributes = attributes + inheritable_attributes + transitive_attributes - # Collect test information. - if AppleTestInfo in target: - provider = target[AppleTestInfo] - srcs = _depset_to_file_metadata_list(provider.sources) - non_arc_srcs = _depset_to_file_metadata_list(provider.non_arc_sources) - target_includes = [_convert_outpath_to_symlink_path(x) for x in provider.includes.to_list()] - swift_transitive_modules = _depset_to_file_metadata_list(provider.swift_modules) - objc_module_maps = _depset_to_file_metadata_list(provider.module_maps) - else: - swift_transitive_modules = swift_transitive_modules.to_list() - objc_module_maps = objc_module_maps.to_list() + objc_provider = _get_opt_attr(target, "objc") + target_includes = [] + target_defines = [] + if objc_provider: + target_includes = [_convert_outpath_to_symlink_path(x) for x in objc_provider.include] + target_defines = objc_provider.define.to_list() - info = _struct_omitting_none( - artifacts=artifacts, - attr=_struct_omitting_none(**all_attributes), - build_file=ctx.build_file_path, - bundle_id=bundle_id, - bundle_name=bundle_name, - defines=target_defines, - deps=compile_deps, - extensions=extensions, - framework_imports=_collect_framework_imports(rule_attr), - generated_files=generated_files, - generated_non_arc_files=generated_non_arc_files, - includes=target_includes, - os_deployment_target=os_deployment_target, - label=str(target.label), - non_arc_srcs=non_arc_srcs, - secondary_product_artifacts=_collect_secondary_artifacts(target, ctx), - srcs=srcs, - swift_transitive_modules=swift_transitive_modules, - objc_module_maps=objc_module_maps, - type=target_kind, - infoplist=infoplist.basename if infoplist else None, - platform_type=platform_type, - product_type=product_type, - ) + platform_type, os_deployment_target = _get_deployment_info(target, ctx) + non_arc_srcs = _collect_files(rule, "attr.non_arc_srcs") - # Create an action to write out this target's info. - output = ctx.new_file(target.label.name + '.tulsiinfo') - ctx.file_action(output, info.to_json()) - tulsi_info_files += depset([output]) + # Collect test information. + if AppleTestInfo in target: + provider = target[AppleTestInfo] + srcs = _depset_to_file_metadata_list(provider.sources) + non_arc_srcs = _depset_to_file_metadata_list(provider.non_arc_sources) + target_includes = [_convert_outpath_to_symlink_path(x) for x in provider.includes.to_list()] + swift_transitive_modules = _depset_to_file_metadata_list(provider.swift_modules) + objc_module_maps = _depset_to_file_metadata_list(provider.module_maps) + else: + swift_transitive_modules = swift_transitive_modules.to_list() + objc_module_maps = objc_module_maps.to_list() - if infoplist: - tulsi_info_files += [infoplist] + info = _struct_omitting_none( + artifacts = artifacts, + attr = _struct_omitting_none(**all_attributes), + build_file = ctx.build_file_path, + bundle_id = bundle_id, + bundle_name = bundle_name, + defines = target_defines, + deps = compile_deps, + extensions = extensions, + framework_imports = _collect_framework_imports(rule_attr), + generated_files = generated_files, + generated_non_arc_files = generated_non_arc_files, + includes = target_includes, + os_deployment_target = os_deployment_target, + label = str(target.label), + non_arc_srcs = non_arc_srcs, + secondary_product_artifacts = _collect_secondary_artifacts(target, ctx), + srcs = srcs, + swift_transitive_modules = swift_transitive_modules, + objc_module_maps = objc_module_maps, + type = target_kind, + infoplist = infoplist.basename if infoplist else None, + platform_type = platform_type, + product_type = product_type, + ) - artifacts_depset = depset(artifacts) if artifacts else depset() + # Create an action to write out this target's info. + output = ctx.new_file(target.label.name + ".tulsiinfo") + ctx.file_action(output, info.to_json()) + tulsi_info_files += depset([output]) - return struct( - # Matches the --output_groups on the bazel commandline. - output_groups={ - 'tulsi-info': tulsi_info_files, - }, - # The file actions used to save this rule's info and that of all of its - # transitive dependencies. - tulsi_info_files=tulsi_info_files, - # The inheritable attributes of this rule, expressed as a dict instead of - # a struct to allow easy joining. - inheritable_attributes=inheritable_attributes, - # Transitive info that should be applied to every rule that depends on - # this rule. - transitive_attributes=transitive_attributes, - # Artifacts from this rule. - artifacts=artifacts_depset, - # Filtering information for this target. - filtering_info=_target_filtering_info(ctx), - ) + if infoplist: + tulsi_info_files += [infoplist] + + artifacts_depset = depset(artifacts) if artifacts else depset() + + return struct( + # Matches the --output_groups on the bazel commandline. + output_groups = { + "tulsi-info": tulsi_info_files, + }, + # The file actions used to save this rule's info and that of all of its + # transitive dependencies. + tulsi_info_files = tulsi_info_files, + # The inheritable attributes of this rule, expressed as a dict instead of + # a struct to allow easy joining. + inheritable_attributes = inheritable_attributes, + # Transitive info that should be applied to every rule that depends on + # this rule. + transitive_attributes = transitive_attributes, + # Artifacts from this rule. + artifacts = artifacts_depset, + # Filtering information for this target. + filtering_info = _target_filtering_info(ctx), + ) def _collect_bundle_info(target): - """Returns Apple bundle info for the given target, None if not a bundle.""" - if AppleBundleInfo in target: - apple_bundle = target[AppleBundleInfo] - has_dsym = (apple_common.AppleDebugOutputs in target) - return [struct( - archive_root=apple_bundle.archive_root, - bundle_name=apple_bundle.bundle_name, - bundle_extension=apple_bundle.bundle_extension, - has_dsym=has_dsym)] + """Returns Apple bundle info for the given target, None if not a bundle.""" + if AppleBundleInfo in target: + apple_bundle = target[AppleBundleInfo] + has_dsym = (apple_common.AppleDebugOutputs in target) + return [struct( + archive_root = apple_bundle.archive_root, + bundle_name = apple_bundle.bundle_name, + bundle_extension = apple_bundle.bundle_extension, + has_dsym = has_dsym, + )] - return None + return None -# Due to b/71744111 we have to manually re-create tag filtering for test_suite -# rules. + # Due to b/71744111 we have to manually re-create tag filtering for test_suite + # rules. + def _tags_conform_to_filter(tags, filter): - """Mirrors Bazel tag filtering for test_suites. + """Mirrors Bazel tag filtering for test_suites. This makes sure that the target has all of the required tags and none of the excluded tags before we include them within a test_suite. @@ -755,158 +764,159 @@ """ - # None of the excluded tags can be present. - for exclude in filter.excluded_tags: - if exclude in tags: - return False + # None of the excluded tags can be present. + for exclude in filter.excluded_tags: + if exclude in tags: + return False - # All of the required tags must be present. - for required in filter.required_tags: - if required not in tags: - return False + # All of the required tags must be present. + for required in filter.required_tags: + if required not in tags: + return False - # All filters have been satisfied. - return True + # All filters have been satisfied. + return True def _filter_for_rule(rule): - """Returns a filter for test_suite rules and None for other rules.""" - if rule.kind != 'test_suite': - return None + """Returns a filter for test_suite rules and None for other rules.""" + if rule.kind != "test_suite": + return None - excluded_tags = [] - required_tags = [] + excluded_tags = [] + required_tags = [] - tags = _getattr_as_list(rule, 'attr.tags') + tags = _getattr_as_list(rule, "attr.tags") - for tag in tags: - if tag.startswith('-'): - excluded_tags.append(tag[1:]) - elif tag.startswith('+'): - required_tags.append(tag[1:]) - elif tag == 'manual': - # The manual tag is treated specially; it is ignored for filters. - continue - else: - required_tags.append(tag) - return struct( - excluded_tags=excluded_tags, - required_tags=required_tags, - ) + for tag in tags: + if tag.startswith("-"): + excluded_tags.append(tag[1:]) + elif tag.startswith("+"): + required_tags.append(tag[1:]) + elif tag == "manual": + # The manual tag is treated specially; it is ignored for filters. + continue + else: + required_tags.append(tag) + return struct( + excluded_tags = excluded_tags, + required_tags = required_tags, + ) def _filter_deps(filter, deps): - """Filters dep targets based on tags.""" - if not filter: - return deps + """Filters dep targets based on tags.""" + if not filter: + return deps - kept_deps = [] - for dep in deps: - info = dep.filtering_info - # Only attempt to filter targets that support filtering. - # test_suites in a test_suite are not filtered, but their - # tests are. - if not info or _tags_conform_to_filter(info.tags, filter): - kept_deps.append(dep) - return kept_deps + kept_deps = [] + for dep in deps: + info = dep.filtering_info + + # Only attempt to filter targets that support filtering. + # test_suites in a test_suite are not filtered, but their + # tests are. + if not info or _tags_conform_to_filter(info.tags, filter): + kept_deps.append(dep) + return kept_deps def _tulsi_outputs_aspect(target, ctx): - """Collects outputs of each build invocation.""" + """Collects outputs of each build invocation.""" - rule = ctx.rule - target_kind = rule.kind - rule_attr = _get_opt_attr(rule, 'attr') - tulsi_generated_files = depset() + rule = ctx.rule + target_kind = rule.kind + rule_attr = _get_opt_attr(rule, "attr") + tulsi_generated_files = depset() - # A set of all bundles embedded into this target, including deps. - # We intentionally do not collect info about _current_ target to exclude the - # root target, which will be covered by other structs in this aspect, from the - # set. - embedded_bundles = depset() + # A set of all bundles embedded into this target, including deps. + # We intentionally do not collect info about _current_ target to exclude the + # root target, which will be covered by other structs in this aspect, from the + # set. + embedded_bundles = depset() - for attr_name in _TULSI_COMPILE_DEPS: - deps = _getattr_as_list(rule_attr, attr_name) - for dep in deps: - if hasattr(dep, 'tulsi_generated_files'): - tulsi_generated_files += dep.tulsi_generated_files + for attr_name in _TULSI_COMPILE_DEPS: + deps = _getattr_as_list(rule_attr, attr_name) + for dep in deps: + if hasattr(dep, "tulsi_generated_files"): + tulsi_generated_files += dep.tulsi_generated_files - # Retrieve the bundle info for embeddable attributes. - if attr_name not in _TULSI_NON_EMBEDDEDABLE_ATTRS: - dep_bundle_info = _collect_bundle_info(dep) - if dep_bundle_info: - embedded_bundles += dep_bundle_info - if hasattr(dep, 'transitive_embedded_bundles'): - embedded_bundles += dep.transitive_embedded_bundles + # Retrieve the bundle info for embeddable attributes. + if attr_name not in _TULSI_NON_EMBEDDEDABLE_ATTRS: + dep_bundle_info = _collect_bundle_info(dep) + if dep_bundle_info: + embedded_bundles += dep_bundle_info + if hasattr(dep, "transitive_embedded_bundles"): + embedded_bundles += dep.transitive_embedded_bundles - artifact = None - bundle_name = None - archive_root = None - bundle_dir = None - if AppleBundleInfo in target: - bundle_info = target[AppleBundleInfo] + artifact = None + bundle_name = None + archive_root = None + bundle_dir = None + if AppleBundleInfo in target: + bundle_info = target[AppleBundleInfo] - artifact = bundle_info.archive.path - archive_root = bundle_info.archive_root + artifact = bundle_info.archive.path + archive_root = bundle_info.archive_root - bundle_name = bundle_info.bundle_name - bundle_dir = bundle_info.bundle_dir - elif target_kind == 'macos_command_line_application': - # Special support for macos_command_line_application which does not have an - # AppleBundleInfo provider. + bundle_name = bundle_info.bundle_name + bundle_dir = bundle_info.bundle_dir + elif target_kind == "macos_command_line_application": + # Special support for macos_command_line_application which does not have an + # AppleBundleInfo provider. - # Both the dSYM binary and executable binary don't have an extension, so - # pick the first extension-less file not in a DWARF folder. - artifacts = [x.path for x in target.files.to_list() - if x.extension == '' - and 'Contents/Resources/DWARF' not in x.path] - if len(artifacts) > 0: - artifact = artifacts[0] + # Both the dSYM binary and executable binary don't have an extension, so + # pick the first extension-less file not in a DWARF folder. + artifacts = [x.path for x in target.files.to_list() if x.extension == "" and + "Contents/Resources/DWARF" not in x.path] + if len(artifacts) > 0: + artifact = artifacts[0] - # Collect generated files for bazel_build.py to copy under Tulsi root. - all_files = depset() - if target_kind in _SOURCE_GENERATING_RULES + _NON_ARC_SOURCE_GENERATING_RULES: - objc_provider = _get_opt_attr(target, 'objc') - if hasattr(objc_provider, 'source') and hasattr(objc_provider, 'header'): - all_files += objc_provider.source - all_files += objc_provider.header + # Collect generated files for bazel_build.py to copy under Tulsi root. + all_files = depset() + if target_kind in _SOURCE_GENERATING_RULES + _NON_ARC_SOURCE_GENERATING_RULES: + objc_provider = _get_opt_attr(target, "objc") + if hasattr(objc_provider, "source") and hasattr(objc_provider, "header"): + all_files += objc_provider.source + all_files += objc_provider.header - all_files += _collect_swift_header(target) - all_files += _collect_swift_modules(target) - all_files += _collect_module_maps(target) - all_files += (_collect_artifacts(rule, 'attr.srcs') - + _collect_artifacts(rule, 'attr.hdrs') - + _collect_artifacts(rule, 'attr.textual_hdrs')) - all_files += _collect_supporting_files(rule_attr, convert_to_metadata=False) - source_files = [x for x in target.files.to_list() - if x.extension.lower() in _GENERATED_SOURCE_FILE_EXTENSIONS] - all_files = depset(source_files, transitive=[all_files]) + all_files += _collect_swift_header(target) + all_files += _collect_swift_modules(target) + all_files += _collect_module_maps(target) + all_files += (_collect_artifacts(rule, "attr.srcs") + + _collect_artifacts(rule, "attr.hdrs") + + _collect_artifacts(rule, "attr.textual_hdrs")) + all_files += _collect_supporting_files(rule_attr, convert_to_metadata = False) + source_files = [x for x in target.files.to_list() if x.extension.lower() in _GENERATED_SOURCE_FILE_EXTENSIONS] + all_files = depset(source_files, transitive = [all_files]) - tulsi_generated_files += depset( - [x for x in all_files.to_list() if not x.is_source]) + tulsi_generated_files += depset( + [x for x in all_files.to_list() if not x.is_source], + ) - has_dsym = False - if hasattr(ctx.fragments, 'objc'): - # Check the fragment directly, as macos_command_line_application does not - # propagate apple_common.AppleDebugOutputs. - has_dsym = ctx.fragments.objc.generate_dsym + has_dsym = False + if hasattr(ctx.fragments, "objc"): + # Check the fragment directly, as macos_command_line_application does not + # propagate apple_common.AppleDebugOutputs. + has_dsym = ctx.fragments.objc.generate_dsym - info = _struct_omitting_none( - artifact=artifact, - bundle_dir=bundle_dir, - archive_root=archive_root, - generated_sources=[(x.path, x.short_path) for x in tulsi_generated_files], - bundle_name=bundle_name, - embedded_bundles=embedded_bundles.to_list(), - has_dsym=has_dsym) + info = _struct_omitting_none( + artifact = artifact, + bundle_dir = bundle_dir, + archive_root = archive_root, + generated_sources = [(x.path, x.short_path) for x in tulsi_generated_files], + bundle_name = bundle_name, + embedded_bundles = embedded_bundles.to_list(), + has_dsym = has_dsym, + ) - output = ctx.new_file(target.label.name + '.tulsiouts') - ctx.file_action(output, info.to_json()) + output = ctx.new_file(target.label.name + ".tulsiouts") + ctx.file_action(output, info.to_json()) - return struct( - output_groups={ - 'tulsi-outputs': [output], - }, - tulsi_generated_files=tulsi_generated_files, - transitive_embedded_bundles=embedded_bundles - ) + return struct( + output_groups = { + "tulsi-outputs": [output], + }, + tulsi_generated_files = tulsi_generated_files, + transitive_embedded_bundles = embedded_bundles, + ) tulsi_sources_aspect = aspect( attr_aspects = _TULSI_COMPILE_DEPS,
diff --git a/src/TulsiGeneratorIntegrationTests/Resources/ComplexSingle.bzl b/src/TulsiGeneratorIntegrationTests/Resources/ComplexSingle.bzl index 18cd62b..6734ded 100644 --- a/src/TulsiGeneratorIntegrationTests/Resources/ComplexSingle.bzl +++ b/src/TulsiGeneratorIntegrationTests/Resources/ComplexSingle.bzl
@@ -15,5 +15,5 @@ """Mock Skylark file for testing.""" def test_macro(): - """A do-nothing macro for use in Tulsi tests.""" - pass + """A do-nothing macro for use in Tulsi tests.""" + pass
diff --git a/version.bzl b/version.bzl index b5f187f..45203db 100644 --- a/version.bzl +++ b/version.bzl
@@ -28,14 +28,14 @@ ) def fill_info_plist_impl(ctx): - ctx.actions.expand_template( - template = ctx.file.template, - output = ctx.outputs.out, - substitutions = { - "$(TULSI_VERSIONINFO_ABOUT)": TULSI_VERSIONINFO_ABOUT, - "$(PRODUCT_MODULE_NAME)": TULSI_PRODUCT_NAME, - }, - ) + ctx.actions.expand_template( + template = ctx.file.template, + output = ctx.outputs.out, + substitutions = { + "$(TULSI_VERSIONINFO_ABOUT)": TULSI_VERSIONINFO_ABOUT, + "$(PRODUCT_MODULE_NAME)": TULSI_PRODUCT_NAME, + }, + ) fill_info_plist = rule( attrs = {