-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cb9ab79
commit 6580d77
Showing
3 changed files
with
14 additions
and
150 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,151 +1,14 @@ | ||
use std::{ | ||
env, fs, | ||
io::{BufRead as _, BufReader}, | ||
path::PathBuf, | ||
process::{Child, Command, Stdio}, | ||
}; | ||
|
||
use cargo_metadata::{ | ||
Artifact, CompilerMessage, Message, Metadata, MetadataCommand, Package, Target, | ||
}; | ||
|
||
/// This crate has a runtime dependency on artifacts produced by the `{{project-name}}-ebpf` crate. | ||
/// This would be better expressed as one or more [artifact-dependencies][bindeps] but issues such | ||
/// as: | ||
/// | ||
/// * https://github.com/rust-lang/cargo/issues/12374 | ||
/// * https://github.com/rust-lang/cargo/issues/12375 | ||
/// * https://github.com/rust-lang/cargo/issues/12385 | ||
/// | ||
/// prevent their use for the time being. | ||
/// | ||
/// [bindeps]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html?highlight=feature#artifact-dependencies | ||
fn main() { | ||
let Metadata { packages, .. } = MetadataCommand::new().no_deps().exec().unwrap(); | ||
use anyhow::{anyhow, Context as _}; | ||
use aya_build::cargo_metadata; | ||
|
||
fn main() -> anyhow::Result<()> { | ||
let cargo_metadata::Metadata { packages, .. } = cargo_metadata::MetadataCommand::new() | ||
.no_deps() | ||
.exec() | ||
.context("MetadataCommand::exec")?; | ||
let ebpf_package = packages | ||
.into_iter() | ||
.find(|Package { name, .. }| name == "{{project-name}}-ebpf") | ||
.unwrap(); | ||
|
||
let out_dir = env::var_os("OUT_DIR").unwrap(); | ||
let out_dir = PathBuf::from(out_dir); | ||
|
||
let endian = env::var_os("CARGO_CFG_TARGET_ENDIAN").unwrap(); | ||
let target = if endian == "big" { | ||
"bpfeb" | ||
} else if endian == "little" { | ||
"bpfel" | ||
} else { | ||
panic!("unsupported endian={:?}", endian) | ||
}; | ||
|
||
// TODO(https://github.com/rust-lang/cargo/issues/4001): Make this `false` if we can determine | ||
// we're in a check build. | ||
let build_ebpf = true; | ||
if build_ebpf { | ||
let arch = env::var_os("CARGO_CFG_TARGET_ARCH").unwrap(); | ||
|
||
let target = format!("{target}-unknown-none"); | ||
|
||
let Package { manifest_path, .. } = ebpf_package; | ||
let ebpf_dir = manifest_path.parent().unwrap(); | ||
|
||
// We have a build-dependency on `{{project-name}}-ebpf`, so cargo will automatically rebuild us | ||
// if `{{project-name}}-ebpf`'s *library* target or any of its dependencies change. Since we | ||
// depend on `{{project-name}}-ebpf`'s *binary* targets, that only gets us half of the way. This | ||
// stanza ensures cargo will rebuild us on changes to the binaries too, which gets us the | ||
// rest of the way. | ||
println!("cargo:rerun-if-changed={}", ebpf_dir.as_str()); | ||
|
||
let mut cmd = Command::new("cargo"); | ||
cmd.args([ | ||
"+nightly", | ||
"build", | ||
"-Z", | ||
"build-std=core", | ||
"--bins", | ||
"--message-format=json", | ||
"--release", | ||
"--target", | ||
&target, | ||
]); | ||
|
||
cmd.env("CARGO_CFG_BPF_TARGET_ARCH", arch); | ||
|
||
// Workaround to make sure that the correct toolchain is used. | ||
for key in ["RUSTC", "RUSTC_WORKSPACE_WRAPPER"] { | ||
cmd.env_remove(key); | ||
} | ||
cmd.current_dir(ebpf_dir); | ||
|
||
// Workaround for https://github.com/rust-lang/cargo/issues/6412 where cargo flocks itself. | ||
let ebpf_target_dir = out_dir.join("{{project-name}}-ebpf"); | ||
cmd.arg("--target-dir").arg(&ebpf_target_dir); | ||
|
||
let mut child = cmd | ||
.stdout(Stdio::piped()) | ||
.stderr(Stdio::piped()) | ||
.spawn() | ||
.unwrap_or_else(|err| panic!("failed to spawn {cmd:?}: {err}")); | ||
let Child { stdout, stderr, .. } = &mut child; | ||
|
||
// Trampoline stdout to cargo warnings. | ||
let stderr = stderr.take().unwrap(); | ||
let stderr = BufReader::new(stderr); | ||
let stderr = std::thread::spawn(move || { | ||
for line in stderr.lines() { | ||
let line = line.unwrap(); | ||
println!("cargo:warning={line}"); | ||
} | ||
}); | ||
|
||
let stdout = stdout.take().unwrap(); | ||
let stdout = BufReader::new(stdout); | ||
let mut executables = Vec::new(); | ||
for message in Message::parse_stream(stdout) { | ||
#[allow(clippy::collapsible_match)] | ||
match message.expect("valid JSON") { | ||
Message::CompilerArtifact(Artifact { | ||
executable, | ||
target: Target { name, .. }, | ||
.. | ||
}) => { | ||
if let Some(executable) = executable { | ||
executables.push((name, executable.into_std_path_buf())); | ||
} | ||
} | ||
Message::CompilerMessage(CompilerMessage { message, .. }) => { | ||
for line in message.rendered.unwrap_or_default().split('\n') { | ||
println!("cargo:warning={line}"); | ||
} | ||
} | ||
Message::TextLine(line) => { | ||
println!("cargo:warning={line}"); | ||
} | ||
_ => {} | ||
} | ||
} | ||
|
||
let status = child | ||
.wait() | ||
.unwrap_or_else(|err| panic!("failed to wait for {cmd:?}: {err}")); | ||
assert_eq!(status.code(), Some(0), "{cmd:?} failed: {status:?}"); | ||
|
||
stderr.join().map_err(std::panic::resume_unwind).unwrap(); | ||
|
||
for (name, binary) in executables { | ||
let dst = out_dir.join(name); | ||
let _: u64 = fs::copy(&binary, &dst) | ||
.unwrap_or_else(|err| panic!("failed to copy {binary:?} to {dst:?}: {err}")); | ||
} | ||
} else { | ||
let Package { targets, .. } = ebpf_package; | ||
for Target { name, kind, .. } in targets { | ||
if *kind != ["bin"] { | ||
continue; | ||
} | ||
let dst = out_dir.join(name); | ||
fs::write(&dst, []).unwrap_or_else(|err| panic!("failed to create {dst:?}: {err}")); | ||
} | ||
} | ||
.find(|cargo_metadata::Package { name, .. }| name == "{{project-name}}-ebpf") | ||
.ok_or_else(|| anyhow!("{{project-name}}-ebpf package not found"))?; | ||
aya_build::build_ebpf([ebpf_package]) | ||
} |