mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-04-19 23:21:15 -03:00
This completely removes our runtime dependency on gettext. As a replacement, we have our own code for runtime localization in `src/wutil/gettext.rs`. It considers the relevant locale variables to decide which message catalogs to take localizations from. The use of locale variables is mostly the same as in gettext, with the notable exception that we do not support "default dialects". If `LANGUAGE=ll` is set and we don't have a `ll` catalog but a `ll_CC` catalog, we will use the catalog with the country code suffix. If multiple such catalogs exist, we use an arbitrary one. (At the moment we have at most one catalog per language, so this is not particularly relevant.) By using an `EnvStack` to pass variables to gettext at runtime, we now respect locale variables which are not exported. For early output, we don't have an `EnvStack` to pass, so we add an initialization function which constructs an `EnvStack` containing the relevant locale variables from the corresponding Environment variables. Treat `LANGUAGE` as path variable. This add automatic colon-splitting. The sourcing of catalogs is completely reworked. Instead of looking for MO files at runtime, we create catalogs as Rust maps at build time, by converting PO files into MO data, which is not stored, but immediately parsed to extract the mappings. From the mappings, we create Rust source code as a build artifact, which is then macro-included in the crate's library, i.e. `crates/gettext-maps/src/lib.rs`. The code in `src/wutil/gettext.rs` includes the message catalogs from this library, resulting in the message catalogs being built into the executable. The `localize-messages` feature can now be used to control whether to build with gettext support. By default, it is enabled. If `msgfmt` is not available at build time, and `gettext` is enabled, a warning will be emitted and fish is built with gettext support, but without any message catalogs, so localization will not work then. As a performance optimization, for each language we cache a separate Rust source file containing its catalog as a map. This allows us to reuse parsing results if the corresponding PO files have not changed since we cached the parsing result. Note that this approach does not eliminate our build-time dependency on gettext. The process for generating PO files (which uses `msguniq` and `msgmerge`) is unchanged, and we still need `msgfmt` to translate from PO to MO. We could parse PO files directly, but these are significantly more complex to parse, so we use `msgfmt` to do it for us and parse the resulting MO data. Advantages of the new approach: - We have no runtime dependency on gettext anymore. - The implementation has the same behavior everywhere. - Our implementation is significantly simpler than GNU gettext. - We can have localization in cargo-only builds by embedding localizations into the code. Previously, localization in such builds could only work reliably as long as the binary was not moved from the build directory. - We no longer have to take care of building and installing MO files in build systems; everything we need for localization to work happens automatically when building fish. - Reduced overhead when disabling localization, both in compilation time and binary size. Disadvantages of this approach: - Our own runtime implementation of gettext needs to be maintained. - The implementation has a more limited feature set (but I don't think it lacks any features which have been in use by fish). Part of #11726 Closes #11583 Closes #11725 Closes #11683
168 lines
6.6 KiB
CMake
168 lines
6.6 KiB
CMake
set(CMAKE_INSTALL_MESSAGE NEVER)
|
|
|
|
set(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fish ${CMAKE_CURRENT_BINARY_DIR}/fish_indent ${CMAKE_CURRENT_BINARY_DIR}/fish_key_reader)
|
|
|
|
set(prefix ${CMAKE_INSTALL_PREFIX})
|
|
set(bindir ${CMAKE_INSTALL_BINDIR})
|
|
set(sysconfdir ${CMAKE_INSTALL_SYSCONFDIR})
|
|
set(mandir ${CMAKE_INSTALL_MANDIR})
|
|
|
|
set(datadir ${CMAKE_INSTALL_FULL_DATADIR})
|
|
file(RELATIVE_PATH rel_datadir ${CMAKE_INSTALL_PREFIX} ${datadir})
|
|
|
|
set(docdir ${CMAKE_INSTALL_DOCDIR})
|
|
|
|
set(rel_completionsdir "fish/vendor_completions.d")
|
|
set(rel_functionsdir "fish/vendor_functions.d")
|
|
set(rel_confdir "fish/vendor_conf.d")
|
|
|
|
set(extra_completionsdir
|
|
"${datadir}/${rel_completionsdir}"
|
|
CACHE STRING "Path for extra completions")
|
|
|
|
set(extra_functionsdir
|
|
"${datadir}/${rel_functionsdir}"
|
|
CACHE STRING "Path for extra functions")
|
|
|
|
set(extra_confdir
|
|
"${datadir}/${rel_confdir}"
|
|
CACHE STRING "Path for extra configuration")
|
|
|
|
|
|
# These are the man pages that go in system manpath; all manpages go in the fish-specific manpath.
|
|
set(MANUALS ${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish.1
|
|
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish_indent.1
|
|
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish_key_reader.1
|
|
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish-doc.1
|
|
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish-tutorial.1
|
|
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish-language.1
|
|
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish-interactive.1
|
|
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish-terminal-compatibility.1
|
|
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish-completions.1
|
|
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish-prompt-tutorial.1
|
|
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish-for-bash-users.1
|
|
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish-faq.1
|
|
)
|
|
|
|
# Determine which man page we don't want to install.
|
|
# On OS X, don't install a man page for open, since we defeat fish's open
|
|
# function on OS X.
|
|
# On other operating systems, don't install a realpath man page, as they almost all have a realpath
|
|
# command, while macOS does not.
|
|
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
|
set(CONDEMNED_PAGE "open.1")
|
|
else()
|
|
set(CONDEMNED_PAGE "realpath.1")
|
|
endif()
|
|
|
|
# Define a function to help us create directories.
|
|
function(FISH_CREATE_DIRS)
|
|
foreach(dir ${ARGV})
|
|
install(DIRECTORY DESTINATION ${dir})
|
|
endforeach(dir)
|
|
endfunction(FISH_CREATE_DIRS)
|
|
|
|
function(FISH_TRY_CREATE_DIRS)
|
|
foreach(dir ${ARGV})
|
|
if(NOT IS_ABSOLUTE ${dir})
|
|
set(abs_dir "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${dir}")
|
|
else()
|
|
set(abs_dir "\$ENV{DESTDIR}${dir}")
|
|
endif()
|
|
install(SCRIPT CODE "EXECUTE_PROCESS(COMMAND mkdir -p ${abs_dir} OUTPUT_QUIET ERROR_QUIET)
|
|
execute_process(COMMAND chmod 755 ${abs_dir} OUTPUT_QUIET ERROR_QUIET)
|
|
")
|
|
endforeach()
|
|
endfunction(FISH_TRY_CREATE_DIRS)
|
|
|
|
install(PROGRAMS ${PROGRAMS}
|
|
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
|
|
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
|
DESTINATION ${bindir})
|
|
|
|
fish_create_dirs(${sysconfdir}/fish/conf.d ${sysconfdir}/fish/completions
|
|
${sysconfdir}/fish/functions)
|
|
install(FILES etc/config.fish DESTINATION ${sysconfdir}/fish/)
|
|
|
|
fish_create_dirs(${rel_datadir}/fish ${rel_datadir}/fish/completions
|
|
${rel_datadir}/fish/functions ${rel_datadir}/fish/groff
|
|
${rel_datadir}/fish/man/man1 ${rel_datadir}/fish/tools
|
|
${rel_datadir}/fish/tools/web_config
|
|
${rel_datadir}/fish/tools/web_config/js
|
|
${rel_datadir}/fish/tools/web_config/sample_prompts
|
|
${rel_datadir}/fish/tools/web_config/themes
|
|
)
|
|
|
|
configure_file(share/__fish_build_paths.fish.in share/__fish_build_paths.fish)
|
|
install(FILES share/config.fish
|
|
${CMAKE_CURRENT_BINARY_DIR}/share/__fish_build_paths.fish
|
|
DESTINATION ${rel_datadir}/fish)
|
|
|
|
# Create only the vendor directories inside the prefix (#5029 / #6508)
|
|
fish_create_dirs(${rel_datadir}/fish/vendor_completions.d ${rel_datadir}/fish/vendor_functions.d
|
|
${rel_datadir}/fish/vendor_conf.d)
|
|
|
|
fish_try_create_dirs(${rel_datadir}/pkgconfig)
|
|
configure_file(fish.pc.in fish.pc.noversion @ONLY)
|
|
|
|
add_custom_command(OUTPUT fish.pc
|
|
COMMAND sed '/Version/d' fish.pc.noversion > fish.pc
|
|
COMMAND printf "Version: " >> fish.pc
|
|
COMMAND cat ${FBVF} >> fish.pc
|
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
|
DEPENDS CHECK-FISH-BUILD-VERSION-FILE ${CMAKE_CURRENT_BINARY_DIR}/fish.pc.noversion)
|
|
|
|
add_custom_target(build_fish_pc ALL DEPENDS fish.pc)
|
|
|
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/fish.pc
|
|
DESTINATION ${rel_datadir}/pkgconfig)
|
|
|
|
install(DIRECTORY share/completions/
|
|
DESTINATION ${rel_datadir}/fish/completions
|
|
FILES_MATCHING PATTERN "*.fish")
|
|
|
|
install(DIRECTORY share/functions/
|
|
DESTINATION ${rel_datadir}/fish/functions
|
|
FILES_MATCHING PATTERN "*.fish")
|
|
|
|
install(DIRECTORY share/groff
|
|
DESTINATION ${rel_datadir}/fish)
|
|
|
|
# CONDEMNED_PAGE is managed by the conditional above
|
|
# Building the man pages is optional: if sphinx isn't installed, they're not built
|
|
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/
|
|
DESTINATION ${rel_datadir}/fish/man/man1
|
|
FILES_MATCHING
|
|
PATTERN "*.1"
|
|
PATTERN ${CONDEMNED_PAGE} EXCLUDE)
|
|
|
|
install(PROGRAMS share/tools/create_manpage_completions.py share/tools/deroff.py
|
|
DESTINATION ${rel_datadir}/fish/tools/)
|
|
|
|
install(DIRECTORY share/tools/web_config
|
|
DESTINATION ${rel_datadir}/fish/tools/
|
|
FILES_MATCHING
|
|
PATTERN "*.png"
|
|
PATTERN "*.css"
|
|
PATTERN "*.html"
|
|
PATTERN "*.py"
|
|
PATTERN "*.js"
|
|
PATTERN "*.theme"
|
|
PATTERN "*.fish")
|
|
|
|
# Building the man pages is optional: if Sphinx isn't installed, they're not built
|
|
install(FILES ${MANUALS} DESTINATION ${mandir}/man1/ OPTIONAL)
|
|
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/user_doc/html/ # Trailing slash is important!
|
|
DESTINATION ${docdir} OPTIONAL)
|
|
install(FILES CHANGELOG.rst DESTINATION ${docdir})
|
|
|
|
# Group install targets into a InstallTargets folder
|
|
set_property(TARGET build_fish_pc CHECK-FISH-BUILD-VERSION-FILE
|
|
PROPERTY FOLDER cmake/InstallTargets)
|
|
|
|
# Make a target build_root that installs into the buildroot directory, for testing.
|
|
set(BUILDROOT_DIR ${CMAKE_CURRENT_BINARY_DIR}/buildroot)
|
|
add_custom_target(build_root
|
|
COMMAND DESTDIR=${BUILDROOT_DIR} ${CMAKE_COMMAND}
|
|
--build ${CMAKE_CURRENT_BINARY_DIR} --target install)
|