mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-04-19 14:51:13 -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
91 lines
2.6 KiB
CMake
91 lines
2.6 KiB
CMake
cmake_minimum_required(VERSION 3.15)
|
|
|
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
|
|
|
project(fish LANGUAGES C)
|
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
|
|
set(DEFAULT_BUILD_TYPE "RelWithDebInfo")
|
|
|
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
message(STATUS "Setting build type to default '${DEFAULT_BUILD_TYPE}'")
|
|
set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}")
|
|
endif()
|
|
|
|
# Set up standard directories.
|
|
include(GNUInstallDirs)
|
|
|
|
# Set up PCRE2
|
|
# This sets an environment variable that needs to be available before the Rust stanzas
|
|
include(cmake/PCRE2.cmake)
|
|
|
|
include(cmake/Rust.cmake)
|
|
|
|
# Work around issue where archive-built libs go in the wrong place.
|
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
|
|
|
# Set up the machinery around FISH-BUILD-VERSION-FILE
|
|
# This defines the FBVF variable.
|
|
include(Version)
|
|
|
|
# Let fish pick up when we're running out of the build directory without installing
|
|
get_filename_component(REAL_CMAKE_BINARY_DIR "${CMAKE_BINARY_DIR}" REALPATH)
|
|
get_filename_component(REAL_CMAKE_SOURCE_DIR "${CMAKE_SOURCE_DIR}" REALPATH)
|
|
add_definitions(-DCMAKE_BINARY_DIR="${REAL_CMAKE_BINARY_DIR}")
|
|
add_definitions(-DCMAKE_SOURCE_DIR="${REAL_CMAKE_SOURCE_DIR}")
|
|
|
|
set(build_types Release RelWithDebInfo Debug "")
|
|
if(NOT "${CMAKE_BUILD_TYPE}" IN_LIST build_types)
|
|
message(WARNING "Unsupported build type ${CMAKE_BUILD_TYPE}. If this doesn't build, try one of Release, RelWithDebInfo or Debug")
|
|
endif()
|
|
|
|
# Define a function to build and link dependencies.
|
|
function(CREATE_TARGET target)
|
|
add_custom_target(
|
|
${target} ALL
|
|
COMMAND
|
|
"${CMAKE_COMMAND}" -E
|
|
env ${VARS_FOR_CARGO}
|
|
${Rust_CARGO}
|
|
build --bin ${target}
|
|
$<$<CONFIG:Release>:--release>
|
|
$<$<CONFIG:RelWithDebInfo>:--profile=release-with-debug>
|
|
--target ${Rust_CARGO_TARGET}
|
|
--no-default-features
|
|
--features=${FISH_CARGO_FEATURES}
|
|
${CARGO_FLAGS}
|
|
&&
|
|
"${CMAKE_COMMAND}" -E
|
|
copy "${rust_target_dir}/${rust_profile}/${target}" "${CMAKE_CURRENT_BINARY_DIR}"
|
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
USES_TERMINAL
|
|
)
|
|
endfunction(CREATE_TARGET)
|
|
|
|
# Define fish.
|
|
create_target(fish)
|
|
|
|
# Define fish_indent.
|
|
create_target(fish_indent)
|
|
|
|
# Define fish_key_reader.
|
|
create_target(fish_key_reader)
|
|
|
|
# Set up the docs.
|
|
include(cmake/Docs.cmake)
|
|
|
|
# Set up tests.
|
|
include(cmake/Tests.cmake)
|
|
|
|
# Benchmarking support.
|
|
include(cmake/Benchmark.cmake)
|
|
|
|
# Set up install.
|
|
include(cmake/Install.cmake)
|
|
|
|
# Mac app.
|
|
include(cmake/MacApp.cmake)
|
|
|
|
include(FeatureSummary)
|
|
feature_summary(WHAT ALL)
|