Skip to content

Commit f3ac1f7

Browse files
committedOct 31, 2022
fix(fluxdoc): use db when generating docs
Previously the fluxdoc gen would run a compilation step using `fluxc` to speed up compilation. Compilation is very fast now and we have the salsa db that does proper caching of intermediate steps. This change removes the `fluxc` binary and the left over unused code. Also we update the `fluxdoc` binary to use the salsa db only. Since this is potentially a perf change I tested how fast the docs generate, its dominated almost exclusively in running the examples. Compiling the stdlib is instantaneous in my system.
1 parent f6a6678 commit f3ac1f7

File tree

9 files changed

+46
-137
lines changed

9 files changed

+46
-137
lines changed
 

‎Makefile

+4-6
Original file line numberDiff line numberDiff line change
@@ -191,17 +191,15 @@ bin/flux: $(STDLIB_SOURCES) $$(call go_deps,./cmd/flux)
191191
$(GO_BUILD) -o ./bin/flux ./cmd/flux
192192

193193

194-
libflux/target/release/fluxc: libflux
195-
cd libflux && $(CARGO) build $(CARGO_ARGS) --release --bin fluxc
196194

197195
libflux/target/release/fluxdoc: libflux
198196
cd libflux && $(CARGO) build $(CARGO_ARGS) --features=doc --release --bin fluxdoc
199197

200-
fluxdocs: $(STDLIB_SOURCES) libflux/target/release/fluxc libflux/target/release/fluxdoc bin/flux
201-
FLUXC=./libflux/target/release/fluxc FLUXDOC=./libflux/target/release/fluxdoc ./etc/gen_docs.sh
198+
fluxdocs: $(STDLIB_SOURCES) libflux/target/release/fluxdoc bin/flux
199+
FLUXDOC=./libflux/target/release/fluxdoc ./etc/gen_docs.sh
202200

203-
checkdocs: $(STDLIB_SOURCES) libflux/target/release/fluxc libflux/target/release/fluxdoc bin/flux
204-
FLUXC=./libflux/target/release/fluxc FLUXDOC=./libflux/target/release/fluxdoc ./etc/checkdocs.sh
201+
checkdocs: $(STDLIB_SOURCES) libflux/target/release/fluxdoc bin/flux
202+
FLUXDOC=./libflux/target/release/fluxdoc ./etc/checkdocs.sh
205203

206204
# This list is sorted for easy inspection
207205
.PHONY: bench \

‎etc/checkdocs.sh

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
set -e
44

55
stdlib=${FLUX_STDLIB_DIR-./stdlib}
6-
fluxc=${FLUXC-fluxc}
76
fluxdoc=${FLUXDOC-fluxdoc}
87

98
# Lint the docs to ensure they are valid
10-
$fluxdoc lint --dir ${stdlib} --stdlib-dir "${stdlib}"
9+
$fluxdoc lint --dir ${stdlib}

‎etc/gen_docs.sh

+2-11
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,13 @@
33
set -e
44

55
stdlib=${FLUX_STDLIB_SRC-./stdlib}
6-
fluxc=${FLUXC-fluxc}
76
fluxdoc=${FLUXDOC-fluxdoc}
87
gendir=${DOCS_GEN_DIR-./generated_docs}
98
full_docs="${gendir}/flux-docs-full.json"
109
short_docs="${gendir}/flux-docs-short.json"
1110

12-
dir=$(mktemp -d)
13-
stdlib_compiled="${dir}/stdlib"
14-
15-
# Compile stdlib to a temporary dir
16-
mkdir -p $stdlib_compiled
17-
$fluxc stdlib --srcdir "${stdlib}" --outdir "${stdlib_compiled}"
18-
1911
# Generate docs JSON files
2012
mkdir -p "${gendir}"
21-
$fluxdoc dump --dir ${stdlib} --stdlib-dir "${stdlib_compiled}" --output ${full_docs} --nested
22-
$fluxdoc dump --dir ${stdlib} --stdlib-dir "${stdlib_compiled}" --output ${short_docs} --short
13+
$fluxdoc dump --dir ${stdlib} --output ${full_docs} --nested
14+
$fluxdoc dump --dir ${stdlib} --output ${short_docs} --short
2315

24-
rm -rf "${dir}"

‎libflux/flux-core/Cargo.toml

-4
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@ test = false
2020
bench = false
2121
required-features = ["doc"]
2222

23-
[[bin]]
24-
name = "fluxc"
25-
test = false
26-
bench = false
2723

2824
[features]
2925
default = ["strict"]

‎libflux/flux-core/src/bin/fluxc.rs

-32
This file was deleted.

‎libflux/flux-core/src/bin/fluxdoc.rs

+15-37
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ use fluxcore::{
2121
enum FluxDoc {
2222
/// Dump JSON encoding of documentation from Flux source code.
2323
Dump {
24-
/// Directory containing Flux source code.
25-
#[structopt(short, long, parse(from_os_str))]
26-
stdlib_dir: Option<PathBuf>,
2724
/// Path to flux command, must be the cmd from internal/cmd/flux
2825
#[structopt(long, parse(from_os_str))]
2926
flux_cmd_path: Option<PathBuf>,
@@ -42,9 +39,6 @@ enum FluxDoc {
4239
},
4340
/// Check Flux source code for documentation linting errors
4441
Lint {
45-
/// Directory containing Flux source code.
46-
#[structopt(short, long, parse(from_os_str))]
47-
stdlib_dir: Option<PathBuf>,
4842
/// Path to flux command, must be the cmd from internal/cmd/flux
4943
#[structopt(long, parse(from_os_str))]
5044
flux_cmd_path: Option<PathBuf>,
@@ -63,64 +57,52 @@ fn main() -> Result<()> {
6357
let app = FluxDoc::from_args();
6458
match app {
6559
FluxDoc::Dump {
66-
stdlib_dir,
6760
flux_cmd_path,
6861
dir,
6962
output,
7063
nested,
7164
short,
7265
} => dump(
73-
stdlib_dir.as_deref(),
7466
flux_cmd_path.as_deref(),
7567
&dir,
7668
output.as_deref(),
7769
nested,
7870
short,
7971
)?,
8072
FluxDoc::Lint {
81-
stdlib_dir,
8273
flux_cmd_path,
8374
dir,
8475
limit,
85-
} => lint(stdlib_dir.as_deref(), flux_cmd_path.as_deref(), &dir, limit)?,
76+
} => lint(flux_cmd_path.as_deref(), &dir, limit)?,
8677
};
8778
Ok(())
8879
}
8980

90-
const DEFAULT_STDLIB_PATH: &str = "./stdlib-compiled";
9181
const DEFAULT_FLUX_CMD_PATH: &str = "flux";
9282

93-
fn resolve_default_paths<'a>(
94-
stdlib_dir: Option<&'a Path>,
95-
flux_cmd_path: Option<&'a Path>,
96-
) -> (&'a Path, &'a Path) {
97-
let stdlib_dir = match stdlib_dir {
98-
Some(stdlib_dir) => stdlib_dir,
99-
None => Path::new(DEFAULT_STDLIB_PATH),
100-
};
83+
fn resolve_default_paths<'a>(flux_cmd_path: Option<&'a Path>) -> &'a Path {
10184
let flux_cmd_path = match flux_cmd_path {
10285
Some(flux_cmd_path) => flux_cmd_path,
10386
None => Path::new(DEFAULT_FLUX_CMD_PATH),
10487
};
105-
(stdlib_dir, flux_cmd_path)
88+
flux_cmd_path
10689
}
10790

10891
fn dump(
109-
stdlib_dir: Option<&Path>,
11092
flux_cmd_path: Option<&Path>,
11193
dir: &Path,
11294
output: Option<&Path>,
11395
nested: bool,
11496
short: bool,
11597
) -> Result<()> {
116-
let (stdlib_dir, flux_cmd_path) = resolve_default_paths(stdlib_dir, flux_cmd_path);
98+
let flux_cmd_path = resolve_default_paths(flux_cmd_path);
11799
let f = match output {
118100
Some(p) => Box::new(File::create(p).context(format!("creating output file {:?}", p))?)
119101
as Box<dyn io::Write>,
120102
None => Box::new(io::stdout()),
121103
};
122104

123-
let (mut docs, diagnostics) = parse_docs(stdlib_dir, dir).context("parsing source code")?;
105+
let (mut docs, diagnostics) = parse_docs(dir).context("parsing source code")?;
124106
if !diagnostics.is_empty() {
125107
bail!(
126108
"found {} diagnostics when building documentation:\n{}",
@@ -157,19 +139,14 @@ fn dump(
157139
Ok(())
158140
}
159141

160-
fn lint(
161-
stdlib_dir: Option<&Path>,
162-
flux_cmd_path: Option<&Path>,
163-
dir: &Path,
164-
limit: Option<i64>,
165-
) -> Result<()> {
166-
let (stdlib_dir, flux_cmd_path) = resolve_default_paths(stdlib_dir, flux_cmd_path);
142+
fn lint(flux_cmd_path: Option<&Path>, dir: &Path, limit: Option<i64>) -> Result<()> {
143+
let flux_cmd_path = resolve_default_paths(flux_cmd_path);
167144
let limit = match limit {
168145
Some(limit) if limit == 0 => i64::MAX,
169146
Some(limit) => limit,
170147
None => 10,
171148
};
172-
let (mut docs, mut diagnostics) = parse_docs(stdlib_dir, dir)?;
149+
let (mut docs, mut diagnostics) = parse_docs(dir)?;
173150
let mut pass = true;
174151
if !diagnostics.is_empty() {
175152
let rest = diagnostics.len() as i64 - limit;
@@ -198,7 +175,9 @@ fn lint(
198175
for result in results {
199176
test_count += 1;
200177
match result {
201-
Ok(name) => eprintln!("OK ... {}", name),
178+
Ok((name, duration)) => {
179+
eprintln!("OK ... {}, took {}ms", name, duration.as_millis())
180+
}
202181
Err(e) => {
203182
eprintln!("Error {:?}\n", e);
204183
pass = false;
@@ -271,14 +250,13 @@ fn consume_sequentially<T>(
271250
}
272251

273252
/// Parse documentation for the specified directory.
274-
fn parse_docs(stdlib_dir: &Path, dir: &Path) -> Result<(Vec<doc::PackageDoc>, doc::Diagnostics)> {
253+
fn parse_docs(dir: &Path) -> Result<(Vec<doc::PackageDoc>, doc::Diagnostics)> {
275254
let db = DatabaseBuilder::default()
276-
// We resolve paths in stdlib_dir first, then `dir` which mimicks the previous behavior
277-
// most closely
278-
.filesystem_roots(vec![stdlib_dir.into(), dir.into()])
255+
.filesystem_roots(vec![dir.into()])
279256
.build();
280257

281-
let package_names = bootstrap::parse_dir(dir)?;
258+
let mut package_names = bootstrap::parse_dir(dir)?;
259+
package_names.sort();
282260
let mut docs = Vec::with_capacity(package_names.len());
283261
let mut diagnostics = Vec::new();
284262
for pkgpath in package_names {

‎libflux/flux-core/src/doc/example.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
//! Parse documentation examples for their code and execute them collecting their inputs and
22
//! outputs.
33
4-
use std::{collections::HashMap, ops::Range};
4+
use std::{
5+
collections::HashMap,
6+
ops::Range,
7+
time::{Duration, SystemTime},
8+
};
59

610
use anyhow::{bail, Context, Result};
711
use csv::StringRecord;
@@ -20,7 +24,7 @@ pub trait Executor {
2024
}
2125

2226
/// A list of test results
23-
pub type TestResults = Vec<Result<String>>;
27+
pub type TestResults = Vec<Result<(String, Duration)>>;
2428

2529
/// Evaluates all examples in the documentation perfoming an inplace update of their inputs/outpts
2630
/// and content.
@@ -31,7 +35,7 @@ pub fn evaluate_package_examples(docs: &mut PackageDoc, executor: &impl Executor
3135
results.push(
3236
evaluate_example(example, executor)
3337
.with_context(|| format!("executing example for package {}", path))
34-
.map(|()| path.to_string()),
38+
.map(|duration| (path.to_string(), duration)),
3539
);
3640
}
3741
for (name, doc) in docs.members.iter_mut() {
@@ -41,7 +45,7 @@ pub fn evaluate_package_examples(docs: &mut PackageDoc, executor: &impl Executor
4145
.map(|result| {
4246
result
4347
.with_context(|| format!("executing example for {}.{}", path, name))
44-
.map(|title| format!("{}.{}.{}", path, name, title))
48+
.map(|(title, duration)| (format!("{}.{}:{}", path, name, title), duration))
4549
}),
4650
);
4751
}
@@ -55,21 +59,27 @@ fn evaluate_doc_examples(doc: &mut Doc, executor: &impl Executor) -> TestResults
5559
Doc::Value(v) => v
5660
.examples
5761
.iter_mut()
58-
.map(|example| evaluate_example(example, executor).map(|()| example.title.clone()))
62+
.map(|example| {
63+
evaluate_example(example, executor)
64+
.with_context(|| format!("executing `{}`", example.title))
65+
.map(|duration| (example.title.clone(), duration))
66+
})
5967
.collect(),
6068
Doc::Function(f) => f
6169
.examples
6270
.iter_mut()
6371
.map(|example| {
6472
evaluate_example(example, executor)
6573
.with_context(|| format!("executing `{}`", example.title))
66-
.map(|()| example.title.clone())
74+
.map(|duration| (example.title.clone(), duration))
6775
})
6876
.collect(),
6977
}
7078
}
7179

72-
fn evaluate_example(example: &mut Example, executor: &impl Executor) -> Result<()> {
80+
fn evaluate_example(example: &mut Example, executor: &impl Executor) -> Result<Duration> {
81+
// Time the evaluation
82+
let start = SystemTime::now();
7383
let blocks = preprocess_code_blocks(&example.content)?;
7484
if blocks.len() > 1 {
7585
bail!(
@@ -89,7 +99,8 @@ fn evaluate_example(example: &mut Example, executor: &impl Executor) -> Result<(
8999
BlockMode::NoRun => {}
90100
}
91101
}
92-
Ok(())
102+
let end = SystemTime::now();
103+
Ok(end.duration_since(start)?)
93104
}
94105

95106
enum BlockMode {

‎libflux/flux-core/src/semantic/bootstrap.rs

+1-32
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@
33
//! This package does not assume a location of the source code but does assume which packages are
44
//! part of the prelude.
55
6-
use std::{env::consts, fs, io, io::Write, path::Path, sync::Arc};
6+
use std::{env::consts, io, path::Path, sync::Arc};
77

88
use anyhow::{bail, Result};
9-
use libflate::gzip::Encoder;
109
use walkdir::WalkDir;
1110

1211
use crate::{
1312
ast,
1413
db::{DatabaseBuilder, Flux},
1514
semantic::{
16-
flatbuffers::types::{build_module, finish_serialize},
1715
fs::{FileSystemImporter, StdFS},
1816
import::{Importer, Packages},
1917
nodes::{self, Package, Symbol},
@@ -202,35 +200,6 @@ pub fn stdlib(dir: &Path) -> Result<(PackageExports, FileSystemImporter<StdFS>)>
202200
Ok((prelude, stdlib_importer))
203201
}
204202

205-
/// Compiles the stdlib found at the srcdir into the outdir.
206-
pub fn compile_stdlib(srcdir: &Path, outdir: &Path) -> Result<()> {
207-
let (_, imports, mut sem_pkgs) = infer_stdlib_dir(srcdir, AnalyzerConfig::default())?;
208-
// Write each file as compiled module
209-
for (path, exports) in &imports {
210-
if let Some(code) = sem_pkgs.remove(path) {
211-
let module = Module {
212-
polytype: Some(exports.typ()),
213-
code: Some(code),
214-
};
215-
let mut builder = flatbuffers::FlatBufferBuilder::new();
216-
let offset = build_module(&mut builder, module);
217-
let buf = finish_serialize(&mut builder, offset);
218-
219-
// Write module contents to file
220-
let mut fpath = outdir.join(path);
221-
fpath.set_extension("fc");
222-
fs::create_dir_all(fpath.parent().unwrap())?;
223-
let file = fs::File::create(&fpath)?;
224-
let mut encoder = Encoder::new(file)?;
225-
encoder.write_all(buf)?;
226-
encoder.finish().into_result()?;
227-
} else {
228-
bail!("package {} missing code", &path);
229-
}
230-
}
231-
Ok(())
232-
}
233-
234203
/// Module represenets the result of compiling Flux source code.
235204
///
236205
/// The polytype represents the type of the entire package as a record type.

0 commit comments

Comments
 (0)