Skip to content

Commit 10ab15b

Browse files
committed
rename reproducible mode to deterministic mode and move to unstable opts
1 parent 2156d30 commit 10ab15b

9 files changed

Lines changed: 44 additions & 54 deletions

File tree

crates/bridge_core/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ impl<'a> CoreBridgeLauncher<'a> {
254254
self
255255
}
256256

257-
/// Ditto for file modification timestamps. In reproducible mode, we return
257+
/// Ditto for file modification timestamps. In deterministic mode, we return
258258
/// the configured build time (i.e. `SOURCE_DATE_EPOCH`) instead of the
259259
/// modification timestamp reported by the IO subsystem.
260260
pub fn with_mtime_override(&mut self, mtime_override: Option<i64>) -> &mut Self {
@@ -815,7 +815,7 @@ struct FsEmulationSettings {
815815
/// resolve paths to TeX sources), we can disable them for reproducibility.
816816
expose_absolute_paths: bool,
817817

818-
/// Ditto for file modification timestamps. In reproducible mode, we return
818+
/// Ditto for file modification timestamps. In deterministic mode, we return
819819
/// the configured build time (i.e. `SOURCE_DATE_EPOCH`) instead of the
820820
/// modification timestamp reported by the IO subsystem.
821821
mtime_override: Option<i64>,

docs/src/ref/v1cli.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ The following are the available flags.
5858
| | `--outfmt <FORMAT>` | The kind of output to generate [default: pdf] [possible values: pdf, html, xdv, aux, format] |
5959
| | `--pass <PASS>` | Which engines to run [default: default] [possible values: default, tex, bibtex_first] |
6060
| `-p` | `--print` | Print the engine's chatter during processing |
61-
| | `--reproducible` | Ensure deterministic builds |
6261
| `-r` | `--reruns <COUNT>` | Rerun the TeX engine exactly this many times after the first |
6362
| | `--synctex` | Generate SyncTeX data |
6463
| | `--untrusted` | Input is untrusted: disable all known-insecure features |

docs/src/v2cli/build.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,4 @@ be easy to forget to use this option; in cases where untrusted inputs are a
6464
genuine concern, we recommend setting the environment variable
6565
`TECTONIC_UNTRUSTED_MODE` to a non-empty value. This has the same effect as the
6666
`--untrusted` option. Note, however, that a hostile shell user can trivially
67-
clear this variable.
68-
69-
The `--reproducible` option ensures a fully deterministic build environment.
70-
The most notable difference is a static document build time (`\today`), which can
71-
be configured explicitly by setting the `SOURCE_DATE_EPOCH` environment variable.
72-
There's a few ways to break determinism (shell escape, reading from `/dev/urandom`),
73-
but anything else (especially behaviour in TeXLive packages) is considered a bug.
67+
clear this variable.

docs/src/v2cli/compile.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ The following are the available flags.
111111
| | `--outfmt <FORMAT>` | The kind of output to generate. Possible values: `pdf` (the default), `html`, `xdv`, `aux`, `format` |
112112
| | `--pass <PASS>` | Which engines to run. Possible values: `default`, `tex`, `bibtex_first` |
113113
| `-p` | `--print` | Print the engine's chatter during processing |
114-
| | `--reproducible` | Ensure deterministic builds |
115114
| `-r` | `--reruns <COUNT>` | Rerun the TeX engine exactly this many times after the first |
116115
| | `--synctex` | Generate SyncTeX data |
117116
| | `--untrusted` | Input is untrusted: disable all known-insecure features |
@@ -135,3 +134,4 @@ the set of unstable options is subject to change at any time.
135134
| `-Z search-path=<path>` | Also look in `<path>` for files (unless `--untrusted` has been specified), like TEXINPUTS. Can be specified multiple times. |
136135
| `-Z shell-escape` | Enable `\write18` (unless `--untrusted` has been specified) |
137136
| `-Z shell-escape-cwd=<path>` | Working directory to use for \write18. Use $(pwd) for same behaviour as most other engines (e.g. for relative paths in \inputminted). Implies -Z shell-escape |
137+
| `-Z deterministic-mode` | Force a deterministic build environment. Note that setting `SOURCE_DATE_EPOCH` is usually sufficient for reproducible builds, and this option makes some extra functionality trade-offs. Specifically, deterministic mode breaks SyncTeX's auxiliary files as they include and rely on absolute file paths |

src/bin/tectonic/compile.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,6 @@ pub struct CompileOptions {
8989
#[structopt(long)]
9090
untrusted: bool,
9191

92-
/// Ensure deterministic build environment
93-
#[structopt(long = "reproducible")]
94-
reproducible_mode: bool,
95-
9692
/// Unstable options. Pass -Zhelp to show a list
9793
#[structopt(name = "option", short = "Z", number_of_values = 1)]
9894
unstable: Vec<UnstableArg>,
@@ -115,14 +111,14 @@ impl CompileOptions {
115111
let mut sess_builder =
116112
ProcessingSessionBuilder::new_with_security(SecuritySettings::new(stance));
117113
let format_path = self.format;
114+
let deterministic_mode = unstable.deterministic_mode;
118115
sess_builder
119116
.unstables(unstable)
120117
.format_name(&format_path)
121118
.keep_logs(self.keep_logs)
122119
.keep_intermediates(self.keep_intermediates)
123120
.format_cache_path(config.format_cache_path()?)
124-
.synctex(self.synctex)
125-
.reproducible_mode(self.reproducible_mode);
121+
.synctex(self.synctex);
126122

127123
sess_builder.output_format(OutputFormat::from_str(&self.outfmt).unwrap());
128124

@@ -202,7 +198,7 @@ impl CompileOptions {
202198
} else {
203199
sess_builder.bundle(config.default_bundle(only_cached, status)?);
204200
}
205-
sess_builder.build_date_from_env(self.reproducible_mode);
201+
sess_builder.build_date_from_env(deterministic_mode);
206202
run_and_report(sess_builder, status).map(|_| 0)
207203
}
208204
}

src/bin/tectonic/v2cli.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -238,10 +238,6 @@ pub struct BuildCommand {
238238
/// Open built document using system handler
239239
#[structopt(long)]
240240
open: bool,
241-
242-
/// Ensure deterministic build environment
243-
#[structopt(long = "reproducible")]
244-
reproducible_mode: bool,
245241
}
246242

247243
impl BuildCommand {
@@ -264,7 +260,6 @@ impl BuildCommand {
264260
let mut setup_options =
265261
DocumentSetupOptions::new_with_security(SecuritySettings::new(stance));
266262
setup_options.only_cached(self.only_cached);
267-
setup_options.reproducible_mode(self.reproducible_mode);
268263

269264
for output_name in doc.output_names() {
270265
let mut builder = doc.setup_session(output_name, &setup_options, status)?;

src/docmodel.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use crate::{
2929
errors::{ErrorKind, Result},
3030
status::StatusBackend,
3131
test_util, tt_note,
32+
unstable_opts::UnstableOptions,
3233
};
3334

3435
/// Options for setting up [`Document`] instances with the driver
@@ -42,7 +43,7 @@ pub struct DocumentSetupOptions {
4243
security: SecuritySettings,
4344

4445
/// Ensure a deterministic build environment.
45-
reproducible_mode: bool,
46+
deterministic_mode: bool,
4647
}
4748

4849
impl DocumentSetupOptions {
@@ -51,7 +52,7 @@ impl DocumentSetupOptions {
5152
pub fn new_with_security(security: SecuritySettings) -> Self {
5253
DocumentSetupOptions {
5354
only_cached: false,
54-
reproducible_mode: false,
55+
deterministic_mode: false,
5556
security,
5657
}
5758
}
@@ -67,8 +68,8 @@ impl DocumentSetupOptions {
6768
}
6869

6970
/// Specify whether we want to ensure a deterministic build environment.
70-
pub fn reproducible_mode(&mut self, s: bool) -> &mut Self {
71-
self.reproducible_mode = s;
71+
pub fn deterministic_mode(&mut self, s: bool) -> &mut Self {
72+
self.deterministic_mode = s;
7273
self
7374
}
7475
}
@@ -167,8 +168,11 @@ impl DocumentExt for Document {
167168
sess_builder
168169
.output_format(output_format)
169170
.format_name(&profile.tex_format)
170-
.build_date_from_env(setup_options.reproducible_mode)
171-
.reproducible_mode(setup_options.reproducible_mode)
171+
.build_date_from_env(setup_options.deterministic_mode)
172+
.unstables(UnstableOptions {
173+
deterministic_mode: setup_options.deterministic_mode,
174+
..Default::default()
175+
})
172176
.pass(PassSetting::Default)
173177
.primary_input_buffer(input_buffer.as_bytes())
174178
.tex_input_name(output_profile);

src/driver.rs

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,6 @@ pub struct ProcessingSessionBuilder {
817817
build_date: Option<SystemTime>,
818818
unstables: UnstableOptions,
819819
shell_escape_mode: ShellEscapeMode,
820-
reproducible_mode: bool,
821820
html_assets_spec_path: Option<String>,
822821
html_precomputed_assets: Option<AssetSpecification>,
823822
html_do_not_emit_files: bool,
@@ -988,11 +987,11 @@ impl ProcessingSessionBuilder {
988987

989988
/// Configures the date and time of the processing session from the environment:
990989
/// If `SOURCE_DATE_EPOCH` is set, it's used as the build date.
991-
/// If `force_reproducible` is set, we fall back to UNIX_EPOCH.
990+
/// If `force_deterministic` is set, we fall back to UNIX_EPOCH.
992991
/// Otherwise, we use the current system time.
993-
pub fn build_date_from_env(&mut self, force_reproducible: bool) -> &mut Self {
992+
pub fn build_date_from_env(&mut self, force_deterministic: bool) -> &mut Self {
994993
let build_date_str = std::env::var("SOURCE_DATE_EPOCH").ok();
995-
let build_date = match (force_reproducible, build_date_str) {
994+
let build_date = match (force_deterministic, build_date_str) {
996995
(_, Some(s)) => {
997996
let epoch = s
998997
.parse::<u64>()
@@ -1047,21 +1046,6 @@ impl ProcessingSessionBuilder {
10471046
self
10481047
}
10491048

1050-
/// Ensure a deterministic build environment.
1051-
///
1052-
/// The most significant user-facing difference is a static document build
1053-
/// date, but this is already covered by [`build_date_from_env`], which
1054-
/// accepts a `reproducible` flag. Additionally, reproducible mode spoofs
1055-
/// file modification times and hides absolute paths from the engine.
1056-
///
1057-
/// There's a few ways to break determinism (shell escape, reading from
1058-
/// `/dev/urandom`), but anything else (especially behaviour in TeXLive
1059-
/// packages) is considered a bug.
1060-
pub fn reproducible_mode(&mut self, reproducible: bool) -> &mut Self {
1061-
self.reproducible_mode = reproducible;
1062-
self
1063-
}
1064-
10651049
/// When using HTML mode, emit an asset specification file instead of actual
10661050
/// asset files.
10671051
///
@@ -1277,7 +1261,6 @@ impl ProcessingSessionBuilder {
12771261
build_date: self.build_date.unwrap_or(SystemTime::UNIX_EPOCH),
12781262
unstables: self.unstables,
12791263
shell_escape_mode,
1280-
reproducible_mode: self.reproducible_mode,
12811264
html_assets_spec_path: self.html_assets_spec_path,
12821265
html_precomputed_assets: self.html_precomputed_assets,
12831266
html_emit_files: !self.html_do_not_emit_files,
@@ -1345,8 +1328,6 @@ pub struct ProcessingSession {
13451328

13461329
unstables: UnstableOptions,
13471330

1348-
reproducible_mode: bool,
1349-
13501331
/// How to handle shell-escape. The `Defaulted` option will never
13511332
/// be used here.
13521333
shell_escape_mode: ShellEscapeMode,
@@ -1871,15 +1852,15 @@ impl ProcessingSession {
18711852
let mut launcher =
18721853
CoreBridgeLauncher::new_with_security(&mut self.bs, status, self.security.clone());
18731854

1874-
// In reproducible mode, we stub a few aspects of the environment.
1855+
// In deterministic mode, we stub a few aspects of the environment.
18751856
// They default to a "realistic" view, but we override them with static values:
1876-
if self.reproducible_mode {
1857+
if self.unstables.deterministic_mode {
18771858
launcher.with_expose_absolute_paths(false);
18781859
launcher.with_mtime_override(Some(
18791860
self.build_date
18801861
.duration_since(SystemTime::UNIX_EPOCH)
18811862
.map(|x| x.as_secs() as i64)
1882-
.expect("invalid build date in reproducible mode"),
1863+
.expect("invalid build date in deterministic mode"),
18831864
));
18841865
}
18851866

src/unstable_opts.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ const HELPMSG: &str = r#"Available unstable options:
2929
-Z shell-escape-cwd Working directory to use for \write18. Use $(pwd) for same behaviour as
3030
most other engines (e.g. for relative paths in \inputminted).
3131
Implies -Z shell-escape
32+
-Z deterministic-mode Force a deterministic build environment. Note that setting
33+
`SOURCE_DATE_EPOCH` is usually sufficient for reproducible builds,
34+
and this option makes some extra functionality trade-offs.
35+
Specifically, deterministic mode breaks SyncTeX's auxiliary files
36+
as they include and rely on absolute file paths
3237
"#;
3338

3439
// Each entry of this should correspond to a field of UnstableOptions.
@@ -41,6 +46,7 @@ pub enum UnstableArg {
4146
SearchPath(PathBuf),
4247
ShellEscapeEnabled,
4348
ShellEscapeCwd(String),
49+
DeterministicModeEnabled,
4450
}
4551

4652
impl FromStr for UnstableArg {
@@ -97,6 +103,8 @@ impl FromStr for UnstableArg {
97103
require_value("path").map(|s| UnstableArg::ShellEscapeCwd(s.to_string()))
98104
}
99105

106+
"deterministic-mode" => require_no_value(value, UnstableArg::DeterministicModeEnabled),
107+
100108
_ => Err(format!("Unknown unstable option '{arg}'").into()),
101109
}
102110
}
@@ -110,6 +118,18 @@ pub struct UnstableOptions {
110118
pub min_crossrefs: Option<i32>,
111119
pub extra_search_paths: Vec<PathBuf>,
112120
pub shell_escape_cwd: Option<String>,
121+
122+
/// Ensure a deterministic build environment.
123+
///
124+
/// The most significant user-facing difference is a static document build
125+
/// date, but this is already covered by [`crate::driver::ProcessingSessionBuilder::build_date_from_env`],
126+
/// which accepts a `deterministic` flag. Additionally, deterministic mode
127+
/// spoofs file modification times and hides absolute paths from the engine.
128+
///
129+
/// There's a few ways to break determinism (shell escape, reading from
130+
/// `/dev/urandom`), but anything else (especially behaviour in TeXLive
131+
/// packages) is considered a bug.
132+
pub deterministic_mode: bool,
113133
}
114134

115135
impl UnstableOptions {
@@ -132,6 +152,7 @@ impl UnstableOptions {
132152
opts.shell_escape_cwd = Some(p);
133153
opts.shell_escape = true;
134154
}
155+
DeterministicModeEnabled => opts.deterministic_mode = true,
135156
}
136157
}
137158

0 commit comments

Comments
 (0)