Skip to content

Commit

Permalink
Support anonymizing symbol extraction actions
Browse files Browse the repository at this point in the history
Summary:
These are frequently duplicated across the different link groups used in
Python binary native python linking.

Reviewed By: christycylee

Differential Revision: D47368429

fbshipit-source-id: 074848534bf94020b805a77aa138872006806856
  • Loading branch information
andrewjcg authored and facebook-github-bot committed Jul 18, 2023
1 parent 46a5c48 commit c456370
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 13 deletions.
6 changes: 5 additions & 1 deletion prelude/cxx/link_groups.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,8 @@ def _stub_library(
def _symbol_files_for_link_group(
ctx: "context",
lib: LinkedObject.type,
prefer_local: bool = False) -> ("artifact", "artifact"):
prefer_local: bool = False,
anonymous: bool = False) -> ("artifact", "artifact"):
"""
Find and return all undefined and global symbols form the given library.
"""
Expand All @@ -652,6 +653,7 @@ def _symbol_files_for_link_group(
output = lib.output,
category_prefix = "link_groups",
prefer_local = prefer_local,
anonymous = anonymous,
)

# Extract global symbols.
Expand All @@ -660,6 +662,7 @@ def _symbol_files_for_link_group(
output = lib.output,
category_prefix = "link_groups",
prefer_local = prefer_local,
anonymous = anonymous,
)

return undefined_symfile, global_symfile
Expand Down Expand Up @@ -805,6 +808,7 @@ def create_link_groups(
undefined_symfile, global_symfile = _symbol_files_for_link_group(
ctx = ctx,
lib = link_group_lib,
anonymous = anonymous,
)
undefined_symfiles.append(undefined_symfile)
global_symfiles.append(global_symfile)
Expand Down
6 changes: 3 additions & 3 deletions prelude/cxx/omnibus.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -596,9 +596,9 @@ def _create_global_symbols_version_script(
# We should probably split this up and operate on individual libs.
if excluded:
global_symbols_files.append(extract_symbol_names(
ctx,
"__excluded_libs__.global_syms.txt",
excluded,
ctx = ctx,
name = "__excluded_libs__.global_syms.txt",
objects = excluded,
dynamic = True,
global_only = True,
category = "omnibus_global_syms_excluded_libs",
Expand Down
97 changes: 88 additions & 9 deletions prelude/cxx/symbols.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
# of this source tree.

load("@prelude//:paths.bzl", "paths")
load("@prelude//cxx:cxx_toolchain_types.bzl", "CxxToolchainInfo")
load(":cxx_context.bzl", "get_cxx_toolchain_info")

def extract_symbol_names(
def _extract_symbol_names(
ctx: "context",
name: str,
objects: ["artifact"],
Expand Down Expand Up @@ -75,29 +76,107 @@ def extract_symbol_names(
)
return output

def extract_undefined_syms(ctx: "context", output: "artifact", category_prefix: str, prefer_local: bool) -> "artifact":
_SymbolsInfo = provider(fields = [
"artifact", # "artifact"
])

def _anon_extract_symbol_names_impl(ctx):
output = _extract_symbol_names(
ctx = ctx,
category = ctx.attrs.category,
dynamic = ctx.attrs.dynamic,
global_only = ctx.attrs.global_only,
identifier = ctx.attrs.identifier,
local_only = ctx.attrs.local_only,
name = ctx.attrs.output,
objects = ctx.attrs.objects,
prefer_local = ctx.attrs.prefer_local,
undefined_only = ctx.attrs.undefined_only,
)
return [DefaultInfo(), _SymbolsInfo(artifact = output)]

# Anonymous wrapper for `extract_symbol_names`.
_anon_extract_symbol_names_impl_rule = rule(
impl = _anon_extract_symbol_names_impl,
attrs = {
"category": attrs.string(),
"dynamic": attrs.bool(default = False),
"global_only": attrs.bool(default = False),
"identifier": attrs.option(attrs.string(), default = None),
"local_only": attrs.bool(default = False),
"objects": attrs.list(attrs.source()),
"output": attrs.string(),
"prefer_local": attrs.bool(default = False),
"undefined_only": attrs.bool(default = False),
"_cxx_toolchain": attrs.dep(providers = [CxxToolchainInfo]),
},
)

def extract_symbol_names(
ctx: "context",
name: str,
anonymous: bool = False,
**kwargs) -> ["artifact", "promise_artifact"]:
"""
Generate a file with a sorted list of symbol names extracted from the given
native objects.
"""

if anonymous:
anon_providers = ctx.actions.anon_target(
_anon_extract_symbol_names_impl_rule,
dict(
_cxx_toolchain = ctx.attrs._cxx_toolchain,
output = name,
**kwargs
),
)
return ctx.actions.artifact_promise(
anon_providers.map(lambda p: p[_SymbolsInfo].artifact),
short_path = paths.join("__symbols__", name),
)
else:
return _extract_symbol_names(
ctx = ctx,
name = name,
**kwargs
)

def extract_undefined_syms(
ctx: "context",
output: "artifact",
category_prefix: str,
prefer_local: bool = False,
anonymous: bool = False) -> "artifact":
return extract_symbol_names(
ctx,
output.short_path + ".undefined_syms.txt",
[output],
ctx = ctx,
name = output.short_path + ".undefined_syms.txt",
objects = [output],
dynamic = True,
global_only = True,
undefined_only = True,
category = "{}_undefined_syms".format(category_prefix),
identifier = output.short_path,
prefer_local = prefer_local,
anonymous = anonymous,
)

def extract_global_syms(ctx: "context", output: "artifact", category_prefix: str, prefer_local: bool) -> "artifact":
def extract_global_syms(
ctx: "context",
output: "artifact",
category_prefix: str,
prefer_local: bool = False,
anonymous: bool = False) -> "artifact":
return extract_symbol_names(
ctx,
output.short_path + ".global_syms.txt",
[output],
ctx = ctx,
name = output.short_path + ".global_syms.txt",
objects = [output],
dynamic = True,
global_only = True,
category = "{}_global_syms".format(category_prefix),
identifier = output.short_path,
prefer_local = prefer_local,
anonymous = anonymous,
)

def _create_symbols_file_from_script(
Expand Down

0 comments on commit c456370

Please sign in to comment.