Skip to content

Commit

Permalink
[antlir] Shared library support
Browse files Browse the repository at this point in the history
Summary:
With certain build configs/modes, some targets require the presence of shared file object to run correctly. `fbpkg.builder` accommodates this by shipping these files in the fbpkg itself. Antlir should do the same to do allow link group binaries to run in images

Consulted link group experts who deem this the right approach https://fb.workplace.com/groups/620835969447929/permalink/1045577510307104/

Test Plan:
- `buck test mode/opt-asan-ubsan antlir/antlir2/features/install/tests/fb:t
est-installed-binary-with-link-groups`
   - manually removed forwarding the shared libraries in install.bzl and observed the test fail with `/foo/cpp-bin-with-link-groups: error while loading shared libraries: libmkl_intel_lp64.so.2: cannot open shared object file: No such file or directory` as expected

Reviewed By: sergeyfd

Differential Revision: D64184556

fbshipit-source-id: 8a179bcb1f68dc340c976c90c5569c4c7d9a4957
  • Loading branch information
Naveed Golafshani authored and facebook-github-bot committed Oct 16, 2024
1 parent a3ff6b3 commit 3f0a5c8
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
26 changes: 26 additions & 0 deletions antlir/antlir2/features/install/install.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,16 @@ binary_record = record(
installed = field([installed_binary, None], default = None),
)

shared_libraries_record = record(
so_targets = field(list[Artifact]),
dir_name = field(str),
)

def _impl(ctx: AnalysisContext) -> list[Provider]:
binary_info = None
required_run_infos = []
required_artifacts = []
shared_libraries = None
if not ctx.attrs.src and ctx.attrs.text == None:
fail("src or text must be set")
src = ctx.attrs.src
Expand Down Expand Up @@ -182,6 +188,25 @@ def _impl(ctx: AnalysisContext) -> list[Provider]:
# machine
required_run_infos.append(src[RunInfo])

src_subtargets = ctx.attrs.src[DefaultInfo].sub_targets
if "rpath-tree" in src_subtargets:
rpath_tree_info = src_subtargets["rpath-tree"][DefaultInfo]
rpath_tree_out = ensure_single_output(rpath_tree_info)
required_artifacts.append(rpath_tree_out)

so_targets = []
for so_subtarget in src_subtargets["shared-libraries"][DefaultInfo].sub_targets.values():
so_info = so_subtarget[DefaultInfo]
so_out = ensure_single_output(so_info)
so_targets.append(so_out)

shared_libraries = shared_libraries_record(
so_targets = so_targets,
dir_name = rpath_tree_out.basename,
)

required_artifacts.extend(so_targets)

# dev mode binaries don't get stripped, they just get symlinked
if ctx.attrs.split_debuginfo and (not ctx.attrs._binaries_require_repo or ctx.attrs.never_use_dev_binary_symlink):
split_anon_target = split_binary_anon(
Expand Down Expand Up @@ -234,6 +259,7 @@ def _impl(ctx: AnalysisContext) -> list[Provider]:
xattrs = ctx.attrs.xattrs,
setcap = ctx.attrs.setcap,
always_use_gnu_debuglink = ctx.attrs.always_use_gnu_debuglink,
shared_libraries = shared_libraries,
),
required_artifacts = [src] + required_artifacts,
required_run_infos = required_run_infos,
Expand Down
27 changes: 27 additions & 0 deletions antlir/antlir2/features/install/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub struct Install {
#[cfg(not(feature = "setcap"))]
pub setcap: Option<String>,
pub always_use_gnu_debuglink: bool,
pub shared_libraries: Option<SharedLibraries>,
}

#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
Expand Down Expand Up @@ -106,6 +107,12 @@ pub enum BinaryInfo {
Installed(InstalledBinary),
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Deserialize)]
pub struct SharedLibraries {
pub so_targets: Vec<BuckOutSource>,
pub dir_name: String,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct InstalledBinary {
pub debuginfo: BuckOutSource,
Expand Down Expand Up @@ -469,6 +476,26 @@ impl antlir2_compile::CompileFeature for Install {
.into());
}
}

if let Some(shared_libraries) = &self.shared_libraries {
// dev mode binaries are symlinked thus already alongside their shared libraries
if self.binary_info != Some(BinaryInfo::Dev) {
let shared_lib_dir = dst
.parent()
.expect("must have parent")
.join(&shared_libraries.dir_name);
std::fs::create_dir_all(&shared_lib_dir)?;
for shared_lib in &shared_libraries.so_targets {
copy_with_metadata(
shared_lib,
&shared_lib_dir
.join(shared_lib.file_name().expect("must have filename")),
Some(uid.as_raw()),
Some(gid.as_raw()),
)?;
}
}
}
}
Ok(())
}
Expand Down

0 comments on commit 3f0a5c8

Please sign in to comment.