mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 13:35:19 +00:00
448 lines
14 KiB
Python
448 lines
14 KiB
Python
load("@build_bazel_rules_swift//swift:swift.bzl", "SwiftInfo")
|
|
load("@bazel_skylib//lib:paths.bzl", "paths")
|
|
load("@bazel_skylib//lib:dicts.bzl", "dicts")
|
|
|
|
# Define provider to propagate data
|
|
SPMModulesInfo = provider(
|
|
fields = {
|
|
"modules": "Dictionary of module information",
|
|
"transitive_sources": "Depset of all transitive source files",
|
|
}
|
|
)
|
|
|
|
_IGNORE_CC_LIBRARY_ATTRS = [
|
|
"data",
|
|
"applicable_licenses",
|
|
"alwayslink",
|
|
"aspect_hints",
|
|
"compatible_with",
|
|
"deprecation",
|
|
"exec_compatible_with",
|
|
"exec_properties",
|
|
"expect_failure",
|
|
"features",
|
|
"generator_function",
|
|
"generator_location",
|
|
"generator_name",
|
|
"generator_platform",
|
|
"generator_script",
|
|
"generator_tool",
|
|
"generator_toolchain",
|
|
"generator_toolchain_type",
|
|
"licenses",
|
|
"linkstamp",
|
|
"linkstatic",
|
|
"name",
|
|
"restricted_to",
|
|
"tags",
|
|
"target_compatible_with",
|
|
"testonly",
|
|
"to_json",
|
|
"to_proto",
|
|
"toolchains",
|
|
"transitive_configs",
|
|
"visibility",
|
|
"win_def_file",
|
|
"linkopts",
|
|
]
|
|
|
|
_IGNORE_CC_LIBRARY_EMPTY_ATTRS = [
|
|
"additional_compiler_inputs",
|
|
"additional_linker_inputs",
|
|
"hdrs_check",
|
|
"implementation_deps",
|
|
"include_prefix",
|
|
"strip_include_prefix",
|
|
"local_defines",
|
|
]
|
|
|
|
_CC_LIBRARY_ATTRS = {
|
|
"copts": [],
|
|
"defines": [],
|
|
"deps": [],
|
|
"hdrs": [],
|
|
"includes": [],
|
|
"srcs": [],
|
|
"textual_hdrs": [],
|
|
}
|
|
|
|
_CC_LIBRARY_REQUIRED_ATTRS = {
|
|
}
|
|
|
|
_IGNORE_OBJC_LIBRARY_ATTRS = [
|
|
"data",
|
|
"alwayslink",
|
|
"applicable_licenses",
|
|
"aspect_hints",
|
|
"compatible_with",
|
|
"enable_modules",
|
|
"exec_compatible_with",
|
|
"exec_properties",
|
|
"expect_failure",
|
|
"features",
|
|
"generator_function",
|
|
"generator_location",
|
|
"generator_name",
|
|
"deprecation",
|
|
"module_name",
|
|
"name",
|
|
"stamp",
|
|
"tags",
|
|
"target_compatible_with",
|
|
"testonly",
|
|
"to_json",
|
|
"to_proto",
|
|
"toolchains",
|
|
"transitive_configs",
|
|
"visibility",
|
|
]
|
|
|
|
_IGNORE_OBJC_LIBRARY_EMPTY_ATTRS = [
|
|
"implementation_deps",
|
|
"linkopts",
|
|
"module_map",
|
|
"non_arc_srcs",
|
|
"pch",
|
|
"restricted_to",
|
|
"textual_hdrs",
|
|
"sdk_includes",
|
|
]
|
|
|
|
_OBJC_LIBRARY_ATTRS = {
|
|
"copts": [],
|
|
"defines": [],
|
|
"deps": [],
|
|
"hdrs": [],
|
|
"srcs": [],
|
|
"sdk_dylibs": [],
|
|
"sdk_frameworks": [],
|
|
"weak_sdk_frameworks": [],
|
|
"includes": [],
|
|
}
|
|
|
|
_OBJC_LIBRARY_REQUIRED_ATTRS = [
|
|
"module_name",
|
|
]
|
|
|
|
_IGNORE_SWIFT_LIBRARY_ATTRS = [
|
|
"data",
|
|
"always_include_developer_search_paths",
|
|
"alwayslink",
|
|
"applicable_licenses",
|
|
"aspect_hints",
|
|
"compatible_with",
|
|
"deprecation",
|
|
"exec_compatible_with",
|
|
"exec_properties",
|
|
"expect_failure",
|
|
"features",
|
|
"generated_header_name",
|
|
"generates_header",
|
|
"generator_function",
|
|
"generator_location",
|
|
"generator_name",
|
|
"linkstatic",
|
|
"module_name",
|
|
"name",
|
|
"package_name",
|
|
"restricted_to",
|
|
"tags",
|
|
"target_compatible_with",
|
|
"testonly",
|
|
"to_json",
|
|
"to_proto",
|
|
"toolchains",
|
|
"transitive_configs",
|
|
"visibility",
|
|
]
|
|
|
|
_IGNORE_SWIFT_LIBRARY_EMPTY_ATTRS = [
|
|
"plugins",
|
|
"private_deps",
|
|
"swiftc_inputs",
|
|
]
|
|
|
|
_SWIFT_LIBRARY_ATTRS = {
|
|
"copts": [],
|
|
"defines": [],
|
|
"deps": [],
|
|
"linkopts": [],
|
|
"srcs": [],
|
|
}
|
|
|
|
_SWIFT_LIBRARY_REQUIRED_ATTRS = [
|
|
"module_name",
|
|
]
|
|
|
|
_LIBRARY_CONFIGS = {
|
|
"cc_library": {
|
|
"ignore_attrs": _IGNORE_CC_LIBRARY_ATTRS,
|
|
"ignore_empty_attrs": _IGNORE_CC_LIBRARY_EMPTY_ATTRS,
|
|
"handled_attrs": _CC_LIBRARY_ATTRS,
|
|
"required_attrs": _CC_LIBRARY_REQUIRED_ATTRS,
|
|
},
|
|
"objc_library": {
|
|
"ignore_attrs": _IGNORE_OBJC_LIBRARY_ATTRS,
|
|
"ignore_empty_attrs": _IGNORE_OBJC_LIBRARY_EMPTY_ATTRS,
|
|
"handled_attrs": _OBJC_LIBRARY_ATTRS,
|
|
"required_attrs": _OBJC_LIBRARY_REQUIRED_ATTRS,
|
|
},
|
|
"swift_library": {
|
|
"ignore_attrs": _IGNORE_SWIFT_LIBRARY_ATTRS,
|
|
"ignore_empty_attrs": _IGNORE_SWIFT_LIBRARY_EMPTY_ATTRS,
|
|
"handled_attrs": _SWIFT_LIBRARY_ATTRS,
|
|
"required_attrs": _SWIFT_LIBRARY_REQUIRED_ATTRS,
|
|
},
|
|
}
|
|
|
|
def get_rule_atts(rule):
|
|
if rule.kind in _LIBRARY_CONFIGS:
|
|
config = _LIBRARY_CONFIGS[rule.kind]
|
|
ignore_attrs = config["ignore_attrs"]
|
|
ignore_empty_attrs = config["ignore_empty_attrs"]
|
|
handled_attrs = config["handled_attrs"]
|
|
required_attrs = config["required_attrs"]
|
|
|
|
for attr_name in dir(rule.attr):
|
|
if attr_name.startswith("_"):
|
|
continue
|
|
if attr_name in ignore_attrs:
|
|
continue
|
|
if attr_name in ignore_empty_attrs:
|
|
attr_value = getattr(rule.attr, attr_name)
|
|
if attr_value == [] or attr_value == None or attr_value == "":
|
|
continue
|
|
else:
|
|
fail("Attribute {} is not empty: {}".format(attr_name, attr_value))
|
|
if attr_name in handled_attrs:
|
|
continue
|
|
fail("Unknown attribute: {}".format(attr_name))
|
|
|
|
result = dict()
|
|
result["type"] = rule.kind
|
|
for attr_name in handled_attrs:
|
|
if hasattr(rule.attr, attr_name):
|
|
result[attr_name] = getattr(rule.attr, attr_name)
|
|
else:
|
|
result[attr_name] = handled_attrs[attr_name] # Use default value
|
|
for attr_name in required_attrs:
|
|
if not hasattr(rule.attr, attr_name):
|
|
if rule.kind == "objc_library" and attr_name == "module_name":
|
|
result[attr_name] = getattr(rule.attr, "name")
|
|
else:
|
|
fail("Required attribute {} is missing".format(attr_name))
|
|
else:
|
|
result[attr_name] = getattr(rule.attr, attr_name)
|
|
result["name"] = getattr(rule.attr, "name")
|
|
return result
|
|
elif rule.kind == "ios_application":
|
|
result = dict()
|
|
result["type"] = "ios_application"
|
|
return result
|
|
elif rule.kind == "generate_spm":
|
|
result = dict()
|
|
result["type"] = "root"
|
|
return result
|
|
elif rule.kind == "apple_static_xcframework_import":
|
|
result = dict()
|
|
result["type"] = "apple_static_xcframework_import"
|
|
return result
|
|
else:
|
|
fail("Unknown rule kind: {}".format(rule.kind))
|
|
|
|
def _collect_spm_modules_impl(target, ctx):
|
|
# Skip targets without DefaultInfo
|
|
if not DefaultInfo in target:
|
|
return []
|
|
|
|
# Get module name
|
|
module_name = ctx.label.name
|
|
if hasattr(ctx.rule.attr, "module_name"):
|
|
module_name = ctx.rule.attr.module_name or ctx.label.name
|
|
|
|
# Collect all modules and transitive sources from dependencies first
|
|
all_modules = {}
|
|
dep_transitive_sources_list = []
|
|
|
|
if hasattr(ctx.rule.attr, "deps"):
|
|
for dep in ctx.rule.attr.deps:
|
|
if SPMModulesInfo in dep:
|
|
# Merge the modules dictionaries
|
|
for label, info in dep[SPMModulesInfo].modules.items():
|
|
all_modules[label] = info
|
|
# Add transitive sources depset from dependency to the list
|
|
dep_transitive_sources_list.append(dep[SPMModulesInfo].transitive_sources)
|
|
|
|
# Merge all transitive sources from dependencies
|
|
transitive_sources_from_deps = depset(transitive = dep_transitive_sources_list)
|
|
|
|
# Keep this for debugging later
|
|
# if result_attrs["type"] == "swift_library":
|
|
# print("Processing rule {}".format(ctx.label.name))
|
|
# print("ctx.rule.kind = {}".format(ctx.rule.kind))
|
|
# for attr_name in dir(ctx.rule.attr):
|
|
# print(" attr1: {}".format(attr_name))
|
|
|
|
result_attrs = get_rule_atts(ctx.rule)
|
|
|
|
sources = []
|
|
current_target_src_files = []
|
|
if "srcs" in result_attrs:
|
|
for src_target in result_attrs["srcs"]:
|
|
src_files = src_target.files.to_list()
|
|
for f in src_files:
|
|
if f.extension in ["swift", "cc", "cpp", "h", "m", "mm", "s", "S"]:
|
|
current_target_src_files.append(f)
|
|
for src_file in src_files:
|
|
sources.append(src_file.path)
|
|
current_target_sources = depset(current_target_src_files)
|
|
|
|
headers = []
|
|
current_target_hdr_files = []
|
|
if "hdrs" in result_attrs:
|
|
for hdr_target in result_attrs["hdrs"]:
|
|
hdr_files = hdr_target.files.to_list()
|
|
for f in hdr_files:
|
|
current_target_hdr_files.append(f)
|
|
for hdr_file in hdr_files:
|
|
headers.append(hdr_file.path)
|
|
current_target_headers = depset(current_target_hdr_files)
|
|
|
|
module_type = result_attrs["type"]
|
|
|
|
if module_type == "root":
|
|
pass
|
|
elif module_type == "apple_static_xcframework_import":
|
|
pass
|
|
elif module_type == "objc_library" or module_type == "swift_library" or module_type == "cc_library":
|
|
# Collect dependency labels
|
|
dep_names = []
|
|
if "deps" in result_attrs:
|
|
for dep in result_attrs["deps"]:
|
|
if hasattr(dep, "label"):
|
|
dep_label = str(dep.label)
|
|
dep_name = dep_label.split(":")[-1]
|
|
dep_names.append(dep_name)
|
|
else:
|
|
fail("Missing dependency label")
|
|
|
|
if module_type == "objc_library" or module_type == "swift_library":
|
|
if result_attrs["module_name"] != result_attrs["name"]:
|
|
fail("Module name mismatch: {} != {}".format(result_attrs["module_name"], result_attrs["name"]))
|
|
|
|
# Extract the path from the label
|
|
# Example: @//path/ModuleName:ModuleSubname -> path/ModuleName
|
|
if not str(ctx.label).startswith("@//"):
|
|
fail("Invalid label: {}".format(ctx.label))
|
|
module_path = str(ctx.label).split(":")[0].split("@//")[1]
|
|
|
|
if module_type == "objc_library":
|
|
module_info = {
|
|
"name": result_attrs["name"],
|
|
"type": module_type,
|
|
"path": module_path,
|
|
"defines": result_attrs["defines"],
|
|
"deps": dep_names,
|
|
"sources": sorted(sources + headers),
|
|
"module_name": module_name,
|
|
"copts": result_attrs["copts"],
|
|
"sdk_frameworks": result_attrs["sdk_frameworks"],
|
|
"sdk_dylibs": result_attrs["sdk_dylibs"],
|
|
"weak_sdk_frameworks": result_attrs["weak_sdk_frameworks"],
|
|
"includes": result_attrs["includes"],
|
|
}
|
|
elif module_type == "cc_library":
|
|
module_info = {
|
|
"name": result_attrs["name"],
|
|
"type": module_type,
|
|
"path": module_path,
|
|
"defines": result_attrs["defines"],
|
|
"deps": dep_names,
|
|
"sources": sorted(sources + headers),
|
|
"module_name": module_name,
|
|
"copts": result_attrs["copts"],
|
|
"includes": result_attrs["includes"],
|
|
}
|
|
elif module_type == "swift_library":
|
|
module_info = {
|
|
"name": result_attrs["name"],
|
|
"type": module_type,
|
|
"path": module_path,
|
|
"deps": dep_names,
|
|
"sources": sorted(sources),
|
|
"module_name": module_name,
|
|
"copts": result_attrs["copts"],
|
|
}
|
|
else:
|
|
fail("Unknown module type: {}".format(module_type))
|
|
|
|
if result_attrs["name"] in all_modules:
|
|
fail("Duplicate module name: {}".format(result_attrs["name"]))
|
|
all_modules[result_attrs["name"]] = module_info
|
|
elif result_attrs["type"] == "ios_application":
|
|
pass
|
|
else:
|
|
fail("Unknown rule type: {}".format(ctx.rule.kind))
|
|
|
|
# Add current target's sources and headers to the transitive set
|
|
final_transitive_sources = depset(transitive = [
|
|
transitive_sources_from_deps,
|
|
current_target_sources,
|
|
current_target_headers,
|
|
])
|
|
|
|
# Return both the SPM output files and the provider with modules data and sources
|
|
return [
|
|
SPMModulesInfo(
|
|
modules = all_modules,
|
|
transitive_sources = final_transitive_sources,
|
|
),
|
|
]
|
|
|
|
spm_modules_aspect = aspect(
|
|
implementation = _collect_spm_modules_impl,
|
|
attr_aspects = ["deps"],
|
|
)
|
|
|
|
def _generate_spm_impl(ctx):
|
|
outputs = []
|
|
dep_transitive_sources_list = []
|
|
|
|
if len(ctx.attr.deps) != 1:
|
|
fail("generate_spm must have exactly one dependency")
|
|
if SPMModulesInfo not in ctx.attr.deps[0]:
|
|
fail("generate_spm must have a dependency with SPMModulesInfo provider")
|
|
|
|
spm_info = ctx.attr.deps[0][SPMModulesInfo]
|
|
modules = spm_info.modules
|
|
|
|
# Declare and write the modules JSON file
|
|
modules_json_out = ctx.actions.declare_file("%s_modules.json" % ctx.label.name)
|
|
ctx.actions.write(
|
|
output = modules_json_out,
|
|
content = json.encode_indent(modules, indent = " "), # Use encode_indent for readability
|
|
)
|
|
outputs.append(modules_json_out)
|
|
|
|
for dep in ctx.attr.deps:
|
|
if SPMModulesInfo in dep:
|
|
# Add transitive sources depset from dependency
|
|
dep_transitive_sources_list.append(dep[SPMModulesInfo].transitive_sources)
|
|
|
|
# Merge all transitive sources from dependencies
|
|
transitive_sources_from_deps = depset(transitive = dep_transitive_sources_list)
|
|
|
|
# Return DefaultInfo containing only the output files in the 'files' field,
|
|
# but include the transitive sources in 'runfiles' to enforce the dependency.
|
|
return [DefaultInfo(
|
|
files = depset(outputs),
|
|
runfiles = ctx.runfiles(transitive_files = transitive_sources_from_deps),
|
|
)]
|
|
|
|
generate_spm = rule(
|
|
implementation = _generate_spm_impl,
|
|
attrs = {
|
|
'deps' : attr.label_list(aspects = [spm_modules_aspect]),
|
|
},
|
|
)
|