mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-07 18:21:16 -03:00
Do not embed man pages in CMake builds
Commit0709e4be8b(Use standalone code paths by default, 2025-10-26) mainly wanted to embed internal functions to unbreak upgrade scenarios. Embedding man pages in CMake has small-ish disadvantages: 1. extra space usage 2. less discoverability 3. a "cyclic" dependency: 1. "sphinx-docs" depends on "fish_indent" 2. "fish_indent" via "crates/build-man-pages" depends on "doc_src/". So every "touch doc_src/foo.rst && ninja -Cbuild sphinx-docs" re-builds fish, just to re-run sphinx-build. The significant one is number 3. It can be worked around by running sphinx-build with stale "fish_indent" but I don't think we want to do that. Let's backtrack a little by stopping embedding man pages in CMake builds; use the on-disk man pages (which we still install). The remaining "regression" from0709e4be8bis that "ninja -Cbuild fish" needs to rebuild whenever anything in "share/" changes. I don't know if that's also annoying? Since man pages for "build/fish" are not in share/, expose the exact path as $__fish_man_dir.
This commit is contained in:
@@ -86,7 +86,7 @@ bitflags.workspace = true
|
|||||||
cfg-if.workspace = true
|
cfg-if.workspace = true
|
||||||
errno.workspace = true
|
errno.workspace = true
|
||||||
fish-build-helper.workspace = true
|
fish-build-helper.workspace = true
|
||||||
fish-build-man-pages.workspace = true
|
fish-build-man-pages = { workspace = true, optional = true }
|
||||||
fish-gettext-extraction = { workspace = true, optional = true }
|
fish-gettext-extraction = { workspace = true, optional = true }
|
||||||
fish-gettext-maps = { workspace = true, optional = true }
|
fish-gettext-maps = { workspace = true, optional = true }
|
||||||
fish-printf.workspace = true
|
fish-printf.workspace = true
|
||||||
@@ -150,8 +150,9 @@ name = "fish_key_reader"
|
|||||||
path = "src/bin/fish_key_reader.rs"
|
path = "src/bin/fish_key_reader.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["localize-messages"]
|
default = ["embed-manpages", "localize-messages"]
|
||||||
benchmark = []
|
benchmark = []
|
||||||
|
embed-manpages = ["dep:fish-build-man-pages"]
|
||||||
# Enable gettext localization at runtime. Requires the `msgfmt` tool to generate catalog data at
|
# Enable gettext localization at runtime. Requires the `msgfmt` tool to generate catalog data at
|
||||||
# build time.
|
# build time.
|
||||||
localize-messages = ["dep:phf", "dep:fish-gettext-maps"]
|
localize-messages = ["dep:phf", "dep:fish-gettext-maps"]
|
||||||
|
|||||||
@@ -184,13 +184,14 @@ You can also install Sphinx another way and drop the ``uv run --no-managed-pytho
|
|||||||
|
|
||||||
This will place standalone binaries in ``~/.cargo/bin/``, but you can move them wherever you want.
|
This will place standalone binaries in ``~/.cargo/bin/``, but you can move them wherever you want.
|
||||||
|
|
||||||
To disable translations, disable the ``localize-messages`` feature by passing ``--no-default-features`` to cargo.
|
To disable translations, disable the ``localize-messages`` feature by passing ``--no-default-features --features=embed-manpages`` to cargo.
|
||||||
|
|
||||||
You can also link this build statically (but not against glibc) and move it to other computers.
|
You can also link this build statically (but not against glibc) and move it to other computers.
|
||||||
|
|
||||||
Here are the remaining advantages of a full installation, as currently done by CMake:
|
Here are the remaining advantages of a full installation, as currently done by CMake:
|
||||||
|
|
||||||
- Man pages like ``fish(1)`` installed in standard locations, easily accessible from outside fish.
|
- Man pages like ``fish(1)`` installed in standard locations, easily accessible from outside fish.
|
||||||
|
- Separate files for builtins (e.g. ``$PREFIX/share/fish/man/man1/abbr.1``).
|
||||||
- A local copy of the HTML documentation, typically accessed via the ``help`` fish function.
|
- A local copy of the HTML documentation, typically accessed via the ``help`` fish function.
|
||||||
In Cargo builds, ``help`` will redirect to `<https://fishshell.com/docs/current/>`__
|
In Cargo builds, ``help`` will redirect to `<https://fishshell.com/docs/current/>`__
|
||||||
- Ability to use our CMake options extra_functionsdir, extra_completionsdir and extra_confdir,
|
- Ability to use our CMake options extra_functionsdir, extra_completionsdir and extra_confdir,
|
||||||
|
|||||||
@@ -70,8 +70,7 @@ function __fish_complete_man
|
|||||||
|
|
||||||
# Fish commands are not given by apropos
|
# Fish commands are not given by apropos
|
||||||
if not set -ql exclude_fish_commands
|
if not set -ql exclude_fish_commands
|
||||||
__fish_data_list_files man/man1 |
|
string join \n -- (__fish_man1_pages)\t'1: fish command'
|
||||||
string replace -rf '.*/([^/]+)\.1(\.gz)?$' '$1\t1: fish command'
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ function __fish_data_with_directory
|
|||||||
set -l cmd $argv[3..]
|
set -l cmd $argv[3..]
|
||||||
set -l temp
|
set -l temp
|
||||||
set -l directory_ref
|
set -l directory_ref
|
||||||
if false
|
if test $relative_directory = man/man1 && not __fish_tried_to_embed_manpages
|
||||||
set directory_ref $__fish_data_dir/$relative_directory
|
set directory_ref $__fish_man_dir/man1
|
||||||
else
|
else
|
||||||
set temp (__fish_mktemp_relative -d fish-data)
|
set temp (__fish_mktemp_relative -d fish-data)
|
||||||
or return
|
or return
|
||||||
|
|||||||
10
share/functions/__fish_man1_pages.fish
Normal file
10
share/functions/__fish_man1_pages.fish
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# localization: skip(private)
|
||||||
|
function __fish_man1_pages
|
||||||
|
if __fish_tried_to_embed_manpages
|
||||||
|
status list-files man/man1
|
||||||
|
else
|
||||||
|
files=$__fish_man_dir/man1/* string join -- \n $files
|
||||||
|
end |
|
||||||
|
path basename |
|
||||||
|
string replace -r -- '.1(.gz)?$' ''
|
||||||
|
end
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
# localization: skip(private)
|
# localization: skip(private)
|
||||||
function __fish_print_commands --description "Print a list of documented fish commands"
|
function __fish_print_commands --description "Print a list of documented fish commands"
|
||||||
__fish_data_list_files man/man1 |
|
__fish_man1_pages |
|
||||||
string replace -r '.*/' '' |
|
|
||||||
string replace -r '.1(.gz)?$' '' |
|
|
||||||
string match -rv '^fish-(?:changelog|completions|doc|tutorial|faq|for-bash-users|interactive|language|releasenotes|terminal-compatibility)$'
|
string match -rv '^fish-(?:changelog|completions|doc|tutorial|faq|for-bash-users|interactive|language|releasenotes|terminal-compatibility)$'
|
||||||
end
|
end
|
||||||
|
|||||||
4
share/functions/__fish_tried_to_embed_manpages.fish
Normal file
4
share/functions/__fish_tried_to_embed_manpages.fish
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# localization: skip(private)
|
||||||
|
function __fish_tried_to_embed_manpages
|
||||||
|
status build-info | string match -rq '(\s)embed-manpages(\s|$)'
|
||||||
|
end
|
||||||
@@ -6,17 +6,16 @@ if not command -qs man
|
|||||||
end
|
end
|
||||||
|
|
||||||
function man
|
function man
|
||||||
# If we have an embedded page, reuse a function that happens to do the
|
|
||||||
# right thing.
|
|
||||||
if not set -q argv[2] &&
|
|
||||||
status list-files "man/man1/$(__fish_canonicalize_builtin $argv).1" &>/dev/null
|
|
||||||
__fish_print_help $argv[1]
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
set -l manpath
|
set -l manpath
|
||||||
if false
|
if __fish_tried_to_embed_manpages
|
||||||
and set -l fish_manpath (path filter -d $__fish_data_dir/man)
|
# If we have an embedded page, reuse a function that happens to do
|
||||||
|
# the right thing.
|
||||||
|
if not set -q argv[2] &&
|
||||||
|
status list-files "man/man1/$(__fish_canonicalize_builtin $argv).1" &>/dev/null
|
||||||
|
__fish_print_help $argv[1]
|
||||||
|
return
|
||||||
|
end
|
||||||
|
else if set -l fish_manpath (path filter -d $__fish_man_dir)
|
||||||
# Prepend fish's man directory if available.
|
# Prepend fish's man directory if available.
|
||||||
|
|
||||||
# Work around the "builtin" manpage that everything symlinks to,
|
# Work around the "builtin" manpage that everything symlinks to,
|
||||||
|
|||||||
@@ -337,11 +337,16 @@ fn parse_cmd_opts(
|
|||||||
#[folder = "user_doc/man/man1"]
|
#[folder = "user_doc/man/man1"]
|
||||||
#[prefix = "man/man1/"]
|
#[prefix = "man/man1/"]
|
||||||
struct Docs;
|
struct Docs;
|
||||||
} else {
|
} else if #[cfg(feature = "embed-manpages")] {
|
||||||
#[derive(RustEmbed)]
|
#[derive(RustEmbed)]
|
||||||
#[folder = "$FISH_RESOLVED_BUILD_DIR/fish-man/man1"]
|
#[folder = "$FISH_RESOLVED_BUILD_DIR/fish-man/man1"]
|
||||||
#[prefix = "man/man1/"]
|
#[prefix = "man/man1/"]
|
||||||
struct Docs;
|
struct Docs;
|
||||||
|
} else {
|
||||||
|
#[derive(RustEmbed)]
|
||||||
|
#[folder = "$FISH_RESOLVED_BUILD_DIR"]
|
||||||
|
#[include = ""]
|
||||||
|
struct Docs;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -601,6 +606,8 @@ pub fn status(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> B
|
|||||||
streams.out.appendln(profile);
|
streams.out.appendln(profile);
|
||||||
streams.out.append(L!("Features: "));
|
streams.out.append(L!("Features: "));
|
||||||
let features: &[&str] = &[
|
let features: &[&str] = &[
|
||||||
|
#[cfg(feature = "embed-manpages")]
|
||||||
|
"embed-manpages",
|
||||||
#[cfg(feature = "localize-messages")]
|
#[cfg(feature = "localize-messages")]
|
||||||
"localize-messages",
|
"localize-messages",
|
||||||
#[cfg(target_feature = "crt-static")]
|
#[cfg(target_feature = "crt-static")]
|
||||||
|
|||||||
42
src/env/config_paths.rs
vendored
42
src/env/config_paths.rs
vendored
@@ -12,6 +12,7 @@ pub struct ConfigPaths {
|
|||||||
pub sysconf: PathBuf, // e.g., /usr/local/etc
|
pub sysconf: PathBuf, // e.g., /usr/local/etc
|
||||||
pub bin: Option<PathBuf>, // e.g., /usr/local/bin
|
pub bin: Option<PathBuf>, // e.g., /usr/local/bin
|
||||||
pub data: Option<PathBuf>, // e.g., /usr/local/share
|
pub data: Option<PathBuf>, // e.g., /usr/local/share
|
||||||
|
pub man: Option<PathBuf>, // e.g., /usr/local/share/fish/man
|
||||||
pub doc: Option<PathBuf>, // e.g., /usr/local/share/doc/fish
|
pub doc: Option<PathBuf>, // e.g., /usr/local/share/doc/fish
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,19 +51,24 @@ macro_rules! log_optional_path {
|
|||||||
}
|
}
|
||||||
log_optional_path!(bin);
|
log_optional_path!(bin);
|
||||||
log_optional_path!(data);
|
log_optional_path!(data);
|
||||||
|
log_optional_path!(man);
|
||||||
log_optional_path!(doc);
|
log_optional_path!(doc);
|
||||||
paths
|
paths
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_exec_path(unresolved_exec_path: &'static FishPath) -> Self {
|
fn from_exec_path(unresolved_exec_path: &'static FishPath) -> Self {
|
||||||
let default_layout = |exec_path_parent: Option<&Path>| Self {
|
let default_layout = |exec_path_parent: Option<&Path>| {
|
||||||
sysconf: PathBuf::from(SYSCONF_DIR).join("fish"),
|
let data = option_env!("DATADIR").map(|p| PathBuf::from(p).join("fish"));
|
||||||
bin: option_env!("BINDIR")
|
Self {
|
||||||
.map(PathBuf::from)
|
sysconf: PathBuf::from(SYSCONF_DIR).join("fish"),
|
||||||
// N.B. the argument may be non-canonical here.
|
bin: option_env!("BINDIR")
|
||||||
.or_else(|| exec_path_parent.map(|p| p.to_owned())),
|
.map(PathBuf::from)
|
||||||
data: option_env!("DATADIR").map(|p| PathBuf::from(p).join("fish")),
|
// N.B. the argument may be non-canonical here.
|
||||||
doc: option_env!("DOCDIR").map(PathBuf::from),
|
.or_else(|| exec_path_parent.map(|p| p.to_owned())),
|
||||||
|
data: data.clone(),
|
||||||
|
man: data.map(|data| data.join("man")),
|
||||||
|
doc: option_env!("DOCDIR").map(PathBuf::from),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let exec_path = {
|
let exec_path = {
|
||||||
@@ -113,10 +119,12 @@ fn from_exec_path(unresolved_exec_path: &'static FishPath) -> Self {
|
|||||||
} {
|
} {
|
||||||
FLOG!(config, "Running from relocatable tree");
|
FLOG!(config, "Running from relocatable tree");
|
||||||
let prefix = exec_path_parent.parent().unwrap();
|
let prefix = exec_path_parent.parent().unwrap();
|
||||||
|
let data = prefix.join("share/fish");
|
||||||
Self {
|
Self {
|
||||||
sysconf: prefix.join("etc/fish"),
|
sysconf: prefix.join("etc/fish"),
|
||||||
bin: Some(exec_path_parent.to_owned()),
|
bin: Some(exec_path_parent.to_owned()),
|
||||||
data: Some(prefix.join("share/fish")),
|
data: Some(data.clone()),
|
||||||
|
man: Some(data.join("man")),
|
||||||
doc: Some(prefix.join("share/doc/fish")),
|
doc: Some(prefix.join("share/doc/fish")),
|
||||||
}
|
}
|
||||||
} else if exec_path.starts_with(BUILD_DIR) {
|
} else if exec_path.starts_with(BUILD_DIR) {
|
||||||
@@ -127,17 +135,21 @@ fn from_exec_path(unresolved_exec_path: &'static FishPath) -> Self {
|
|||||||
workspace_root.display()
|
workspace_root.display()
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
let user_doc_join = |dir| {
|
||||||
|
if cfg!(use_prebuilt_docs) {
|
||||||
|
Some(workspace_root)
|
||||||
|
} else {
|
||||||
|
cfg!(using_cmake).then_some(Path::new(BUILD_DIR))
|
||||||
|
}
|
||||||
|
.map(|path| path.join("user_doc").join(dir))
|
||||||
|
};
|
||||||
// If we're in Cargo's target directory or in CMake's build directory, use the source files.
|
// If we're in Cargo's target directory or in CMake's build directory, use the source files.
|
||||||
Self {
|
Self {
|
||||||
sysconf: workspace_root.join("etc"),
|
sysconf: workspace_root.join("etc"),
|
||||||
bin: Some(exec_path_parent.to_owned()),
|
bin: Some(exec_path_parent.to_owned()),
|
||||||
data: Some(workspace_root.join("share")),
|
data: Some(workspace_root.join("share")),
|
||||||
doc: if cfg!(use_prebuilt_docs) {
|
man: user_doc_join("man"),
|
||||||
Some(workspace_root)
|
doc: user_doc_join("html"),
|
||||||
} else {
|
|
||||||
cfg!(using_cmake).then_some(Path::new(BUILD_DIR))
|
|
||||||
}
|
|
||||||
.map(|p| p.join("user_doc/html")),
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
FLOG!(
|
FLOG!(
|
||||||
|
|||||||
2
src/env/environment.rs
vendored
2
src/env/environment.rs
vendored
@@ -418,6 +418,7 @@ fn get_pwd_slash(&self) -> WString {
|
|||||||
const FISH_DATADIR_VAR: &wstr = L!("__fish_data_dir");
|
const FISH_DATADIR_VAR: &wstr = L!("__fish_data_dir");
|
||||||
const FISH_SYSCONFDIR_VAR: &wstr = L!("__fish_sysconf_dir");
|
const FISH_SYSCONFDIR_VAR: &wstr = L!("__fish_sysconf_dir");
|
||||||
const FISH_HELPDIR_VAR: &wstr = L!("__fish_help_dir");
|
const FISH_HELPDIR_VAR: &wstr = L!("__fish_help_dir");
|
||||||
|
const FISH_MANDIR_VAR: &wstr = L!("__fish_man_dir");
|
||||||
const FISH_BIN_DIR: &wstr = L!("__fish_bin_dir");
|
const FISH_BIN_DIR: &wstr = L!("__fish_bin_dir");
|
||||||
const FISH_CONFIG_DIR: &wstr = L!("__fish_config_dir");
|
const FISH_CONFIG_DIR: &wstr = L!("__fish_config_dir");
|
||||||
const FISH_USER_DATA_DIR: &wstr = L!("__fish_user_data_dir");
|
const FISH_USER_DATA_DIR: &wstr = L!("__fish_user_data_dir");
|
||||||
@@ -647,6 +648,7 @@ pub fn env_init(paths: Option<&ConfigPaths>, do_uvars: bool, default_paths: bool
|
|||||||
set_path(FISH_BIN_DIR, paths.bin.as_ref());
|
set_path(FISH_BIN_DIR, paths.bin.as_ref());
|
||||||
|
|
||||||
set_path(FISH_DATADIR_VAR, paths.data.as_ref());
|
set_path(FISH_DATADIR_VAR, paths.data.as_ref());
|
||||||
|
set_path(FISH_MANDIR_VAR, paths.man.as_ref());
|
||||||
set_path(FISH_HELPDIR_VAR, paths.doc.as_ref());
|
set_path(FISH_HELPDIR_VAR, paths.doc.as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
tests/checks/__fish_tried_to_embed_manpages.fish
Normal file
13
tests/checks/__fish_tried_to_embed_manpages.fish
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# RUN: %fish %s
|
||||||
|
|
||||||
|
set -l value (string join , \
|
||||||
|
embed-manpages="$(__fish_tried_to_embed_manpages && echo true || echo false)" \
|
||||||
|
"build-system=$(status build-info | string replace -rf 'Build system: (.*)' '$1')"
|
||||||
|
)
|
||||||
|
switch $value
|
||||||
|
case embed-manpages=true,build-system=Cargo
|
||||||
|
case embed-manpages=false,build-system=CMake
|
||||||
|
case '*'
|
||||||
|
echo Expected embedded man pages to be detected as true iff using Cargo
|
||||||
|
echo got: $value
|
||||||
|
end
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
# NOTE: When our executable is located outside the build directory, these are different.
|
# NOTE: When our executable is located outside the build directory, these are different.
|
||||||
# CHECKERR: config: paths.data: {{.*}}/share
|
# CHECKERR: config: paths.data: {{.*}}/share
|
||||||
|
# CHECKERR: config: paths.man: {{.*/user_doc/man|\|not found\|}}
|
||||||
# CHECKERR: config: paths.doc: {{.*/user_doc/html|\|not found\|}}
|
# CHECKERR: config: paths.doc: {{.*/user_doc/html|\|not found\|}}
|
||||||
|
|
||||||
# CHECKERR: config: sourcing {{.+}}/etc/config.fish
|
# CHECKERR: config: sourcing {{.+}}/etc/config.fish
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
# RUN: %fish %s
|
# RUN: %fish %s
|
||||||
|
|
||||||
# Override the test-override again.
|
|
||||||
__fish_data_with_file functions/__fish_print_help.fish source
|
|
||||||
|
|
||||||
# REQUIRES: command -v sphinx-build
|
# REQUIRES: command -v sphinx-build
|
||||||
# REQUIRES: command -v man
|
# REQUIRES: command -v man
|
||||||
# REQUIRES: test "$FISH_BUILD_DOCS" != "0"
|
# REQUIRES: test "$FISH_BUILD_DOCS" != "0"
|
||||||
|
|
||||||
|
# Override the test-override again.
|
||||||
|
__fish_data_with_file functions/__fish_print_help.fish source
|
||||||
|
|
||||||
set -l deroff col -b -p -x
|
set -l deroff col -b -p -x
|
||||||
|
|
||||||
set -lx MANWIDTH 80
|
set -lx MANWIDTH 80
|
||||||
|
|||||||
Reference in New Issue
Block a user