Skip to content

Commit 5ec50cd

Browse files
committed
Add ersatz hh_fanout for OSS
The `hh_fanout` binary was removed in D53956499, preventing OSS users from generating dependency graph files needed for loading saved states. Fortunately, the backing logic still exists in the repo and we can trivially create a Rust executable to expose it again. Do so, replacing some `panic`s in the backing code with `Err` returns for consistency.
1 parent b1f24f7 commit 5ec50cd

File tree

5 files changed

+78
-4
lines changed

5 files changed

+78
-4
lines changed

hphp/hack/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,18 @@ build_cxx_bridge(
334334
EXTRA_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/hackc/hhvm_cxx/hhvm_hhbc_defs/as-hhbc-ffi.cpp"
335335
)
336336

337+
set(HH_FANOUT_EXECUTABLE "${HACK_BUILD_ROOT}/target/hh_fanout_oss/${PROFILE}/hh_fanout")
338+
add_custom_command(
339+
OUTPUT ${HH_FANOUT_EXECUTABLE}
340+
COMMAND
341+
. "${CMAKE_CURRENT_BINARY_DIR}/dev_env_rust_only.sh" &&
342+
${INVOKE_CARGO} hh_fanout_oss hh_fanout_oss --exe
343+
DEPENDS opam_setup rustc cargo
344+
COMMENT "Building hh_fanout"
345+
)
346+
347+
add_custom_target(hh_fanout DEPENDS ${HH_FANOUT_EXECUTABLE})
348+
337349
if (NOT LZ4_FOUND)
338350
add_dependencies(hack_dune lz4)
339351
add_dependencies(hack_dune_debug lz4)
@@ -365,3 +377,7 @@ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/hackfmt
365377
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/hh_parse
366378
DESTINATION bin
367379
COMPONENT dev)
380+
381+
install(PROGRAMS ${HH_FANOUT_EXECUTABLE}
382+
DESTINATION bin
383+
COMPONENT dev)

hphp/hack/src/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ members = [
4040
"hh_fanout/cargo/hh_fanout_build_rust",
4141
"hh_fanout/cargo/hh_fanout_dep_graph_is_subgraph_rust",
4242
"hh_fanout/cargo/hh_fanout_dep_graph_stats_rust",
43+
"hh_fanout/cargo/hh_fanout_oss",
4344
"hh_naming_table_builder/cargo/naming_table_builder_ffi",
4445
"naming",
4546
"naming/cargo/elaborate_namespaces",
@@ -107,5 +108,5 @@ members = [
107108
"utils/rust/measure/ffi",
108109
"utils/stack_limit",
109110
"utils/test",
110-
"utils/test/arena_deserializer",
111+
"utils/test/arena_deserializer"
111112
]
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "hh_fanout_oss"
3+
version = "0.1.0"
4+
edition = "2024"
5+
repository = "https://github.com/facebook/hhvm"
6+
license = "MIT"
7+
8+
[[bin]]
9+
name = "hh_fanout"
10+
path = "../../hh_fanout_oss/main.rs"
11+
12+
[dependencies]
13+
clap = { version = "4.5.42", features = ["derive", "env", "string", "unicode", "wrap_help"] }
14+
hh_fanout_build = { version = "0.0.0", path = "../hh_fanout_build" }

hphp/hack/src/hh_fanout/hh_fanout_build_rust/build.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::ffi::OsString;
66
use std::fs;
77
use std::fs::File;
88
use std::io;
9+
use std::io::{Error, ErrorKind};
910
use std::path::Path;
1011
use std::path::PathBuf;
1112
use std::sync::atomic::AtomicUsize;
@@ -353,10 +354,16 @@ pub fn build(
353354
) -> io::Result<()> {
354355
let all_edges = match (new_edges_dir, delta_file) {
355356
(None, None) => {
356-
panic!("build: at least one of --edges-dir or --delta-file flags should be passed")
357+
return Err(Error::new(
358+
ErrorKind::InvalidInput,
359+
"build: at least one of --edges-dir or --delta-file flags should be passed",
360+
));
357361
}
358362
(Some(_), Some(_)) => {
359-
panic!("build: cannot specify both --edges-dir and --delta-file")
363+
return Err(Error::new(
364+
ErrorKind::InvalidInput,
365+
"build: cannot specify both --edges-dir and --delta-file",
366+
));
360367
}
361368
(Some(new_edges_dir), None) => {
362369
info!("Opening binary files in {:?}", new_edges_dir);
@@ -402,7 +409,10 @@ pub fn build(
402409
info!("Converting to structured_edges & unique hashes done");
403410

404411
if !allow_empty && mem_dep_graph.edge_lists.iter().all(|list| list.is_empty()) {
405-
panic!("No input edges. Refusing to build as --allow-empty not set.");
412+
return Err(Error::new(
413+
ErrorKind::InvalidInput,
414+
"No input edges. Refusing to build as --allow-empty not set.",
415+
));
406416
}
407417

408418
info!("Registering {} unique hashes", mem_dep_graph.hashes.len());
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use std::io;
2+
use std::path::PathBuf;
3+
4+
use clap::Parser;
5+
6+
/// Executable wrapper around hh_fanout functionality
7+
/// that provides saved state support for HHVM open-source.
8+
///
9+
/// Builds a 64-bit dependency graph from a collection of edges.
10+
#[derive(Parser)]
11+
#[command(about)]
12+
struct Args {
13+
/// A file containing a dependency graph delta in binary format,
14+
/// as produced by `hh --save-state /path/`.
15+
#[arg(long)]
16+
delta_file: PathBuf,
17+
18+
/// Where to put the 64-bit dependency graph.
19+
#[arg(long)]
20+
output: PathBuf,
21+
}
22+
23+
fn main() -> io::Result<()> {
24+
let args = Args::parse();
25+
26+
hh_fanout_build::build(
27+
false,
28+
None,
29+
None,
30+
Some(args.delta_file.into_os_string()),
31+
&args.output,
32+
)
33+
}

0 commit comments

Comments
 (0)