mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-31 12:21:19 -03:00
Compare commits
40 Commits
4.0.6
...
coverity_s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9da2f9c77 | ||
|
|
62b69532b1 | ||
|
|
2f1e8d9f8b | ||
|
|
64c8cee001 | ||
|
|
2ea6b8c128 | ||
|
|
ed844fa0ac | ||
|
|
b0bda695b5 | ||
|
|
e945a5f179 | ||
|
|
dfeccf2a1e | ||
|
|
593675e05e | ||
|
|
50a5460c17 | ||
|
|
172436f508 | ||
|
|
10a3eedcab | ||
|
|
53d8d9e0d9 | ||
|
|
642edbc434 | ||
|
|
d85bf9c0da | ||
|
|
37503f5f01 | ||
|
|
193dbe2a78 | ||
|
|
e95b9c16f0 | ||
|
|
d1bfea9ee5 | ||
|
|
c9c2cd069d | ||
|
|
c5409335ee | ||
|
|
db9259210d | ||
|
|
998b878dda | ||
|
|
32e2d36a7a | ||
|
|
37dc28f354 | ||
|
|
20ee1ce94b | ||
|
|
5c95da56a4 | ||
|
|
82325778a5 | ||
|
|
49d8e71e1f | ||
|
|
a9d1fb23da | ||
|
|
d8d194af63 | ||
|
|
85295488a6 | ||
|
|
7a8c5f53d5 | ||
|
|
bec4c374f5 | ||
|
|
d925862350 | ||
|
|
1f2a2de414 | ||
|
|
c21d880f34 | ||
|
|
e1dde5d7e1 | ||
|
|
66d7850b18 |
@@ -1,27 +1,24 @@
|
|||||||
image: alpine/edge
|
image: alpine/edge
|
||||||
packages:
|
packages:
|
||||||
- cargo
|
|
||||||
- clang17-libclang
|
|
||||||
- cmake
|
- cmake
|
||||||
- ninja
|
- ninja
|
||||||
|
- ncurses-dev
|
||||||
- pcre2-dev
|
- pcre2-dev
|
||||||
- py3-pexpect
|
- expect
|
||||||
- python3
|
- python
|
||||||
- rust
|
|
||||||
- tmux
|
|
||||||
sources:
|
sources:
|
||||||
- https://github.com/fish-shell/fish-shell
|
- https://git.sr.ht/~faho/fish
|
||||||
tasks:
|
tasks:
|
||||||
- build: |
|
- build: |
|
||||||
cd fish-shell
|
cd fish
|
||||||
mkdir build
|
mkdir build || :
|
||||||
cd build
|
cd build
|
||||||
cmake -G Ninja .. \
|
cmake -G Ninja .. \
|
||||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||||
-DCMAKE_INSTALL_DATADIR=share \
|
-DCMAKE_INSTALL_DATADIR=share \
|
||||||
-DCMAKE_INSTALL_DOCDIR=share/doc/fish \
|
-DCMAKE_INSTALL_DOCDIR=share/doc/fish \
|
||||||
-DCMAKE_INSTALL_SYSCONFDIR=/etc
|
-DCMAKE_INSTALL_SYSCONFDIR=/etc
|
||||||
ninja
|
ninja
|
||||||
- test: |
|
- test: |
|
||||||
cd fish-shell/build
|
cd fish/build
|
||||||
env ninja test
|
env SHOW_INTERACTIVE_LOG=1 ninja test
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ image: archlinux
|
|||||||
packages:
|
packages:
|
||||||
- cmake
|
- cmake
|
||||||
- ninja
|
- ninja
|
||||||
|
- expect
|
||||||
- python
|
- python
|
||||||
- python-pexpect
|
|
||||||
- tmux
|
|
||||||
sources:
|
sources:
|
||||||
- https://git.sr.ht/~faho/fish
|
- https://git.sr.ht/~faho/fish
|
||||||
tasks:
|
tasks:
|
||||||
@@ -20,4 +19,4 @@ tasks:
|
|||||||
ninja
|
ninja
|
||||||
- test: |
|
- test: |
|
||||||
cd fish/build
|
cd fish/build
|
||||||
env ninja test
|
env SHOW_INTERACTIVE_LOG=1 ninja test
|
||||||
|
|||||||
@@ -1,30 +1,26 @@
|
|||||||
image: freebsd/latest
|
image: freebsd/latest
|
||||||
packages:
|
packages:
|
||||||
- cmake
|
- ncurses
|
||||||
- gcc
|
- gcc
|
||||||
- gettext
|
- gettext
|
||||||
|
- expect
|
||||||
|
- cmake
|
||||||
- gmake
|
- gmake
|
||||||
- llvm
|
|
||||||
- terminfo-db
|
|
||||||
- ninja
|
|
||||||
- pcre2
|
- pcre2
|
||||||
- py311-pexpect
|
|
||||||
- python
|
- python
|
||||||
- rust
|
|
||||||
- tmux
|
|
||||||
sources:
|
sources:
|
||||||
- https://github.com/fish-shell/fish-shell
|
- https://git.sr.ht/~faho/fish
|
||||||
tasks:
|
tasks:
|
||||||
- build: |
|
- build: |
|
||||||
cd fish-shell
|
cd fish
|
||||||
mkdir build
|
mkdir build || :
|
||||||
cd build
|
cd build
|
||||||
cmake -GNinja .. \
|
cmake .. \
|
||||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||||
-DCMAKE_INSTALL_DATADIR=share \
|
-DCMAKE_INSTALL_DATADIR=share \
|
||||||
-DCMAKE_INSTALL_DOCDIR=share/doc/fish \
|
-DCMAKE_INSTALL_DOCDIR=share/doc/fish \
|
||||||
-DCMAKE_INSTALL_SYSCONFDIR=/etc
|
-DCMAKE_INSTALL_SYSCONFDIR=/etc
|
||||||
ninja
|
gmake -j2
|
||||||
- test: |
|
- test: |
|
||||||
cd fish-shell/build
|
cd fish/build
|
||||||
ninja test
|
gmake test SHOW_INTERACTIVE_LOG=1
|
||||||
|
|||||||
96
.cirrus.yml
96
.cirrus.yml
@@ -1,96 +0,0 @@
|
|||||||
env:
|
|
||||||
CIRRUS_CLONE_DEPTH: 100
|
|
||||||
CI: 1
|
|
||||||
|
|
||||||
linux_task:
|
|
||||||
matrix:
|
|
||||||
- name: alpine
|
|
||||||
container: &step
|
|
||||||
image: ghcr.io/krobelus/fish-ci/alpine:latest
|
|
||||||
memory: 4GB
|
|
||||||
- name: jammy
|
|
||||||
container:
|
|
||||||
<<: *step
|
|
||||||
image: ghcr.io/krobelus/fish-ci/jammy:latest
|
|
||||||
# - name: jammy-asan
|
|
||||||
# container:
|
|
||||||
# <<: *step
|
|
||||||
# image: ghcr.io/krobelus/fish-ci/jammy-asan:latest
|
|
||||||
# - name: focal-32bit
|
|
||||||
# container:
|
|
||||||
# <<: *step
|
|
||||||
# image: ghcr.io/krobelus/fish-ci/focal-32bit:latest
|
|
||||||
|
|
||||||
tests_script:
|
|
||||||
# cirrus at times gives us 32 procs and 2 GB of RAM
|
|
||||||
# Unrestriced parallelism results in OOM
|
|
||||||
- lscpu || true
|
|
||||||
- (cat /proc/meminfo | grep MemTotal) || true
|
|
||||||
- mkdir build && cd build
|
|
||||||
- cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCTEST_PARALLEL_LEVEL=6 ..
|
|
||||||
- ninja -j 6 fish
|
|
||||||
- ninja fish_run_tests
|
|
||||||
|
|
||||||
only_if: $CIRRUS_REPO_OWNER == 'fish-shell'
|
|
||||||
|
|
||||||
linux_arm_task:
|
|
||||||
matrix:
|
|
||||||
- name: focal-arm64
|
|
||||||
arm_container:
|
|
||||||
image: ghcr.io/fish-shell/fish-ci/focal-arm64
|
|
||||||
- name: jammy-armv7-32bit
|
|
||||||
arm_container:
|
|
||||||
image: ghcr.io/fish-shell/fish-ci/jammy-armv7-32bit
|
|
||||||
|
|
||||||
tests_script:
|
|
||||||
# cirrus at times gives us 32 procs and 2 GB of RAM
|
|
||||||
# Unrestriced parallelism results in OOM
|
|
||||||
- lscpu || true
|
|
||||||
- (cat /proc/meminfo | grep MemTotal) || true
|
|
||||||
- mkdir build && cd build
|
|
||||||
- cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCTEST_PARALLEL_LEVEL=6 ..
|
|
||||||
- ninja -j 6 fish
|
|
||||||
- file ./fish
|
|
||||||
- ninja fish_run_tests
|
|
||||||
|
|
||||||
# CI task disabled during RIIR transition
|
|
||||||
only_if: false && $CIRRUS_REPO_OWNER == 'fish-shell'
|
|
||||||
|
|
||||||
freebsd_task:
|
|
||||||
matrix:
|
|
||||||
# - name: FreeBSD 14
|
|
||||||
# freebsd_instance:
|
|
||||||
# image_family: freebsd-14-0-snap
|
|
||||||
- name: FreeBSD 13
|
|
||||||
freebsd_instance:
|
|
||||||
image: freebsd-13-2-release-amd64
|
|
||||||
# - name: FreeBSD 12.3
|
|
||||||
# freebsd_instance:
|
|
||||||
# image: freebsd-12-3-release-amd64
|
|
||||||
tests_script:
|
|
||||||
- pkg install -y cmake-core devel/pcre2 devel/ninja misc/py-pexpect git-lite terminfo-db
|
|
||||||
# libclang.so is a required build dependency for rust-c++ ffi bridge
|
|
||||||
- pkg install -y llvm
|
|
||||||
# BSDs have the following behavior: root may open or access files even if
|
|
||||||
# the mode bits would otherwise disallow it. For example root may open()
|
|
||||||
# a file with write privileges even if the file has mode 400. This breaks
|
|
||||||
# our tests for e.g. cd and path. So create a new unprivileged user to run tests.
|
|
||||||
- pw user add -n fish-user -s /bin/csh -d /home/fish-user
|
|
||||||
- mkdir -p /home/fish-user
|
|
||||||
- chown -R fish-user /home/fish-user
|
|
||||||
- mkdir build && cd build
|
|
||||||
- chown -R fish-user ..
|
|
||||||
- sudo -u fish-user -s whoami
|
|
||||||
# FreeBSD's pkg currently has rust 1.66.0 while we need rust 1.70.0+. Use rustup to install
|
|
||||||
# the latest, but note that it only installs rust per-user.
|
|
||||||
- sudo -u fish-user -s fetch -qo - https://sh.rustup.rs > rustup.sh
|
|
||||||
- sudo -u fish-user -s sh ./rustup.sh -y --profile=minimal
|
|
||||||
# `sudo -s ...` does not invoke a login shell so we need a workaround to make sure the
|
|
||||||
# rustup environment is configured for subsequent `sudo -s ...` commands.
|
|
||||||
# For some reason, this doesn't do the job:
|
|
||||||
# - sudo -u fish-user sh -c 'echo source \$HOME/.cargo/env >> $HOME/.cshrc'
|
|
||||||
- sudo -u fish-user -s cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCTEST_PARALLEL_LEVEL=1 ..
|
|
||||||
- sudo -u fish-user sh -c '. $HOME/.cargo/env; ninja -j 6 fish'
|
|
||||||
- sudo -u fish-user sh -c '. $HOME/.cargo/env; ninja fish_run_tests'
|
|
||||||
|
|
||||||
only_if: $CIRRUS_REPO_OWNER == 'fish-shell'
|
|
||||||
@@ -6,3 +6,11 @@
|
|||||||
BasedOnStyle: Google
|
BasedOnStyle: Google
|
||||||
ColumnLimit: 100
|
ColumnLimit: 100
|
||||||
IndentWidth: 4
|
IndentWidth: 4
|
||||||
|
|
||||||
|
# Place config.h first always.
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^"config.h"'
|
||||||
|
Priority: -1
|
||||||
|
|
||||||
|
# We don't want OCLint pragmas to be reformatted.
|
||||||
|
CommentPragmas: '^!OCLINT'
|
||||||
|
|||||||
17
.clang-tidy
Normal file
17
.clang-tidy
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
Checks: 'clang-diagnostic-*,clang-analyzer-*,cert-*,performance-*,portability-*,modernize-use-auto,modernize-loop-convert,modernize-use-bool-literals,modernize-use-using,hicpp-uppercase-literal-suffix,readability-make-member-function-const,readability-redundant-string-init,readability-inconsistent-declaration-parameter-name,readability-redundant-access-specifiers'
|
||||||
|
WarningsAsErrors: ''
|
||||||
|
HeaderFilterRegex: ''
|
||||||
|
AnalyzeTemporaryDtors: false
|
||||||
|
FormatStyle: File
|
||||||
|
CheckOptions:
|
||||||
|
- key: cert-dcl16-c.NewSuffixes
|
||||||
|
value: 'L;LL;LU;LLU'
|
||||||
|
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
|
||||||
|
value: '0'
|
||||||
|
- key: modernize-loop-convert.MinConfidence
|
||||||
|
value: 'risky'
|
||||||
|
- key: modernize-use-auto.RemoveStars
|
||||||
|
value: '1'
|
||||||
|
...
|
||||||
|
|
||||||
26
.cppcheck.rules
Normal file
26
.cppcheck.rules
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<![CDATA[
|
||||||
|
<!-- Sadly we can't enable the following two rules since doing so causes false
|
||||||
|
positives in standard header files rather than just project specific
|
||||||
|
source files. If we can find a way to enable these rules by also
|
||||||
|
excluding system include files we should do so.
|
||||||
|
<rule version="1">
|
||||||
|
<pattern> wcwidth \(</pattern>
|
||||||
|
<message>
|
||||||
|
<id>wcwidthForbidden</id>
|
||||||
|
<severity>warning</severity>
|
||||||
|
<summary>Always use fish_wcwidth rather than wcwidth.</summary>
|
||||||
|
</message>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<rule version="1">
|
||||||
|
<pattern> wcswidth \(</pattern>
|
||||||
|
<message>
|
||||||
|
<id>wcswidthForbidden</id>
|
||||||
|
<severity>warning</severity>
|
||||||
|
<summary>Always use fish_wcswidth rather than wcswidth.</summary>
|
||||||
|
</message>
|
||||||
|
</rule>
|
||||||
|
<--!>
|
||||||
|
]]>
|
||||||
12
.cppcheck.suppressions
Normal file
12
.cppcheck.suppressions
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// suppress all instances of varFuncNullUB: "Passing NULL after the last typed
|
||||||
|
// argument to a variadic function leads to undefined behaviour." That's
|
||||||
|
// because all the places we do this are valid and won't cause problems even
|
||||||
|
// on a ILP64 platform because we're careful about using NULL rather than 0.
|
||||||
|
varFuncNullUB
|
||||||
|
// Suppress the warning about unmatched suppressions. At the moment these
|
||||||
|
// warnings are emitted even when removing the suppression comment results in
|
||||||
|
// the warning being suppressed. In other words this unmatchedSuppression
|
||||||
|
// warnings are false positives.
|
||||||
|
unmatchedSuppression
|
||||||
|
// Suppress this one because it reports assert(condition && "message"), which we use all over the place
|
||||||
|
incorrectStringBooleanError
|
||||||
@@ -13,20 +13,10 @@ max_line_length = 100
|
|||||||
indent_style = tab
|
indent_style = tab
|
||||||
|
|
||||||
[*.{md,rst}]
|
[*.{md,rst}]
|
||||||
max_line_length = unset
|
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
[*.sh]
|
[*.{sh,ac}]
|
||||||
indent_size = 4
|
indent_size = 2
|
||||||
|
|
||||||
[build_tools/release.sh]
|
|
||||||
max_line_length = 72
|
|
||||||
|
|
||||||
[Dockerfile]
|
[Dockerfile]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
[share/{completions,functions}/**.fish]
|
|
||||||
max_line_length = unset
|
|
||||||
|
|
||||||
[{COMMIT_EDITMSG,git-revise-todo,*.jjdescription}]
|
|
||||||
max_line_length = 72
|
|
||||||
|
|||||||
11
.gitattributes
vendored
11
.gitattributes
vendored
@@ -21,12 +21,11 @@
|
|||||||
/.github/* export-ignore
|
/.github/* export-ignore
|
||||||
/.builds export-ignore
|
/.builds export-ignore
|
||||||
/.builds/* export-ignore
|
/.builds/* export-ignore
|
||||||
|
/.travis.yml export-ignore
|
||||||
|
|
||||||
# for linguist; let github identify our project as C++ instead of C due to pcre2
|
# for linguist; let github identify our project as C++ instead of C due to pcre2
|
||||||
pcre2/** linguist-vendored
|
/pcre2/* linguist-vendored
|
||||||
alpine.js linguist-vendored
|
angular.js linguist-vendored
|
||||||
doc_src/** linguist-documentation
|
/doc_src/* linguist-documentation
|
||||||
*.fish linguist-language=fish
|
*.fish linguist-language=fish
|
||||||
src/*.h linguist-language=c++
|
/tests/*.in linguist-language=fish
|
||||||
src/builtins/*.h linguist-language=c++
|
|
||||||
share/completions/*.fish linguist-documentation
|
|
||||||
|
|||||||
4
.github/ISSUE_TEMPLATE.md
vendored
4
.github/ISSUE_TEMPLATE.md
vendored
@@ -8,9 +8,7 @@ Please tell us which operating system and terminal you are using. The output of
|
|||||||
|
|
||||||
Please tell us if you tried fish without third-party customizations by executing this command and whether it affected the behavior you are reporting:
|
Please tell us if you tried fish without third-party customizations by executing this command and whether it affected the behavior you are reporting:
|
||||||
|
|
||||||
sh -c 'env HOME=$(mktemp -d) XDG_CONFIG_HOME= XDG_DATA_DIRS= fish'
|
sh -c 'env HOME=$(mktemp -d) fish'
|
||||||
|
|
||||||
Tell us how to reproduce the problem. Including an asciinema.org recording is useful for problems that involve the visual display of fish output such as its prompt.
|
Tell us how to reproduce the problem. Including an asciinema.org recording is useful for problems that involve the visual display of fish output such as its prompt.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
**YOUR TEXT HERE**
|
|
||||||
|
|||||||
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -8,4 +8,4 @@ Fixes issue #
|
|||||||
<!-- Just check off what what we know been done so far. We can help you with this stuff. -->
|
<!-- Just check off what what we know been done so far. We can help you with this stuff. -->
|
||||||
- [ ] Changes to fish usage are reflected in user documentation/manpages.
|
- [ ] Changes to fish usage are reflected in user documentation/manpages.
|
||||||
- [ ] Tests have been added for regressions fixed
|
- [ ] Tests have been added for regressions fixed
|
||||||
- [ ] User-visible changes noted in CHANGELOG.rst <!-- Don't document changes for completions inside CHANGELOG.rst, there are lot of such edits -->
|
- [ ] User-visible changes noted in CHANGELOG.rst
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
name: Oldest Supported Rust Toolchain
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
targets:
|
|
||||||
description: Comma-separated list of target triples to install for this toolchain
|
|
||||||
required: false
|
|
||||||
components:
|
|
||||||
description: Comma-separated list of components to be additionally installed
|
|
||||||
required: false
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- uses: dtolnay/rust-toolchain@1.70
|
|
||||||
with:
|
|
||||||
targets: ${{ inputs.targets }}
|
|
||||||
components: ${{ inputs.components}}
|
|
||||||
20
.github/actions/rust-toolchain@stable/action.yml
vendored
20
.github/actions/rust-toolchain@stable/action.yml
vendored
@@ -1,20 +0,0 @@
|
|||||||
name: Stable Rust Toolchain
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
targets:
|
|
||||||
description: Comma-separated list of target triples to install for this toolchain
|
|
||||||
required: false
|
|
||||||
components:
|
|
||||||
description: Comma-separated list of components to be additionally installed
|
|
||||||
required: false
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- uses: dtolnay/rust-toolchain@1.89
|
|
||||||
with:
|
|
||||||
targets: ${{ inputs.targets }}
|
|
||||||
components: ${{ inputs.components }}
|
|
||||||
66
.github/workflows/autolabel_prs.yml
vendored
66
.github/workflows/autolabel_prs.yml
vendored
@@ -1,66 +0,0 @@
|
|||||||
name: Auto-Label PRs
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened, synchronize]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
label-and-milestone:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
# - name: Checkout repository
|
|
||||||
# uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Set label and milestone
|
|
||||||
id: set-label-milestone
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const completionsLabel = 'completions';
|
|
||||||
const completionsMilestone = 'fish next-3.x';
|
|
||||||
|
|
||||||
// Get changed files in the pull request
|
|
||||||
const prNumber = context.payload.pull_request.number;
|
|
||||||
const { data: files } = await github.rest.pulls.listFiles({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
pull_number: prNumber,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check if any file matches /share/completions/*.fish and no change is outside of /share/
|
|
||||||
const completionsRegex = new RegExp('^share/completions/.*\.fish');
|
|
||||||
const isCompletions = files.some(file => completionsRegex.test(file.filename))
|
|
||||||
&& files.every(file => file.filename.startsWith('share/'));
|
|
||||||
|
|
||||||
if (isCompletions) {
|
|
||||||
// Add label to PR
|
|
||||||
await github.rest.issues.addLabels({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: prNumber,
|
|
||||||
labels: [completionsLabel],
|
|
||||||
});
|
|
||||||
console.log(`PR ${prNumber} assigned label "${completionsLabel}"`);
|
|
||||||
|
|
||||||
// Get the list of milestones
|
|
||||||
const { data: milestones } = await github.rest.issues.listMilestones({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Find the milestone id
|
|
||||||
const milestone = milestones.find(milestone => milestone.title === completionsMilestone);
|
|
||||||
|
|
||||||
if (milestone) {
|
|
||||||
// Set the milestone for the PR
|
|
||||||
await github.rest.issues.update({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: prNumber,
|
|
||||||
milestone: milestone.number
|
|
||||||
});
|
|
||||||
console.log(`PR ${prNumber} assigned milestone "${completionsMilestone}"`);
|
|
||||||
} else {
|
|
||||||
console.error(`Milestone "${completionsMilestone}" not found`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
19
.github/workflows/lockthreads.yml
vendored
19
.github/workflows/lockthreads.yml
vendored
@@ -2,24 +2,15 @@ name: 'Lock threads'
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 18 * * 1'
|
- cron: '0 * * * *'
|
||||||
# │ │ │ │ │
|
|
||||||
# min 0-59 ┘ │ │ │ └ weekday 0-6
|
|
||||||
# hour 0-23 ┘ │ └ month 1-12
|
|
||||||
# └ day 1-31
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lock:
|
lock:
|
||||||
permissions:
|
|
||||||
issues: write # for dessant/lock-threads to lock issues
|
|
||||||
pull-requests: write # for dessant/lock-threads to lock PRs
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: dessant/lock-threads@v4
|
- uses: dessant/lock-threads@v2
|
||||||
with:
|
with:
|
||||||
github-token: ${{ github.token }}
|
github-token: ${{ github.token }}
|
||||||
issue-inactive-days: '365'
|
issue-lock-inactive-days: '90'
|
||||||
pr-inactive-days: '365'
|
pr-lock-inactive-days: '90'
|
||||||
exclude-any-issue-labels: 'question, needs more info'
|
issue-exclude-labels: 'question'
|
||||||
|
|||||||
156
.github/workflows/main.yml
vendored
156
.github/workflows/main.yml
vendored
@@ -1,13 +1,10 @@
|
|||||||
name: make fish_run_tests
|
name: C/C++ CI
|
||||||
|
|
||||||
on: [push, pull_request]
|
on:
|
||||||
|
push:
|
||||||
env:
|
branches: [ master ]
|
||||||
CTEST_PARALLEL_LEVEL: "1"
|
pull_request:
|
||||||
CMAKE_BUILD_PARALLEL_LEVEL: "4"
|
branches: [ master ]
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ubuntu:
|
ubuntu:
|
||||||
@@ -15,152 +12,37 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- uses: dtolnay/rust-toolchain@1.70
|
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: |
|
run: |
|
||||||
sudo apt install gettext libpcre2-dev python3-pexpect tmux
|
sudo apt install expect gettext libncurses5-dev libpcre2-dev
|
||||||
# Generate a locale that uses a comma as decimal separator.
|
|
||||||
sudo locale-gen fr_FR.UTF-8
|
|
||||||
- name: cmake
|
- name: cmake
|
||||||
run: |
|
run: |
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
cmake ..
|
||||||
- name: make
|
- name: make
|
||||||
run: |
|
run: |
|
||||||
make -C build VERBOSE=1
|
make
|
||||||
- name: make fish_run_tests
|
- name: make test
|
||||||
run: |
|
run: |
|
||||||
make -C build VERBOSE=1 fish_run_tests
|
make test
|
||||||
|
|
||||||
ubuntu-32bit-static-pcre2:
|
# macos:
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
# runs-on: macos-latest
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: dtolnay/rust-toolchain@1.70
|
|
||||||
with:
|
|
||||||
targets: "i586-unknown-linux-gnu" # rust-toolchain wants this comma-separated
|
|
||||||
- name: Install deps
|
|
||||||
run: |
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install gettext python3-pexpect g++-multilib tmux
|
|
||||||
- name: cmake
|
|
||||||
env:
|
|
||||||
CFLAGS: "-m32"
|
|
||||||
run: |
|
|
||||||
mkdir build && cd build
|
|
||||||
cmake -DFISH_USE_SYSTEM_PCRE2=OFF -DRust_CARGO_TARGET=i586-unknown-linux-gnu ..
|
|
||||||
- name: make
|
|
||||||
run: |
|
|
||||||
make -C build VERBOSE=1
|
|
||||||
- name: make fish_run_tests
|
|
||||||
run: |
|
|
||||||
make -C build VERBOSE=1 fish_run_tests
|
|
||||||
|
|
||||||
ubuntu-asan:
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
# Rust has two different memory sanitizers of interest; they can't be used at the same time:
|
|
||||||
# * AddressSanitizer detects out-of-bound access, use-after-free, use-after-return,
|
|
||||||
# use-after-scope, double-free, invalid-free, and memory leaks.
|
|
||||||
# * MemorySanitizer detects uninitialized reads.
|
|
||||||
#
|
|
||||||
RUSTFLAGS: "-Zsanitizer=address"
|
|
||||||
# RUSTFLAGS: "-Zsanitizer=memory -Zsanitizer-memory-track-origins"
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# All -Z options require running nightly
|
|
||||||
- uses: dtolnay/rust-toolchain@nightly
|
|
||||||
with:
|
|
||||||
# ASAN uses `cargo build -Zbuild-std` which requires the rust-src component
|
|
||||||
# this is comma-separated
|
|
||||||
components: rust-src
|
|
||||||
- name: Install deps
|
|
||||||
run: |
|
|
||||||
sudo apt install gettext libpcre2-dev python3-pexpect tmux
|
|
||||||
- name: cmake
|
|
||||||
env:
|
|
||||||
CC: clang
|
|
||||||
run: |
|
|
||||||
mkdir build && cd build
|
|
||||||
# Rust's ASAN requires the build system to explicitly pass a --target triple. We read that
|
|
||||||
# value from CMake variable Rust_CARGO_TARGET (shared with corrosion).
|
|
||||||
cmake .. -DASAN=1 -DRust_CARGO_TARGET=x86_64-unknown-linux-gnu -DCMAKE_BUILD_TYPE=Debug
|
|
||||||
- name: make
|
|
||||||
run: |
|
|
||||||
make -C build VERBOSE=1
|
|
||||||
- name: make fish_run_tests
|
|
||||||
env:
|
|
||||||
FISH_CI_SAN: 1
|
|
||||||
ASAN_OPTIONS: check_initialization_order=1:detect_stack_use_after_return=1:detect_leaks=1:fast_unwind_on_malloc=0
|
|
||||||
# use_tls=0 is a workaround for LSAN crashing with "Tracer caught signal 11" (SIGSEGV),
|
|
||||||
# which seems to be an issue with TLS support in newer glibc versions under virtualized
|
|
||||||
# environments. Follow https://github.com/google/sanitizers/issues/1342 and
|
|
||||||
# https://github.com/google/sanitizers/issues/1409 to track this issue.
|
|
||||||
# UPDATE: this can cause spurious leak reports for __cxa_thread_atexit_impl() under glibc.
|
|
||||||
LSAN_OPTIONS: verbosity=0:log_threads=0:use_tls=1:print_suppressions=0
|
|
||||||
run: |
|
|
||||||
llvm_version=$(clang --version | awk 'NR==1 { split($NF, version, "."); print version[1] }')
|
|
||||||
export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer-$llvm_version
|
|
||||||
export LSAN_OPTIONS="$LSAN_OPTIONS:suppressions=$PWD/build_tools/lsan_suppressions.txt"
|
|
||||||
make -C build VERBOSE=1 fish_run_tests
|
|
||||||
|
|
||||||
# Our clang++ tsan builds are not recognizing safe rust patterns (such as the fact that Drop
|
|
||||||
# cannot be called while a thread is using the object in question). Rust has its own way of
|
|
||||||
# running TSAN, but for the duration of the port from C++ to Rust, we'll keep this disabled.
|
|
||||||
|
|
||||||
# ubuntu-threadsan:
|
|
||||||
#
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
#
|
|
||||||
# steps:
|
# steps:
|
||||||
# - uses: actions/checkout@v4
|
# - uses: actions/checkout@v2
|
||||||
# - uses: dtolnay/rust-toolchain@1.70
|
|
||||||
# - name: Install deps
|
# - name: Install deps
|
||||||
# run: |
|
# run: |
|
||||||
# sudo apt install gettext libpcre2-dev python3-pexpect tmux
|
# brew install pcre2
|
||||||
# - name: cmake
|
# - name: cmake
|
||||||
# env:
|
|
||||||
# FISH_CI_SAN: 1
|
|
||||||
# CC: clang
|
|
||||||
# run: |
|
# run: |
|
||||||
# mkdir build && cd build
|
# mkdir build && cd build
|
||||||
# cmake ..
|
# cmake ..
|
||||||
# - name: make
|
# - name: make
|
||||||
# run: |
|
# run: |
|
||||||
# make
|
# make
|
||||||
# - name: make fish_run_tests
|
# - name: make test
|
||||||
# run: |
|
# run: |
|
||||||
# make -C build fish_run_tests
|
# make test
|
||||||
|
|
||||||
macos:
|
|
||||||
|
|
||||||
runs-on: macos-latest
|
|
||||||
|
|
||||||
env:
|
|
||||||
# macOS runners keep having issues loading Cargo.toml dependencies from git (GitHub) instead
|
|
||||||
# of crates.io, so give this a try. It's also sometimes significantly faster on all platforms.
|
|
||||||
CARGO_NET_GIT_FETCH_WITH_CLI: true
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: dtolnay/rust-toolchain@1.70
|
|
||||||
- name: Install deps
|
|
||||||
run: |
|
|
||||||
# --break-system-packages because homebrew has now declared itself "externally managed".
|
|
||||||
# this is CI so we don't actually care.
|
|
||||||
sudo pip3 install --break-system-packages pexpect
|
|
||||||
brew install tmux
|
|
||||||
- name: cmake
|
|
||||||
run: |
|
|
||||||
mkdir build && cd build
|
|
||||||
cmake -DWITH_GETTEXT=NO -DCMAKE_BUILD_TYPE=Debug ..
|
|
||||||
- name: make
|
|
||||||
run: |
|
|
||||||
make -C build VERBOSE=1
|
|
||||||
- name: make fish_run_tests
|
|
||||||
run: |
|
|
||||||
make -C build VERBOSE=1 fish_run_tests
|
|
||||||
|
|||||||
211
.github/workflows/release.yml
vendored
211
.github/workflows/release.yml
vendored
@@ -1,211 +0,0 @@
|
|||||||
name: Create a new release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- '*.*.*'
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
is-release-tag:
|
|
||||||
name: Pre-release checks
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
# Workaround for https://github.com/actions/checkout/issues/882
|
|
||||||
ref: ${{ github.ref }}
|
|
||||||
- name: Check if the pushed tag looks like a release
|
|
||||||
run: |
|
|
||||||
set -x
|
|
||||||
commit_subject=$(git log -1 --format=%s)
|
|
||||||
tag=$(git describe)
|
|
||||||
[ "$commit_subject" = "Release $tag" ]
|
|
||||||
|
|
||||||
|
|
||||||
source-tarball:
|
|
||||||
needs: [is-release-tag]
|
|
||||||
name: Create the source tarball
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
version: ${{ steps.version.outputs.version }}
|
|
||||||
tarball-name: ${{ steps.version.outputs.tarball-name }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
# Workaround for https://github.com/actions/checkout/issues/882
|
|
||||||
ref: ${{ github.ref }}
|
|
||||||
- name: Install dependencies
|
|
||||||
run: sudo apt install cmake gettext ninja-build python3-pip python3-sphinx
|
|
||||||
- name: Create tarball
|
|
||||||
run: |
|
|
||||||
set -x
|
|
||||||
mkdir /tmp/fish-built
|
|
||||||
FISH_ARTEFACT_PATH=/tmp/fish-built ./build_tools/make_tarball.sh
|
|
||||||
{
|
|
||||||
pip install sphinx-markdown-builder==0.6.8
|
|
||||||
relnotes_tmp=$(mktemp -d)
|
|
||||||
mkdir "$relnotes_tmp/src" "$relnotes_tmp/out"
|
|
||||||
version=$(git describe)
|
|
||||||
minor_version=${version%.*}
|
|
||||||
# Delete notes for prior releases.
|
|
||||||
# Also fix up any relative references to other documentation files.
|
|
||||||
awk <CHANGELOG.rst '
|
|
||||||
/^fish/ && $2 != "'"$version"'" { exit }
|
|
||||||
{ print }
|
|
||||||
' |
|
|
||||||
sed >"$relnotes_tmp/src"/index.rst \
|
|
||||||
-e 's,:doc:`\(.*\) <\([^>]*\)>`,`\1 <https://fishshell.com/docs/'"$minor_version"'/\2.html>`_,g' \
|
|
||||||
-e 's,:envvar:`\([^`]*\)`,``$\1``,g'
|
|
||||||
# In future, we could reuse doctree from when we made HTML docs.
|
|
||||||
sphinx-build -j 1 $(: "sphinx-markdown-builder is not marked concurrency-safe") \
|
|
||||||
-W -E -b markdown -c doc_src \
|
|
||||||
-d "$relnotes_tmp/doctree" "$relnotes_tmp/src" $relnotes_tmp/out
|
|
||||||
# Delete title
|
|
||||||
sed -n 1p "$relnotes_tmp/out/index.md" | grep -q "^# fish .*"
|
|
||||||
sed -n 2p "$relnotes_tmp/out/index.md" | grep -q '^$'
|
|
||||||
sed -i 1,2d "$relnotes_tmp/out/index.md"
|
|
||||||
{
|
|
||||||
cat "$relnotes_tmp/out/index.md" - <<EOF
|
|
||||||
----
|
|
||||||
|
|
||||||
*Download links: To download the source code for fish, we suggest the file named "fish-$version.tar.xz". The file downloaded from "Source code (tar.gz)" will not build correctly.*
|
|
||||||
|
|
||||||
*There is no GPG signature because we haven't yet decided how to integrate signing into the new release automation.*
|
|
||||||
|
|
||||||
*The files called fish-$version-linux-\*.tar.xz are experimental packages containing a single standalone ``fish`` binary for any Linux with the given architecture.*
|
|
||||||
EOF
|
|
||||||
} >/tmp/fish-built/release-notes.md
|
|
||||||
rm -r "$relnotes_tmp"
|
|
||||||
}
|
|
||||||
- name: Upload tarball artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: source-tarball
|
|
||||||
path: |
|
|
||||||
/tmp/fish-built/fish-${{ github.ref_name }}.tar.xz
|
|
||||||
/tmp/fish-built/release-notes.md
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
packages-for-linux:
|
|
||||||
needs: [is-release-tag]
|
|
||||||
name: Build single-file fish for Linux (experimental)
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
# Workaround for https://github.com/actions/checkout/issues/882
|
|
||||||
ref: ${{ github.ref }}
|
|
||||||
- name: Install Rust Stable
|
|
||||||
uses: ./.github/actions/rust-toolchain@stable
|
|
||||||
with:
|
|
||||||
targets: x86_64-unknown-linux-musl,aarch64-unknown-linux-musl
|
|
||||||
- name: Install dependencies
|
|
||||||
run: sudo apt install crossbuild-essential-arm64 musl-tools python3-sphinx
|
|
||||||
- name: Build statically-linked executables
|
|
||||||
run: |
|
|
||||||
set -x
|
|
||||||
CFLAGS="-D_FORTIFY_SOURCE=2" \
|
|
||||||
CMAKE_WITH_GETTEXT=0 \
|
|
||||||
CC=aarch64-linux-gnu-gcc \
|
|
||||||
RUSTFLAGS="-C linker=aarch64-linux-gnu-gcc -C link-arg=-lgcc -C link-arg=-D_FORTIFY_SOURCE=0" \
|
|
||||||
cargo build --release --target aarch64-unknown-linux-musl --bin fish
|
|
||||||
cargo build --release --target x86_64-unknown-linux-musl --bin fish
|
|
||||||
- name: Compress
|
|
||||||
run: |
|
|
||||||
set -x
|
|
||||||
for arch in x86_64 aarch64; do
|
|
||||||
tar -cazf fish-$(git describe)-linux-$arch.tar.xz \
|
|
||||||
-C target/$arch-unknown-linux-musl/release fish
|
|
||||||
done
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: Static builds for Linux
|
|
||||||
path: fish-${{ github.ref_name }}-linux-*.tar.xz
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
create-draft-release:
|
|
||||||
needs:
|
|
||||||
- is-release-tag
|
|
||||||
- source-tarball
|
|
||||||
- packages-for-linux
|
|
||||||
name: Create release draft
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
# Workaround for https://github.com/actions/checkout/issues/882
|
|
||||||
ref: ${{ github.ref }}
|
|
||||||
- name: Download all artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
merge-multiple: true
|
|
||||||
path: /tmp/artifacts
|
|
||||||
- name: List artifacts
|
|
||||||
run: find /tmp/artifacts -type f
|
|
||||||
- name: Create draft release
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
with:
|
|
||||||
tag_name: ${{ github.ref_name }}
|
|
||||||
name: fish ${{ github.ref_name }}
|
|
||||||
body_path: /tmp/artifacts/release-notes.md
|
|
||||||
draft: true
|
|
||||||
files: |
|
|
||||||
/tmp/artifacts/fish-${{ github.ref_name }}.tar.xz
|
|
||||||
/tmp/artifacts/fish-${{ github.ref_name }}-linux-*.tar.xz
|
|
||||||
|
|
||||||
packages-for-macos:
|
|
||||||
needs: [is-release-tag, create-draft-release]
|
|
||||||
name: Build packages for macOS
|
|
||||||
runs-on: macos-latest
|
|
||||||
environment: macos-codesign
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
# Workaround for https://github.com/actions/checkout/issues/882
|
|
||||||
ref: ${{ github.ref }}
|
|
||||||
- name: Install Rust
|
|
||||||
uses: ./.github/actions/rust-toolchain@oldest-supported
|
|
||||||
with:
|
|
||||||
targets: x86_64-apple-darwin
|
|
||||||
- name: Install Rust Stable
|
|
||||||
uses: ./.github/actions/rust-toolchain@stable
|
|
||||||
with:
|
|
||||||
targets: aarch64-apple-darwin
|
|
||||||
- name: Build and codesign
|
|
||||||
run: |
|
|
||||||
die() { echo >&2 "$*"; exit 1; }
|
|
||||||
[ -n "$MAC_CODESIGN_APP_P12_BASE64" ] || die "Missing MAC_CODESIGN_APP_P12_BASE64"
|
|
||||||
[ -n "$MAC_CODESIGN_INSTALLER_P12_BASE64" ] || die "Missing MAC_CODESIGN_INSTALLER_P12_BASE64"
|
|
||||||
[ -n "$MAC_CODESIGN_PASSWORD" ] || die "Missing MAC_CODESIGN_PASSWORD"
|
|
||||||
[ -n "$MACOS_NOTARIZE_JSON" ] || die "Missing MACOS_NOTARIZE_JSON"
|
|
||||||
set -x
|
|
||||||
export FISH_ARTEFACT_PATH=/tmp/fish-built
|
|
||||||
# macOS runners keep having issues loading Cargo.toml dependencies from git (GitHub) instead
|
|
||||||
# of crates.io, so give this a try. It's also sometimes significantly faster on all platforms.
|
|
||||||
export CARGO_NET_GIT_FETCH_WITH_CLI=true
|
|
||||||
cargo install apple-codesign
|
|
||||||
mkdir -p "$FISH_ARTEFACT_PATH"
|
|
||||||
echo "$MAC_CODESIGN_APP_P12_BASE64" | base64 --decode >/tmp/app.p12
|
|
||||||
echo "$MAC_CODESIGN_INSTALLER_P12_BASE64" | base64 --decode >/tmp/installer.p12
|
|
||||||
echo "$MACOS_NOTARIZE_JSON" >/tmp/notarize.json
|
|
||||||
./build_tools/make_macos_pkg.sh -s -f /tmp/app.p12 \
|
|
||||||
-i /tmp/installer.p12 -p "$MAC_CODESIGN_PASSWORD" \
|
|
||||||
-n -j /tmp/notarize.json
|
|
||||||
[ -f "${FISH_ARTEFACT_PATH}/fish-${{ github.ref_name }}.app.zip" ]
|
|
||||||
[ -f "${FISH_ARTEFACT_PATH}/fish-${{ github.ref_name }}.pkg" ]
|
|
||||||
rm /tmp/installer.p12 /tmp/app.p12 /tmp/notarize.json
|
|
||||||
env:
|
|
||||||
MAC_CODESIGN_APP_P12_BASE64: ${{ secrets.MAC_CODESIGN_APP_P12_BASE64 }}
|
|
||||||
MAC_CODESIGN_INSTALLER_P12_BASE64: ${{ secrets.MAC_CODESIGN_INSTALLER_P12_BASE64 }}
|
|
||||||
MAC_CODESIGN_PASSWORD: ${{ secrets.MAC_CODESIGN_PASSWORD }}
|
|
||||||
MACOS_NOTARIZE_JSON: ${{ secrets.MACOS_NOTARIZE_JSON }}
|
|
||||||
- name: Add macOS packages to the release
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
gh release upload $(git describe) \
|
|
||||||
/tmp/fish-built/fish-${{ github.ref_name }}.app.zip \
|
|
||||||
/tmp/fish-built/fish-${{ github.ref_name }}.pkg
|
|
||||||
41
.github/workflows/rust_checks.yml
vendored
41
.github/workflows/rust_checks.yml
vendored
@@ -1,41 +0,0 @@
|
|||||||
name: Rust checks
|
|
||||||
|
|
||||||
on: [push, pull_request]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
rustfmt:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
- name: cargo fmt
|
|
||||||
run: cargo fmt --check --all
|
|
||||||
|
|
||||||
clippy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
- name: Install deps
|
|
||||||
run: |
|
|
||||||
sudo apt install gettext libpcre2-dev
|
|
||||||
- name: cmake
|
|
||||||
run: |
|
|
||||||
cmake -B build
|
|
||||||
- name: cargo clippy
|
|
||||||
# This used to have --deny=warnings, but that turns rust release day
|
|
||||||
# into automatic CI failure day, so we don't do that.
|
|
||||||
run: cargo clippy --workspace --all-targets
|
|
||||||
|
|
||||||
# Disabling for now because it also checks "advisories",
|
|
||||||
# making CI fail for reasons unrelated to the patch
|
|
||||||
# cargo-deny:
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
# steps:
|
|
||||||
# - uses: actions/checkout@v3
|
|
||||||
# - uses: EmbarkStudios/cargo-deny-action@v1
|
|
||||||
13
.gitignore
vendored
13
.gitignore
vendored
@@ -89,16 +89,3 @@ __pycache__
|
|||||||
/tags
|
/tags
|
||||||
xcuserdata/
|
xcuserdata/
|
||||||
|
|
||||||
# Generated by Cargo
|
|
||||||
# will have compiled files and executables
|
|
||||||
debug/
|
|
||||||
target/
|
|
||||||
|
|
||||||
# These are backup files generated by rustfmt
|
|
||||||
**/*.rs.bk
|
|
||||||
|
|
||||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
|
||||||
*.pdb
|
|
||||||
|
|
||||||
# Generated by clangd
|
|
||||||
/.cache
|
|
||||||
|
|||||||
95
.oclint
Normal file
95
.oclint
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
rules:
|
||||||
|
rule-configurations:
|
||||||
|
#
|
||||||
|
# This is the default value (as of the time I wrote this) but I'm making
|
||||||
|
# it explicit since it needs to agree with the value used by clang-format.
|
||||||
|
# Thus, if we ever change the fish style to allow longer or shorter lines
|
||||||
|
# this should be changed (as well as the corresponding .clang-format file).
|
||||||
|
#
|
||||||
|
- key: LONG_LINE
|
||||||
|
value: 100
|
||||||
|
#
|
||||||
|
# The default limit for the length of variable names is 20. Long names are
|
||||||
|
# problematic but twenty chars results in way too many errors. So increase
|
||||||
|
# the limit to something more reasonable.
|
||||||
|
#
|
||||||
|
- key: LONG_VARIABLE_NAME
|
||||||
|
value: 30
|
||||||
|
#
|
||||||
|
# This allows us to avoid peppering our code with inline comments such as
|
||||||
|
#
|
||||||
|
# scoped_lock locker(m_lock); //!OCLINT(side-effect)
|
||||||
|
#
|
||||||
|
# Specifically, this config key tells oclint that the named classes have
|
||||||
|
# RAII behavior so the local vars are actually used.
|
||||||
|
#
|
||||||
|
- key: RAII_CUSTOM_CLASSES
|
||||||
|
value: scoped_lock scoped_buffer_t builtin_commandline_scoped_transient_t scoped_push
|
||||||
|
|
||||||
|
# We're slightly more persmissive regarding the total number of lines in a
|
||||||
|
# function. Default is 50.
|
||||||
|
- key: LONG_METHOD
|
||||||
|
value: 60
|
||||||
|
|
||||||
|
# We're slightly more persmissive regarding the number of non-comment
|
||||||
|
# lines in a function. Default is 30.
|
||||||
|
- key: NCSS_METHOD
|
||||||
|
value: 40
|
||||||
|
|
||||||
|
# We're willing to allow slighly more linearly independent paths through a
|
||||||
|
# function. Most of our code has a lot of `switch` blocks or consecutive
|
||||||
|
# `if` tests that are straightforward to interpret but which increase this
|
||||||
|
# metric. Default is 10.
|
||||||
|
- key: CYCLOMATIC_COMPLEXITY
|
||||||
|
value: 14
|
||||||
|
|
||||||
|
# We're willing to allow slighly more execution paths through a function.
|
||||||
|
# Default is 200.
|
||||||
|
- key: NPATH_COMPLEXITY
|
||||||
|
value: 300
|
||||||
|
|
||||||
|
disable-rules:
|
||||||
|
#
|
||||||
|
# A few instances of "useless parentheses" errors are meaningful. Mostly
|
||||||
|
# in the context of the `return` statement. Unfortunately the vast
|
||||||
|
# majority would result in removing parentheses that decreases
|
||||||
|
# readability. So we're going to ignore this warning and rely on humans to
|
||||||
|
# notice when the parentheses are truly not needed.
|
||||||
|
#
|
||||||
|
# Also, some macro expansions, such as FD_SET(), trigger this warning and
|
||||||
|
# we don't want to suppress each of those individually.
|
||||||
|
#
|
||||||
|
- UselessParentheses
|
||||||
|
#
|
||||||
|
# OCLint wants variable names to be at least three characters in length.
|
||||||
|
# Which would be fine if it supported a reasonable set of exceptions
|
||||||
|
# (e.g., "i", "j", "k") and allowed adding additional exceptions to match
|
||||||
|
# conventions employed by a project. Since it doesn't, and thus generates
|
||||||
|
# a lot of really annoying warnings, we're going to disable this rule.
|
||||||
|
#
|
||||||
|
- ShortVariableName
|
||||||
|
#
|
||||||
|
# This rule flags perfectly reasonable conditions like `if (!some_condition)`
|
||||||
|
# and is therefore just noise. Disable this rule.
|
||||||
|
#
|
||||||
|
- InvertedLogic
|
||||||
|
#
|
||||||
|
# The idea behind the "double negative" rule is sound since constructs
|
||||||
|
# like "!!(var & flag)" should be written as "static_cast<bool>(var &
|
||||||
|
# flag)". Unfortunately this rule has way too many false positives;
|
||||||
|
# especially in the context of assert statements. So disable this rule.
|
||||||
|
#
|
||||||
|
- DoubleNegative
|
||||||
|
#
|
||||||
|
# Avoiding bitwise operators in a conditional is a good idea with one
|
||||||
|
# exception: testing whether a bit flag is set. Which happens to be the
|
||||||
|
# only time you'll see something like `if (j->flags & JOB_CONSTRUCTED)`
|
||||||
|
# in fish source.
|
||||||
|
#
|
||||||
|
- BitwiseOperatorInConditional
|
||||||
|
#
|
||||||
|
# I don't think I've ever seen a case where assigning a value to a
|
||||||
|
# parameter inside the function body was unclear, let along dangerous or
|
||||||
|
# an error. This rule is therefore just noise. Disable this rule.
|
||||||
|
#
|
||||||
|
- ParameterReassignment
|
||||||
122
.travis.yml
Normal file
122
.travis.yml
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
language: cpp
|
||||||
|
dist: xenial
|
||||||
|
sudo: required
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- expect
|
||||||
|
- gettext
|
||||||
|
- libncurses5-dev
|
||||||
|
- libpcre2-dev
|
||||||
|
- python3
|
||||||
|
- python3-pip
|
||||||
|
before_install:
|
||||||
|
- sudo pip3 install pexpect
|
||||||
|
env:
|
||||||
|
# Some warnings upgraded to errors to match Open Build Service platforms
|
||||||
|
- CXXFLAGS="-Werror=address -Werror=return-type"
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages: # Don't use libpcre2-dev here, so that one build uses the vendored code
|
||||||
|
- expect
|
||||||
|
- gettext
|
||||||
|
- lib32ncurses5-dev
|
||||||
|
- g++-multilib
|
||||||
|
- python3
|
||||||
|
- python3-pip
|
||||||
|
before_install:
|
||||||
|
- sudo pip3 install pexpect
|
||||||
|
env:
|
||||||
|
- CXXFLAGS="-m32 -Werror=address -Werror=return-type" CFLAGS="-m32"
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
env:
|
||||||
|
- CXXFLAGS="-fno-omit-frame-pointer -fsanitize=undefined -fsanitize=address"
|
||||||
|
- ASAN_OPTIONS=check_initialization_order=1:detect_stack_use_after_return=1:detect_leaks=1
|
||||||
|
- UBSAN_OPTIONS=print_stacktrace=1:report_error_type=1:suppressions=$TRAVIS_BUILD_DIR/build_tools/ubsan.blacklist
|
||||||
|
before_install:
|
||||||
|
- sudo pip3 install pexpect
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- expect
|
||||||
|
- gettext
|
||||||
|
- libncurses5-dev
|
||||||
|
- libpcre2-dev
|
||||||
|
- python
|
||||||
|
- python3
|
||||||
|
- python3-pip
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
env:
|
||||||
|
- CXXFLAGS="-fsanitize=thread"
|
||||||
|
before_install:
|
||||||
|
- sudo pip3 install pexpect
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- expect
|
||||||
|
- gettext
|
||||||
|
- libncurses5-dev
|
||||||
|
- libpcre2-dev
|
||||||
|
- python3
|
||||||
|
- python3-pip
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
coverity_scan:
|
||||||
|
project:
|
||||||
|
name: "fish-shell/fish-shell"
|
||||||
|
description: "The friendly interactive shell"
|
||||||
|
notification_email: corydoras@ridiculousfish.com
|
||||||
|
build_command_prepend: "mkdir -p build; cd build; cmake -G Ninja .."
|
||||||
|
build_command: "ninja"
|
||||||
|
branch_pattern: coverity_scan_master
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- expect
|
||||||
|
- gettext
|
||||||
|
- libncurses5-dev
|
||||||
|
- libpcre2-dev
|
||||||
|
- python3
|
||||||
|
- python3-pip
|
||||||
|
before_install:
|
||||||
|
- sudo pip3 install pexpect
|
||||||
|
- echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-
|
||||||
|
env:
|
||||||
|
- secure: "Q1AS5iEi17s+xsRaMwfkxmm62UDaV47uE39pvXsNL+DO9YWbMMuhTpIOeYhxLvFNL3LMUFU2TwVpVRYX2YFGhNNaMSmjQfyQ+7q7/oSEo0aSqvQkwelpK/pwuRAXdv1MU4aQ6FrCEQ4VMO45WRo0o5WD26pvxjqRyAQ6ry+serA="
|
||||||
|
# Some warnings upgraded to errors to match Open Build Service platforms
|
||||||
|
- CXXFLAGS="-Werror=address -Werror=return-type"
|
||||||
|
- os: osx
|
||||||
|
before_install:
|
||||||
|
- sudo pip3 install pexpect
|
||||||
|
fast_finish: true
|
||||||
|
|
||||||
|
script:
|
||||||
|
- cmake -DCMAKE_INSTALL_PREFIX=$HOME/prefix . || cat CMakeFiles/CMakeError.log &&
|
||||||
|
make -j2 &&
|
||||||
|
make install &&
|
||||||
|
make test SHOW_INTERACTIVE_LOG=1
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
# Some items are encrypted so that notifications from other repositories
|
||||||
|
# don't flood the official repositories.
|
||||||
|
irc:
|
||||||
|
channels:
|
||||||
|
#- "irc.oftc.net#fish"
|
||||||
|
secure: "eRk9KGZ5+mrlD2SoI8yg2Sp8OYrh7YPyGe3WCDQUwTnNgNDII34rbM9a6UOA/l7AeWSNY8joLq5xVLCU4wpFgUcJ11SYIpMnLosZK29OW4ubDOHmdBDvJ971rLgAVG9cXngZtIxEVVxN/jnS1Qr8GKZx4DjkaTMgz1pemb4WxCc="
|
||||||
|
template:
|
||||||
|
- "%{repository}#%{build_number} (%{commit} on %{branch} by %{author}): %{message} Details at %{build_url}"
|
||||||
|
use_notice: true
|
||||||
|
skip_join: true
|
||||||
|
webhooks:
|
||||||
|
urls:
|
||||||
|
#- https://webhooks.gitter.im/e/61821cec3015bf0f8bb1
|
||||||
|
secure: fPfOmxnC3MCsfR1oocVFeWLawGcRZkn+8fNHlSOeZ+SqqoZfcCHgQTvQ22TqmVl1yvkXbNlaXjo6dbVzTOAh7r7H0bRMEKBVh3dQS7wqjB1sKivpXd8PAS3BTj5MQpGeJzdHnDuwVlwDktGtfHfhGeq1Go/4IosOq8u+6RTe28g=
|
||||||
18
BSDmakefile
18
BSDmakefile
@@ -20,22 +20,20 @@ _GENERATOR!=which ninja 2>/dev/null >/dev/null && echo Ninja || echo "Unix Makef
|
|||||||
GENERATOR?=$(_GENERATOR)
|
GENERATOR?=$(_GENERATOR)
|
||||||
|
|
||||||
.if $(GENERATOR) == "Ninja"
|
.if $(GENERATOR) == "Ninja"
|
||||||
BUILDFILE=build.ninja
|
BUILDFILE=build/build.ninja
|
||||||
.else
|
.else
|
||||||
BUILDFILE=Makefile
|
BUILDFILE=build/Makefile
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
PREFIX?=/usr/local
|
PREFIX?=/usr/local
|
||||||
|
|
||||||
.PHONY: build/fish
|
|
||||||
build/fish: build/$(BUILDFILE)
|
build/fish: build/$(BUILDFILE)
|
||||||
$(CMAKE) --build build
|
$(CMAKE) --build build
|
||||||
|
|
||||||
# Don't split the mkdir into its own rule because that would cause CMake to regenerate the build
|
build:
|
||||||
# files after each build (because it adds the mdate of the build directory into the out-of-date
|
|
||||||
# calculation tree). GNUmake supports order-only dependencies, BSDmake does not seem to.
|
|
||||||
build/$(BUILDFILE):
|
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
|
|
||||||
|
build/$(BUILDFILE): build
|
||||||
cd build; $(CMAKE) .. -G "$(GENERATOR)" -DCMAKE_INSTALL_PREFIX="$(PREFIX)" -DCMAKE_EXPORT_COMPILE_COMMANDS=1
|
cd build; $(CMAKE) .. -G "$(GENERATOR)" -DCMAKE_INSTALL_PREFIX="$(PREFIX)" -DCMAKE_EXPORT_COMPILE_COMMANDS=1
|
||||||
|
|
||||||
.PHONY: install
|
.PHONY: install
|
||||||
@@ -48,11 +46,7 @@ clean:
|
|||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: build/fish
|
test: build/fish
|
||||||
$(CMAKE) --build build --target fish_run_tests
|
$(CMAKE) --build build --target test
|
||||||
|
|
||||||
.PHONY: fish_run_tests
|
|
||||||
fish_run_tests: build/fish
|
|
||||||
$(CMAKE) --build build --target fish_run_tests
|
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: build/fish
|
run: build/fish
|
||||||
|
|||||||
3336
CHANGELOG.rst
3336
CHANGELOG.rst
File diff suppressed because it is too large
Load Diff
209
CMakeLists.txt
209
CMakeLists.txt
@@ -1,41 +1,149 @@
|
|||||||
cmake_minimum_required(VERSION 3.15)
|
cmake_minimum_required(VERSION 3.2)
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
if(POLICY CMP0066)
|
||||||
|
cmake_policy(SET CMP0066 OLD)
|
||||||
|
endif()
|
||||||
|
if(POLICY CMP0067)
|
||||||
|
cmake_policy(SET CMP0067 NEW)
|
||||||
|
endif()
|
||||||
|
|
||||||
project(fish LANGUAGES C)
|
include(cmake/Mac.cmake)
|
||||||
|
|
||||||
|
project(fish)
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
# We are C++11.
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
set(DEFAULT_BUILD_TYPE "RelWithDebInfo")
|
set(DEFAULT_BUILD_TYPE "RelWithDebInfo")
|
||||||
|
|
||||||
# Generate Xcode schemas (but not for tests).
|
# Use the default flags (#6296) but remove -DNDEBUG so that asserts remain enabled.
|
||||||
set(CMAKE_XCODE_GENERATE_SCHEME 1)
|
string(REPLACE "-DNDEBUG" ""
|
||||||
|
CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||||
|
"${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||||
|
|
||||||
|
string(REPLACE "-DNDEBUG" ""
|
||||||
|
CMAKE_CXX_FLAGS_RELEASE
|
||||||
|
"${CMAKE_CXX_FLAGS_RELEASE}")
|
||||||
|
|
||||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
message(STATUS "Setting build type to default '${DEFAULT_BUILD_TYPE}'")
|
message(STATUS "Setting build type to default '${DEFAULT_BUILD_TYPE}'")
|
||||||
set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}")
|
set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Set up standard directories.
|
# Force colored warnings in Ninja's output, if the compiler has -fdiagnostics-color support.
|
||||||
include(GNUInstallDirs)
|
# Rationale in https://github.com/ninja-build/ninja/issues/814
|
||||||
add_definitions(-D_UNICODE=1)
|
if (CMAKE_GENERATOR STREQUAL "Ninja" AND
|
||||||
|
((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR
|
||||||
|
(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5) OR
|
||||||
|
(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)))
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=always")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always")
|
||||||
|
endif()
|
||||||
|
# Enable a whole bunch of warnings, but turn off:
|
||||||
|
# - implicit fallthrough because that does not recognize some cases where it's desired (and I *really* want this one!)
|
||||||
|
# - comment because we use a bunch of those, and they're not really all that harmful.
|
||||||
|
# - address, because that occurs for our mkostemp check (weak-linking requires us to compare `&mkostemp == nullptr`).
|
||||||
|
# - strict-aliasing, because on old GCCs (*Travis*) those are triggered by maybe.h, so you get it every time it is included.
|
||||||
|
# - redundant-move, because we have one that is required on old libc
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra \
|
||||||
|
-Wno-implicit-fallthrough \
|
||||||
|
-Wno-comment \
|
||||||
|
-Wno-address \
|
||||||
|
-Wno-strict-aliasing \
|
||||||
|
-Wno-redundant-move \
|
||||||
|
")
|
||||||
|
|
||||||
include(cmake/gettext.cmake)
|
# Disable exception handling.
|
||||||
|
add_compile_options(-fno-exceptions)
|
||||||
|
|
||||||
# Set up PCRE2
|
# Prefer the gold linker because it doesn't emit useless warnings about sys_nerr and _sys_errlist.
|
||||||
# This sets an environment variable that needs to be available before the Rust stanzas
|
if (UNIX AND NOT APPLE)
|
||||||
include(cmake/PCRE2.cmake)
|
execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version
|
||||||
|
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
|
||||||
|
if ("${LD_VERSION}" MATCHES "GNU gold")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
include(cmake/Rust.cmake)
|
# Hide the CMake Rules directories in Xcode projects.
|
||||||
|
source_group("CMake Rules" REGULAR_EXPRESSION "^$")
|
||||||
|
|
||||||
|
# Put source and header files at top level under targets.
|
||||||
|
source_group("Source Files" REGULAR_EXPRESSION "^$")
|
||||||
|
source_group("Header Files" REGULAR_EXPRESSION "^$")
|
||||||
|
source_group("Builtins" REGULAR_EXPRESSION "builtin_.*")
|
||||||
|
|
||||||
|
# Support folders.
|
||||||
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
|
||||||
# Work around issue where archive-built libs go in the wrong place.
|
# Work around issue where archive-built libs go in the wrong place.
|
||||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
||||||
|
|
||||||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||||
set(FISH_IN_TREE_BUILD TRUE)
|
set(FISH_IN_TREE_BUILD TRUE)
|
||||||
else()
|
else()
|
||||||
set(FISH_IN_TREE_BUILD FALSE)
|
set(FISH_IN_TREE_BUILD FALSE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# NetBSD does weird things with finding libraries,
|
||||||
|
# making the tests fail by failing to find pcre.
|
||||||
|
#
|
||||||
|
# Keep the rpath used to build.
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL NetBSD)
|
||||||
|
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# All objects that the system needs to build fish, except fish.cpp
|
||||||
|
set(FISH_SRCS
|
||||||
|
src/autoload.cpp src/builtin.cpp src/builtin_bg.cpp src/builtin_bind.cpp
|
||||||
|
src/builtin_block.cpp src/builtin_builtin.cpp src/builtin_cd.cpp
|
||||||
|
src/builtin_command.cpp src/builtin_commandline.cpp
|
||||||
|
src/builtin_complete.cpp src/builtin_contains.cpp src/builtin_disown.cpp
|
||||||
|
src/builtin_echo.cpp src/builtin_emit.cpp src/builtin_exit.cpp
|
||||||
|
src/builtin_fg.cpp src/builtin_function.cpp src/builtin_functions.cpp
|
||||||
|
src/builtin_argparse.cpp src/builtin_history.cpp src/builtin_jobs.cpp
|
||||||
|
src/builtin_math.cpp src/builtin_printf.cpp src/builtin_pwd.cpp
|
||||||
|
src/builtin_random.cpp src/builtin_read.cpp src/builtin_realpath.cpp
|
||||||
|
src/builtin_return.cpp src/builtin_set.cpp src/builtin_set_color.cpp
|
||||||
|
src/builtin_source.cpp src/builtin_status.cpp src/builtin_string.cpp
|
||||||
|
src/builtin_test.cpp src/builtin_ulimit.cpp src/builtin_wait.cpp src/builtin_eval.cpp
|
||||||
|
src/color.cpp src/common.cpp src/complete.cpp src/env.cpp src/env_dispatch.cpp
|
||||||
|
src/env_universal_common.cpp src/event.cpp src/exec.cpp src/expand.cpp
|
||||||
|
src/fallback.cpp src/fish_version.cpp src/function.cpp src/highlight.cpp
|
||||||
|
src/history.cpp src/history_file.cpp src/input.cpp src/input_common.cpp src/intern.cpp
|
||||||
|
src/io.cpp src/iothread.cpp src/kill.cpp src/output.cpp src/pager.cpp
|
||||||
|
src/parse_execution.cpp src/parse_productions.cpp src/parse_tree.cpp
|
||||||
|
src/parse_util.cpp src/parser.cpp src/parser_keywords.cpp src/path.cpp
|
||||||
|
src/postfork.cpp src/proc.cpp src/reader.cpp src/sanity.cpp src/screen.cpp
|
||||||
|
src/signal.cpp src/tinyexpr.cpp src/tnode.cpp src/tokenizer.cpp src/utf8.cpp src/util.cpp
|
||||||
|
src/wcstringutil.cpp src/wgetopt.cpp src/wildcard.cpp src/wutil.cpp
|
||||||
|
src/future_feature_flags.cpp src/redirection.cpp src/topic_monitor.cpp
|
||||||
|
src/flog.cpp src/trace.cpp src/timer.cpp src/null_terminated_array.cpp
|
||||||
|
src/operation_context.cpp src/fd_monitor.cpp src/termsize.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Header files are just globbed.
|
||||||
|
file(GLOB FISH_HEADERS src/*.h)
|
||||||
|
|
||||||
|
# Set up config.h
|
||||||
|
include(cmake/ConfigureChecks.cmake)
|
||||||
|
include(cmake/gettext.cmake)
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config_cmake.h.in
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
# Set up standard directories.
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
add_definitions(-D_UNICODE=1
|
||||||
|
-DLOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}"
|
||||||
|
-DPREFIX=L"${CMAKE_INSTALL_PREFIX}"
|
||||||
|
-DDATADIR=L"${CMAKE_INSTALL_FULL_DATADIR}"
|
||||||
|
-DSYSCONFDIR=L"${CMAKE_INSTALL_FULL_SYSCONFDIR}"
|
||||||
|
-DBINDIR=L"${CMAKE_INSTALL_FULL_BINDIR}"
|
||||||
|
-DDOCDIR=L"${CMAKE_INSTALL_FULL_DOCDIR}")
|
||||||
|
|
||||||
# Set up the machinery around FISH-BUILD-VERSION-FILE
|
# Set up the machinery around FISH-BUILD-VERSION-FILE
|
||||||
# This defines the FBVF variable.
|
# This defines the FBVF variable.
|
||||||
include(Version)
|
include(Version)
|
||||||
@@ -46,43 +154,51 @@ get_filename_component(REAL_CMAKE_SOURCE_DIR "${CMAKE_SOURCE_DIR}" REALPATH)
|
|||||||
add_definitions(-DCMAKE_BINARY_DIR="${REAL_CMAKE_BINARY_DIR}")
|
add_definitions(-DCMAKE_BINARY_DIR="${REAL_CMAKE_BINARY_DIR}")
|
||||||
add_definitions(-DCMAKE_SOURCE_DIR="${REAL_CMAKE_SOURCE_DIR}")
|
add_definitions(-DCMAKE_SOURCE_DIR="${REAL_CMAKE_SOURCE_DIR}")
|
||||||
|
|
||||||
# Define a function to build and link dependencies.
|
# Teach fish_version.o to rebuild when FBVF changes.
|
||||||
function(CREATE_TARGET target)
|
# The standard C++ include detection machinery misses this.
|
||||||
add_custom_target(
|
set_source_files_properties(src/fish_version.cpp
|
||||||
${target} ALL
|
PROPERTIES OBJECT_DEPENDS
|
||||||
COMMAND
|
${CMAKE_CURRENT_BINARY_DIR}/${FBVF})
|
||||||
"${CMAKE_COMMAND}" -E
|
|
||||||
env ${VARS_FOR_CARGO}
|
# Enable thread-safe errno on Solaris (#5611)
|
||||||
${Rust_CARGO}
|
add_definitions(-D_REENTRANT)
|
||||||
build --bin ${target}
|
|
||||||
$<$<CONFIG:Release>:--release>
|
# Set up PCRE2
|
||||||
$<$<CONFIG:RelWithDebInfo>:--profile=release-with-debug>
|
include(cmake/PCRE2.cmake)
|
||||||
--target ${Rust_CARGO_TARGET}
|
|
||||||
--no-default-features
|
# Define a function to link dependencies.
|
||||||
${CARGO_FLAGS}
|
function(FISH_LINK_DEPS_AND_SIGN target)
|
||||||
${FEATURES_ARG}
|
target_link_libraries(${target} fishlib)
|
||||||
&&
|
codesign_on_mac(${target})
|
||||||
"${CMAKE_COMMAND}" -E
|
endfunction(FISH_LINK_DEPS_AND_SIGN)
|
||||||
copy "${rust_target_dir}/${rust_profile}/${target}" "${CMAKE_CURRENT_BINARY_DIR}"
|
|
||||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
# Define libfish.a.
|
||||||
USES_TERMINAL
|
add_library(fishlib STATIC ${FISH_SRCS})
|
||||||
)
|
target_sources(fishlib PRIVATE ${FISH_HEADERS})
|
||||||
endfunction(CREATE_TARGET)
|
target_link_libraries(fishlib
|
||||||
|
${CURSES_LIBRARY} ${CURSES_EXTRA_LIBRARY} Threads::Threads ${CMAKE_DL_LIBS}
|
||||||
|
${PCRE2_LIB} ${Intl_LIBRARIES} ${ATOMIC_LIBRARY})
|
||||||
|
|
||||||
# Define fish.
|
# Define fish.
|
||||||
create_target(fish)
|
add_executable(fish src/fish.cpp)
|
||||||
|
fish_link_deps_and_sign(fish)
|
||||||
|
|
||||||
# Define fish_indent.
|
# Define fish_indent.
|
||||||
create_target(fish_indent)
|
add_executable(fish_indent
|
||||||
|
src/fish_indent.cpp src/print_help.cpp)
|
||||||
|
fish_link_deps_and_sign(fish_indent)
|
||||||
|
|
||||||
# Define fish_key_reader.
|
# Define fish_key_reader.
|
||||||
create_target(fish_key_reader)
|
add_executable(fish_key_reader
|
||||||
|
src/fish_key_reader.cpp src/print_help.cpp)
|
||||||
|
fish_link_deps_and_sign(fish_key_reader)
|
||||||
|
|
||||||
# Set up the docs.
|
# Set up the docs.
|
||||||
include(cmake/Docs.cmake)
|
include(cmake/Docs.cmake)
|
||||||
|
|
||||||
# A helper for running tests.
|
# A helper for running tests.
|
||||||
add_executable(fish_test_helper src/fish_test_helper.c)
|
add_executable(fish_test_helper src/fish_test_helper.cpp)
|
||||||
|
|
||||||
# Set up tests.
|
# Set up tests.
|
||||||
include(cmake/Tests.cmake)
|
include(cmake/Tests.cmake)
|
||||||
|
|
||||||
@@ -95,5 +211,20 @@ include(cmake/Install.cmake)
|
|||||||
# Mac app.
|
# Mac app.
|
||||||
include(cmake/MacApp.cmake)
|
include(cmake/MacApp.cmake)
|
||||||
|
|
||||||
|
# Lint targets
|
||||||
|
# This could be implemented as target properties, but the script has the useful feature of only
|
||||||
|
# checking the currently-staged commands
|
||||||
|
# The generator expressions below rebuild the command line for the fishlib targets
|
||||||
|
# CMake does not support the "iquote" flag - https://gitlab.kitware.com/cmake/cmake/issues/15491
|
||||||
|
set(LINT_ARGS "-D$<JOIN:$<TARGET_PROPERTY:fishlib,COMPILE_DEFINITIONS>, -D>" "-I$<JOIN:$<TARGET_PROPERTY:fishlib,INCLUDE_DIRECTORIES>, -I>")
|
||||||
|
add_custom_target(lint
|
||||||
|
COMMAND build_tools/lint.fish -p ${CMAKE_BINARY_DIR} -- ${LINT_ARGS}
|
||||||
|
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||||
|
)
|
||||||
|
add_custom_target(lint-all
|
||||||
|
COMMAND build_tools/lint.fish --all -p ${CMAKE_BINARY_DIR} -- ${LINT_ARGS}
|
||||||
|
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||||
|
)
|
||||||
|
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
feature_summary(WHAT ALL)
|
feature_summary(WHAT ALL)
|
||||||
|
|||||||
@@ -1,129 +0,0 @@
|
|||||||
|
|
||||||
# Contributor Covenant Code of Conduct
|
|
||||||
|
|
||||||
## Our Pledge
|
|
||||||
|
|
||||||
We as members, contributors, and leaders pledge to make participation in our
|
|
||||||
community a harassment-free experience for everyone, regardless of age, body
|
|
||||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
||||||
identity and expression, level of experience, education, socio-economic status,
|
|
||||||
nationality, personal appearance, race, religion, or sexual identity
|
|
||||||
and orientation.
|
|
||||||
|
|
||||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
||||||
diverse, inclusive, and healthy community.
|
|
||||||
|
|
||||||
## Our Standards
|
|
||||||
|
|
||||||
Examples of behavior that contributes to a positive environment for our
|
|
||||||
community include:
|
|
||||||
|
|
||||||
* Demonstrating empathy and kindness toward other people
|
|
||||||
* Being respectful of differing opinions, viewpoints, and experiences
|
|
||||||
* Giving and gracefully accepting constructive feedback
|
|
||||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
|
||||||
and learning from the experience
|
|
||||||
* Focusing on what is best not just for us as individuals, but for the
|
|
||||||
overall community
|
|
||||||
|
|
||||||
Examples of unacceptable behavior include:
|
|
||||||
|
|
||||||
* The use of sexualized language or imagery, and sexual attention or
|
|
||||||
advances of any kind
|
|
||||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
||||||
* Public or private harassment
|
|
||||||
* Publishing others' private information, such as a physical or email
|
|
||||||
address, without their explicit permission
|
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
|
||||||
professional setting
|
|
||||||
|
|
||||||
## Enforcement Responsibilities
|
|
||||||
|
|
||||||
Community leaders are responsible for clarifying and enforcing our standards of
|
|
||||||
acceptable behavior and will take appropriate and fair corrective action in
|
|
||||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
||||||
or harmful.
|
|
||||||
|
|
||||||
Community leaders have the right and responsibility to remove, edit, or reject
|
|
||||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
||||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
|
||||||
decisions when appropriate.
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This Code of Conduct applies within all community spaces, and also applies when
|
|
||||||
an individual is officially representing the community in public spaces.
|
|
||||||
Examples of representing our community include using an official e-mail address,
|
|
||||||
posting via an official social media account, or acting as an appointed
|
|
||||||
representative at an online or offline event.
|
|
||||||
|
|
||||||
## Enforcement
|
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
||||||
reported to the community leaders.
|
|
||||||
All complaints will be reviewed and investigated promptly and fairly.
|
|
||||||
|
|
||||||
All community leaders are obligated to respect the privacy and security of the
|
|
||||||
reporter of any incident.
|
|
||||||
|
|
||||||
## Enforcement Guidelines
|
|
||||||
|
|
||||||
Community leaders will follow these Community Impact Guidelines in determining
|
|
||||||
the consequences for any action they deem in violation of this Code of Conduct:
|
|
||||||
|
|
||||||
### 1. Correction
|
|
||||||
|
|
||||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
|
||||||
unprofessional or unwelcome in the community.
|
|
||||||
|
|
||||||
**Consequence**: A private, written warning from community leaders, providing
|
|
||||||
clarity around the nature of the violation and an explanation of why the
|
|
||||||
behavior was inappropriate. A public apology may be requested.
|
|
||||||
|
|
||||||
### 2. Warning
|
|
||||||
|
|
||||||
**Community Impact**: A violation through a single incident or series
|
|
||||||
of actions.
|
|
||||||
|
|
||||||
**Consequence**: A warning with consequences for continued behavior. No
|
|
||||||
interaction with the people involved, including unsolicited interaction with
|
|
||||||
those enforcing the Code of Conduct, for a specified period of time. This
|
|
||||||
includes avoiding interactions in community spaces as well as external channels
|
|
||||||
like social media. Violating these terms may lead to a temporary or
|
|
||||||
permanent ban.
|
|
||||||
|
|
||||||
### 3. Temporary Ban
|
|
||||||
|
|
||||||
**Community Impact**: A serious violation of community standards, including
|
|
||||||
sustained inappropriate behavior.
|
|
||||||
|
|
||||||
**Consequence**: A temporary ban from any sort of interaction or public
|
|
||||||
communication with the community for a specified period of time. No public or
|
|
||||||
private interaction with the people involved, including unsolicited interaction
|
|
||||||
with those enforcing the Code of Conduct, is allowed during this period.
|
|
||||||
Violating these terms may lead to a permanent ban.
|
|
||||||
|
|
||||||
### 4. Permanent Ban
|
|
||||||
|
|
||||||
**Community Impact**: Demonstrating a pattern of violation of community
|
|
||||||
standards, including sustained inappropriate behavior, harassment of an
|
|
||||||
individual, or aggression toward or disparagement of classes of individuals.
|
|
||||||
|
|
||||||
**Consequence**: A permanent ban from any sort of public interaction within
|
|
||||||
the community.
|
|
||||||
|
|
||||||
## Attribution
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
||||||
version 2.0, available at
|
|
||||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
|
||||||
|
|
||||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
|
||||||
enforcement ladder](https://github.com/mozilla/diversity).
|
|
||||||
|
|
||||||
[homepage]: https://www.contributor-covenant.org
|
|
||||||
|
|
||||||
For answers to common questions about this code of conduct, see the FAQ at
|
|
||||||
https://www.contributor-covenant.org/faq. Translations are available at
|
|
||||||
https://www.contributor-covenant.org/translations.
|
|
||||||
|
|
||||||
479
CONTRIBUTING.rst
479
CONTRIBUTING.rst
@@ -1,109 +1,136 @@
|
|||||||
####################
|
Guidelines For Developers
|
||||||
Contributing To Fish
|
=========================
|
||||||
####################
|
|
||||||
|
|
||||||
This document tells you how you can contribute to fish.
|
This document provides guidelines for making changes to the fish-shell
|
||||||
|
project. This includes rules for how to format the code, naming
|
||||||
|
conventions, et cetera. Generally known as the style of the code. It
|
||||||
|
also includes recommended best practices such as creating a Travis CI
|
||||||
|
account so you can verify that your changes pass all the tests before
|
||||||
|
making a pull request.
|
||||||
|
|
||||||
Fish is free and open source software, distributed under the terms of the GPLv2.
|
See the bottom of this document for help on installing the linting and
|
||||||
|
style reformatting tools discussed in the following sections.
|
||||||
|
|
||||||
Contributions are welcome, and there are many ways to contribute!
|
Fish source should limit the C++ features it uses to those available in
|
||||||
|
C++11. It should not use exceptions.
|
||||||
|
|
||||||
Whether you want to change some of the core Rust source, enhance or add a completion script or function,
|
Before introducing a new dependency, please make it optional with
|
||||||
improve the documentation or translate something, this document will tell you how.
|
graceful failure if possible. Add any new dependencies to the README.rst
|
||||||
|
under the *Running* and/or *Building* sections.
|
||||||
|
|
||||||
Getting Set Up
|
Versioning
|
||||||
==============
|
----------
|
||||||
|
|
||||||
Fish is developed on Github, at https://github.com/fish-shell/fish-shell.
|
The fish version is constructed by the *build_tools/git_version_gen.sh*
|
||||||
|
script. For developers the version is the branch name plus the output of
|
||||||
|
``git describe --always --dirty``. Normally the main part of the version
|
||||||
|
will be the closest annotated tag. Which itself is usually the most
|
||||||
|
recent release number (e.g., ``2.6.0``).
|
||||||
|
|
||||||
First, you'll need an account there, and you'll need a git clone of fish.
|
Include What You Use
|
||||||
Fork it on Github and then run::
|
--------------------
|
||||||
|
|
||||||
git clone https://github.com/<USERNAME>/fish-shell.git
|
You should not depend on symbols being visible to a ``*.cpp`` module
|
||||||
|
from ``#include`` statements inside another header file. In other words
|
||||||
|
if your module does ``#include "common.h"`` and that header does
|
||||||
|
``#include "signal.h"`` your module should not assume the sub-include is
|
||||||
|
present. It should instead directly ``#include "signal.h"`` if it needs
|
||||||
|
any symbol from that header. That makes the actual dependencies much
|
||||||
|
clearer. It also makes it easy to modify the headers included by a
|
||||||
|
specific header file without having to worry that will break any module
|
||||||
|
(or header) that includes a particular header.
|
||||||
|
|
||||||
This will create a copy of the fish repository in the directory fish-shell in your current working directory.
|
To help enforce this rule the ``make lint`` (and ``make lint-all``)
|
||||||
|
command will run the
|
||||||
|
`include-what-you-use <https://include-what-you-use.org/>`__ tool. You
|
||||||
|
can find the IWYU project on
|
||||||
|
`github <https://github.com/include-what-you-use/include-what-you-use>`__.
|
||||||
|
|
||||||
Also, for most changes you want to run the tests and so you'd get a setup to compile fish.
|
To install the tool on OS X you’ll need to add a
|
||||||
For that, you'll require:
|
`formula <https://github.com/jasonmp85/homebrew-iwyu>`__ then install
|
||||||
|
it:
|
||||||
|
|
||||||
- Rust - when in doubt, try rustup
|
::
|
||||||
- CMake
|
|
||||||
- PCRE2 (headers and libraries) - optional, this will be downloaded if missing
|
|
||||||
- gettext (headers and libraries) - optional, for translation support
|
|
||||||
- Sphinx - optional, to build the documentation
|
|
||||||
|
|
||||||
Of course not everything is required always - if you just want to contribute something to the documentation you'll just need Sphinx,
|
brew tap jasonmp85/iwyu
|
||||||
and if the change is very simple and obvious you can just send it in. Use your judgement!
|
brew install iwyu
|
||||||
|
|
||||||
Once you have your changes, open a pull request on https://github.com/fish-shell/fish-shell/pulls.
|
On Ubuntu you can install it via ``apt-get``:
|
||||||
|
|
||||||
Guidelines
|
::
|
||||||
==========
|
|
||||||
|
|
||||||
In short:
|
sudo apt-get install iwyu
|
||||||
|
|
||||||
- Be conservative in what you need (keep to the agreed minimum supported Rust version, limit new dependencies)
|
Lint Free Code
|
||||||
- Use automated tools to help you (including ``make fish_run_tests`` and ``build_tools/style.fish``)
|
--------------
|
||||||
|
|
||||||
Contributing completions
|
Automated analysis tools like cppcheck and oclint can point out
|
||||||
========================
|
potential bugs or code that is extremely hard to understand. They also
|
||||||
|
help ensure the code has a consistent style and that it avoids patterns
|
||||||
|
that tend to confuse people.
|
||||||
|
|
||||||
Completion scripts are the most common contribution to fish, and they are very welcome.
|
Ultimately we want lint free code. However, at the moment a lot of
|
||||||
|
cleanup is required to reach that goal. For now simply try to avoid
|
||||||
|
introducing new lint.
|
||||||
|
|
||||||
In general, we'll take all well-written completion scripts for a command that is publically available.
|
To make linting the code easy there are two make targets: ``lint`` and
|
||||||
This means no private tools or personal scripts, and we do reserve the right to reject for other reasons.
|
``lint-all``. The latter does exactly what the name implies. The former
|
||||||
|
will lint any modified but not committed ``*.cpp`` files. If there is no
|
||||||
|
uncommitted work it will lint the files in the most recent commit.
|
||||||
|
|
||||||
Before you try to contribute them to fish, consider if the authors of the tool you are completing want to maintain the script instead.
|
Fish has custom cppcheck rules in the file ``.cppcheck.rule``. These
|
||||||
Often that makes more sense, specifically because they can add new options to the script immediately once they add them,
|
help catch mistakes such as using ``wcwidth()`` rather than
|
||||||
and don't have to maintain one completion script for multiple versions. If the authors no longer wish to maintain the script,
|
``fish_wcwidth()``. Please add a new rule if you find similar mistakes
|
||||||
they can of course always contact the fish maintainers to hand it over, preferably by opening a PR.
|
being made.
|
||||||
This isn't a requirement - if the authors don't want to maintain it, or you simply don't want to contact them,
|
|
||||||
you can contribute your script to fish.
|
|
||||||
|
|
||||||
Completion scripts should
|
Fish also depends on ``diff`` and ``expect`` for its tests.
|
||||||
|
|
||||||
1. Use as few dependencies as possible - try to use fish's builtins like ``string`` instead of ``grep`` and ``awk``,
|
Dealing With Lint Warnings
|
||||||
use ``python`` to read json instead of ``jq`` (because it's already a soft dependency for fish's tools)
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
2. If it uses a common unix tool, use posix-compatible invocations - ideally it would work on GNU/Linux, macOS, the BSDs and other systems
|
|
||||||
3. Option and argument descriptions should be kept short.
|
|
||||||
The shorter the description, the more likely it is that fish can use more columns.
|
|
||||||
4. Function names should start with ``__fish``, and functions should be kept in the completion file unless they're used elsewhere.
|
|
||||||
5. Run ``fish_indent`` on your script.
|
|
||||||
6. Try not to use minor convenience features right after they are available in fish - we do try to keep completion scripts backportable.
|
|
||||||
If something has a real impact on the correctness or performance, feel free to use it,
|
|
||||||
but if it is just a shortcut, please leave it.
|
|
||||||
|
|
||||||
Put your completion script into share/completions/name-of-command.fish. If you have multiple commands, you need multiple files.
|
You are strongly encouraged to address a lint warning by refactoring the
|
||||||
|
code, changing variable names, or whatever action is implied by the
|
||||||
|
warning.
|
||||||
|
|
||||||
If you want to add tests, you probably want to add a littlecheck test. See below for details.
|
Suppressing Lint Warnings
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Contributing documentation
|
Once in a while the lint tools emit a false positive warning. For
|
||||||
==========================
|
example, cppcheck might suggest a memory leak is present when that is
|
||||||
|
not the case. To suppress that cppcheck warning you should insert a line
|
||||||
|
like the following immediately prior to the line cppcheck warned about:
|
||||||
|
|
||||||
The documentation is stored in ``doc_src/``, and written in ReStructured Text and built with Sphinx.
|
::
|
||||||
|
|
||||||
To build it locally, run from the main fish-shell directory::
|
// cppcheck-suppress memleak // addr not really leaked
|
||||||
|
|
||||||
sphinx-build -j 8 -b html -n doc_src/ /tmp/fish-doc/
|
The explanatory portion of the suppression comment is optional. For
|
||||||
|
other types of warnings replace “memleak” with the value inside the
|
||||||
|
parenthesis (e.g., “nullPointerRedundantCheck”) from a warning like the
|
||||||
|
following:
|
||||||
|
|
||||||
which will build the docs as html in /tmp/fish-doc. You can open it in a browser and see that it looks okay.
|
::
|
||||||
|
|
||||||
The builtins and various functions shipped with fish are documented in doc_src/cmds/.
|
[src/complete.cpp:1727]: warning (nullPointerRedundantCheck): Either the condition 'cmd_node' is redundant or there is possible null pointer dereference: cmd_node.
|
||||||
|
|
||||||
Code Style
|
Suppressing oclint warnings is more complicated to describe so I’ll
|
||||||
==========
|
refer you to the `OCLint
|
||||||
|
HowTo <http://docs.oclint.org/en/latest/howto/suppress.html#annotations>`__
|
||||||
|
on the topic.
|
||||||
|
|
||||||
To ensure your changes conform to the style rules run
|
Ensuring Your Changes Conform to the Style Guides
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
The following sections discuss the specific rules for the style that
|
||||||
|
should be used when writing fish code. To ensure your changes conform to
|
||||||
|
the style rules you simply need to run
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
build_tools/style.fish
|
build_tools/style.fish
|
||||||
|
|
||||||
before committing your change. That will run our autoformatters:
|
before committing your change. That will run ``git-clang-format`` to
|
||||||
|
rewrite only the lines you’re modifying.
|
||||||
- ``rustfmt`` for Rust
|
|
||||||
- ``fish_indent`` (shipped with fish) for fish script
|
|
||||||
- ``black`` for python
|
|
||||||
|
|
||||||
If you’ve already committed your changes that’s okay since it will then
|
If you’ve already committed your changes that’s okay since it will then
|
||||||
check the files in the most recent commit. This can be useful after
|
check the files in the most recent commit. This can be useful after
|
||||||
@@ -121,24 +148,40 @@ If you want to check the style of the entire code base run
|
|||||||
That command will refuse to restyle any files if you have uncommitted
|
That command will refuse to restyle any files if you have uncommitted
|
||||||
changes.
|
changes.
|
||||||
|
|
||||||
Fish Script Style Guide
|
Configuring Your Editor for Fish C++ Code
|
||||||
-----------------------
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
1. All fish scripts, such as those in the *share/functions* and *tests*
|
ViM
|
||||||
directories, should be formatted using the ``fish_indent`` command.
|
^^^
|
||||||
|
|
||||||
2. Function names should be in all lowercase with words separated by
|
As of ViM 7.4 it does not recognize triple-slash comments as used by
|
||||||
underscores. Private functions should begin with an underscore. The
|
Doxygen and the OS X Xcode IDE to flag comments that explain the
|
||||||
first word should be ``fish`` if the function is unique to fish.
|
following C symbol. This means the ``gq`` key binding to reformat such
|
||||||
|
comments doesn’t behave as expected. You can fix that by adding the
|
||||||
|
following to your vimrc:
|
||||||
|
|
||||||
3. The first word of global variable names should generally be ``fish``
|
::
|
||||||
for public vars or ``_fish`` for private vars to minimize the
|
|
||||||
possibility of name clashes with user defined vars.
|
autocmd Filetype c,cpp setlocal comments^=:///
|
||||||
|
|
||||||
|
If you use ViM I recommend the `vim-clang-format
|
||||||
|
plugin <https://github.com/rhysd/vim-clang-format>`__ by
|
||||||
|
[@rhysd](https://github.com/rhysd).
|
||||||
|
|
||||||
|
You can also get ViM to provide reasonably correct behavior by
|
||||||
|
installing
|
||||||
|
|
||||||
|
http://www.vim.org/scripts/script.php?script_id=2636
|
||||||
|
|
||||||
|
Emacs
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
If you use Emacs: TBD
|
||||||
|
|
||||||
Configuring Your Editor for Fish Scripts
|
Configuring Your Editor for Fish Scripts
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
If you use Vim: Install `vim-fish <https://github.com/dag/vim-fish>`__,
|
If you use ViM: Install `vim-fish <https://github.com/dag/vim-fish>`__,
|
||||||
make sure you have syntax and filetype functionality in ``~/.vimrc``:
|
make sure you have syntax and filetype functionality in ``~/.vimrc``:
|
||||||
|
|
||||||
::
|
::
|
||||||
@@ -171,46 +214,131 @@ made to run fish_indent via e.g.
|
|||||||
(add-hook 'fish-mode-hook (lambda ()
|
(add-hook 'fish-mode-hook (lambda ()
|
||||||
(add-hook 'before-save-hook 'fish_indent-before-save)))
|
(add-hook 'before-save-hook 'fish_indent-before-save)))
|
||||||
|
|
||||||
Rust Style Guide
|
Suppressing Reformatting of C++ Code
|
||||||
----------------
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Use ``cargo fmt`` and ``cargo clippy``. Clippy warnings can be turned off if there's a good reason to.
|
If you have a good reason for doing so you can tell ``clang-format`` to
|
||||||
|
not reformat a block of code by enclosing it in comments like this:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
code to ignore
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
However, as I write this there are no places in the code where we use
|
||||||
|
this and I can’t think of any legitimate reasons for exempting blocks of
|
||||||
|
code from clang-format.
|
||||||
|
|
||||||
|
Fish Script Style Guide
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
1. All fish scripts, such as those in the *share/functions* and *tests*
|
||||||
|
directories, should be formatted using the ``fish_indent`` command.
|
||||||
|
|
||||||
|
2. Function names should be in all lowercase with words separated by
|
||||||
|
underscores. Private functions should begin with an underscore. The
|
||||||
|
first word should be ``fish`` if the function is unique to fish.
|
||||||
|
|
||||||
|
3. The first word of global variable names should generally be ``fish``
|
||||||
|
for public vars or ``_fish`` for private vars to minimize the
|
||||||
|
possibility of name clashes with user defined vars.
|
||||||
|
|
||||||
|
C++ Style Guide
|
||||||
|
---------------
|
||||||
|
|
||||||
|
1. The `Google C++ Style
|
||||||
|
Guide <https://google.github.io/styleguide/cppguide.html>`__ forms
|
||||||
|
the basis of the fish C++ style guide. There are two major deviations
|
||||||
|
for the fish project. First, a four, rather than two, space indent.
|
||||||
|
Second, line lengths up to 100, rather than 80, characters.
|
||||||
|
|
||||||
|
2. The ``clang-format`` command is authoritative with respect to
|
||||||
|
indentation, whitespace around operators, etc.
|
||||||
|
|
||||||
|
3. All names in code should be ``small_snake_case``. No Hungarian
|
||||||
|
notation is used. The names for classes and structs should be
|
||||||
|
followed by ``_t``.
|
||||||
|
|
||||||
|
4. Always attach braces to the surrounding context.
|
||||||
|
|
||||||
|
5. Indent with spaces, not tabs and use four spaces per indent.
|
||||||
|
|
||||||
|
6. Document the purpose of a function or class with doxygen-style
|
||||||
|
comment blocks. e.g.:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sum numbers in a vector.
|
||||||
|
*
|
||||||
|
* @param values Container whose values are summed.
|
||||||
|
* @return sum of `values`, or 0.0 if `values` is empty.
|
||||||
|
*/
|
||||||
|
double sum(std::vector<double> & const values) {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
/// brief description of somefunction()
|
||||||
|
void somefunction() {
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
=======
|
-------
|
||||||
|
|
||||||
The source code for fish includes a large collection of tests. If you
|
The source code for fish includes a large collection of tests. If you
|
||||||
are making any changes to fish, running these tests is a good way to make
|
are making any changes to fish, running these tests is mandatory to make
|
||||||
sure the behaviour remains consistent and regressions are not
|
sure the behaviour remains consistent and regressions are not
|
||||||
introduced. Even if you don’t run the tests on your machine, they will
|
introduced. Even if you don’t run the tests on your machine, they will
|
||||||
still be run via Github Actions.
|
still be run via the `Travis
|
||||||
|
CI <https://travis-ci.org/fish-shell/fish-shell>`__ service.
|
||||||
|
|
||||||
You are strongly encouraged to add tests when changing the functionality
|
You are strongly encouraged to add tests when changing the functionality
|
||||||
of fish, especially if you are fixing a bug to help ensure there are no
|
of fish, especially if you are fixing a bug to help ensure there are no
|
||||||
regressions in the future (i.e., we don’t reintroduce the bug).
|
regressions in the future (i.e., we don’t reintroduce the bug).
|
||||||
|
|
||||||
The tests can be found in three places:
|
|
||||||
|
|
||||||
- src/tests for unit tests.
|
|
||||||
- tests/checks for script tests, run by `littlecheck <https://github.com/ridiculousfish/littlecheck>`__
|
|
||||||
- tests/pexpects for interactive tests using `pexpect <https://pexpect.readthedocs.io/en/stable/>`__
|
|
||||||
|
|
||||||
When in doubt, the bulk of the tests should be added as a littlecheck test in tests/checks, as they are the easiest to modify and run, and much faster and more dependable than pexpect tests. The syntax is fairly self-explanatory. It's a fish script with the expected output in ``# CHECK:`` or ``# CHECKERR:`` (for stderr) comments.
|
|
||||||
|
|
||||||
The pexpects are written in python and can simulate input and output to/from a terminal, so they are needed for anything that needs actual interactivity. The runner is in build_tools/pexpect_helper.py, in case you need to modify something there.
|
|
||||||
|
|
||||||
Local testing
|
Local testing
|
||||||
-------------
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
The tests can be run on your local computer on all operating systems.
|
The tests can be run on your local computer on all operating systems.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
cmake path/to/fish-shell
|
cmake path/to/fish-shell
|
||||||
make fish_run_tests
|
make test
|
||||||
|
|
||||||
|
Travis CI Build and Test
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The Travis Continuous Integration services can be used to test your
|
||||||
|
changes using multiple configurations. This is the same service that the
|
||||||
|
fish-shell project uses to ensure new changes haven’t broken anything.
|
||||||
|
Thus it is a really good idea that you leverage Travis CI before making
|
||||||
|
a pull request to avoid potential embarrassment at breaking the build.
|
||||||
|
|
||||||
|
You will need to `fork the fish-shell repository on
|
||||||
|
GitHub <https://help.github.com/articles/fork-a-repo/>`__, then setup
|
||||||
|
Travis to test your changes before making a pull request.
|
||||||
|
|
||||||
|
1. `Sign in to Travis CI <https://travis-ci.org/auth>`__ with your
|
||||||
|
GitHub account, accepting the GitHub access permissions confirmation.
|
||||||
|
2. Once you’re signed in and your repositories are synchronized, go to
|
||||||
|
your `profile page <https://travis-ci.org/profile>`__ and enable the
|
||||||
|
fish-shell repository.
|
||||||
|
3. Push your changes to GitHub.
|
||||||
|
|
||||||
|
You’ll receive an email when the tests are complete telling you whether
|
||||||
|
or not any tests failed.
|
||||||
|
|
||||||
|
You’ll find the configuration used to control Travis in the
|
||||||
|
``.travis.yml`` file.
|
||||||
|
|
||||||
Git hooks
|
Git hooks
|
||||||
---------
|
~~~~~~~~~
|
||||||
|
|
||||||
Since developers sometimes forget to run the tests, it can be helpful to
|
Since developers sometimes forget to run the tests, it can be helpful to
|
||||||
use git hooks (see githooks(5)) to automate it.
|
use git hooks (see githooks(5)) to automate it.
|
||||||
@@ -235,7 +363,7 @@ One possibility is a pre-push hook script like this one:
|
|||||||
done
|
done
|
||||||
if [ "x$isprotected" = x1 ]; then
|
if [ "x$isprotected" = x1 ]; then
|
||||||
echo "Running tests before push to master"
|
echo "Running tests before push to master"
|
||||||
make fish_run_tests
|
make test
|
||||||
RESULT=$?
|
RESULT=$?
|
||||||
if [ $RESULT -ne 0 ]; then
|
if [ $RESULT -ne 0 ]; then
|
||||||
echo "Tests failed for a push to master, we can't let you do that" >&2
|
echo "Tests failed for a push to master, we can't let you do that" >&2
|
||||||
@@ -245,7 +373,7 @@ One possibility is a pre-push hook script like this one:
|
|||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
This will check if the push is to the master branch and, if it is, only
|
This will check if the push is to the master branch and, if it is, only
|
||||||
allow the push if running ``make fish_run_tests`` succeeds. In some circumstances
|
allow the push if running ``make test`` succeeds. In some circumstances
|
||||||
it may be advisable to circumvent this check with
|
it may be advisable to circumvent this check with
|
||||||
``git push --no-verify``, but usually that isn’t necessary.
|
``git push --no-verify``, but usually that isn’t necessary.
|
||||||
|
|
||||||
@@ -253,7 +381,7 @@ To install the hook, place the code in a new file
|
|||||||
``.git/hooks/pre-push`` and make it executable.
|
``.git/hooks/pre-push`` and make it executable.
|
||||||
|
|
||||||
Coverity Scan
|
Coverity Scan
|
||||||
-------------
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
We use Coverity’s static analysis tool which offers free access to open
|
We use Coverity’s static analysis tool which offers free access to open
|
||||||
source projects. While access to the tool itself is restricted,
|
source projects. While access to the tool itself is restricted,
|
||||||
@@ -263,75 +391,67 @@ with their GitHub account. Currently, tests are triggered upon merging
|
|||||||
the ``master`` branch into ``coverity_scan_master``. Even if you are not
|
the ``master`` branch into ``coverity_scan_master``. Even if you are not
|
||||||
a fish developer, you can keep an eye on our statistics there.
|
a fish developer, you can keep an eye on our statistics there.
|
||||||
|
|
||||||
Contributing Translations
|
Installing the Required Tools
|
||||||
=========================
|
-----------------------------
|
||||||
|
|
||||||
|
Installing the Linting Tools
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
To install the lint checkers on Mac OS X using Homebrew:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
brew tap oclint/formulae
|
||||||
|
brew install oclint
|
||||||
|
brew install cppcheck
|
||||||
|
|
||||||
|
To install the lint checkers on Debian-based Linux distributions:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo apt-get install clang
|
||||||
|
sudo apt-get install oclint
|
||||||
|
sudo apt-get install cppcheck
|
||||||
|
|
||||||
|
Installing the Reformatting Tools
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Mac OS X:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
brew install clang-format
|
||||||
|
|
||||||
|
Debian-based:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
apt-cache search clang-format
|
||||||
|
|
||||||
|
Above will list all the versions available. Pick the newest one
|
||||||
|
available (3.9 for Ubuntu 16.10 as I write this) and install it:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo apt-get install clang-format-3.9
|
||||||
|
sudo ln -s /usr/bin/clang-format-3.9 /usr/bin/clang-format
|
||||||
|
|
||||||
|
Message Translations
|
||||||
|
--------------------
|
||||||
|
|
||||||
Fish uses the GNU gettext library to translate messages from English to
|
Fish uses the GNU gettext library to translate messages from English to
|
||||||
other languages.
|
other languages.
|
||||||
|
|
||||||
Creating and updating translations requires the Gettext tools, including
|
|
||||||
``xgettext``, ``msgfmt`` and ``msgmerge``. Translation sources are
|
|
||||||
stored in the ``po`` directory, named ``LANG.po``, where ``LANG`` is the
|
|
||||||
two letter ISO 639-1 language code of the target language (eg ``de`` for
|
|
||||||
German).
|
|
||||||
|
|
||||||
To create a new translation:
|
|
||||||
|
|
||||||
* generate a ``messages.pot`` file by running ``build_tools/fish_xgettext.fish`` from
|
|
||||||
the source tree
|
|
||||||
* copy ``messages.pot`` to ``po/LANG.po``
|
|
||||||
|
|
||||||
To update a translation:
|
|
||||||
|
|
||||||
* generate a ``messages.pot`` file by running
|
|
||||||
``build_tools/fish_xgettext.fish`` from the source tree
|
|
||||||
|
|
||||||
* update the existing translation by running
|
|
||||||
``msgmerge --update --no-fuzzy-matching po/LANG.po messages.pot``
|
|
||||||
|
|
||||||
The ``--no-fuzzy-matching`` is important as we have had terrible experiences with gettext's "fuzzy" translations in the past.
|
|
||||||
|
|
||||||
Many tools are available for editing translation files, including
|
|
||||||
command-line and graphical user interface programs. For simple use, you can just use your text editor.
|
|
||||||
|
|
||||||
Open up the po file, for example ``po/sv.po``, and you'll see something like::
|
|
||||||
|
|
||||||
msgid "%ls: No suitable job\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
The ``msgid`` here is the "name" of the string to translate, typically the english string to translate. The second line (``msgstr``) is where your translation goes.
|
|
||||||
|
|
||||||
For example::
|
|
||||||
|
|
||||||
msgid "%ls: No suitable job\n"
|
|
||||||
msgstr "%ls: Inget passande jobb\n"
|
|
||||||
|
|
||||||
Any ``%s`` / ``%ls`` or ``%d`` are placeholders that fish will use for formatting at runtime. It is important that they match - the translated string should have the same placeholders in the same order.
|
|
||||||
|
|
||||||
Also any escaped characters, like that ``\n`` newline at the end, should be kept so the translation has the same behavior.
|
|
||||||
|
|
||||||
Our tests run ``msgfmt --check-format /path/to/file``, so they would catch mismatched placeholders - otherwise fish would crash at runtime when the string is about to be used.
|
|
||||||
|
|
||||||
Be cautious about blindly updating an existing translation file. Trivial
|
|
||||||
changes to an existing message (eg changing the punctuation) will cause
|
|
||||||
existing translations to be removed, since the tools do literal string
|
|
||||||
matching. Therefore, in general, you need to carefully review any
|
|
||||||
recommended deletions.
|
|
||||||
|
|
||||||
Setting Code Up For Translations
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
All non-debug messages output for user consumption should be marked for
|
All non-debug messages output for user consumption should be marked for
|
||||||
translation. In Rust, this requires the use of the ``wgettext!`` or ``wgettext_fmt!``
|
translation. In C++, this requires the use of the ``_`` (underscore)
|
||||||
macros:
|
macro:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
streams.out.append(wgettext_fmt!("%ls: There are no jobs\n", argv[0]));
|
streams.out.append_format(_(L"%ls: There are no jobs\n"), argv[0]);
|
||||||
|
|
||||||
All messages in fish script must be enclosed in single or double quote
|
All messages in fish script must be enclosed in single or double quote
|
||||||
characters for our message extraction script to find them.
|
characters. They must also be translated via a subcommand. This means
|
||||||
They must also be translated via a command substitution. This means
|
|
||||||
that the following are **not** valid:
|
that the following are **not** valid:
|
||||||
|
|
||||||
::
|
::
|
||||||
@@ -346,15 +466,34 @@ Above should be written like this instead:
|
|||||||
echo (_ "hello")
|
echo (_ "hello")
|
||||||
echo (_ "goodbye")
|
echo (_ "goodbye")
|
||||||
|
|
||||||
You can use either single or double quotes to enclose the
|
Note that you can use either single or double quotes to enclose the
|
||||||
message to be translated. You can also optionally include spaces after
|
message to be translated. You can also optionally include spaces after
|
||||||
the opening parentheses or before the closing parentheses.
|
the opening parentheses and once again before the closing parentheses.
|
||||||
|
|
||||||
Versioning
|
Creating and updating translations requires the Gettext tools, including
|
||||||
==========
|
``xgettext``, ``msgfmt`` and ``msgmerge``. Translation sources are
|
||||||
|
stored in the ``po`` directory, named ``LANG.po``, where ``LANG`` is the
|
||||||
|
two letter ISO 639-1 language code of the target language (eg ``de`` for
|
||||||
|
German).
|
||||||
|
|
||||||
The fish version is constructed by the *build_tools/git_version_gen.sh*
|
To create a new translation, for example for German: \* generate a
|
||||||
script. For developers the version is the branch name plus the output of
|
``messages.pot`` file by running ``build_tools/fish_xgettext.fish`` from
|
||||||
``git describe --always --dirty``. Normally the main part of the version
|
the source tree \* copy ``messages.pot`` to ``po/LANG.po`` ()
|
||||||
will be the closest annotated tag. Which itself is usually the most
|
|
||||||
recent release number (e.g., ``2.6.0``).
|
To update a translation: \* generate a ``messages.pot`` file by running
|
||||||
|
``build_tools/fish_xgettext.fish`` from the source tree \* update the
|
||||||
|
existing translation by running
|
||||||
|
``msgmerge --update --no-fuzzy-matching po/LANG.po messages.pot``
|
||||||
|
|
||||||
|
Many tools are available for editing translation files, including
|
||||||
|
command-line and graphical user interface programs.
|
||||||
|
|
||||||
|
Be cautious about blindly updating an existing translation file. Trivial
|
||||||
|
changes to an existing message (eg changing the punctuation) will cause
|
||||||
|
existing translations to be removed, since the tools do literal string
|
||||||
|
matching. Therefore, in general, you need to carefully review any
|
||||||
|
recommended deletions.
|
||||||
|
|
||||||
|
Read the `translations
|
||||||
|
wiki <https://github.com/fish-shell/fish-shell/wiki/Translations>`__ for
|
||||||
|
more information.
|
||||||
|
|||||||
8
COPYING
8
COPYING
@@ -1,7 +1,7 @@
|
|||||||
Fish is a smart and user-friendly command line shell.
|
Fish is a smart and user-friendly command line shell.
|
||||||
|
|
||||||
Copyright (C) 2005-2009 Axel Liljencrantz
|
Copyright (C) 2005-2009 Axel Liljencrantz
|
||||||
Copyright (C) 2009-2024 fish-shell contributors
|
Copyright (C) 2009-2020 fish-shell contributors
|
||||||
|
|
||||||
fish is free software.
|
fish is free software.
|
||||||
|
|
||||||
@@ -9,10 +9,10 @@ Most of fish is licensed under the GNU General Public License version 2, and
|
|||||||
you can redistribute it and/or modify it under the terms of the GNU GPL as
|
you can redistribute it and/or modify it under the terms of the GNU GPL as
|
||||||
published by the Free Software Foundation.
|
published by the Free Software Foundation.
|
||||||
|
|
||||||
fish also includes software licensed under the Python Software Foundation License version 2, the MIT
|
fish also includes software licensed under the GNU Lesser General Public
|
||||||
license, and the GNU Library General Public License version 2.
|
License version 2, the OpenBSD license, the ISC license, and the NetBSD license.
|
||||||
|
|
||||||
Full licensing information is contained in doc_src/license.rst.
|
Full licensing information is contained in doc_src/license.hdr.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
|||||||
695
Cargo.lock
generated
695
Cargo.lock
generated
@@ -1,695 +0,0 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
version = 3
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "allocator-api2"
|
|
||||||
version = "0.2.18"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bitflags"
|
|
||||||
version = "2.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "block-buffer"
|
|
||||||
version = "0.10.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
|
||||||
dependencies = [
|
|
||||||
"generic-array",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cc"
|
|
||||||
version = "1.1.30"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945"
|
|
||||||
dependencies = [
|
|
||||||
"jobserver",
|
|
||||||
"libc",
|
|
||||||
"shlex",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfg-if"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfg_aliases"
|
|
||||||
version = "0.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cpufeatures"
|
|
||||||
version = "0.2.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crypto-common"
|
|
||||||
version = "0.1.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
|
||||||
dependencies = [
|
|
||||||
"generic-array",
|
|
||||||
"typenum",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "dashmap"
|
|
||||||
version = "5.5.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"hashbrown 0.14.5",
|
|
||||||
"lock_api",
|
|
||||||
"once_cell",
|
|
||||||
"parking_lot_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "digest"
|
|
||||||
version = "0.10.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
|
||||||
dependencies = [
|
|
||||||
"block-buffer",
|
|
||||||
"crypto-common",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "equivalent"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "errno"
|
|
||||||
version = "0.3.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fish"
|
|
||||||
version = "4.0.6"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"cc",
|
|
||||||
"errno",
|
|
||||||
"fish-printf",
|
|
||||||
"lazy_static",
|
|
||||||
"libc",
|
|
||||||
"lru",
|
|
||||||
"nix",
|
|
||||||
"num-traits",
|
|
||||||
"once_cell",
|
|
||||||
"pcre2",
|
|
||||||
"portable-atomic",
|
|
||||||
"rand",
|
|
||||||
"rsconf",
|
|
||||||
"rust-embed",
|
|
||||||
"serial_test",
|
|
||||||
"terminfo",
|
|
||||||
"widestring",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fish-printf"
|
|
||||||
version = "0.2.1"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"unicode-segmentation",
|
|
||||||
"unicode-width",
|
|
||||||
"widestring",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fnv"
|
|
||||||
version = "1.0.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "foldhash"
|
|
||||||
version = "0.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "generic-array"
|
|
||||||
version = "0.14.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
|
||||||
dependencies = [
|
|
||||||
"typenum",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hashbrown"
|
|
||||||
version = "0.14.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hashbrown"
|
|
||||||
version = "0.15.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
|
|
||||||
dependencies = [
|
|
||||||
"allocator-api2",
|
|
||||||
"equivalent",
|
|
||||||
"foldhash",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "jobserver"
|
|
||||||
version = "0.1.32"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lazy_static"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libc"
|
|
||||||
version = "0.2.159"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lock_api"
|
|
||||||
version = "0.4.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"scopeguard",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "log"
|
|
||||||
version = "0.4.22"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lru"
|
|
||||||
version = "0.12.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
|
|
||||||
dependencies = [
|
|
||||||
"hashbrown 0.15.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "memchr"
|
|
||||||
version = "2.7.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "minimal-lexical"
|
|
||||||
version = "0.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nix"
|
|
||||||
version = "0.29.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"cfg-if",
|
|
||||||
"cfg_aliases",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nom"
|
|
||||||
version = "7.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
"minimal-lexical",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-traits"
|
|
||||||
version = "0.2.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "once_cell"
|
|
||||||
version = "1.20.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot"
|
|
||||||
version = "0.12.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
|
||||||
dependencies = [
|
|
||||||
"lock_api",
|
|
||||||
"parking_lot_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot_core"
|
|
||||||
version = "0.9.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"redox_syscall",
|
|
||||||
"smallvec",
|
|
||||||
"windows-targets",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pcre2"
|
|
||||||
version = "0.2.9"
|
|
||||||
source = "git+https://github.com/fish-shell/rust-pcre2?tag=0.2.9-utf32#85b7afba1a9d9bd445779800e5bcafeb732e4421"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"pcre2-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pcre2-sys"
|
|
||||||
version = "0.2.9"
|
|
||||||
source = "git+https://github.com/fish-shell/rust-pcre2?tag=0.2.9-utf32#85b7afba1a9d9bd445779800e5bcafeb732e4421"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
"pkg-config",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "phf"
|
|
||||||
version = "0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
|
|
||||||
dependencies = [
|
|
||||||
"phf_shared",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "phf_codegen"
|
|
||||||
version = "0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
|
|
||||||
dependencies = [
|
|
||||||
"phf_generator",
|
|
||||||
"phf_shared",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "phf_generator"
|
|
||||||
version = "0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
|
|
||||||
dependencies = [
|
|
||||||
"phf_shared",
|
|
||||||
"rand",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "phf_shared"
|
|
||||||
version = "0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
|
|
||||||
dependencies = [
|
|
||||||
"siphasher",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pkg-config"
|
|
||||||
version = "0.3.31"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "portable-atomic"
|
|
||||||
version = "1.9.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro2"
|
|
||||||
version = "1.0.87"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "quote"
|
|
||||||
version = "1.0.37"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand"
|
|
||||||
version = "0.8.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.6.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "redox_syscall"
|
|
||||||
version = "0.5.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rsconf"
|
|
||||||
version = "0.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bd2af859f1af0401e7fc7577739c87b0d239d8a5da400d717183bca92336bcdc"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rust-embed"
|
|
||||||
version = "8.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0"
|
|
||||||
dependencies = [
|
|
||||||
"rust-embed-impl",
|
|
||||||
"rust-embed-utils",
|
|
||||||
"walkdir",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rust-embed-impl"
|
|
||||||
version = "8.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"rust-embed-utils",
|
|
||||||
"syn 2.0.79",
|
|
||||||
"walkdir",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rust-embed-utils"
|
|
||||||
version = "8.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d"
|
|
||||||
dependencies = [
|
|
||||||
"sha2",
|
|
||||||
"walkdir",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "same-file"
|
|
||||||
version = "1.0.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
|
||||||
dependencies = [
|
|
||||||
"winapi-util",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scopeguard"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serial_test"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "538c30747ae860d6fb88330addbbd3e0ddbe46d662d032855596d8a8ca260611"
|
|
||||||
dependencies = [
|
|
||||||
"dashmap",
|
|
||||||
"lazy_static",
|
|
||||||
"parking_lot",
|
|
||||||
"serial_test_derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serial_test_derive"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "079a83df15f85d89a68d64ae1238f142f172b1fa915d0d76b26a7cba1b659a69"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sha2"
|
|
||||||
version = "0.10.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"cpufeatures",
|
|
||||||
"digest",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "shlex"
|
|
||||||
version = "1.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "siphasher"
|
|
||||||
version = "0.3.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "smallvec"
|
|
||||||
version = "1.13.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "syn"
|
|
||||||
version = "1.0.109"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "syn"
|
|
||||||
version = "2.0.79"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "terminfo"
|
|
||||||
version = "0.9.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d4ea810f0692f9f51b382fff5893887bb4580f5fa246fde546e0b13e7fcee662"
|
|
||||||
dependencies = [
|
|
||||||
"fnv",
|
|
||||||
"nom",
|
|
||||||
"phf",
|
|
||||||
"phf_codegen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typenum"
|
|
||||||
version = "1.17.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-ident"
|
|
||||||
version = "1.0.13"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-segmentation"
|
|
||||||
version = "1.12.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-width"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "version_check"
|
|
||||||
version = "0.9.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "walkdir"
|
|
||||||
version = "2.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
|
||||||
dependencies = [
|
|
||||||
"same-file",
|
|
||||||
"winapi-util",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "widestring"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-util"
|
|
||||||
version = "0.1.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
|
||||||
dependencies = [
|
|
||||||
"windows-sys 0.59.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-sys"
|
|
||||||
version = "0.52.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
|
||||||
dependencies = [
|
|
||||||
"windows-targets",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-sys"
|
|
||||||
version = "0.59.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
|
||||||
dependencies = [
|
|
||||||
"windows-targets",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-targets"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
|
||||||
dependencies = [
|
|
||||||
"windows_aarch64_gnullvm",
|
|
||||||
"windows_aarch64_msvc",
|
|
||||||
"windows_i686_gnu",
|
|
||||||
"windows_i686_gnullvm",
|
|
||||||
"windows_i686_msvc",
|
|
||||||
"windows_x86_64_gnu",
|
|
||||||
"windows_x86_64_gnullvm",
|
|
||||||
"windows_x86_64_msvc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_gnullvm"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_msvc"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnu"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnullvm"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_msvc"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnu"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnullvm"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_msvc"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
|
||||||
106
Cargo.toml
106
Cargo.toml
@@ -1,106 +0,0 @@
|
|||||||
[workspace]
|
|
||||||
resolver = "2"
|
|
||||||
members = ["printf"]
|
|
||||||
|
|
||||||
[workspace.package]
|
|
||||||
rust-version = "1.70"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
overflow-checks = true
|
|
||||||
lto = true
|
|
||||||
|
|
||||||
[profile.release-with-debug]
|
|
||||||
inherits = "release"
|
|
||||||
debug = true
|
|
||||||
|
|
||||||
[package]
|
|
||||||
name = "fish"
|
|
||||||
version = "4.0.6"
|
|
||||||
edition.workspace = true
|
|
||||||
rust-version.workspace = true
|
|
||||||
default-run = "fish"
|
|
||||||
# see doc_src/license.rst for details
|
|
||||||
# don't forget to update COPYING and debian/copyright too
|
|
||||||
license = "GPL-2.0-only AND LGPL-2.0-or-later AND MIT AND PSF-2.0"
|
|
||||||
repository = "https://github.com/fish-shell/fish-shell"
|
|
||||||
homepage = "https://fishshell.com"
|
|
||||||
readme = "README.rst"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
pcre2 = { git = "https://github.com/fish-shell/rust-pcre2", tag = "0.2.9-utf32", default-features = false, features = [
|
|
||||||
"utf32",
|
|
||||||
] }
|
|
||||||
|
|
||||||
bitflags = "2.5.0"
|
|
||||||
errno = "0.3.0"
|
|
||||||
lazy_static = "1.4.0"
|
|
||||||
libc = "0.2.155"
|
|
||||||
# lru pulls in hashbrown by default, which uses a faster (though less DoS resistant) hashing algo.
|
|
||||||
# disabling default features uses the stdlib instead, but it doubles the time to rewrite the history
|
|
||||||
# files as of 22 April 2024.
|
|
||||||
lru = "0.12.3"
|
|
||||||
nix = { version = "0.29.0", default-features = false, features = [
|
|
||||||
"event",
|
|
||||||
"inotify",
|
|
||||||
"resource",
|
|
||||||
"fs",
|
|
||||||
] }
|
|
||||||
num-traits = "0.2.19"
|
|
||||||
once_cell = "1.19.0"
|
|
||||||
fish-printf = { path = "./printf", features = ["widestring"] }
|
|
||||||
|
|
||||||
# Don't use the "getrandom" feature as it requires "getentropy" which was not
|
|
||||||
# available on macOS < 10.12. We can enable "getrandom" when we raise the
|
|
||||||
# minimum supported version to 10.12.
|
|
||||||
rand = { version = "0.8.5", default-features = false, features = ["small_rng"] }
|
|
||||||
widestring = "1.1.0"
|
|
||||||
# We need 0.9.0 specifically for some crash fixes.
|
|
||||||
terminfo = "0.9.0"
|
|
||||||
rust-embed = { version = "8.2.0", optional = true }
|
|
||||||
|
|
||||||
[target.'cfg(not(target_has_atomic = "64"))'.dependencies]
|
|
||||||
portable-atomic = { version = "1", default-features = false, features = [
|
|
||||||
"fallback",
|
|
||||||
] }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
serial_test = { version = "1.0.0", default-features = false }
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
cc = "1.0.94"
|
|
||||||
rsconf = "0.2.2"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
crate-type = ["rlib"]
|
|
||||||
path = "src/lib.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "fish"
|
|
||||||
path = "src/bin/fish.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "fish_indent"
|
|
||||||
path = "src/bin/fish_indent.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "fish_key_reader"
|
|
||||||
path = "src/bin/fish_key_reader.rs"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["installable"]
|
|
||||||
benchmark = []
|
|
||||||
installable = ["dep:rust-embed"]
|
|
||||||
|
|
||||||
# The following features are auto-detected by the build-script and should not be enabled manually.
|
|
||||||
asan = []
|
|
||||||
tsan = []
|
|
||||||
|
|
||||||
[lints]
|
|
||||||
rust.non_camel_case_types = "allow"
|
|
||||||
rust.non_upper_case_globals = "allow"
|
|
||||||
rust.unknown_lints = "allow"
|
|
||||||
rust.unstable_name_collisions = "allow"
|
|
||||||
clippy.manual_range_contains = "allow"
|
|
||||||
clippy.needless_return = "allow"
|
|
||||||
clippy.needless_lifetimes = "allow"
|
|
||||||
@@ -3,7 +3,7 @@ FROM centos:latest
|
|||||||
# Build dependency
|
# Build dependency
|
||||||
RUN yum update -y &&\
|
RUN yum update -y &&\
|
||||||
yum install -y epel-release &&\
|
yum install -y epel-release &&\
|
||||||
yum install -y clang cmake3 gcc-c++ make &&\
|
yum install -y clang cmake3 gcc-c++ make ncurses-devel &&\
|
||||||
yum clean all
|
yum clean all
|
||||||
|
|
||||||
# Test dependency
|
# Test dependency
|
||||||
|
|||||||
15
GNUmakefile
15
GNUmakefile
@@ -31,19 +31,16 @@ else
|
|||||||
|
|
||||||
all: .begin build/fish
|
all: .begin build/fish
|
||||||
|
|
||||||
.PHONY: .begin
|
PHONY: .begin
|
||||||
.begin:
|
.begin:
|
||||||
@which $(CMAKE) > /dev/null 2> /dev/null || \
|
@which $(CMAKE) > /dev/null 2> /dev/null || \
|
||||||
(echo 'Please install CMake and then re-run the `make` command!' 1>&2 && false)
|
(echo 'Please install CMake and then re-run the `make` command!' 1>&2 && false)
|
||||||
|
|
||||||
.PHONY: build/fish
|
|
||||||
build/fish: build/$(BUILDFILE)
|
build/fish: build/$(BUILDFILE)
|
||||||
$(CMAKE) --build build
|
$(CMAKE) --build build
|
||||||
|
|
||||||
# Use build as an order-only dependency. This prevents the target from always being outdated
|
build/$(BUILDFILE): build
|
||||||
# after a make run, and more importantly, doesn't clobber manually specified CMake options.
|
cd build; $(CMAKE) .. -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -G "$(GENERATOR)" \
|
||||||
build/$(BUILDFILE): | build
|
|
||||||
cd build; $(CMAKE) .. -G "$(GENERATOR)" \
|
|
||||||
-DCMAKE_INSTALL_PREFIX="$(PREFIX)" -DCMAKE_EXPORT_COMPILE_COMMANDS=1
|
-DCMAKE_INSTALL_PREFIX="$(PREFIX)" -DCMAKE_EXPORT_COMPILE_COMMANDS=1
|
||||||
|
|
||||||
build:
|
build:
|
||||||
@@ -55,11 +52,7 @@ clean:
|
|||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: build/fish
|
test: build/fish
|
||||||
$(CMAKE) --build build --target fish_run_tests
|
$(CMAKE) --build build --target test
|
||||||
|
|
||||||
.PHONY: fish_run_tests
|
|
||||||
fish_run_tests: build/fish
|
|
||||||
$(CMAKE) --build build --target fish_run_tests
|
|
||||||
|
|
||||||
.PHONY: install
|
.PHONY: install
|
||||||
install: build/fish
|
install: build/fish
|
||||||
|
|||||||
165
README.rst
165
README.rst
@@ -1,16 +1,13 @@
|
|||||||
.. |Cirrus CI| image:: https://api.cirrus-ci.com/github/fish-shell/fish-shell.svg?branch=master
|
`fish <https://fishshell.com/>`__ - the friendly interactive shell |Build Status|
|
||||||
:target: https://cirrus-ci.com/github/fish-shell/fish-shell
|
=================================================================================
|
||||||
:alt: Cirrus CI Build Status
|
|
||||||
|
|
||||||
`fish <https://fishshell.com/>`__ - the friendly interactive shell |Build Status| |Cirrus CI|
|
|
||||||
=============================================================================================
|
|
||||||
|
|
||||||
fish is a smart and user-friendly command line shell for macOS, Linux,
|
fish is a smart and user-friendly command line shell for macOS, Linux,
|
||||||
and the rest of the family. fish includes features like syntax
|
and the rest of the family. fish includes features like syntax
|
||||||
highlighting, autosuggest-as-you-type, and fancy tab completions that
|
highlighting, autosuggest-as-you-type, and fancy tab completions that
|
||||||
just work, with no configuration required.
|
just work, with no configuration required.
|
||||||
|
|
||||||
For downloads, screenshots and more, go to https://fishshell.com/.
|
For more on fish’s design philosophy, see the `design
|
||||||
|
document <https://fishshell.com/docs/current/design.html>`__.
|
||||||
|
|
||||||
Quick Start
|
Quick Start
|
||||||
-----------
|
-----------
|
||||||
@@ -23,6 +20,11 @@ magic phrase “unlike other shells”.
|
|||||||
Detailed user documentation is available by running ``help`` within
|
Detailed user documentation is available by running ``help`` within
|
||||||
fish, and also at https://fishshell.com/docs/current/index.html
|
fish, and also at https://fishshell.com/docs/current/index.html
|
||||||
|
|
||||||
|
You can quickly play with fish right in your browser by clicking the
|
||||||
|
button below:
|
||||||
|
|
||||||
|
|Try in browser|
|
||||||
|
|
||||||
Getting fish
|
Getting fish
|
||||||
------------
|
------------
|
||||||
|
|
||||||
@@ -37,8 +39,6 @@ fish can be installed:
|
|||||||
- using the `installer from fishshell.com <https://fishshell.com/>`__
|
- using the `installer from fishshell.com <https://fishshell.com/>`__
|
||||||
- as a `standalone app from fishshell.com <https://fishshell.com/>`__
|
- as a `standalone app from fishshell.com <https://fishshell.com/>`__
|
||||||
|
|
||||||
Note: The minimum supported macOS version is 10.10 "Yosemite".
|
|
||||||
|
|
||||||
Packages for Linux
|
Packages for Linux
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@@ -53,8 +53,8 @@ and can be installed using the following commands:
|
|||||||
::
|
::
|
||||||
|
|
||||||
sudo apt-add-repository ppa:fish-shell/release-3
|
sudo apt-add-repository ppa:fish-shell/release-3
|
||||||
sudo apt update
|
sudo apt-get update
|
||||||
sudo apt install fish
|
sudo apt-get install fish
|
||||||
|
|
||||||
Instructions for other distributions may be found at
|
Instructions for other distributions may be found at
|
||||||
`fishshell.com <https://fishshell.com>`__.
|
`fishshell.com <https://fishshell.com>`__.
|
||||||
@@ -62,11 +62,12 @@ Instructions for other distributions may be found at
|
|||||||
Windows
|
Windows
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|
||||||
- On Windows 10/11, fish can be installed under the WSL Windows Subsystem
|
- On Windows 10, fish can be installed under the WSL Windows Subsystem
|
||||||
for Linux with the instructions for the appropriate distribution
|
for Linux with the instructions for the appropriate distribution
|
||||||
listed above under “Packages for Linux”, or from source with the
|
listed above under “Packages for Linux”, or from source with the
|
||||||
instructions below.
|
instructions below.
|
||||||
- fish (4.0 on and onwards) cannot be installed in Cygwin, due to a lack of Rust support.
|
- Fish can also be installed on all versions of Windows using
|
||||||
|
`Cygwin <https://cygwin.com/>`__ (from the **Shells** category).
|
||||||
|
|
||||||
Building from source
|
Building from source
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
@@ -75,7 +76,7 @@ If packages are not available for your platform, GPG-signed tarballs are
|
|||||||
available from `fishshell.com <https://fishshell.com/>`__ and
|
available from `fishshell.com <https://fishshell.com/>`__ and
|
||||||
`fish-shell on
|
`fish-shell on
|
||||||
GitHub <https://github.com/fish-shell/fish-shell/releases>`__. See the
|
GitHub <https://github.com/fish-shell/fish-shell/releases>`__. See the
|
||||||
`Building <#building>`__ section for instructions.
|
*Building* section for instructions.
|
||||||
|
|
||||||
Running fish
|
Running fish
|
||||||
------------
|
------------
|
||||||
@@ -87,30 +88,56 @@ Dependencies
|
|||||||
|
|
||||||
Running fish requires:
|
Running fish requires:
|
||||||
|
|
||||||
- A terminfo database, typically from curses or ncurses (preinstalled on most \*nix systems) - this needs to be the directory tree format, not the "hashed" database.
|
- curses or ncurses (preinstalled on most \*nix systems)
|
||||||
If this is unavailable, fish uses an included xterm-256color definition.
|
|
||||||
- some common \*nix system utilities (currently ``mktemp``), in
|
- some common \*nix system utilities (currently ``mktemp``), in
|
||||||
addition to the basic POSIX utilities (``cat``, ``cut``, ``dirname``,
|
addition to the basic POSIX utilities (``cat``, ``cut``, ``dirname``,
|
||||||
``file``, ``ls``, ``mkdir``, ``mkfifo``, ``rm``, ``sort``, ``tee``, ``tr``,
|
``ls``, ``mkdir``, ``mkfifo``, ``rm``, ``sort``, ``tee``, ``tr``,
|
||||||
``uname`` and ``sed`` at least, but the full coreutils plus ``find`` and
|
``uname`` and ``sed`` at least, but the full coreutils plus find, sed
|
||||||
``awk`` is preferred)
|
and awk is preferred)
|
||||||
- The gettext library, if compiled with
|
- gettext (library and ``gettext`` command), if compiled with
|
||||||
translation support
|
translation support
|
||||||
|
|
||||||
The following optional features also have specific requirements:
|
The following optional features also have specific requirements:
|
||||||
|
|
||||||
- builtin commands that have the ``--help`` option or print usage
|
- builtin commands that have the ``--help`` option or print usage
|
||||||
messages require ``nroff`` or ``mandoc`` for
|
messages require ``ul`` and either ``nroff`` or ``mandoc`` for
|
||||||
display
|
display
|
||||||
- automated completion generation from manual pages requires Python 3.5+
|
- automated completion generation from manual pages requires Python
|
||||||
- the ``fish_config`` web configuration tool requires Python 3.5+ and a web browser
|
(2.7+ or 3.3+) and possibly the ``backports.lzma`` module for Python
|
||||||
|
2.7
|
||||||
|
- the ``fish_config`` web configuration tool requires Python (2.7+ or
|
||||||
|
3.3 +) and a web browser
|
||||||
- system clipboard integration (with the default Ctrl-V and Ctrl-X
|
- system clipboard integration (with the default Ctrl-V and Ctrl-X
|
||||||
bindings) require either the ``xsel``, ``xclip``,
|
bindings) require either the ``xsel``, ``xclip``,
|
||||||
``wl-copy``/``wl-paste`` or ``pbcopy``/``pbpaste`` utilities
|
``wl-copy``/``wl-paste`` or ``pbcopy``/``pbpaste`` utilities
|
||||||
- full completions for ``yarn`` and ``npm`` require the
|
- full completions for ``yarn`` and ``npm`` require the
|
||||||
``all-the-package-names`` NPM module
|
``all-the-package-names`` NPM module
|
||||||
- ``colorls`` is used, if installed, to add color when running ``ls`` on platforms
|
|
||||||
that do not have color support (such as OpenBSD)
|
Switching to fish
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
If you wish to use fish as your default shell, use the following
|
||||||
|
command:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
chsh -s /usr/local/bin/fish
|
||||||
|
|
||||||
|
``chsh`` will prompt you for your password and change your default
|
||||||
|
shell. (Substitute ``/usr/local/bin/fish`` with whatever path fish was
|
||||||
|
installed to, if it differs.) Log out, then log in again for the changes
|
||||||
|
to take effect.
|
||||||
|
|
||||||
|
Use the following command if fish isn’t already added to ``/etc/shells``
|
||||||
|
to permit fish to be your login shell:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
echo /usr/local/bin/fish | sudo tee -a /etc/shells
|
||||||
|
|
||||||
|
To switch your default shell back, you can run ``chsh -s /bin/bash``
|
||||||
|
(substituting ``/bin/bash`` with ``/bin/tcsh`` or ``/bin/zsh`` as
|
||||||
|
appropriate).
|
||||||
|
|
||||||
Building
|
Building
|
||||||
--------
|
--------
|
||||||
@@ -122,25 +149,17 @@ Dependencies
|
|||||||
|
|
||||||
Compiling fish requires:
|
Compiling fish requires:
|
||||||
|
|
||||||
- Rust (version 1.70 or later)
|
- a C++11 compiler (g++ 4.8 or later, or clang 3.3 or later)
|
||||||
- CMake (version 3.15 or later)
|
- CMake (version 3.2 or later)
|
||||||
- a C compiler (for system feature detection and the test helper binary)
|
- a curses implementation such as ncurses (headers and libraries)
|
||||||
- PCRE2 (headers and libraries) - optional, this will be downloaded if missing
|
- PCRE2 (headers and libraries) - a copy is included with fish
|
||||||
- gettext (headers and libraries) - optional, for translation support
|
- gettext (headers and libraries) - optional, for translation support
|
||||||
- an Internet connection, as other dependencies will be downloaded automatically
|
|
||||||
|
|
||||||
Sphinx is also optionally required to build the documentation from a
|
Sphinx is also optionally required to build the documentation from a
|
||||||
cloned git repository.
|
cloned git repository.
|
||||||
|
|
||||||
Additionally, running the full test suite requires Python 3, tmux, and the pexpect package.
|
Building from source (all platforms) - Makefile generator
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
Building from source with CMake
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Rather than building from source, consider using a packaged build for your platform. Using the
|
|
||||||
steps below makes fish difficult to uninstall or upgrade. Release packages are available from the
|
|
||||||
links above, and up-to-date `development builds of fish are available for many platforms
|
|
||||||
<https://github.com/fish-shell/fish-shell/wiki/Development-builds>`__
|
|
||||||
|
|
||||||
To install into ``/usr/local``, run:
|
To install into ``/usr/local``, run:
|
||||||
|
|
||||||
@@ -148,50 +167,49 @@ To install into ``/usr/local``, run:
|
|||||||
|
|
||||||
mkdir build; cd build
|
mkdir build; cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
cmake --build .
|
make
|
||||||
sudo cmake --install .
|
sudo make install
|
||||||
|
|
||||||
The install directory can be changed using the
|
The install directory can be changed using the
|
||||||
``-DCMAKE_INSTALL_PREFIX`` parameter for ``cmake``.
|
``-DCMAKE_INSTALL_PREFIX`` parameter for ``cmake``.
|
||||||
|
|
||||||
CMake Build options
|
Building from source (macOS) - Xcode
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
In addition to the normal CMake build options (like ``CMAKE_INSTALL_PREFIX``), fish's CMake build has some other options available to customize it.
|
.. code:: bash
|
||||||
|
|
||||||
- BUILD_DOCS=ON|OFF - whether to build the documentation. This is automatically set to OFF when Sphinx isn't installed.
|
mkdir build; cd build
|
||||||
- INSTALL_DOCS=ON|OFF - whether to install the docs. This is automatically set to on when BUILD_DOCS is or prebuilt documentation is available (like when building in-tree from a tarball).
|
cmake .. -G Xcode
|
||||||
- FISH_USE_SYSTEM_PCRE2=ON|OFF - whether to use an installed pcre2. This is normally autodetected.
|
|
||||||
- MAC_CODESIGN_ID=String|OFF - the codesign ID to use on Mac, or "OFF" to disable codesigning.
|
|
||||||
- WITH_GETTEXT=ON|OFF - whether to build with gettext support for translations.
|
|
||||||
- extra_functionsdir, extra_completionsdir and extra_confdir - to compile in an additional directory to be searched for functions, completions and configuration snippets
|
|
||||||
|
|
||||||
Building fish as self-installable (experimental)
|
An Xcode project will now be available in the ``build`` subdirectory.
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
You can open it with Xcode, or run the following to build and install in
|
||||||
|
``/usr/local``:
|
||||||
|
|
||||||
You can also build fish as a self-installing binary.
|
.. code:: bash
|
||||||
|
|
||||||
This will include all the datafiles like the included functions or web configuration tool in the main ``fish`` binary.
|
xcodebuild
|
||||||
|
xcodebuild -scheme install
|
||||||
|
|
||||||
On the first interactive run, and whenever it notices they are out of date, it will extract the datafiles to ~/.local/share/fish/install/ (currently, subject to change). You can do this manually by running ``fish --install``.
|
The install directory can be changed using the
|
||||||
|
``-DCMAKE_INSTALL_PREFIX`` parameter for ``cmake``.
|
||||||
|
|
||||||
To install fish as self-installable, just use ``cargo``, like::
|
Help, it didn’t build!
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
cargo install --path /path/to/fish # if you have a git clone
|
If fish reports that it could not find curses, try installing a curses
|
||||||
cargo install --git https://github.com/fish-shell/fish-shell --tag 4.0 # to build from git once 4.0 is released
|
development package and build again.
|
||||||
cargo install --git https://github.com/fish-shell/fish-shell # to build the current development snapshot without cloning
|
|
||||||
|
|
||||||
This will place the binaries in ``~/.cargo/bin/``, but you can place them wherever you want.
|
On Debian or Ubuntu you want:
|
||||||
|
|
||||||
This build won't have the HTML docs (``help`` will open the online version) or translations.
|
::
|
||||||
|
|
||||||
It will try to build the man pages with sphinx-build. If that is not available and you would like to include man pages, you need to install it and retrigger the build script, e.g. by setting FISH_BUILD_DOCS=1::
|
sudo apt-get install build-essential cmake ncurses-dev libncurses5-dev libpcre2-dev gettext
|
||||||
|
|
||||||
FISH_BUILD_DOCS=1 cargo install --path .
|
On RedHat, CentOS, or Amazon EC2:
|
||||||
|
|
||||||
Setting it to "0" disables the inclusion of man pages.
|
::
|
||||||
|
|
||||||
You can also link this build statically (but not against glibc) and move it to other computers.
|
sudo yum install ncurses-devel
|
||||||
|
|
||||||
Contributing Changes to the Code
|
Contributing Changes to the Code
|
||||||
--------------------------------
|
--------------------------------
|
||||||
@@ -203,13 +221,18 @@ Contact Us
|
|||||||
|
|
||||||
Questions, comments, rants and raves can be posted to the official fish
|
Questions, comments, rants and raves can be posted to the official fish
|
||||||
mailing list at https://lists.sourceforge.net/lists/listinfo/fish-users
|
mailing list at https://lists.sourceforge.net/lists/listinfo/fish-users
|
||||||
or join us on our `matrix
|
or join us on our `gitter.im
|
||||||
channel <https://matrix.to/#/#fish-shell:matrix.org>`__. Or use the `fish tag
|
channel <https://gitter.im/fish-shell/fish-shell>`__. Or use the `fish
|
||||||
on Unix & Linux Stackexchange <https://unix.stackexchange.com/questions/tagged/fish>`__.
|
tag on
|
||||||
There is also a fish tag on Stackoverflow, but it is typically a poor fit.
|
Stackoverflow <https://stackoverflow.com/questions/tagged/fish>`__ for
|
||||||
|
questions related to fish script and the `fish tag on
|
||||||
|
Superuser <https://superuser.com/questions/tagged/fish>`__ for all other
|
||||||
|
questions (e.g., customizing colors, changing key bindings).
|
||||||
|
|
||||||
Found a bug? Have an awesome idea? Please `open an
|
Found a bug? Have an awesome idea? Please `open an
|
||||||
issue <https://github.com/fish-shell/fish-shell/issues/new>`__.
|
issue <https://github.com/fish-shell/fish-shell/issues/new>`__.
|
||||||
|
|
||||||
.. |Build Status| image:: https://github.com/fish-shell/fish-shell/workflows/make%20test/badge.svg
|
.. |Build Status| image:: https://travis-ci.org/fish-shell/fish-shell.svg?branch=master
|
||||||
:target: https://github.com/fish-shell/fish-shell/actions
|
:target: https://travis-ci.org/fish-shell/fish-shell
|
||||||
|
.. |Try in browser| image:: https://cdn.rawgit.com/rootnroll/library/assets/try.svg
|
||||||
|
:target: https://rootnroll.com/d/fish-shell/
|
||||||
|
|||||||
@@ -1089,3 +1089,4 @@ alias alias1020='something --arg1020'
|
|||||||
alias alias1021='something --arg1021'
|
alias alias1021='something --arg1021'
|
||||||
alias alias1022='something --arg1022'
|
alias alias1022='something --arg1022'
|
||||||
alias alias1023='something --arg1023'
|
alias alias1023='something --arg1023'
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
for i in (seq 1000)
|
for i in (seq 2000)
|
||||||
command true
|
command true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
# Glob fish's source directory.
|
|
||||||
# This timing is bound to change if the repo does,
|
|
||||||
# so it's best to build two fishes, check out one version of the repo,
|
|
||||||
# and then run this script with both.
|
|
||||||
set -l dir (dirname (status current-filename))
|
|
||||||
# No repetitions, this is plenty slow enough.
|
|
||||||
echo $dir/../../**
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
set -l compdir (status dirname)/../../share/completions
|
|
||||||
cd $compdir
|
|
||||||
for file in *.fish
|
|
||||||
set -l bname (string replace -r '.fish$' '' -- $file)
|
|
||||||
if type -q $bname
|
|
||||||
source $file >/dev/null
|
|
||||||
if test $status -gt 0
|
|
||||||
echo FAILING FILE $file
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
for i in (seq 100000)
|
|
||||||
math $i + $i
|
|
||||||
end
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
set -l path (status dirname)
|
|
||||||
set -l fish (status fish-path)
|
|
||||||
for f in (seq 100)
|
|
||||||
echo $fish -n $path/aliases.fish
|
|
||||||
$fish -n $path/aliases.fish
|
|
||||||
end
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
printf (string repeat -n 200 \\x7f)%s\n (string repeat -n 2000 aaa\n)
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
for i in (seq 100000)
|
|
||||||
printf '%f\n' $i.$i
|
|
||||||
end
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
set -l tmp (mktemp)
|
|
||||||
string repeat -n 2000 >$tmp
|
|
||||||
for i in (seq 1000)
|
|
||||||
cat $tmp | read -l foo
|
|
||||||
end
|
|
||||||
|
|
||||||
true
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
for i in (seq 10000)
|
for i in (seq 1000)
|
||||||
echo $i
|
echo $i
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
for abc in (seq 100000)
|
|
||||||
set -l def
|
|
||||||
end
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
for i in (string repeat -n 100 \n)
|
|
||||||
string repeat -n 50000 a\n
|
|
||||||
end
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
for i in (seq 100000)
|
|
||||||
string match '*o' fooooooo
|
|
||||||
end
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
for i in (seq 100000)
|
|
||||||
string match -r '^.*$' fooooooo
|
|
||||||
end | string match -re o
|
|
||||||
@@ -1,43 +1,17 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if [ "$#" -gt 2 -o "$#" -eq 0 ]; then
|
if [ "$#" -ne 1 ]; then
|
||||||
echo "Usage: driver.sh /path/to/fish [/path/to/other/fish]"
|
echo "Usage: driver.sh /path/to/fish"
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
FISH_PATH=$1
|
FISH_PATH=$1
|
||||||
FISH2_PATH=$2
|
|
||||||
BENCHMARKS_DIR=$(dirname "$0")/benchmarks
|
BENCHMARKS_DIR=$(dirname "$0")/benchmarks
|
||||||
|
|
||||||
quote() {
|
|
||||||
# Single-quote the given string for a POSIX shell, except in common cases that don't need it.
|
|
||||||
printf %s "$1" |
|
|
||||||
sed "/[^[:alnum:]\/.-]/ {
|
|
||||||
s/'/'\\\''/g
|
|
||||||
s/^/'/
|
|
||||||
s/\$/'/
|
|
||||||
}"
|
|
||||||
}
|
|
||||||
|
|
||||||
for benchmark in "$BENCHMARKS_DIR"/*; do
|
for benchmark in "$BENCHMARKS_DIR"/*; do
|
||||||
basename "$benchmark"
|
basename "$benchmark"
|
||||||
# If we have hyperfine, use it first to warm up the cache
|
${FISH_PATH} --print-rusage-self "$benchmark" > /dev/null
|
||||||
if command -v hyperfine >/dev/null 2>&1; then
|
if command -v hyperfine >/dev/null 2>&1; then
|
||||||
cmd1="$(quote "${FISH_PATH}") --no-config $(quote "$benchmark")"
|
hyperfine "${FISH_PATH} $benchmark > /dev/null"
|
||||||
if [ -n "$FISH2_PATH" ]; then
|
|
||||||
cmd2="$(quote "${FISH2_PATH}") --no-config $(quote "$benchmark")"
|
|
||||||
hyperfine --warmup 3 "$cmd1" "$cmd2"
|
|
||||||
else
|
|
||||||
hyperfine --warmup 3 "$cmd1"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[ -n "$FISH2_PATH" ] && echo "$FISH_PATH"
|
|
||||||
"${FISH_PATH}" --print-rusage-self "$benchmark" > /dev/null
|
|
||||||
if [ -n "$FISH2_PATH" ]; then
|
|
||||||
echo "$FISH2_PATH"
|
|
||||||
"${FISH2_PATH}" --print-rusage-self "$benchmark" > /dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
413
build.rs
413
build.rs
@@ -1,413 +0,0 @@
|
|||||||
#![allow(clippy::uninlined_format_args)]
|
|
||||||
|
|
||||||
use rsconf::{LinkType, Target};
|
|
||||||
use std::env;
|
|
||||||
use std::error::Error;
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
setup_paths();
|
|
||||||
|
|
||||||
// Add our default to enable tools that don't go through CMake, like "cargo test" and the
|
|
||||||
// language server.
|
|
||||||
|
|
||||||
// FISH_BUILD_DIR is set by CMake, if we are using it.
|
|
||||||
// OUT_DIR is set by Cargo when the build script is running (not compiling)
|
|
||||||
let default_build_dir = env::var("OUT_DIR").unwrap();
|
|
||||||
let build_dir = option_env!("FISH_BUILD_DIR").unwrap_or(&default_build_dir);
|
|
||||||
let build_dir = std::fs::canonicalize(build_dir).unwrap();
|
|
||||||
let build_dir = build_dir.to_str().unwrap();
|
|
||||||
rsconf::set_env_value("FISH_BUILD_DIR", build_dir);
|
|
||||||
// We need to canonicalize (i.e. realpath) the manifest dir because we want to be able to
|
|
||||||
// compare it directly as a string at runtime.
|
|
||||||
rsconf::set_env_value(
|
|
||||||
"CARGO_MANIFEST_DIR",
|
|
||||||
std::fs::canonicalize(env!("CARGO_MANIFEST_DIR"))
|
|
||||||
.unwrap()
|
|
||||||
.as_path()
|
|
||||||
.to_str()
|
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Some build info
|
|
||||||
rsconf::set_env_value("BUILD_TARGET_TRIPLE", &env::var("TARGET").unwrap());
|
|
||||||
rsconf::set_env_value("BUILD_HOST_TRIPLE", &env::var("HOST").unwrap());
|
|
||||||
rsconf::set_env_value("BUILD_PROFILE", &env::var("PROFILE").unwrap());
|
|
||||||
|
|
||||||
let version = &get_version(&env::current_dir().unwrap());
|
|
||||||
// Per https://doc.rust-lang.org/cargo/reference/build-scripts.html#inputs-to-the-build-script,
|
|
||||||
// the source directory is the current working directory of the build script
|
|
||||||
rsconf::set_env_value("FISH_BUILD_VERSION", version);
|
|
||||||
|
|
||||||
std::env::set_var("FISH_BUILD_VERSION", version);
|
|
||||||
|
|
||||||
#[cfg(feature = "installable")]
|
|
||||||
#[cfg(not(clippy))]
|
|
||||||
{
|
|
||||||
let cman = std::fs::canonicalize(env!("CARGO_MANIFEST_DIR")).unwrap();
|
|
||||||
let targetman = cman.as_path().join("target").join("man");
|
|
||||||
build_man(&targetman);
|
|
||||||
}
|
|
||||||
rsconf::rebuild_if_path_changed("src/libc.c");
|
|
||||||
cc::Build::new()
|
|
||||||
.file("src/libc.c")
|
|
||||||
.include(build_dir)
|
|
||||||
.compile("flibc.a");
|
|
||||||
|
|
||||||
let mut build = cc::Build::new();
|
|
||||||
// Add to the default library search path
|
|
||||||
build.flag_if_supported("-L/usr/local/lib/");
|
|
||||||
rsconf::add_library_search_path("/usr/local/lib");
|
|
||||||
let mut target = Target::new_from(build).unwrap();
|
|
||||||
// Keep verbose mode on until we've ironed out rust build script stuff
|
|
||||||
target.set_verbose(true);
|
|
||||||
detect_cfgs(&mut target);
|
|
||||||
|
|
||||||
#[cfg(all(target_env = "gnu", target_feature = "crt-static"))]
|
|
||||||
compile_error!("Statically linking against glibc has unavoidable crashes and is unsupported. Use dynamic linking or link statically against musl.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check target system support for certain functionality dynamically when the build is invoked,
|
|
||||||
/// without their having to be explicitly enabled in the `cargo build --features xxx` invocation.
|
|
||||||
///
|
|
||||||
/// We are using [`rsconf::enable_cfg()`] instead of [`rsconf::enable_feature()`] as rust features
|
|
||||||
/// should be used for things that a user can/would reasonably enable or disable to tweak or coerce
|
|
||||||
/// behavior, but here we are testing for whether or not things are supported altogether.
|
|
||||||
///
|
|
||||||
/// This can be used to enable features that we check for and conditionally compile according to in
|
|
||||||
/// our own codebase, but [can't be used to pull in dependencies](0) even if they're gated (in
|
|
||||||
/// `Cargo.toml`) behind a feature we just enabled.
|
|
||||||
///
|
|
||||||
/// [0]: https://github.com/rust-lang/cargo/issues/5499
|
|
||||||
#[rustfmt::skip]
|
|
||||||
fn detect_cfgs(target: &mut Target) {
|
|
||||||
for (name, handler) in [
|
|
||||||
// Ignore the first entry, it just sets up the type inference. Model new entries after the
|
|
||||||
// second line.
|
|
||||||
(
|
|
||||||
"",
|
|
||||||
&(|_: &Target| Ok(false)) as &dyn Fn(&Target) -> Result<bool, Box<dyn Error>>,
|
|
||||||
),
|
|
||||||
("bsd", &detect_bsd),
|
|
||||||
("gettext", &have_gettext),
|
|
||||||
("small_main_stack", &has_small_stack),
|
|
||||||
// See if libc supports the thread-safe localeconv_l(3) alternative to localeconv(3).
|
|
||||||
("localeconv_l", &|target| {
|
|
||||||
Ok(target.has_symbol("localeconv_l"))
|
|
||||||
}),
|
|
||||||
("FISH_USE_POSIX_SPAWN", &|target| {
|
|
||||||
Ok(target.has_header("spawn.h"))
|
|
||||||
}),
|
|
||||||
("HAVE_PIPE2", &|target| {
|
|
||||||
Ok(target.has_symbol("pipe2"))
|
|
||||||
}),
|
|
||||||
("HAVE_EVENTFD", &|target| {
|
|
||||||
// FIXME: NetBSD 10 has eventfd, but the libc crate does not expose it.
|
|
||||||
if cfg!(target_os = "netbsd") {
|
|
||||||
Ok(false)
|
|
||||||
} else {
|
|
||||||
Ok(target.has_header("sys/eventfd.h"))
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
("HAVE_WAITSTATUS_SIGNAL_RET", &|target| {
|
|
||||||
Ok(target.r#if("WEXITSTATUS(0x007f) == 0x7f", &["sys/wait.h"]))
|
|
||||||
}),
|
|
||||||
] {
|
|
||||||
match handler(target) {
|
|
||||||
Err(e) => {
|
|
||||||
rsconf::warn!("{}: {}", name, e);
|
|
||||||
rsconf::declare_cfg(name, false);
|
|
||||||
},
|
|
||||||
Ok(enabled) => rsconf::declare_cfg(name, enabled),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Detect if we're being compiled for a BSD-derived OS, allowing targeting code conditionally with
|
|
||||||
/// `#[cfg(bsd)]`.
|
|
||||||
///
|
|
||||||
/// Rust offers fine-grained conditional compilation per-os for the popular operating systems, but
|
|
||||||
/// doesn't necessarily include less-popular forks nor does it group them into families more
|
|
||||||
/// specific than "windows" vs "unix" so we can conditionally compile code for BSD systems.
|
|
||||||
fn detect_bsd(_: &Target) -> Result<bool, Box<dyn Error>> {
|
|
||||||
// Instead of using `uname`, we can inspect the TARGET env variable set by Cargo. This lets us
|
|
||||||
// support cross-compilation scenarios.
|
|
||||||
let mut target = std::env::var("TARGET").unwrap();
|
|
||||||
if !target.chars().all(|c| c.is_ascii_lowercase()) {
|
|
||||||
target = target.to_ascii_lowercase();
|
|
||||||
}
|
|
||||||
let is_bsd = target.ends_with("bsd") || target.ends_with("dragonfly");
|
|
||||||
#[cfg(any(
|
|
||||||
target_os = "dragonfly",
|
|
||||||
target_os = "freebsd",
|
|
||||||
target_os = "netbsd",
|
|
||||||
target_os = "openbsd",
|
|
||||||
))]
|
|
||||||
assert!(is_bsd, "Target incorrectly detected as not BSD!");
|
|
||||||
Ok(is_bsd)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Detect libintl/gettext and its needed symbols to enable internationalization/localization
|
|
||||||
/// support.
|
|
||||||
fn have_gettext(target: &Target) -> Result<bool, Box<dyn Error>> {
|
|
||||||
// The following script correctly detects and links against gettext, but so long as we are using
|
|
||||||
// C++ and generate a static library linked into the C++ binary via CMake, we need to account
|
|
||||||
// for the CMake option WITH_GETTEXT being explicitly disabled.
|
|
||||||
rsconf::rebuild_if_env_changed("CMAKE_WITH_GETTEXT");
|
|
||||||
if let Some(with_gettext) = std::env::var_os("CMAKE_WITH_GETTEXT") {
|
|
||||||
if with_gettext.eq_ignore_ascii_case("0") {
|
|
||||||
return Ok(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// In order for fish to correctly operate, we need some way of notifying libintl to invalidate
|
|
||||||
// its localizations when the locale environment variables are modified. Without the libintl
|
|
||||||
// symbol _nl_msg_cat_cntr, we cannot use gettext even if we find it.
|
|
||||||
let mut libraries = Vec::new();
|
|
||||||
let mut found = 0;
|
|
||||||
let symbols = ["gettext", "_nl_msg_cat_cntr"];
|
|
||||||
for symbol in &symbols {
|
|
||||||
// Historically, libintl was required in order to use gettext() and co, but that
|
|
||||||
// functionality was subsumed by some versions of libc.
|
|
||||||
if target.has_symbol(symbol) {
|
|
||||||
// No need to link anything special for this symbol
|
|
||||||
found += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for library in ["intl", "gettextlib"] {
|
|
||||||
if target.has_symbol_in(symbol, &[library]) {
|
|
||||||
libraries.push(library);
|
|
||||||
found += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match found {
|
|
||||||
0 => Ok(false),
|
|
||||||
1 => Err(format!("gettext found but cannot be used without {}", symbols[1]).into()),
|
|
||||||
_ => {
|
|
||||||
rsconf::link_libraries(&libraries, LinkType::Default);
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Rust sets the stack size of newly created threads to a sane value, but is at at the mercy of the
|
|
||||||
/// OS when it comes to the size of the main stack. Some platforms we support default to a tiny
|
|
||||||
/// 0.5 MiB main stack, which is insufficient for fish's MAX_EVAL_DEPTH/MAX_STACK_DEPTH values.
|
|
||||||
///
|
|
||||||
/// 0.5 MiB is small enough that we'd have to drastically reduce MAX_STACK_DEPTH to less than 10, so
|
|
||||||
/// we instead use a workaround to increase the main thread size.
|
|
||||||
fn has_small_stack(_: &Target) -> Result<bool, Box<dyn Error>> {
|
|
||||||
#[cfg(not(any(target_os = "macos", target_os = "netbsd")))]
|
|
||||||
return Ok(false);
|
|
||||||
|
|
||||||
// NetBSD 10 also needs this but can't find pthread_get_stacksize_np.
|
|
||||||
#[cfg(target_os = "netbsd")]
|
|
||||||
return Ok(true);
|
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
{
|
|
||||||
use core::ffi;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
fn pthread_get_stacksize_np(thread: *const ffi::c_void) -> usize;
|
|
||||||
fn pthread_self() -> *const ffi::c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
// build.rs is executed on the main thread, so we are getting the main thread's stack size.
|
|
||||||
// Modern macOS versions default to an 8 MiB main stack but legacy OS X have a 0.5 MiB one.
|
|
||||||
let stack_size = unsafe { pthread_get_stacksize_np(pthread_self()) };
|
|
||||||
const TWO_MIB: usize = 2 * 1024 * 1024 - 1;
|
|
||||||
match stack_size {
|
|
||||||
0..=TWO_MIB => Ok(true),
|
|
||||||
_ => Ok(false),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup_paths() {
|
|
||||||
fn get_path(name: &str, default: &str, onvar: &Path) -> PathBuf {
|
|
||||||
let mut var = PathBuf::from(env::var(name).unwrap_or(default.to_string()));
|
|
||||||
if var.is_relative() {
|
|
||||||
var = onvar.join(var);
|
|
||||||
}
|
|
||||||
var
|
|
||||||
}
|
|
||||||
|
|
||||||
let (prefix_from_home, prefix) = if let Ok(pre) = env::var("PREFIX") {
|
|
||||||
(false, PathBuf::from(pre))
|
|
||||||
} else {
|
|
||||||
(true, PathBuf::from(".local/"))
|
|
||||||
};
|
|
||||||
|
|
||||||
// If someone gives us a $PREFIX, we need it to be absolute.
|
|
||||||
// Otherwise we would try to get it from $HOME and that won't really work.
|
|
||||||
if !prefix_from_home && prefix.is_relative() {
|
|
||||||
panic!("Can't have relative prefix");
|
|
||||||
}
|
|
||||||
|
|
||||||
rsconf::rebuild_if_env_changed("PREFIX");
|
|
||||||
rsconf::set_env_value("PREFIX", prefix.to_str().unwrap());
|
|
||||||
|
|
||||||
let datadir = get_path("DATADIR", "share/", &prefix);
|
|
||||||
rsconf::set_env_value("DATADIR", datadir.to_str().unwrap());
|
|
||||||
rsconf::rebuild_if_env_changed("DATADIR");
|
|
||||||
|
|
||||||
let datadir_subdir = if prefix_from_home {
|
|
||||||
"fish/install"
|
|
||||||
} else {
|
|
||||||
"fish"
|
|
||||||
};
|
|
||||||
rsconf::set_env_value("DATADIR_SUBDIR", datadir_subdir);
|
|
||||||
|
|
||||||
let bindir = get_path("BINDIR", "bin/", &prefix);
|
|
||||||
rsconf::set_env_value("BINDIR", bindir.to_str().unwrap());
|
|
||||||
rsconf::rebuild_if_env_changed("BINDIR");
|
|
||||||
|
|
||||||
let sysconfdir = get_path(
|
|
||||||
"SYSCONFDIR",
|
|
||||||
// If we get our prefix from $HOME, we should use the system's /etc/
|
|
||||||
// ~/.local/share/etc/ makes no sense
|
|
||||||
if prefix_from_home { "/etc/" } else { "etc/" },
|
|
||||||
&datadir,
|
|
||||||
);
|
|
||||||
rsconf::set_env_value("SYSCONFDIR", sysconfdir.to_str().unwrap());
|
|
||||||
rsconf::rebuild_if_env_changed("SYSCONFDIR");
|
|
||||||
|
|
||||||
let localedir = get_path("LOCALEDIR", "locale/", &datadir);
|
|
||||||
rsconf::set_env_value("LOCALEDIR", localedir.to_str().unwrap());
|
|
||||||
rsconf::rebuild_if_env_changed("LOCALEDIR");
|
|
||||||
|
|
||||||
let docdir = get_path("DOCDIR", "doc/fish", &datadir);
|
|
||||||
rsconf::set_env_value("DOCDIR", docdir.to_str().unwrap());
|
|
||||||
rsconf::rebuild_if_env_changed("DOCDIR");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_version(src_dir: &Path) -> String {
|
|
||||||
use std::fs::read_to_string;
|
|
||||||
use std::process::Command;
|
|
||||||
|
|
||||||
if let Ok(var) = std::env::var("FISH_BUILD_VERSION") {
|
|
||||||
return var;
|
|
||||||
}
|
|
||||||
|
|
||||||
let path = src_dir.join("version");
|
|
||||||
if let Ok(strver) = read_to_string(path) {
|
|
||||||
return strver.to_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
let args = &["describe", "--always", "--dirty=-dirty"];
|
|
||||||
if let Ok(output) = Command::new("git").args(args).output() {
|
|
||||||
let rev = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
|
||||||
if !rev.is_empty() {
|
|
||||||
// If it contains a ".", we have a proper version like "3.7",
|
|
||||||
// or "23.2.1-1234-gfab1234"
|
|
||||||
if rev.contains('.') {
|
|
||||||
return rev;
|
|
||||||
}
|
|
||||||
// If it doesn't, we probably got *just* the commit SHA,
|
|
||||||
// like "f1242abcdef".
|
|
||||||
// So we prepend the crate version so it at least looks like
|
|
||||||
// "3.8-gf1242abcdef"
|
|
||||||
// This lacks the commit *distance*, but that can't be helped without
|
|
||||||
// tags.
|
|
||||||
let version = env!("CARGO_PKG_VERSION").to_owned();
|
|
||||||
return version + "-g" + &rev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// git did not tell us a SHA either because it isn't installed,
|
|
||||||
// or because it refused (safe.directory applies to `git describe`!)
|
|
||||||
// So we read the SHA ourselves.
|
|
||||||
fn get_git_hash() -> Result<String, Box<dyn std::error::Error>> {
|
|
||||||
let gitdir = Path::new(env!("CARGO_MANIFEST_DIR")).join(".git");
|
|
||||||
|
|
||||||
// .git/HEAD contains ref: refs/heads/branch
|
|
||||||
let headpath = gitdir.join("HEAD");
|
|
||||||
let headstr = read_to_string(headpath)?;
|
|
||||||
let headref = headstr.split(' ').collect::<Vec<_>>()[1].trim();
|
|
||||||
|
|
||||||
// .git/refs/heads/branch contains the SHA
|
|
||||||
let refpath = gitdir.join(headref);
|
|
||||||
// Shorten to 9 characters (what git describe does currently)
|
|
||||||
let refstr = &read_to_string(refpath)?[0..9];
|
|
||||||
let refstr = refstr.trim();
|
|
||||||
|
|
||||||
let version = env!("CARGO_PKG_VERSION").to_owned();
|
|
||||||
Ok(version + "-g" + refstr)
|
|
||||||
}
|
|
||||||
|
|
||||||
get_git_hash().expect("Could not get a version. Either set $FISH_BUILD_VERSION or install git.")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "installable")]
|
|
||||||
// disable clippy because otherwise it would panic without sphinx
|
|
||||||
#[cfg(not(clippy))]
|
|
||||||
fn build_man(build_dir: &Path) {
|
|
||||||
use std::process::Command;
|
|
||||||
let mandir = build_dir;
|
|
||||||
let sec1dir = mandir.join("man1");
|
|
||||||
let docsrc_path = std::fs::canonicalize(env!("CARGO_MANIFEST_DIR"))
|
|
||||||
.unwrap()
|
|
||||||
.as_path()
|
|
||||||
.join("doc_src");
|
|
||||||
let docsrc = docsrc_path.to_str().unwrap();
|
|
||||||
let args = &[
|
|
||||||
"-j",
|
|
||||||
"auto",
|
|
||||||
"-q",
|
|
||||||
"-b",
|
|
||||||
"man",
|
|
||||||
"-c",
|
|
||||||
docsrc,
|
|
||||||
// doctree path - put this *above* the man1 dir to exclude it.
|
|
||||||
// this is ~6M
|
|
||||||
"-d",
|
|
||||||
mandir.to_str().unwrap(),
|
|
||||||
docsrc,
|
|
||||||
sec1dir.to_str().unwrap(),
|
|
||||||
];
|
|
||||||
let _ = std::fs::create_dir_all(sec1dir.to_str().unwrap());
|
|
||||||
|
|
||||||
rsconf::rebuild_if_env_changed("FISH_BUILD_DOCS");
|
|
||||||
if env::var("FISH_BUILD_DOCS") == Ok("0".to_string()) {
|
|
||||||
println!("cargo:warning=Skipping man pages because $FISH_BUILD_DOCS is set to 0");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We run sphinx to build the man pages.
|
|
||||||
// Every error here is fatal so cargo doesn't cache the result
|
|
||||||
// - if we skipped the docs with sphinx not installed, installing it would not then build the docs.
|
|
||||||
// That means you need to explicitly set $FISH_BUILD_DOCS=0 (`FISH_BUILD_DOCS=0 cargo install --path .`),
|
|
||||||
// which is unfortunate - but the docs are pretty important because they're also used for --help.
|
|
||||||
match Command::new("sphinx-build").args(args).spawn() {
|
|
||||||
Err(x) if x.kind() == std::io::ErrorKind::NotFound => {
|
|
||||||
if env::var("FISH_BUILD_DOCS") == Ok("1".to_string()) {
|
|
||||||
panic!("Could not find sphinx-build to build man pages.\nInstall sphinx or disable building the docs by setting $FISH_BUILD_DOCS=0.");
|
|
||||||
}
|
|
||||||
println!("cargo:warning=Cannot find sphinx-build to build man pages.");
|
|
||||||
println!("cargo:warning=If you install it now you need to run `cargo clean` and rebuild, or set $FISH_BUILD_DOCS=1 explicitly.");
|
|
||||||
}
|
|
||||||
Err(x) => {
|
|
||||||
// Another error - permissions wrong etc
|
|
||||||
panic!("Error starting sphinx-build to build man pages: {:?}", x);
|
|
||||||
}
|
|
||||||
Ok(mut x) => match x.wait() {
|
|
||||||
Err(err) => {
|
|
||||||
panic!(
|
|
||||||
"Error waiting for sphinx-build to build man pages: {:?}",
|
|
||||||
err
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Ok(out) => {
|
|
||||||
if out.success() {
|
|
||||||
// Success!
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
panic!("sphinx-build failed to build the man pages.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
3
build_tools/cppcheck.sh
Executable file
3
build_tools/cppcheck.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/local/bin/fish
|
||||||
|
|
||||||
|
cppcheck --enable=all --std=posix --quiet ./src/
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#!/usr/bin/env fish
|
|
||||||
# Build a list of all sections in the html sphinx docs, separately by page,
|
|
||||||
# so it can be added to share/functions/help.fish
|
|
||||||
# Use like
|
|
||||||
# fish extract_help_sections.fish user_doc/html/{fish_for_bash_users.html,faq.html,interactive.html,language.html,tutorial.html}
|
|
||||||
# TODO: Currently `help` uses variable names we can't generate, so it needs to be touched up manually.
|
|
||||||
# Also this could easily be broken by changes in sphinx, ideally we'd have a way to let it print the section titles.
|
|
||||||
#
|
|
||||||
|
|
||||||
for file in $argv
|
|
||||||
set -l varname (string replace -r '.*/(.*).html' '$1' -- $file | string escape --style=var)pages
|
|
||||||
# Technically we can use any id in the document as an anchor, but listing them all is probably too much.
|
|
||||||
# Sphinx stores section titles (in a slug-ized form) in the id,
|
|
||||||
# and stores explicit section links in a `span` tag like
|
|
||||||
# `<span id="identifiers"></span>`
|
|
||||||
# We extract both separately.
|
|
||||||
set -l sections (string replace -rf '.*class="headerlink" href="#([^"]*)".*' '$1' <$file)
|
|
||||||
# Sections titled "id5" and such are internal cruft and shouldn't be offered.
|
|
||||||
set -a sections (string replace -rf '.*span id="([^"]*)".*' '$1' <$file | string match -rv 'id\d+')
|
|
||||||
|
|
||||||
set sections (printf '%s\n' $sections | sort -u)
|
|
||||||
echo set -l $varname $sections
|
|
||||||
end
|
|
||||||
112
build_tools/find_globals.fish
Executable file
112
build_tools/find_globals.fish
Executable file
@@ -0,0 +1,112 @@
|
|||||||
|
#!/usr/bin/env fish
|
||||||
|
|
||||||
|
# Finds global variables by parsing the output of 'nm'
|
||||||
|
# for object files in this directory.
|
||||||
|
# This was written for macOS nm.
|
||||||
|
|
||||||
|
set -l FISH_SOURCE_DIR $argv[1]
|
||||||
|
if not test -d "$FISH_SOURCE_DIR"
|
||||||
|
echo "FISH_SOURCE_DIR not given"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
set -g whitelist \
|
||||||
|
# unclear what this is \
|
||||||
|
l_constinit \
|
||||||
|
# hacks to work around missing ncurses strings on mac \
|
||||||
|
sitm_esc ritm_esc dim_esc \
|
||||||
|
|
||||||
|
|
||||||
|
# In our nm regex, we are interested in data (dD) and bss (bB) segments.
|
||||||
|
set -g nm_regex '^([^ ]+) ([dDbB])'
|
||||||
|
|
||||||
|
set -l total_globals 0
|
||||||
|
set -l boring_files \
|
||||||
|
fish_key_reader.cpp.o \
|
||||||
|
fish_tests.cpp.o \
|
||||||
|
fish_indent.cpp.o \
|
||||||
|
|
||||||
|
|
||||||
|
# return if we should ignore the given symbol name
|
||||||
|
function should_ignore
|
||||||
|
set -l symname $argv[1]
|
||||||
|
string match -q '*guard variable for*' $symname
|
||||||
|
and return 0
|
||||||
|
contains $symname $whitelist
|
||||||
|
and return 0
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# echo a cleaned-up symbol name, e.g. replacing template gunk
|
||||||
|
function cleanup_syname
|
||||||
|
set -l symname $argv[1]
|
||||||
|
set symname (string replace --all 'std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >' 'wcstring' $symname)
|
||||||
|
set symname (string replace --all 'std::__1::vector<wcstring, std::__1::allocator<wcstring > >' 'wcstring_list_t' $symname)
|
||||||
|
echo $symname
|
||||||
|
end
|
||||||
|
|
||||||
|
# Output the declaration for a symbol name in a given file.
|
||||||
|
function print_decl -a FISH_SOURCE_DIR objfile symname
|
||||||
|
set -l varname (string split '::' $symname)[-1]
|
||||||
|
set -l srcfile (basename $objfile .o)
|
||||||
|
set -l srcpath $FISH_SOURCE_DIR/src/$srcfile
|
||||||
|
|
||||||
|
# A leading underscore indicates a global, strip it.
|
||||||
|
set varname (string replace --regex '^_' '' $varname)
|
||||||
|
|
||||||
|
if not test -f "$srcpath"
|
||||||
|
echo "Could not find $srcpath"
|
||||||
|
end
|
||||||
|
# Guess the variable as the first usage of the name.
|
||||||
|
# Strip everything after the first =.
|
||||||
|
set -l vardecl (egrep -m 1 " $varname\\b" $srcpath | cut -f -1 -d '=' | string trim)
|
||||||
|
if test -z "$vardecl"
|
||||||
|
echo "COULD_NOT_FIND_$varname"
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
echo $vardecl
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
# Return if a variable declaration is "thread safe".
|
||||||
|
function decl_is_threadsafe
|
||||||
|
set -l vardecl $argv[1]
|
||||||
|
# decls starting with 'const ' or containing ' const ' are assumed safe.
|
||||||
|
string match -q --regex '(^|\\*| )const ' $vardecl
|
||||||
|
and return 0
|
||||||
|
|
||||||
|
# Ordinary types indicating a safe variable.
|
||||||
|
set -l safes relaxed_atomic_bool_t std::mutex std::condition_variable std::once_flag sig_atomic_t
|
||||||
|
for safe in $safes
|
||||||
|
string match -q "*$safe*" $vardecl
|
||||||
|
and return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
# Template types indicate a safe variable.
|
||||||
|
set safes owning_lock mainthread_t std::atomic relaxed_atomic_t latch_t
|
||||||
|
for safe in $safes
|
||||||
|
string match -q "*$safe<*" $vardecl
|
||||||
|
and return 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for file in ./**.o
|
||||||
|
set -l filename (basename $file)
|
||||||
|
# Skip boring files.
|
||||||
|
contains $filename $boring_files
|
||||||
|
and continue
|
||||||
|
for line in (nm -p -P -U $file | egrep $nm_regex)
|
||||||
|
set -l matches (string match --regex $nm_regex -- $line)
|
||||||
|
or continue
|
||||||
|
set -l symname (cleanup_syname (echo $matches[2] | c++filt))
|
||||||
|
should_ignore $symname
|
||||||
|
and continue
|
||||||
|
set -l vardecl (print_decl $FISH_SOURCE_DIR $filename $symname)
|
||||||
|
decl_is_threadsafe $vardecl
|
||||||
|
and continue
|
||||||
|
echo $filename $symname $matches[3] ":" $vardecl
|
||||||
|
set total_globals (math $total_globals + 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
echo "Total: $total_globals"
|
||||||
@@ -1,40 +1,18 @@
|
|||||||
#!/usr/bin/env fish
|
#!/usr/bin/env fish
|
||||||
#
|
#
|
||||||
# Tool to generate messages.pot
|
# Tool to generate messages.pot
|
||||||
|
# Extended to replace the old Makefile rule which did not port easily to CMak
|
||||||
|
|
||||||
# Create temporary directory for these operations. OS X `mktemp` is somewhat restricted, so this block
|
# This script was originally motivated to work around a quirk (or bug depending on your viewpoint)
|
||||||
# works around that - based on share/functions/funced.fish.
|
# of the xgettext command. See https://lists.gnu.org/archive/html/bug-gettext/2014-11/msg00006.html.
|
||||||
set -q TMPDIR
|
# However, it turns out that even if that quirk did not exist we would still need something like
|
||||||
or set -l TMPDIR /tmp
|
# this script to properly extract descriptions. That's because we need to normalize the strings to
|
||||||
set -l tmpdir (mktemp -d $TMPDIR/fish.XXXXXX)
|
# a format that xgettext will handle correctly. Also, `xgettext -LShell` doesn't correctly extract
|
||||||
or exit 1
|
# all the strings we want translated. So we extract and normalize all such strings into a format
|
||||||
|
# that `xgettext` can handle.
|
||||||
|
|
||||||
# This is a gigantic crime.
|
# Start with the C++ source
|
||||||
# xgettext still does not support rust *at all*, so we use cargo-expand to get all our wgettext invocations.
|
xgettext -k -k_ -kN_ -LC++ --no-wrap -o messages.pot src/*.cpp src/*.h
|
||||||
set -l expanded (cargo expand --lib; for f in fish{,_indent,_key_reader}; cargo expand --bin $f; end)
|
|
||||||
|
|
||||||
# Extract any gettext call
|
|
||||||
set -l strs (printf '%s\n' $expanded | grep -A1 wgettext_static_str |
|
|
||||||
grep 'widestring::internals::core::primitive::str =' |
|
|
||||||
string match -rg '"(.*)"' | string match -rv '^%ls$|^$' |
|
|
||||||
# escaping difference between gettext and cargo-expand: single-quotes
|
|
||||||
string replace -a "\'" "'" | sort -u)
|
|
||||||
|
|
||||||
# Extract any constants
|
|
||||||
set -a strs (string match -rv 'BUILD_VERSION:|PACKAGE_NAME' -- $expanded |
|
|
||||||
string match -rg 'const [A-Z_]*: &str = "(.*)"' | string replace -a "\'" "'")
|
|
||||||
|
|
||||||
# We construct messages.pot ourselves instead of forcing this into msgmerge or whatever.
|
|
||||||
# The escaping so far works out okay.
|
|
||||||
for str in $strs
|
|
||||||
# grep -P needed for string escape to be compatible (PCRE-style),
|
|
||||||
# -H gives the filename, -n the line number.
|
|
||||||
# If you want to run this on non-GNU grep: Don't.
|
|
||||||
echo "#:" (grep -PHn -r -- (string escape --style=regex -- $str) src/ |
|
|
||||||
head -n1 | string replace -r ':\s.*' '')
|
|
||||||
echo "msgid \"$str\""
|
|
||||||
echo 'msgstr ""'
|
|
||||||
end >messages.pot
|
|
||||||
|
|
||||||
# This regex handles descriptions for `complete` and `function` statements. These messages are not
|
# This regex handles descriptions for `complete` and `function` statements. These messages are not
|
||||||
# particularly important to translate. Hence the "implicit" label.
|
# particularly important to translate. Hence the "implicit" label.
|
||||||
@@ -44,25 +22,34 @@ set -l implicit_regex '(?:^| +)(?:complete|function).*? (?:-d|--description) (([
|
|||||||
# than messages which should be implicitly translated.
|
# than messages which should be implicitly translated.
|
||||||
set -l explicit_regex '.*\( *_ (([\'"]).+?(?<!\\\\)\\2) *\).*'
|
set -l explicit_regex '.*\( *_ (([\'"]).+?(?<!\\\\)\\2) *\).*'
|
||||||
|
|
||||||
mkdir -p $tmpdir/implicit/share/completions $tmpdir/implicit/share/functions
|
rm -r /tmp/fish
|
||||||
mkdir -p $tmpdir/explicit/share/completions $tmpdir/explicit/share/functions
|
|
||||||
|
mkdir -p /tmp/fish/implicit/share/completions /tmp/fish/implicit/share/functions
|
||||||
|
mkdir -p /tmp/fish/explicit/share/completions /tmp/fish/explicit/share/functions
|
||||||
|
|
||||||
for f in share/config.fish share/completions/*.fish share/functions/*.fish
|
for f in share/config.fish share/completions/*.fish share/functions/*.fish
|
||||||
# Extract explicit attempts to translate a message. That is, those that are of the form
|
# Extract explicit attempts to translate a message. That is, those that are of the form
|
||||||
# `(_ "message")`.
|
# `(_ "message")`.
|
||||||
string replace --filter --regex $explicit_regex '$1' <$f | string unescape \
|
string replace --filter --regex $explicit_regex 'echo $1' <$f | fish >/tmp/fish/explicit/$f.tmp ^/dev/null
|
||||||
| string replace --all '"' '\\"' | string replace -r '(.*)' 'N_ "$1"' >$tmpdir/explicit/$f
|
while read description
|
||||||
|
echo 'N_ "'(string replace --all '"' '\\"' -- $description)'"'
|
||||||
|
end </tmp/fish/explicit/$f.tmp >/tmp/fish/explicit/$f
|
||||||
|
rm /tmp/fish/explicit/$f.tmp
|
||||||
|
|
||||||
# Handle `complete` / `function` description messages. The `| fish` is subtle. It basically
|
# Handle `complete` / `function` description messages. The `| fish` is subtle. It basically
|
||||||
# avoids the need to use `source` with a command substitution that could affect the current
|
# avoids the need to use `source` with a command substitution that could affect the current
|
||||||
# shell.
|
# shell.
|
||||||
string replace --filter --regex $implicit_regex '$1' <$f | string unescape \
|
string replace --filter --regex $implicit_regex 'echo $1' <$f | fish >/tmp/fish/implicit/$f.tmp ^/dev/null
|
||||||
| string replace --all '"' '\\"' | string replace -r '(.*)' 'N_ "$1"' >$tmpdir/implicit/$f
|
while read description
|
||||||
|
# We don't use `string escape` as shown in the next comment because it produces output that
|
||||||
|
# is not parsed correctly by xgettext. Instead just escape double-quotes and quote the
|
||||||
|
# resulting string.
|
||||||
|
echo 'N_ "'(string replace --all '"' '\\"' -- $description)'"'
|
||||||
|
end </tmp/fish/implicit/$f.tmp >/tmp/fish/implicit/$f
|
||||||
|
rm /tmp/fish/implicit/$f.tmp
|
||||||
end
|
end
|
||||||
|
|
||||||
xgettext -j -k -kN_ -LShell --from-code=UTF-8 -cDescription --no-wrap -o messages.pot $tmpdir/{ex,im}plicit/share/*/*.fish
|
xgettext -j -k -kN_ -LShell --from-code=UTF-8 -cDescription --no-wrap -o messages.pot /tmp/fish/explicit/share/*/*.fish
|
||||||
|
xgettext -j -k -kN_ -LShell --from-code=UTF-8 -cDescription --no-wrap -o messages.pot /tmp/fish/implicit/share/*/*.fish
|
||||||
|
|
||||||
# Remove the tmpdir from the location to avoid churn
|
rm -r /tmp/fish
|
||||||
sed -i 's_^#: /.*/share/_#: share/_' messages.pot
|
|
||||||
|
|
||||||
rm -r $tmpdir
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/usr/bin/env sh
|
||||||
# Originally from the git sources (GIT-VERSION-GEN)
|
# Originally from the git sources (GIT-VERSION-GEN)
|
||||||
# Presumably (C) Junio C Hamano <junkio@cox.net>
|
# Presumably (C) Junio C Hamano <junkio@cox.net>
|
||||||
# Reused under GPL v2.0
|
# Reused under GPL v2.0
|
||||||
@@ -9,26 +9,14 @@ set -e
|
|||||||
# Find the fish directory as two levels up from script directory.
|
# Find the fish directory as two levels up from script directory.
|
||||||
FISH_BASE_DIR="$( cd "$( dirname "$( dirname "$0" )" )" && pwd )"
|
FISH_BASE_DIR="$( cd "$( dirname "$( dirname "$0" )" )" && pwd )"
|
||||||
DEF_VER=unknown
|
DEF_VER=unknown
|
||||||
git_permission_failed=0
|
|
||||||
|
|
||||||
# First see if there is a version file (included in release tarballs),
|
# First see if there is a version file (included in release tarballs),
|
||||||
# then try git-describe, then default.
|
# then try git-describe, then default.
|
||||||
if test -f version
|
if test -f version
|
||||||
then
|
then
|
||||||
VN=$(cat version) || VN="$DEF_VER"
|
VN=$(cat version) || VN="$DEF_VER"
|
||||||
else
|
elif ! VN=$(git -C "$FISH_BASE_DIR" describe --always --dirty 2>/dev/null); then
|
||||||
if VN=$(git -C "$FISH_BASE_DIR" describe --always --dirty 2>/dev/null); then
|
VN="$DEF_VER"
|
||||||
:
|
|
||||||
else
|
|
||||||
if test $? = 128; then
|
|
||||||
# Current git versions return status 128
|
|
||||||
# when run in a repo owned by another user.
|
|
||||||
# Even for describe and everything.
|
|
||||||
# This occurs for `sudo make install`.
|
|
||||||
git_permission_failed=1
|
|
||||||
fi
|
|
||||||
VN="$DEF_VER"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If the first param is --stdout, then output to stdout and exit.
|
# If the first param is --stdout, then output to stdout and exit.
|
||||||
@@ -40,29 +28,20 @@ fi
|
|||||||
|
|
||||||
# Set the output directory as either the first param or cwd.
|
# Set the output directory as either the first param or cwd.
|
||||||
test -n "$1" && OUTPUT_DIR=$1/ || OUTPUT_DIR=
|
test -n "$1" && OUTPUT_DIR=$1/ || OUTPUT_DIR=
|
||||||
FBVF="${OUTPUT_DIR}FISH-BUILD-VERSION-FILE"
|
FBVF=${OUTPUT_DIR}FISH-BUILD-VERSION-FILE
|
||||||
|
|
||||||
if test "$VN" = unknown && test -r "$FBVF" && test "$git_permission_failed" = 1
|
if test -r $FBVF
|
||||||
then
|
then
|
||||||
# HACK: Git failed, so we keep the current version file.
|
VC=$(grep -v '^#' $FBVF | tr -d '"' | sed -e 's/^FISH_BUILD_VERSION=//')
|
||||||
# This helps in case you built fish as a normal user
|
|
||||||
# and then try to `sudo make install` it.
|
|
||||||
date +%s > ${OUTPUT_DIR}fish-build-version-witness.txt
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test -r "$FBVF"
|
|
||||||
then
|
|
||||||
VC=$(cat "$FBVF")
|
|
||||||
else
|
else
|
||||||
VC="unset"
|
VC="unset"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Maybe output the FBVF
|
# Maybe output the FBVF
|
||||||
# It looks like "2.7.1-621-ga2f065e6"
|
# It looks like FISH_BUILD_VERSION="2.7.1-621-ga2f065e6"
|
||||||
test "$VN" = "$VC" || {
|
test "$VN" = "$VC" || {
|
||||||
echo >&2 "$VN"
|
echo >&2 "FISH_BUILD_VERSION=$VN"
|
||||||
echo "$VN" >"$FBVF"
|
echo "FISH_BUILD_VERSION=\"$VN\"" >${FBVF}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Output the fish-build-version-witness.txt
|
# Output the fish-build-version-witness.txt
|
||||||
|
|||||||
28
build_tools/iwyu.linux.imp
Normal file
28
build_tools/iwyu.linux.imp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Map file for the include-what-you-use tool on Linux.
|
||||||
|
[
|
||||||
|
{ include: ["<bits/fcntl-linux.h>", "private", "<fcntl.h>", "public"] },
|
||||||
|
{ include: ["<bits/mman-linux.h>", "private", "<sys/mman.h>", "public"] },
|
||||||
|
{ include: ["<bits/socket-linux.h>", "private", "<sys/socket.h>", "public"] },
|
||||||
|
{ include: ["<bits/socket_type.h>", "private", "<sys/socket.h>", "public"] },
|
||||||
|
{ include: ["<bits/local_lim.h>", "private", "<limits.h>", "public"] },
|
||||||
|
{ include: ["<tr1/memory>", "public", "<memory>", "public"] },
|
||||||
|
{ include: ["<features.h>", "public", "<stdio.h>", "public"] },
|
||||||
|
{ include: ["<features.h>", "public", "<stddef.h>", "public"] },
|
||||||
|
{ include: ["<features.h>", "public", "<unistd.h>", "public"] },
|
||||||
|
|
||||||
|
{ symbol: ["size_t", "private", "<unistd.h>", "public"] },
|
||||||
|
{ symbol: ["size_t", "private", "<stddef.h>", "public"] },
|
||||||
|
{ symbol: ["size_t", "private", "<stdlib.h>", "public"] },
|
||||||
|
{ symbol: ["intmax_t", "private", "<sys/stdint.h>", "public"] },
|
||||||
|
{ symbol: ["intmax_t", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ symbol: ["uint32_t", "private", "<sys/stdint.h>", "public"] },
|
||||||
|
{ symbol: ["uint32_t", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ symbol: ["uint64_t", "private", "<sys/stdint.h>", "public"] },
|
||||||
|
{ symbol: ["uint64_t", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ symbol: ["uintmax_t", "private", "<sys/stdint.h>", "public"] },
|
||||||
|
{ symbol: ["uintmax_t", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ symbol: ["clock_gettime", "private", "<sys/time.h>", "public"] },
|
||||||
|
{ symbol: ["timespec", "private", "<sys/time.h>", "public"] },
|
||||||
|
{ symbol: ["memset", "private", "<string.h>", "public"] },
|
||||||
|
{ symbol: ["strerror", "private", "<string.h>", "public"] },
|
||||||
|
]
|
||||||
109
build_tools/iwyu.osx.imp
Normal file
109
build_tools/iwyu.osx.imp
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# Map file for the include-what-you-use tool on OS X. For some reason
|
||||||
|
# the version installed by HomeBrew doesn't have useful mappings for the
|
||||||
|
# system provided headers. This also has mappings for FreeBSD.
|
||||||
|
[
|
||||||
|
{ include: ["<sys/_pthread/_pthread_once_t.h>", "private", "<pthread.h>", "public"] },
|
||||||
|
{ include: ["<sys/_pthread/_pthread_mutex_t.h>", "private", "<pthread.h>", "public"] },
|
||||||
|
{ include: ["<sys/_pthread/_pthread_rwlock_t.h>", "private", "<pthread.h>", "public"] },
|
||||||
|
{ include: ["<sys/_pthread/_pthread_mutexattr_t.h>", "private", "<pthread.h>", "public"] },
|
||||||
|
{ include: ["<sys/_pthread/_pthread_cond_t.h>", "private", "<pthread.h>", "public"] },
|
||||||
|
{ include: ["<sys/_pthread/_pthread_t.h>", "private", "<pthread.h>", "public"] },
|
||||||
|
{ include: ["<sys/_pthread/_pthread_key_t.h>", "private", "<pthread.h>", "public"] },
|
||||||
|
{ include: ["<sys/_pthreadtypes.h>", "private", "<pthread.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_posix_vdisable.h>", "private", "<pthread.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_time_t.h>", "private", "<time.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_suseconds_t.h>", "private", "<time.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_suseconds_t.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/errno.h>", "private", "<errno.h>", "public"] },
|
||||||
|
{ include: ["<sys/unistd.h>", "private", "<unistd.h>", "public"] },
|
||||||
|
{ include: ["<_wctype.h>", "private", "<wctype.h>", "public"] },
|
||||||
|
{ include: ["<sys/fcntl.h>", "private", "<fcntl.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_seek_set.h>", "private", "<fcntl.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_mbstate_t.h>", "private", "<wchar.h>", "public"] },
|
||||||
|
{ include: ["<iosfwd>", "private", "<string>", "public"] },
|
||||||
|
{ include: ["<sys/_stdint.h>", "private", "<stdint.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_s_ifmt.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_size_t.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_size_t.h>", "private", "<stdlib.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_mode_t.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_pid_t.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_fd_def.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_fd_isset.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_fd_set.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_fd_zero.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_timeval.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_uid_t.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<_types/_intmax_t.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<_types/_uintmax_t.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<_types/_uint8_t.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_int32_t.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<_types/_uint64_t.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_uintptr_t.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_dev_t.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_ino_t.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_va_list.h>", "private", "<stdio.h>", "public"] },
|
||||||
|
{ include: ["<__functional_base>", "private", "<memory>", "public"] },
|
||||||
|
{ include: ["<__functional_base>", "private", "<vector>", "public"] },
|
||||||
|
{ include: ["<__functional_base>", "private", "<string>", "public"] },
|
||||||
|
{ include: ["<__tree>", "private", "<map>", "public"] },
|
||||||
|
{ include: ["<__tree>", "private", "<set>", "public"] },
|
||||||
|
{ include: ["<_types/_uint32_t.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_va_list.h>", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_sigset_t.h>", "private", "<signal.h>", "public"] },
|
||||||
|
{ include: ["<sys/signal.h>", "private", "<signal.h>", "public"] },
|
||||||
|
{ include: ["<strings.h>", "private", "<string.h>", "public"] },
|
||||||
|
{ include: ["<sys/termios.h>", "private", "<termios.h>", "public"] },
|
||||||
|
{ include: ["<sys/_termios.h>", "private", "<termios.h>", "public"] },
|
||||||
|
{ include: ["<sys/ttycom.h>", "private", "<termios.h>", "public"] },
|
||||||
|
{ include: ["<sys/syslimits.h>", "private", "<limits.h>", "public"] },
|
||||||
|
{ include: ["<i386/limits.h>", "private", "<limits.h>", "public"] },
|
||||||
|
{ include: ["<sys/limits.h>", "private", "<limits.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_wint_t.h>", "private", "<stddef.h>", "public"] },
|
||||||
|
{ include: ["<sys/_select.h>", "private", "<select.h>", "public"] },
|
||||||
|
{ include: ["<sys/cdefs.h>", "private", "<unistd.h>", "public"] },
|
||||||
|
{ include: ["<istream>", "private", "<iostream>", "public"] },
|
||||||
|
{ include: ["<sys/_endian.h>", "private", "<netinet/in.h>", "public"] },
|
||||||
|
{ include: ["<sys/_types/_timespec.h>", "private", "<time.h>", "public"] },
|
||||||
|
{ include: ["<sys/_timespec.h>", "private", "<time.h>", "public"] },
|
||||||
|
{ include: ["<sys/spawn.h>", "private", "<spawn.h>", "public"] },
|
||||||
|
{ include: ["<sys/dirent.h>", "private", "<dirent.h>", "public"] },
|
||||||
|
{ include: ["<__mutex_base>", "private", "<mutex>", "public"] },
|
||||||
|
{ include: ["<__hash_table>", "private", "<unordered_map>", "public"] },
|
||||||
|
{ include: ["<__hash_table>", "private", "<unordered_set>", "public"] },
|
||||||
|
# { include: ["<>", "private", "<>", "public"] },
|
||||||
|
|
||||||
|
{ symbol: ["size_t", "private", "<cstddef>", "public"] },
|
||||||
|
{ symbol: ["mutex", "private", "<mutex>", "public"] },
|
||||||
|
{ symbol: ["sig_atomic_t", "private", "<csignal>", "public"] },
|
||||||
|
{ symbol: ["va_end", "private", "<stdarg.h>", "public"] },
|
||||||
|
{ symbol: ["va_list", "private", "<stdarg.h>", "public"] },
|
||||||
|
{ symbol: ["va_start", "private", "<stdarg.h>", "public"] },
|
||||||
|
{ symbol: ["NULL", "private", "<stddef.h>", "public"] },
|
||||||
|
{ symbol: ["NULL", "private", "<stdlib.h>", "public"] },
|
||||||
|
{ symbol: ["NULL", "private", "<stdio.h>", "public"] },
|
||||||
|
{ symbol: ["NULL", "private", "<unistd.h>", "public"] },
|
||||||
|
{ symbol: ["off_t", "private", "<unistd.h>", "public"] },
|
||||||
|
{ symbol: ["off_t", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ symbol: ["size_t", "private", "<stddef.h>", "public"] },
|
||||||
|
{ symbol: ["ssize_t", "private", "<stddef.h>", "public"] },
|
||||||
|
{ symbol: ["intptr_t", "private", "<unistd.h>", "public"] },
|
||||||
|
{ symbol: ["gid_t", "private", "<unistd.h>", "public"] },
|
||||||
|
{ symbol: ["uid_t", "private", "<unistd.h>", "public"] },
|
||||||
|
{ symbol: ["pid_t", "private", "<unistd.h>", "public"] },
|
||||||
|
{ symbol: ["pid_t", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ symbol: ["uid_t", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ symbol: ["gid_t", "private", "<sys/types.h>", "public"] },
|
||||||
|
{ symbol: ["timeval", "private", "<sys/time.h>", "public"] },
|
||||||
|
{ symbol: ["__uint32_t", "private", "<stdint.h>", "public"] },
|
||||||
|
{ symbol: ["uint32_t", "private", "<stdint.h>", "public"] },
|
||||||
|
{ symbol: ["intptr_t", "private", "<stdint.h>", "public"] },
|
||||||
|
{ symbol: ["tparm", "private", "<ncurses.h>", "public"] },
|
||||||
|
{ symbol: ["tigetflag", "private", "<ncurses.h>", "public"] },
|
||||||
|
{ symbol: ["ERR", "private", "<ncurses.h>", "public"] },
|
||||||
|
{ symbol: ["OK", "private", "<ncurses.h>", "public"] },
|
||||||
|
{ symbol: ["select", "private", "<sys/select.h>", "public"] },
|
||||||
|
{ symbol: ["_LIBCPP_VERSION", "private", "<stddef.h>", "public"] },
|
||||||
|
{ symbol: ["_LIBCPP_VERSION", "private", "<unistd.h>", "public"] },
|
||||||
|
{ symbol: ["MB_CUR_MAX", "private", "<xlocale.h>", "public"] },
|
||||||
|
{ symbol: ["MB_CUR_MAX", "private", "<stdlib.h>", "public"] },
|
||||||
|
]
|
||||||
132
build_tools/lint.fish
Executable file
132
build_tools/lint.fish
Executable file
@@ -0,0 +1,132 @@
|
|||||||
|
#!/usr/bin/env fish
|
||||||
|
#
|
||||||
|
# This is meant to be run by "make lint" or "make lint-all". It is not meant to
|
||||||
|
# be run directly from a shell prompt.
|
||||||
|
#
|
||||||
|
|
||||||
|
# We don't include "missingInclude" as that doesn't find our config.h.
|
||||||
|
# Missing includes will quickly be found by... compiling the thing anyway.
|
||||||
|
set -l cppchecks warning,performance,portability,information #,missingInclude
|
||||||
|
set -l cppcheck_args
|
||||||
|
set -l c_files
|
||||||
|
set -l all no
|
||||||
|
set -l kernel_name (uname -s)
|
||||||
|
set -l machine_type (uname -m)
|
||||||
|
|
||||||
|
argparse a/all p/project= -- $argv
|
||||||
|
|
||||||
|
# We only want -D and -I options to be passed thru to cppcheck.
|
||||||
|
for arg in $argv
|
||||||
|
if string match -q -- '-D*' $arg
|
||||||
|
set cppcheck_args $cppcheck_args $arg
|
||||||
|
else if string match -q -- '-I*' $arg
|
||||||
|
set cppcheck_args $cppcheck_args $arg
|
||||||
|
else if string match -q -- '-iquote*' $arg
|
||||||
|
set cppcheck_args $cppcheck_args $arg
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Not sure when this became necessary but without these flags cppcheck no longer works on macOS.
|
||||||
|
# It complains that "Cppcheck cannot find all the include files." Adding these include paths should
|
||||||
|
# be harmless everywhere else.
|
||||||
|
set cppcheck_args $cppcheck_args -I /usr/include -I .
|
||||||
|
|
||||||
|
if test "$machine_type" = x86_64
|
||||||
|
set cppcheck_args -D__x86_64__ -D__LP64__ $cppcheck_args
|
||||||
|
end
|
||||||
|
|
||||||
|
if set -q _flag_all
|
||||||
|
set c_files src/*.cpp
|
||||||
|
set cppchecks "$cppchecks,unusedFunction"
|
||||||
|
else
|
||||||
|
# We haven't been asked to lint all the source. If there are uncommitted
|
||||||
|
# changes lint those, else lint the files in the most recent commit.
|
||||||
|
# Select (cached files) (modified but not cached, and untracked files)
|
||||||
|
set -l files (git diff-index --cached HEAD --name-only)
|
||||||
|
set files $files (git ls-files --exclude-standard --others --modified)
|
||||||
|
if not set -q files[1]
|
||||||
|
# No pending changes so lint the files in the most recent commit.
|
||||||
|
set files (git diff-tree --no-commit-id --name-only -r HEAD)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Extract just the C/C++ files that exist.
|
||||||
|
set c_files
|
||||||
|
for file in (string match -r '.*\.c(?:pp)?$' -- $files)
|
||||||
|
test -f $file; and set c_files $c_files $file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# We now have a list of files to check so run the linters.
|
||||||
|
if set -q c_files[1]
|
||||||
|
if type -q include-what-you-use
|
||||||
|
echo
|
||||||
|
echo ========================================
|
||||||
|
echo Running IWYU
|
||||||
|
echo ========================================
|
||||||
|
for c_file in $c_files
|
||||||
|
switch $kernel_name
|
||||||
|
case Darwin FreeBSD
|
||||||
|
include-what-you-use -Xiwyu --no_default_mappings -Xiwyu \
|
||||||
|
--mapping_file=build_tools/iwyu.osx.imp --std=c++11 \
|
||||||
|
$cppcheck_args $c_file 2>&1
|
||||||
|
case Linux
|
||||||
|
include-what-you-use -Xiwyu --mapping_file=build_tools/iwyu.linux.imp \
|
||||||
|
$cppcheck_args $c_file 2>&1
|
||||||
|
case '*' # hope for the best
|
||||||
|
include-what-you-use --std=c++11 $cppcheck_args $c_file 2>&1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if type -q cppcheck
|
||||||
|
echo
|
||||||
|
echo ========================================
|
||||||
|
echo Running cppcheck
|
||||||
|
echo ========================================
|
||||||
|
# The stderr to stdout redirection is because cppcheck, incorrectly IMHO, writes its
|
||||||
|
# diagnostic messages to stderr. Anyone running this who wants to capture its output will
|
||||||
|
# expect those messages to be written to stdout.
|
||||||
|
set -l cn (set_color normal)
|
||||||
|
set -l cb (set_color --bold)
|
||||||
|
set -l cu (set_color --underline)
|
||||||
|
set -l cm (set_color magenta)
|
||||||
|
set -l cbrm (set_color brmagenta)
|
||||||
|
set -l template "[$cb$cu{file}$cn$cb:{line}$cn] $cbrm{severity}$cm ({id}):$cn\n {message}"
|
||||||
|
set cppcheck_args -q --verbose --std=c++11 --std=posix --language=c++ --template $template \
|
||||||
|
--suppress=missingIncludeSystem --inline-suppr --enable=$cppchecks \
|
||||||
|
--rule-file=.cppcheck.rules --suppressions-list=.cppcheck.suppressions $cppcheck_args
|
||||||
|
|
||||||
|
cppcheck $cppcheck_args $c_files 2>&1
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo ========================================
|
||||||
|
echo 'Running `cppcheck --check-config` to identify missing includes and similar problems.'
|
||||||
|
echo 'Ignore unmatchedSuppression warnings as they are probably false positives we'
|
||||||
|
echo 'cannot suppress.'
|
||||||
|
echo ========================================
|
||||||
|
cppcheck $cppcheck_args --check-config $c_files 2>&1
|
||||||
|
end
|
||||||
|
|
||||||
|
if type -q oclint
|
||||||
|
echo
|
||||||
|
echo ========================================
|
||||||
|
echo Running oclint
|
||||||
|
echo ========================================
|
||||||
|
# The stderr to stdout redirection is because oclint, incorrectly writes its final summary
|
||||||
|
# counts of the errors detected to stderr. Anyone running this who wants to capture its
|
||||||
|
# output will expect those messages to be written to stdout.
|
||||||
|
oclint $c_files -- $argv 2>&1
|
||||||
|
end
|
||||||
|
|
||||||
|
if type -q clang-tidy; and set -q _flag_project
|
||||||
|
echo
|
||||||
|
echo ========================================
|
||||||
|
echo Running clang-tidy
|
||||||
|
echo ========================================
|
||||||
|
clang-tidy -p $_flag_project $c_files
|
||||||
|
end
|
||||||
|
else
|
||||||
|
echo
|
||||||
|
echo 'WARNING: No C/C++ files to check'
|
||||||
|
echo
|
||||||
|
end
|
||||||
@@ -13,9 +13,7 @@ if not contains -- $TAG (git tag)
|
|||||||
end
|
end
|
||||||
|
|
||||||
set -l committers_to_tag (mktemp)
|
set -l committers_to_tag (mktemp)
|
||||||
or exit 1
|
|
||||||
set -l committers_from_tag (mktemp)
|
set -l committers_from_tag (mktemp)
|
||||||
or exit 1
|
|
||||||
|
|
||||||
# You might think it would be better to case-insensitively sort/compare the names
|
# You might think it would be better to case-insensitively sort/compare the names
|
||||||
# to produce a more natural-looking list.
|
# to produce a more natural-looking list.
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from __future__ import unicode_literals
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
from collections import deque
|
||||||
import datetime
|
import datetime
|
||||||
import io
|
import io
|
||||||
import re
|
import re
|
||||||
@@ -13,39 +14,15 @@ import shlex
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
try:
|
|
||||||
from itertools import zip_longest
|
|
||||||
except ImportError:
|
|
||||||
from itertools import izip_longest as zip_longest
|
|
||||||
from difflib import SequenceMatcher
|
|
||||||
|
|
||||||
# Directives can occur at the beginning of a line, or anywhere in a line that does not start with #.
|
|
||||||
COMMENT_RE = r"^(?:[^#].*)?#\s*"
|
|
||||||
|
|
||||||
# A regex showing how to run the file.
|
# A regex showing how to run the file.
|
||||||
RUN_RE = re.compile(COMMENT_RE + r"RUN:\s+(.*)\n")
|
RUN_RE = re.compile(r"\s*#\s*RUN:\s+(.*)\n")
|
||||||
REQUIRES_RE = re.compile(COMMENT_RE + r"REQUIRES:\s+(.*)\n")
|
|
||||||
|
|
||||||
# A regex capturing lines that should be checked against stdout.
|
# A regex capturing lines that should be checked against stdout.
|
||||||
CHECK_STDOUT_RE = re.compile(COMMENT_RE + r"CHECK:\s+(.*)\n")
|
CHECK_STDOUT_RE = re.compile(r"\s*#\s*CHECK:\s+(.*)\n")
|
||||||
|
|
||||||
# A regex capturing lines that should be checked against stderr.
|
# A regex capturing lines that should be checked against stderr.
|
||||||
CHECK_STDERR_RE = re.compile(COMMENT_RE + r"CHECKERR:\s+(.*)\n")
|
CHECK_STDERR_RE = re.compile(r"\s*#\s*CHECKERR:\s+(.*)\n")
|
||||||
|
|
||||||
SKIP = object()
|
|
||||||
|
|
||||||
def find_command(program):
|
|
||||||
import os
|
|
||||||
|
|
||||||
path, name = os.path.split(program)
|
|
||||||
if path:
|
|
||||||
return os.path.isfile(program) and os.access(program, os.X_OK)
|
|
||||||
for path in os.environ["PATH"].split(os.pathsep):
|
|
||||||
exe = os.path.join(path, program)
|
|
||||||
if os.path.isfile(exe) and os.access(exe, os.X_OK):
|
|
||||||
return exe
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
class Config(object):
|
class Config(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -55,6 +32,10 @@ class Config(object):
|
|||||||
self.colorize = False
|
self.colorize = False
|
||||||
# Whether to show which file was tested.
|
# Whether to show which file was tested.
|
||||||
self.progress = False
|
self.progress = False
|
||||||
|
# How many after lines to print
|
||||||
|
self.after = 5
|
||||||
|
# How many before lines to print
|
||||||
|
self.before = 5
|
||||||
|
|
||||||
def colors(self):
|
def colors(self):
|
||||||
""" Return a dictionary mapping color names to ANSI escapes """
|
""" Return a dictionary mapping color names to ANSI escapes """
|
||||||
@@ -96,6 +77,8 @@ def esc(m):
|
|||||||
map = {
|
map = {
|
||||||
"\n": "\\n",
|
"\n": "\\n",
|
||||||
"\\": "\\\\",
|
"\\": "\\\\",
|
||||||
|
"'": "\\'",
|
||||||
|
'"': '\\"',
|
||||||
"\a": "\\a",
|
"\a": "\\a",
|
||||||
"\b": "\\b",
|
"\b": "\\b",
|
||||||
"\f": "\\f",
|
"\f": "\\f",
|
||||||
@@ -135,26 +118,6 @@ class Line(object):
|
|||||||
self.number = number
|
self.number = number
|
||||||
self.file = file
|
self.file = file
|
||||||
|
|
||||||
def __hash__(self):
|
|
||||||
# Chosen by fair diceroll
|
|
||||||
# No, just kidding.
|
|
||||||
# HACK: We pass this to the Sequencematcher, which puts the Checks into a dict.
|
|
||||||
# To force it to match the regexes, we return a hash collision intentionally,
|
|
||||||
# so it falls back on __eq__().
|
|
||||||
#
|
|
||||||
# CheckCmd has the same thing.
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
if other is None:
|
|
||||||
return False
|
|
||||||
if isinstance(other, CheckCmd):
|
|
||||||
return other.regex.match(self.text)
|
|
||||||
if isinstance(other, Line):
|
|
||||||
# We only compare the text here so SequenceMatcher can reshuffle these
|
|
||||||
return self.text == other.text
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def subline(self, text):
|
def subline(self, text):
|
||||||
""" Return a substring of our line with the given text, preserving number and file. """
|
""" Return a substring of our line with the given text, preserving number and file. """
|
||||||
return Line(text, self.number, self.file)
|
return Line(text, self.number, self.file)
|
||||||
@@ -166,16 +129,10 @@ class Line(object):
|
|||||||
def is_empty_space(self):
|
def is_empty_space(self):
|
||||||
return not self.text or self.text.isspace()
|
return not self.text or self.text.isspace()
|
||||||
|
|
||||||
def escaped_text(self, for_formatting=False):
|
|
||||||
ret = escape_string(self.text.rstrip("\n"))
|
|
||||||
if for_formatting:
|
|
||||||
ret = ret.replace("{", "{{").replace("}", "}}")
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
class RunCmd(object):
|
class RunCmd(object):
|
||||||
"""A command to run on a given Checker.
|
""" A command to run on a given Checker.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
args: Unexpanded shell command as a string.
|
args: Unexpanded shell command as a string.
|
||||||
"""
|
"""
|
||||||
@@ -192,17 +149,17 @@ class RunCmd(object):
|
|||||||
|
|
||||||
|
|
||||||
class TestFailure(object):
|
class TestFailure(object):
|
||||||
def __init__(self, line, check, testrun, diff=None, lines=[], checks=[]):
|
def __init__(self, line, check, testrun, before=None, after=None):
|
||||||
self.line = line
|
self.line = line
|
||||||
self.check = check
|
self.check = check
|
||||||
self.testrun = testrun
|
self.testrun = testrun
|
||||||
self.error_annotation_lines = None
|
self.error_annotation_line = None
|
||||||
self.diff = diff
|
# The output that comes *after* the failure.
|
||||||
self.lines = lines
|
self.after = after
|
||||||
self.checks = checks
|
self.before = before
|
||||||
self.signal = None
|
|
||||||
|
|
||||||
def message(self):
|
def message(self):
|
||||||
|
afterlines = self.testrun.config.after
|
||||||
fields = self.testrun.config.colors()
|
fields = self.testrun.config.colors()
|
||||||
fields["name"] = self.testrun.name
|
fields["name"] = self.testrun.name
|
||||||
fields["subbed_command"] = self.testrun.subbed_command
|
fields["subbed_command"] = self.testrun.subbed_command
|
||||||
@@ -211,7 +168,7 @@ class TestFailure(object):
|
|||||||
{
|
{
|
||||||
"output_file": self.line.file,
|
"output_file": self.line.file,
|
||||||
"output_lineno": self.line.number,
|
"output_lineno": self.line.number,
|
||||||
"output_line": self.line.escaped_text(),
|
"output_line": self.line.text.rstrip("\n"),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if self.check:
|
if self.check:
|
||||||
@@ -219,17 +176,12 @@ class TestFailure(object):
|
|||||||
{
|
{
|
||||||
"input_file": self.check.line.file,
|
"input_file": self.check.line.file,
|
||||||
"input_lineno": self.check.line.number,
|
"input_lineno": self.check.line.number,
|
||||||
"input_line": self.check.line.escaped_text(),
|
"input_line": self.check.line.text,
|
||||||
"check_type": self.check.type,
|
"check_type": self.check.type,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
filemsg = "" if self.testrun.config.progress else " in {name}"
|
filemsg = "" if self.testrun.config.progress else " in {name}"
|
||||||
fmtstrs = ["{RED}Failure{RESET}" + filemsg + ":", ""]
|
fmtstrs = ["{RED}Failure{RESET}" + filemsg + ":", ""]
|
||||||
if self.signal:
|
|
||||||
fmtstrs += [
|
|
||||||
" Process was killed by signal {BOLD}" + self.signal + "{RESET}",
|
|
||||||
""
|
|
||||||
]
|
|
||||||
if self.line and self.check:
|
if self.line and self.check:
|
||||||
fmtstrs += [
|
fmtstrs += [
|
||||||
" The {check_type} on line {input_lineno} wants:",
|
" The {check_type} on line {input_lineno} wants:",
|
||||||
@@ -254,97 +206,24 @@ class TestFailure(object):
|
|||||||
" {BOLD}{output_line}{RESET}",
|
" {BOLD}{output_line}{RESET}",
|
||||||
"",
|
"",
|
||||||
]
|
]
|
||||||
if self.error_annotation_lines:
|
if self.error_annotation_line:
|
||||||
fields["error_annotation"] = " ".join(
|
fields["error_annotation"] = self.error_annotation_line.text
|
||||||
[x.text for x in self.error_annotation_lines]
|
fields["error_annotation_lineno"] = self.error_annotation_line.number
|
||||||
)
|
|
||||||
fields["error_annotation_lineno"] = str(
|
|
||||||
self.error_annotation_lines[0].number
|
|
||||||
)
|
|
||||||
if len(self.error_annotation_lines) > 1:
|
|
||||||
fields["error_annotation_lineno"] += ":" + str(
|
|
||||||
self.error_annotation_lines[-1].number
|
|
||||||
)
|
|
||||||
fmtstrs += [
|
fmtstrs += [
|
||||||
" additional output on stderr:{error_annotation_lineno}:",
|
" additional output on stderr:{error_annotation_lineno}:",
|
||||||
" {BOLD}{error_annotation}{RESET}",
|
" {BOLD}{error_annotation}{RESET}",
|
||||||
]
|
]
|
||||||
if self.diff:
|
if self.before:
|
||||||
fmtstrs += [" Context:"]
|
fields["before_output"] = " ".join(self.before)
|
||||||
lasthi = 0
|
fields["additional_output"] = " ".join(self.after[:afterlines])
|
||||||
lastcheckline = None
|
fmtstrs += [
|
||||||
for d in self.diff.get_grouped_opcodes():
|
" Context:",
|
||||||
for op, alo, ahi, blo, bhi in d:
|
" {BOLD}{before_output} {RED}{output_line}{RESET} <= does not match '{LIGHTBLUE}{input_line}{RESET}'",
|
||||||
color = "{BOLD}"
|
" {BOLD}{additional_output}{RESET}",
|
||||||
if op == "replace" or op == "delete":
|
]
|
||||||
color = "{RED}"
|
elif self.after:
|
||||||
# We got a new chunk, so we print a marker.
|
fields["additional_output"] = " ".join(self.after[:afterlines])
|
||||||
if alo > lasthi:
|
fmtstrs += [" additional output:", " {BOLD}{additional_output}{RESET}"]
|
||||||
fmtstrs += [
|
|
||||||
" [...] from line "
|
|
||||||
+ str(self.checks[blo].line.number)
|
|
||||||
+ " ("
|
|
||||||
+ self.lines[alo].file
|
|
||||||
+ ":"
|
|
||||||
+ str(self.lines[alo].number)
|
|
||||||
+ "):"
|
|
||||||
]
|
|
||||||
lasthi = ahi
|
|
||||||
|
|
||||||
# We print one "no more checks" after the last check and then skip any markers
|
|
||||||
lastcheck = False
|
|
||||||
for a, b in zip_longest(self.lines[alo:ahi], self.checks[blo:bhi]):
|
|
||||||
# Clean up strings for use in a format string - double up the curlies.
|
|
||||||
astr = (
|
|
||||||
color + a.escaped_text(for_formatting=True) + "{RESET}"
|
|
||||||
if a
|
|
||||||
else ""
|
|
||||||
)
|
|
||||||
if b:
|
|
||||||
bstr = (
|
|
||||||
"on line "
|
|
||||||
+ str(b.line.number)
|
|
||||||
+ ": {BLUE}"
|
|
||||||
+ b.line.escaped_text(for_formatting=True)
|
|
||||||
+ "{RESET}"
|
|
||||||
)
|
|
||||||
lastcheckline = b.line.number
|
|
||||||
|
|
||||||
if op == "equal":
|
|
||||||
fmtstrs += [" " + astr]
|
|
||||||
elif b and a:
|
|
||||||
fmtstrs += [
|
|
||||||
" "
|
|
||||||
+ astr
|
|
||||||
+ " <= does not match "
|
|
||||||
+ b.type
|
|
||||||
+ " "
|
|
||||||
+ bstr
|
|
||||||
]
|
|
||||||
elif b:
|
|
||||||
fmtstrs += [
|
|
||||||
" "
|
|
||||||
+ astr
|
|
||||||
+ " <= nothing to match "
|
|
||||||
+ b.type
|
|
||||||
+ " "
|
|
||||||
+ bstr
|
|
||||||
]
|
|
||||||
elif not b:
|
|
||||||
string = " " + astr
|
|
||||||
if bhi == len(self.checks):
|
|
||||||
if not lastcheck:
|
|
||||||
string += " <= no more checks"
|
|
||||||
lastcheck = True
|
|
||||||
elif lastcheckline is not None:
|
|
||||||
string += (
|
|
||||||
" <= no check matches this, previous check on line "
|
|
||||||
+ str(lastcheckline)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
string += " <= no check matches"
|
|
||||||
fmtstrs.append(string)
|
|
||||||
fmtstrs.append("")
|
|
||||||
fmtstrs += [" when running command:", " {subbed_command}"]
|
fmtstrs += [" when running command:", " {subbed_command}"]
|
||||||
return "\n".join(fmtstrs).format(**fields)
|
return "\n".join(fmtstrs).format(**fields)
|
||||||
|
|
||||||
@@ -354,8 +233,8 @@ class TestFailure(object):
|
|||||||
|
|
||||||
|
|
||||||
def perform_substitution(input_str, subs):
|
def perform_substitution(input_str, subs):
|
||||||
"""Perform the substitutions described by subs to str
|
""" Perform the substitutions described by subs to str
|
||||||
Return the substituted string.
|
Return the substituted string.
|
||||||
"""
|
"""
|
||||||
# Sort our substitutions into a list of tuples (key, value), descending by length.
|
# Sort our substitutions into a list of tuples (key, value), descending by length.
|
||||||
# It needs to be descending because we need to try longer substitutions first.
|
# It needs to be descending because we need to try longer substitutions first.
|
||||||
@@ -375,20 +254,6 @@ def perform_substitution(input_str, subs):
|
|||||||
return re.sub(r"%(%|[a-zA-Z0-9_-]+)", subber, input_str)
|
return re.sub(r"%(%|[a-zA-Z0-9_-]+)", subber, input_str)
|
||||||
|
|
||||||
|
|
||||||
def runproc(cmd):
|
|
||||||
""" Wrapper around subprocess.Popen to save typing """
|
|
||||||
PIPE = subprocess.PIPE
|
|
||||||
proc = subprocess.Popen(
|
|
||||||
cmd,
|
|
||||||
stdin=PIPE,
|
|
||||||
stdout=PIPE,
|
|
||||||
stderr=PIPE,
|
|
||||||
shell=True,
|
|
||||||
close_fds=True, # For Python 2.6 as shipped on RHEL 6
|
|
||||||
)
|
|
||||||
return proc
|
|
||||||
|
|
||||||
|
|
||||||
class TestRun(object):
|
class TestRun(object):
|
||||||
def __init__(self, name, runcmd, checker, subs, config):
|
def __init__(self, name, runcmd, checker, subs, config):
|
||||||
self.name = name
|
self.name = name
|
||||||
@@ -402,95 +267,74 @@ class TestRun(object):
|
|||||||
# Reverse our lines and checks so we can pop off the end.
|
# Reverse our lines and checks so we can pop off the end.
|
||||||
lineq = lines[::-1]
|
lineq = lines[::-1]
|
||||||
checkq = checks[::-1]
|
checkq = checks[::-1]
|
||||||
usedlines = []
|
# We keep the last couple of lines in a deque so we can show context.
|
||||||
usedchecks = []
|
before = deque(maxlen=self.config.before)
|
||||||
mismatches = []
|
|
||||||
while lineq and checkq:
|
while lineq and checkq:
|
||||||
line = lineq[-1]
|
line = lineq[-1]
|
||||||
check = checkq[-1]
|
check = checkq[-1]
|
||||||
if check == line:
|
if check.regex.match(line.text):
|
||||||
# This line matched this checker, continue on.
|
# This line matched this checker, continue on.
|
||||||
usedlines.append(line)
|
|
||||||
usedchecks.append(check)
|
|
||||||
lineq.pop()
|
lineq.pop()
|
||||||
checkq.pop()
|
checkq.pop()
|
||||||
|
before.append(line)
|
||||||
elif line.is_empty_space():
|
elif line.is_empty_space():
|
||||||
# Skip all whitespace input lines.
|
# Skip all whitespace input lines.
|
||||||
lineq.pop()
|
lineq.pop()
|
||||||
else:
|
else:
|
||||||
usedlines.append(line)
|
|
||||||
usedchecks.append(check)
|
|
||||||
mismatches.append((line, check))
|
|
||||||
# Failed to match.
|
# Failed to match.
|
||||||
lineq.pop()
|
lineq.pop()
|
||||||
checkq.pop()
|
line.text = escape_string(line.text.strip()) + "\n"
|
||||||
|
# Add context, ignoring empty lines.
|
||||||
# Drain empties
|
return TestFailure(
|
||||||
|
line,
|
||||||
|
check,
|
||||||
|
self,
|
||||||
|
before=[escape_string(line.text.strip()) + "\n" for line in before],
|
||||||
|
after=[
|
||||||
|
escape_string(line.text.strip()) + "\n"
|
||||||
|
for line in lineq[::-1]
|
||||||
|
if not line.is_empty_space()
|
||||||
|
],
|
||||||
|
)
|
||||||
|
# Drain empties.
|
||||||
while lineq and lineq[-1].is_empty_space():
|
while lineq and lineq[-1].is_empty_space():
|
||||||
lineq.pop()
|
lineq.pop()
|
||||||
|
# If there's still lines or checkers, we have a failure.
|
||||||
# Store the remaining lines for the diff
|
|
||||||
for i in lineq[::-1]:
|
|
||||||
if not i.is_empty_space():
|
|
||||||
usedlines.append(i)
|
|
||||||
# Store remaining checks for the diff
|
|
||||||
for i in checkq[::-1]:
|
|
||||||
usedchecks.append(i)
|
|
||||||
|
|
||||||
# If we have no more output, there's no reason to give
|
|
||||||
# SCREENFULS of text.
|
|
||||||
# So we truncate the check list.
|
|
||||||
if len(usedchecks) > len(usedlines):
|
|
||||||
usedchecks = usedchecks[:len(usedlines) + 5]
|
|
||||||
|
|
||||||
# Do a SequenceMatch! This gives us a diff-like thing.
|
|
||||||
diff = SequenceMatcher(a=usedlines, b=usedchecks, autojunk=False)
|
|
||||||
# If there's a mismatch or still lines or checkers, we have a failure.
|
|
||||||
# Otherwise it's success.
|
# Otherwise it's success.
|
||||||
if mismatches:
|
if lineq:
|
||||||
return TestFailure(
|
return TestFailure(lineq[-1], None, self)
|
||||||
mismatches[0][0],
|
|
||||||
mismatches[0][1],
|
|
||||||
self,
|
|
||||||
diff=diff,
|
|
||||||
lines=usedlines,
|
|
||||||
checks=usedchecks,
|
|
||||||
)
|
|
||||||
elif lineq:
|
|
||||||
return TestFailure(
|
|
||||||
lineq[-1], None, self, diff=diff, lines=usedlines, checks=usedchecks
|
|
||||||
)
|
|
||||||
elif checkq:
|
elif checkq:
|
||||||
return TestFailure(
|
return TestFailure(None, checkq[-1], self)
|
||||||
None, checkq[-1], self, diff=diff, lines=usedlines, checks=usedchecks
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
# Success!
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
""" Run the command. Return a TestFailure, or None. """
|
""" Run the command. Return a TestFailure, or None. """
|
||||||
|
|
||||||
def split_by_newlines(s):
|
def split_by_newlines(s):
|
||||||
"""Decode a string and split it by newlines only,
|
""" Decode a string and split it by newlines only,
|
||||||
retaining the newlines.
|
retaining the newlines.
|
||||||
"""
|
"""
|
||||||
return [s + "\n" for s in s.decode("utf-8").split("\n")]
|
return [s + "\n" for s in s.decode("utf-8").split("\n")]
|
||||||
|
|
||||||
|
PIPE = subprocess.PIPE
|
||||||
if self.config.verbose:
|
if self.config.verbose:
|
||||||
print(self.subbed_command)
|
print(self.subbed_command)
|
||||||
proc = runproc(self.subbed_command)
|
proc = subprocess.Popen(
|
||||||
|
self.subbed_command,
|
||||||
|
stdin=PIPE,
|
||||||
|
stdout=PIPE,
|
||||||
|
stderr=PIPE,
|
||||||
|
shell=True,
|
||||||
|
close_fds=True, # For Python 2.6 as shipped on RHEL 6
|
||||||
|
)
|
||||||
stdout, stderr = proc.communicate()
|
stdout, stderr = proc.communicate()
|
||||||
# HACK: This is quite cheesy: POSIX specifies that sh should return 127 for a missing command.
|
# HACK: This is quite cheesy: POSIX specifies that sh should return 127 for a missing command.
|
||||||
# It's also possible that it'll be returned in other situations,
|
# Technically it's also possible to return it in other conditions.
|
||||||
# most likely when the last command in a shell script doesn't exist.
|
# Practically, that's *probably* not going to happen.
|
||||||
# So we check if the command *we execute* exists, and complain then.
|
|
||||||
status = proc.returncode
|
status = proc.returncode
|
||||||
cmd = shlex.split(self.subbed_command)[0]
|
if status == 127:
|
||||||
if status == 127 and not find_command(cmd):
|
raise CheckerError("Command could not be found: " + self.subbed_command)
|
||||||
raise CheckerError("Command could not be found: " + cmd)
|
|
||||||
if status == 126 and not find_command(cmd):
|
|
||||||
raise CheckerError("Command is not executable: " + cmd)
|
|
||||||
|
|
||||||
outlines = [
|
outlines = [
|
||||||
Line(text, idx + 1, "stdout")
|
Line(text, idx + 1, "stdout")
|
||||||
@@ -507,38 +351,8 @@ class TestRun(object):
|
|||||||
# non-matching or unmatched stderr text, then annotate the outfail
|
# non-matching or unmatched stderr text, then annotate the outfail
|
||||||
# with it.
|
# with it.
|
||||||
if outfail and errfail and errfail.line:
|
if outfail and errfail and errfail.line:
|
||||||
outfail.error_annotation_lines = errlines[errfail.line.number - 1 :]
|
outfail.error_annotation_line = errfail.line
|
||||||
# Trim a trailing newline
|
return outfail if outfail else errfail
|
||||||
if outfail.error_annotation_lines[-1].text == "\n":
|
|
||||||
del outfail.error_annotation_lines[-1]
|
|
||||||
failure = outfail if outfail else errfail
|
|
||||||
|
|
||||||
if failure and status < 0:
|
|
||||||
# Process was killed by a signal and failed,
|
|
||||||
# add a message.
|
|
||||||
import signal
|
|
||||||
# Unfortunately strsignal only exists in python 3.8+,
|
|
||||||
# and signal.signals is 3.5+.
|
|
||||||
if hasattr(signal, "Signals"):
|
|
||||||
try:
|
|
||||||
sig = signal.Signals(-status)
|
|
||||||
failure.signal = sig.name + " (" + signal.strsignal(sig.value) + ")"
|
|
||||||
except ValueError:
|
|
||||||
failure.signal = str(-status)
|
|
||||||
else:
|
|
||||||
# No easy way to get the full list,
|
|
||||||
# make up a dict.
|
|
||||||
signals = {
|
|
||||||
signal.SIGABRT: "SIGABRT",
|
|
||||||
signal.SIGBUS: "SIGBUS",
|
|
||||||
signal.SIGFPE: "SIGFPE",
|
|
||||||
signal.SIGILL: "SIGILL",
|
|
||||||
signal.SIGSEGV: "SIGSEGV",
|
|
||||||
signal.SIGTERM: "SIGTERM",
|
|
||||||
}
|
|
||||||
failure.signal = signals.get(-status, str(-status))
|
|
||||||
|
|
||||||
return failure
|
|
||||||
|
|
||||||
|
|
||||||
class CheckCmd(object):
|
class CheckCmd(object):
|
||||||
@@ -547,28 +361,6 @@ class CheckCmd(object):
|
|||||||
self.type = checktype
|
self.type = checktype
|
||||||
self.regex = regex
|
self.regex = regex
|
||||||
|
|
||||||
def __hash__(self):
|
|
||||||
# HACK: We pass this to the Sequencematcher, which puts the Checks into a dict.
|
|
||||||
# To force it to match the regexes, we return a hash collision intentionally,
|
|
||||||
# so it falls back on __eq__().
|
|
||||||
#
|
|
||||||
# Line has the same thing.
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
# "Magical" comparison with lines and strings.
|
|
||||||
# Typically I wouldn't use this, but it allows us to check if a line matches any check in a dict or list via
|
|
||||||
# the `in` operator.
|
|
||||||
if other is None:
|
|
||||||
return False
|
|
||||||
if isinstance(other, CheckCmd):
|
|
||||||
return self.regex == other.regex
|
|
||||||
if isinstance(other, Line):
|
|
||||||
return self.regex.match(other.text)
|
|
||||||
if isinstance(other, str):
|
|
||||||
return self.regex.match(other)
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse(line, checktype):
|
def parse(line, checktype):
|
||||||
# type: (Line) -> CheckCmd
|
# type: (Line) -> CheckCmd
|
||||||
@@ -628,19 +420,14 @@ class Checker(object):
|
|||||||
|
|
||||||
# Find run commands.
|
# Find run commands.
|
||||||
self.runcmds = [RunCmd.parse(sl) for sl in group1s(RUN_RE)]
|
self.runcmds = [RunCmd.parse(sl) for sl in group1s(RUN_RE)]
|
||||||
self.shebang_cmd = None
|
|
||||||
if not self.runcmds:
|
if not self.runcmds:
|
||||||
# If no RUN command has been given, fall back to the shebang.
|
# If no RUN command has been given, fall back to the shebang.
|
||||||
if lines[0].text.startswith("#!"):
|
if lines[0].text.startswith("#!"):
|
||||||
# Remove the "#!" at the beginning, and the newline at the end.
|
# Remove the "#!" at the beginning, and the newline at the end.
|
||||||
cmd = lines[0].text[2:-1]
|
self.runcmds = [RunCmd(lines[0].text[2:-1] + " %s", lines[0])]
|
||||||
self.shebang_cmd = cmd
|
|
||||||
self.runcmds = [RunCmd(cmd + " %s", lines[0])]
|
|
||||||
else:
|
else:
|
||||||
raise CheckerError("No runlines ('# RUN') found")
|
raise CheckerError("No runlines ('# RUN') found")
|
||||||
|
|
||||||
self.requirecmds = [RunCmd.parse(sl) for sl in group1s(REQUIRES_RE)]
|
|
||||||
|
|
||||||
# Find check cmds.
|
# Find check cmds.
|
||||||
self.outchecks = [
|
self.outchecks = [
|
||||||
CheckCmd.parse(sl, "CHECK") for sl in group1s(CHECK_STDOUT_RE)
|
CheckCmd.parse(sl, "CHECK") for sl in group1s(CHECK_STDOUT_RE)
|
||||||
@@ -655,21 +442,6 @@ def check_file(input_file, name, subs, config, failure_handler):
|
|||||||
success = True
|
success = True
|
||||||
lines = Line.readfile(input_file, name)
|
lines = Line.readfile(input_file, name)
|
||||||
checker = Checker(name, lines)
|
checker = Checker(name, lines)
|
||||||
|
|
||||||
# Run all the REQUIRES lines first,
|
|
||||||
# if any of them fail it's a SKIP
|
|
||||||
for reqcmd in checker.requirecmds:
|
|
||||||
proc = runproc(
|
|
||||||
perform_substitution(reqcmd.args, subs)
|
|
||||||
)
|
|
||||||
proc.communicate()
|
|
||||||
if proc.returncode > 0:
|
|
||||||
return SKIP
|
|
||||||
|
|
||||||
if checker.shebang_cmd is not None and not find_command(checker.shebang_cmd):
|
|
||||||
raise CheckerError("Command could not be found: " + checker.shebang_cmd)
|
|
||||||
|
|
||||||
# Only then run the RUN lines.
|
|
||||||
for runcmd in checker.runcmds:
|
for runcmd in checker.runcmds:
|
||||||
failure = TestRun(name, runcmd, checker, subs, config).run()
|
failure = TestRun(name, runcmd, checker, subs, config).run()
|
||||||
if failure:
|
if failure:
|
||||||
@@ -684,8 +456,8 @@ def check_path(path, subs, config, failure_handler):
|
|||||||
|
|
||||||
|
|
||||||
def parse_subs(subs):
|
def parse_subs(subs):
|
||||||
"""Given a list of input substitutions like 'foo=bar',
|
""" Given a list of input substitutions like 'foo=bar',
|
||||||
return a dictionary like {foo:bar}, or exit if invalid.
|
return a dictionary like {foo:bar}, or exit if invalid.
|
||||||
"""
|
"""
|
||||||
result = {}
|
result = {}
|
||||||
for sub in subs:
|
for sub in subs:
|
||||||
@@ -725,14 +497,23 @@ def get_argparse():
|
|||||||
help="Show the files to be checked",
|
help="Show the files to be checked",
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
|
||||||
"--force-color",
|
|
||||||
action="store_true",
|
|
||||||
dest="force_color",
|
|
||||||
help="Force usage of color even if not connected to a terminal",
|
|
||||||
default=False,
|
|
||||||
)
|
|
||||||
parser.add_argument("file", nargs="+", help="File to check")
|
parser.add_argument("file", nargs="+", help="File to check")
|
||||||
|
parser.add_argument(
|
||||||
|
"-A",
|
||||||
|
"--after",
|
||||||
|
type=int,
|
||||||
|
help="How many non-empty lines of output after a failure to print (default: 5)",
|
||||||
|
action="store",
|
||||||
|
default=5,
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-B",
|
||||||
|
"--before",
|
||||||
|
type=int,
|
||||||
|
help="How many non-empty lines of output before a failure to print (default: 5)",
|
||||||
|
action="store",
|
||||||
|
default=5,
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@@ -742,16 +523,19 @@ def main():
|
|||||||
def_subs = {"%": "%"}
|
def_subs = {"%": "%"}
|
||||||
def_subs.update(parse_subs(args.substitute))
|
def_subs.update(parse_subs(args.substitute))
|
||||||
|
|
||||||
tests_count = 0
|
failure_count = 0
|
||||||
failed = False
|
|
||||||
skip_count = 0
|
|
||||||
config = Config()
|
config = Config()
|
||||||
config.colorize = args.force_color or sys.stdout.isatty()
|
config.colorize = sys.stdout.isatty()
|
||||||
config.progress = args.progress
|
config.progress = args.progress
|
||||||
fields = config.colors()
|
fields = config.colors()
|
||||||
|
config.after = args.after
|
||||||
|
config.before = args.before
|
||||||
|
if config.before < 0:
|
||||||
|
raise ValueError("Before must be at least 0")
|
||||||
|
if config.after < 0:
|
||||||
|
raise ValueError("After must be at least 0")
|
||||||
|
|
||||||
for path in args.file:
|
for path in args.file:
|
||||||
tests_count += 1
|
|
||||||
fields["path"] = path
|
fields["path"] = path
|
||||||
if config.progress:
|
if config.progress:
|
||||||
print("Testing file {path} ... ".format(**fields), end="")
|
print("Testing file {path} ... ".format(**fields), end="")
|
||||||
@@ -759,33 +543,17 @@ def main():
|
|||||||
subs = def_subs.copy()
|
subs = def_subs.copy()
|
||||||
subs["s"] = path
|
subs["s"] = path
|
||||||
starttime = datetime.datetime.now()
|
starttime = datetime.datetime.now()
|
||||||
ret = check_path(path, subs, config, TestFailure.print_message)
|
if not check_path(path, subs, config, TestFailure.print_message):
|
||||||
if ret is SKIP:
|
failure_count += 1
|
||||||
skip_count += 1
|
|
||||||
if not ret:
|
|
||||||
failed = True
|
|
||||||
elif config.progress:
|
elif config.progress:
|
||||||
endtime = datetime.datetime.now()
|
endtime = datetime.datetime.now()
|
||||||
duration_ms = round((endtime - starttime).total_seconds() * 1000)
|
duration_ms = round((endtime - starttime).total_seconds() * 1000)
|
||||||
reason = "ok"
|
|
||||||
color = "{GREEN}"
|
|
||||||
if ret is SKIP:
|
|
||||||
reason = "SKIPPED"
|
|
||||||
color = "{BLUE}"
|
|
||||||
print(
|
print(
|
||||||
(color + "{reason}{RESET} ({duration} ms)").format(
|
"{GREEN}ok{RESET} ({duration} ms)".format(
|
||||||
duration=duration_ms, reason=reason, **fields
|
duration=duration_ms, **fields
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
sys.exit(failure_count)
|
||||||
# To facilitate integration with testing frameworks, use exit code 125 to indicate that all
|
|
||||||
# tests have been skipped (primarily for use when tests are run one at a time). Exit code 125 is
|
|
||||||
# used to indicate to automated `git bisect` runs that a revision has been skipped; we use it
|
|
||||||
# for the same reasons git does.
|
|
||||||
if skip_count > 0 and skip_count == tests_count:
|
|
||||||
sys.exit(125)
|
|
||||||
|
|
||||||
sys.exit(1 if failed else 0)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
# LSAN can detect leaks tracing back to __asan::AsanThread::ThreadStart (probably caused by our
|
|
||||||
# threads not exiting before their TLS dtors are called). Just ignore it.
|
|
||||||
leak:AsanThread
|
|
||||||
@@ -1,22 +1,76 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Helper to notarize an .app.zip or .pkg file.
|
# Helper to notarize an .app.zip or .pkg file.
|
||||||
|
# Based on https://www.logcg.com/en/archives/3222.html
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
die() { echo "$*" 1>&2 ; exit 1; }
|
die() { echo "$*" 1>&2 ; exit 1; }
|
||||||
|
|
||||||
|
check_status() {
|
||||||
|
echo "STATUS" $1
|
||||||
|
}
|
||||||
|
|
||||||
test "$#" -ge 1 || die "No paths specified."
|
get_req_uuid() {
|
||||||
|
RESPONSE=$(</dev/stdin)
|
||||||
|
if echo "$RESPONSE" | egrep -q "RequestUUID"; then
|
||||||
|
echo "$RESPONSE" | egrep RequestUUID | awk '{print $3'}
|
||||||
|
elif echo "$RESPONSE" | egrep -q "The upload ID is "; then
|
||||||
|
echo "$RESPONSE" | egrep -p "The upload ID is [-a-z0-9]+" | awk '{print $5}'
|
||||||
|
else
|
||||||
|
die "Could not get Request UUID"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
for INPUT in "$@"; do
|
INPUT=$1
|
||||||
echo "Processing $INPUT"
|
AC_USER=$2
|
||||||
test -f "$INPUT" || die "Not a file: $INPUT"
|
|
||||||
ext="${INPUT##*.}"
|
|
||||||
(test "$ext" = "zip" || test "$ext" = "pkg") || die "Unrecognized extension: $ext"
|
|
||||||
|
|
||||||
xcrun notarytool submit "$INPUT" --keychain-profile AC_PASSWORD --wait
|
test -z "$AC_USER" && die "AC_USER not specified as second param"
|
||||||
|
test -z "$INPUT" && die "No path specified"
|
||||||
|
test -f "$INPUT" || die "Not a file: $INPUT"
|
||||||
|
|
||||||
|
ext="${INPUT##*.}"
|
||||||
|
(test "$ext" = "zip" || test "$ext" = "pkg") || die "Unrecognized extension: $ext"
|
||||||
|
|
||||||
|
LOGFILE=$(mktemp -t mac_notarize_log)
|
||||||
|
AC_PASS="@keychain:AC_PASSWORD"
|
||||||
|
echo "Logs at $LOGFILE"
|
||||||
|
|
||||||
|
NOTARIZE_UUID=$(xcrun altool --notarize-app \
|
||||||
|
--primary-bundle-id "com.ridiculousfish.fish-shell" \
|
||||||
|
--username "$AC_USER" \
|
||||||
|
--password "$AC_PASS" \
|
||||||
|
--file "$INPUT" 2>&1 |
|
||||||
|
tee -a "$LOGFILE" |
|
||||||
|
get_req_uuid)
|
||||||
|
|
||||||
|
test -z "$NOTARIZE_UUID" && cat "$LOGFILE" && die "Could not get RequestUUID"
|
||||||
|
echo "RequestUUID: $NOTARIZE_UUID"
|
||||||
|
|
||||||
|
success=0
|
||||||
|
for i in $(seq 20); do
|
||||||
|
echo "Checking progress..."
|
||||||
|
PROGRESS=$(xcrun altool --notarization-info "${NOTARIZE_UUID}" \
|
||||||
|
-u "$AC_USER" \
|
||||||
|
-p "$AC_PASS" 2>&1 |
|
||||||
|
tee -a "$LOGFILE")
|
||||||
|
echo "${PROGRESS}" | tail -n 1
|
||||||
|
|
||||||
|
if [ $? -ne 0 ] || [[ "${PROGRESS}" =~ "Invalid" ]] ; then
|
||||||
|
echo "Error with notarization. Exiting"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ "${PROGRESS}" =~ "in progress" ]]; then
|
||||||
|
success=1
|
||||||
|
break
|
||||||
|
else
|
||||||
|
echo "Not completed yet. Sleeping for 30 seconds."
|
||||||
|
fi
|
||||||
|
sleep 30
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $success -eq 1 ] ; then
|
||||||
if test "$ext" = "zip"; then
|
if test "$ext" = "zip"; then
|
||||||
TMPDIR=$(mktemp -d)
|
TMPDIR=$(mktemp -d)
|
||||||
echo "Extracting to $TMPDIR"
|
echo "Extracting to $TMPDIR"
|
||||||
@@ -37,9 +91,9 @@ for INPUT in "$@"; do
|
|||||||
cd "$(dirname "$STAPLE_TARGET")"
|
cd "$(dirname "$STAPLE_TARGET")"
|
||||||
zip -r -q "$INPUT_FULL" $(basename "$STAPLE_TARGET")
|
zip -r -q "$INPUT_FULL" $(basename "$STAPLE_TARGET")
|
||||||
fi
|
fi
|
||||||
echo "Processed $INPUT"
|
fi
|
||||||
|
echo "Processed $INPUT"
|
||||||
|
|
||||||
if test "$ext" = "zip"; then
|
if test "$ext" = "zip"; then
|
||||||
spctl -a -v "$STAPLE_TARGET"
|
spctl -a -v "$STAPLE_TARGET"
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
|||||||
@@ -1,183 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Script to produce an OS X installer .pkg and .app(.zip)
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
echo "Build macOS packages, optionally signing and notarizing them."
|
|
||||||
echo "Usage: $0 options"
|
|
||||||
echo "Options:"
|
|
||||||
echo " -s Enables code signing"
|
|
||||||
echo " -f <APP_KEY.p12> Path to .p12 file for application signing"
|
|
||||||
echo " -i <INSTALLER_KEY.p12> Path to .p12 file for installer signing"
|
|
||||||
echo " -p <PASSWORD> Password for the .p12 files (necessary to access the certificates)"
|
|
||||||
echo " -e <entitlements file> (Optional) Path to an entitlements XML file"
|
|
||||||
echo " -n Enables notarization. This will fail if code signing is not also enabled."
|
|
||||||
echo " -j <API_KEY.JSON> Path to JSON file generated with \`rcodesign encode-app-store-connect-api-key\` (required for notarization)"
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
set -x
|
|
||||||
set -e
|
|
||||||
|
|
||||||
SIGN=
|
|
||||||
NOTARIZE=
|
|
||||||
|
|
||||||
ARM64_DEPLOY_TARGET='MACOSX_DEPLOYMENT_TARGET=11.0'
|
|
||||||
X86_64_DEPLOY_TARGET='MACOSX_DEPLOYMENT_TARGET=10.9'
|
|
||||||
|
|
||||||
# As of this writing, the most recent Rust release supports macOS back to 10.12.
|
|
||||||
# The first supported version of macOS on arm64 is 10.15, so any Rust is fine for arm64.
|
|
||||||
# We wish to support back to 10.9 on x86-64; the last version of Rust to support that is
|
|
||||||
# version 1.73.0.
|
|
||||||
RUST_VERSION_X86_64=1.70.0
|
|
||||||
|
|
||||||
while getopts "sf:i:p:e:nj:" opt; do
|
|
||||||
case $opt in
|
|
||||||
s) SIGN=1;;
|
|
||||||
f) P12_APP_FILE=$(realpath "$OPTARG");;
|
|
||||||
i) P12_INSTALL_FILE=$(realpath "$OPTARG");;
|
|
||||||
p) P12_PASSWORD="$OPTARG";;
|
|
||||||
e) ENTITLEMENTS_FILE=$(realpath "$OPTARG");;
|
|
||||||
n) NOTARIZE=1;;
|
|
||||||
j) API_KEY_FILE=$(realpath "$OPTARG");;
|
|
||||||
\?) usage;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -n "$SIGN" ] && { [ -z "$P12_APP_FILE" ] || [ -z "$P12_INSTALL_FILE" ] || [ -z "$P12_PASSWORD" ]; }; then
|
|
||||||
usage
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$NOTARIZE" ] && [ -z "$API_KEY_FILE" ]; then
|
|
||||||
usage
|
|
||||||
fi
|
|
||||||
|
|
||||||
VERSION=$(git describe --always --dirty 2>/dev/null)
|
|
||||||
if test -z "$VERSION" ; then
|
|
||||||
echo "Could not get version from git"
|
|
||||||
if test -f version; then
|
|
||||||
VERSION=$(cat version)
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Version is $VERSION"
|
|
||||||
|
|
||||||
PKGDIR=$(mktemp -d)
|
|
||||||
echo "$PKGDIR"
|
|
||||||
|
|
||||||
SRC_DIR=$PWD
|
|
||||||
OUTPUT_PATH=${FISH_ARTEFACT_PATH:-~/fish_built}
|
|
||||||
|
|
||||||
mkdir -p "$PKGDIR/build_x86_64" "$PKGDIR/build_arm64" "$PKGDIR/root" "$PKGDIR/intermediates" "$PKGDIR/dst"
|
|
||||||
|
|
||||||
# Build and install for arm64.
|
|
||||||
# Pass FISH_USE_SYSTEM_PCRE2=OFF because a system PCRE2 on macOS will not be signed by fish,
|
|
||||||
# and will probably not be built universal, so the package will fail to validate/run on other systems.
|
|
||||||
# Note CMAKE_OSX_ARCHITECTURES is still relevant for the Mac app.
|
|
||||||
{ cd "$PKGDIR/build_arm64" \
|
|
||||||
&& cmake \
|
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
|
||||||
-DCMAKE_EXE_LINKER_FLAGS="-Wl,-ld_classic" \
|
|
||||||
-DWITH_GETTEXT=OFF \
|
|
||||||
-DRust_CARGO_TARGET=aarch64-apple-darwin \
|
|
||||||
-DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' \
|
|
||||||
-DFISH_USE_SYSTEM_PCRE2=OFF \
|
|
||||||
"$SRC_DIR" \
|
|
||||||
&& env $ARM64_DEPLOY_TARGET make VERBOSE=1 -j 12 \
|
|
||||||
&& env DESTDIR="$PKGDIR/root/" $ARM64_DEPLOY_TARGET make install;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build for x86-64 but do not install; instead we will make some fat binaries inside the root.
|
|
||||||
# Set RUST_VERSION_X86_64 to the last version of Rust that supports macOS 10.9.
|
|
||||||
{ cd "$PKGDIR/build_x86_64" \
|
|
||||||
&& cmake \
|
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
|
||||||
-DCMAKE_EXE_LINKER_FLAGS="-Wl,-ld_classic" \
|
|
||||||
-DWITH_GETTEXT=OFF \
|
|
||||||
-DRust_TOOLCHAIN="$RUST_VERSION_X86_64" \
|
|
||||||
-DRust_CARGO_TARGET=x86_64-apple-darwin \
|
|
||||||
-DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' \
|
|
||||||
-DFISH_USE_SYSTEM_PCRE2=OFF "$SRC_DIR" \
|
|
||||||
&& env $X86_64_DEPLOY_TARGET make VERBOSE=1 -j 12; }
|
|
||||||
|
|
||||||
# Fatten them up.
|
|
||||||
for FILE in "$PKGDIR"/root/usr/local/bin/*; do
|
|
||||||
X86_FILE="$PKGDIR/build_x86_64/$(basename "$FILE")"
|
|
||||||
rcodesign macho-universal-create --output "$FILE" "$FILE" "$X86_FILE"
|
|
||||||
chmod 755 "$FILE"
|
|
||||||
done
|
|
||||||
|
|
||||||
if test -n "$SIGN"; then
|
|
||||||
echo "Signing executables"
|
|
||||||
ARGS=(
|
|
||||||
--p12-file "$P12_APP_FILE"
|
|
||||||
--p12-password "$P12_PASSWORD"
|
|
||||||
--code-signature-flags runtime
|
|
||||||
--for-notarization
|
|
||||||
)
|
|
||||||
if [ -n "$ENTITLEMENTS_FILE" ]; then
|
|
||||||
ARGS+=(--entitlements-xml-file "$ENTITLEMENTS_FILE")
|
|
||||||
fi
|
|
||||||
for FILE in "$PKGDIR"/root/usr/local/bin/*; do
|
|
||||||
(set +x; rcodesign sign "${ARGS[@]}" "$FILE")
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
pkgbuild --scripts "$SRC_DIR/build_tools/osx_package_scripts" --root "$PKGDIR/root/" --identifier 'com.ridiculousfish.fish-shell-pkg' --version "$VERSION" "$PKGDIR/intermediates/fish.pkg"
|
|
||||||
productbuild --package-path "$PKGDIR/intermediates" --distribution "$SRC_DIR/build_tools/osx_distribution.xml" --resources "$SRC_DIR/build_tools/osx_package_resources/" "$OUTPUT_PATH/fish-$VERSION.pkg"
|
|
||||||
|
|
||||||
if test -n "$SIGN"; then
|
|
||||||
echo "Signing installer"
|
|
||||||
ARGS=(
|
|
||||||
--p12-file "$P12_INSTALL_FILE"
|
|
||||||
--p12-password "$P12_PASSWORD"
|
|
||||||
--code-signature-flags runtime
|
|
||||||
--for-notarization
|
|
||||||
)
|
|
||||||
(set +x; rcodesign sign "${ARGS[@]}" "$OUTPUT_PATH/fish-$VERSION.pkg")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Make the app
|
|
||||||
(cd "$PKGDIR/build_arm64" && env $ARM64_DEPLOY_TARGET make -j 12 fish_macapp)
|
|
||||||
(cd "$PKGDIR/build_x86_64" && env $X86_64_DEPLOY_TARGET make -j 12 fish_macapp)
|
|
||||||
|
|
||||||
# Make the app's /usr/local/bin binaries universal. Note fish.app/Contents/MacOS/fish already is, courtesy of CMake.
|
|
||||||
cd "$PKGDIR/build_arm64"
|
|
||||||
for FILE in fish.app/Contents/Resources/base/usr/local/bin/*; do
|
|
||||||
X86_FILE="$PKGDIR/build_x86_64/fish.app/Contents/Resources/base/usr/local/bin/$(basename "$FILE")"
|
|
||||||
rcodesign macho-universal-create --output "$FILE" "$FILE" "$X86_FILE"
|
|
||||||
|
|
||||||
# macho-universal-create screws up the permissions.
|
|
||||||
chmod 755 "$FILE"
|
|
||||||
done
|
|
||||||
|
|
||||||
if test -n "$SIGN"; then
|
|
||||||
echo "Signing app"
|
|
||||||
ARGS=(
|
|
||||||
--p12-file "$P12_APP_FILE"
|
|
||||||
--p12-password "$P12_PASSWORD"
|
|
||||||
--code-signature-flags runtime
|
|
||||||
--for-notarization
|
|
||||||
)
|
|
||||||
if [ -n "$ENTITLEMENTS_FILE" ]; then
|
|
||||||
ARGS+=(--entitlements-xml-file "$ENTITLEMENTS_FILE")
|
|
||||||
fi
|
|
||||||
(set +x; rcodesign sign "${ARGS[@]}" "fish.app")
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
cp -R "fish.app" "$OUTPUT_PATH/fish-$VERSION.app"
|
|
||||||
cd "$OUTPUT_PATH"
|
|
||||||
|
|
||||||
# Maybe notarize.
|
|
||||||
if test -n "$NOTARIZE"; then
|
|
||||||
echo "Notarizing"
|
|
||||||
rcodesign notarize --staple --wait --max-wait-seconds 1800 --api-key-file "$API_KEY_FILE" "$OUTPUT_PATH/fish-$VERSION.pkg"
|
|
||||||
rcodesign notarize --staple --wait --max-wait-seconds 1800 --api-key-file "$API_KEY_FILE" "$OUTPUT_PATH/fish-$VERSION.app"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Zip it up.
|
|
||||||
zip -r "fish-$VERSION.app.zip" "fish-$VERSION.app" && rm -Rf "fish-$VERSION.app"
|
|
||||||
|
|
||||||
rm -rf "$PKGDIR"
|
|
||||||
@@ -2,182 +2,38 @@
|
|||||||
|
|
||||||
# Script to produce an OS X installer .pkg and .app(.zip)
|
# Script to produce an OS X installer .pkg and .app(.zip)
|
||||||
|
|
||||||
usage() {
|
|
||||||
echo "Build macOS packages, optionally signing and notarizing them."
|
|
||||||
echo "Usage: $0 options"
|
|
||||||
echo "Options:"
|
|
||||||
echo " -s Enables code signing"
|
|
||||||
echo " -f <APP_KEY.p12> Path to .p12 file for application signing"
|
|
||||||
echo " -i <INSTALLER_KEY.p12> Path to .p12 file for installer signing"
|
|
||||||
echo " -p <PASSWORD> Password for the .p12 files (necessary to access the certificates)"
|
|
||||||
echo " -e <entitlements file> (Optional) Path to an entitlements XML file"
|
|
||||||
echo " -n Enables notarization. This will fail if code signing is not also enabled."
|
|
||||||
echo " -j <API_KEY.JSON> Path to JSON file generated with \`rcodesign encode-app-store-connect-api-key\` (required for notarization)"
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
set -x
|
|
||||||
set -e
|
|
||||||
|
|
||||||
SIGN=
|
|
||||||
NOTARIZE=
|
|
||||||
|
|
||||||
ARM64_DEPLOY_TARGET='MACOSX_DEPLOYMENT_TARGET=11.0'
|
|
||||||
X86_64_DEPLOY_TARGET='MACOSX_DEPLOYMENT_TARGET=10.9'
|
|
||||||
|
|
||||||
# As of this writing, the most recent Rust release supports macOS back to 10.12.
|
|
||||||
# The first supported version of macOS on arm64 is 10.15, so any Rust is fine for arm64.
|
|
||||||
# We wish to support back to 10.9 on x86-64; the last version of Rust to support that is
|
|
||||||
# version 1.73.0.
|
|
||||||
RUST_VERSION_X86_64=1.70.0
|
|
||||||
|
|
||||||
while getopts "sf:i:p:e:nj:" opt; do
|
|
||||||
case $opt in
|
|
||||||
s) SIGN=1;;
|
|
||||||
f) P12_APP_FILE=$(realpath "$OPTARG");;
|
|
||||||
i) P12_INSTALL_FILE=$(realpath "$OPTARG");;
|
|
||||||
p) P12_PASSWORD="$OPTARG";;
|
|
||||||
e) ENTITLEMENTS_FILE=$(realpath "$OPTARG");;
|
|
||||||
n) NOTARIZE=1;;
|
|
||||||
j) API_KEY_FILE=$(realpath "$OPTARG");;
|
|
||||||
\?) usage;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -n "$SIGN" ] && { [ -z "$P12_APP_FILE" ] || [ -z "$P12_INSTALL_FILE" ] || [ -z "$P12_PASSWORD" ]; }; then
|
|
||||||
usage
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$NOTARIZE" ] && [ -z "$API_KEY_FILE" ]; then
|
|
||||||
usage
|
|
||||||
fi
|
|
||||||
|
|
||||||
VERSION=$(git describe --always --dirty 2>/dev/null)
|
VERSION=$(git describe --always --dirty 2>/dev/null)
|
||||||
if test -z "$VERSION" ; then
|
if test -z "$VERSION" ; then
|
||||||
echo "Could not get version from git"
|
echo "Could not get version from git"
|
||||||
if test -f version; then
|
if test -f version; then
|
||||||
VERSION=$(cat version)
|
VERSION=$(cat version)
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Version is $VERSION"
|
echo "Version is $VERSION"
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
#Exit on error
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Respect MAC_CODESIGN_ID and MAC_PRODUCTSIGN_ID, or default for ad-hoc.
|
||||||
|
# Note the :- means "or default" and the following - is the value.
|
||||||
|
MAC_CODESIGN_ID=${MAC_CODESIGN_ID:--}
|
||||||
|
MAC_PRODUCTSIGN_ID=${MAC_PRODUCTSIGN_ID:--}
|
||||||
|
|
||||||
PKGDIR=$(mktemp -d)
|
PKGDIR=$(mktemp -d)
|
||||||
echo "$PKGDIR"
|
|
||||||
|
|
||||||
SRC_DIR=$PWD
|
SRC_DIR=$PWD
|
||||||
OUTPUT_PATH=${FISH_ARTEFACT_PATH:-~/fish_built}
|
OUTPUT_PATH=${FISH_ARTEFACT_PATH:-~/fish_built}
|
||||||
|
|
||||||
mkdir -p "$PKGDIR/build_x86_64" "$PKGDIR/build_arm64" "$PKGDIR/root" "$PKGDIR/intermediates" "$PKGDIR/dst"
|
mkdir -p "$PKGDIR/build" "$PKGDIR/root" "$PKGDIR/intermediates" "$PKGDIR/dst"
|
||||||
|
{ cd "$PKGDIR/build" && cmake -DMAC_INJECT_GET_TASK_ALLOW=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DMAC_CODESIGN_ID="${MAC_CODESIGN_ID}" "$SRC_DIR" && make -j 12 && env DESTDIR="$PKGDIR/root/" make install; }
|
||||||
# Build and install for arm64.
|
|
||||||
# Pass FISH_USE_SYSTEM_PCRE2=OFF because a system PCRE2 on macOS will not be signed by fish,
|
|
||||||
# and will probably not be built universal, so the package will fail to validate/run on other systems.
|
|
||||||
# Note CMAKE_OSX_ARCHITECTURES is still relevant for the Mac app.
|
|
||||||
{ cd "$PKGDIR/build_arm64" \
|
|
||||||
&& cmake \
|
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
|
||||||
-DCMAKE_EXE_LINKER_FLAGS="-Wl,-ld_classic" \
|
|
||||||
-DWITH_GETTEXT=OFF \
|
|
||||||
-DRust_CARGO_TARGET=aarch64-apple-darwin \
|
|
||||||
-DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' \
|
|
||||||
-DFISH_USE_SYSTEM_PCRE2=OFF \
|
|
||||||
"$SRC_DIR" \
|
|
||||||
&& env $ARM64_DEPLOY_TARGET make VERBOSE=1 -j 12 \
|
|
||||||
&& env DESTDIR="$PKGDIR/root/" $ARM64_DEPLOY_TARGET make install;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build for x86-64 but do not install; instead we will make some fat binaries inside the root.
|
|
||||||
# Set RUST_VERSION_X86_64 to the last version of Rust that supports macOS 10.9.
|
|
||||||
{ cd "$PKGDIR/build_x86_64" \
|
|
||||||
&& cmake \
|
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
|
||||||
-DCMAKE_EXE_LINKER_FLAGS="-Wl,-ld_classic" \
|
|
||||||
-DWITH_GETTEXT=OFF \
|
|
||||||
-DRust_TOOLCHAIN="$RUST_VERSION_X86_64" \
|
|
||||||
-DRust_CARGO_TARGET=x86_64-apple-darwin \
|
|
||||||
-DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' \
|
|
||||||
-DFISH_USE_SYSTEM_PCRE2=OFF "$SRC_DIR" \
|
|
||||||
&& env $X86_64_DEPLOY_TARGET make VERBOSE=1 -j 12; }
|
|
||||||
|
|
||||||
# Fatten them up.
|
|
||||||
for FILE in "$PKGDIR"/root/usr/local/bin/*; do
|
|
||||||
X86_FILE="$PKGDIR/build_x86_64/$(basename "$FILE")"
|
|
||||||
rcodesign macho-universal-create --output "$FILE" "$FILE" "$X86_FILE"
|
|
||||||
chmod 755 "$FILE"
|
|
||||||
done
|
|
||||||
|
|
||||||
if test -n "$SIGN"; then
|
|
||||||
echo "Signing executables"
|
|
||||||
ARGS=(
|
|
||||||
--p12-file "$P12_APP_FILE"
|
|
||||||
--p12-password "$P12_PASSWORD"
|
|
||||||
--code-signature-flags runtime
|
|
||||||
--for-notarization
|
|
||||||
)
|
|
||||||
if [ -n "$ENTITLEMENTS_FILE" ]; then
|
|
||||||
ARGS+=(--entitlements-xml-file "$ENTITLEMENTS_FILE")
|
|
||||||
fi
|
|
||||||
for FILE in "$PKGDIR"/root/usr/local/bin/*; do
|
|
||||||
(set +x; rcodesign sign "${ARGS[@]}" "$FILE")
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
pkgbuild --scripts "$SRC_DIR/build_tools/osx_package_scripts" --root "$PKGDIR/root/" --identifier 'com.ridiculousfish.fish-shell-pkg' --version "$VERSION" "$PKGDIR/intermediates/fish.pkg"
|
pkgbuild --scripts "$SRC_DIR/build_tools/osx_package_scripts" --root "$PKGDIR/root/" --identifier 'com.ridiculousfish.fish-shell-pkg' --version "$VERSION" "$PKGDIR/intermediates/fish.pkg"
|
||||||
productbuild --package-path "$PKGDIR/intermediates" --distribution "$SRC_DIR/build_tools/osx_distribution.xml" --resources "$SRC_DIR/build_tools/osx_package_resources/" "$OUTPUT_PATH/fish-$VERSION.pkg"
|
productbuild --package-path "$PKGDIR/intermediates" --distribution "$SRC_DIR/build_tools/osx_distribution.xml" --resources "$SRC_DIR/build_tools/osx_package_resources/" "$OUTPUT_PATH/fish-$VERSION.pkg"
|
||||||
|
productsign --sign "${MAC_PRODUCTSIGN_ID}" "$OUTPUT_PATH/fish-$VERSION.pkg" "$OUTPUT_PATH/fish-$VERSION-signed.pkg" && mv "$OUTPUT_PATH/fish-$VERSION-signed.pkg" "$OUTPUT_PATH/fish-$VERSION.pkg"
|
||||||
if test -n "$SIGN"; then
|
|
||||||
echo "Signing installer"
|
|
||||||
ARGS=(
|
|
||||||
--p12-file "$P12_INSTALL_FILE"
|
|
||||||
--p12-password "$P12_PASSWORD"
|
|
||||||
--code-signature-flags runtime
|
|
||||||
--for-notarization
|
|
||||||
)
|
|
||||||
(set +x; rcodesign sign "${ARGS[@]}" "$OUTPUT_PATH/fish-$VERSION.pkg")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Make the app
|
# Make the app
|
||||||
(cd "$PKGDIR/build_arm64" && env $ARM64_DEPLOY_TARGET make -j 12 fish_macapp)
|
{ cd "$PKGDIR/build" && make signed_fish_macapp && zip -r "$OUTPUT_PATH/fish-$VERSION.app.zip" fish.app; }
|
||||||
(cd "$PKGDIR/build_x86_64" && env $X86_64_DEPLOY_TARGET make -j 12 fish_macapp)
|
|
||||||
|
|
||||||
# Make the app's /usr/local/bin binaries universal. Note fish.app/Contents/MacOS/fish already is, courtesy of CMake.
|
rm -r "$PKGDIR"
|
||||||
cd "$PKGDIR/build_arm64"
|
|
||||||
for FILE in fish.app/Contents/Resources/base/usr/local/bin/*; do
|
|
||||||
X86_FILE="$PKGDIR/build_x86_64/fish.app/Contents/Resources/base/usr/local/bin/$(basename "$FILE")"
|
|
||||||
rcodesign macho-universal-create --output "$FILE" "$FILE" "$X86_FILE"
|
|
||||||
|
|
||||||
# macho-universal-create screws up the permissions.
|
|
||||||
chmod 755 "$FILE"
|
|
||||||
done
|
|
||||||
|
|
||||||
if test -n "$SIGN"; then
|
|
||||||
echo "Signing app"
|
|
||||||
ARGS=(
|
|
||||||
--p12-file "$P12_APP_FILE"
|
|
||||||
--p12-password "$P12_PASSWORD"
|
|
||||||
--code-signature-flags runtime
|
|
||||||
--for-notarization
|
|
||||||
)
|
|
||||||
if [ -n "$ENTITLEMENTS_FILE" ]; then
|
|
||||||
ARGS+=(--entitlements-xml-file "$ENTITLEMENTS_FILE")
|
|
||||||
fi
|
|
||||||
(set +x; rcodesign sign "${ARGS[@]}" "fish.app")
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
cp -R "fish.app" "$OUTPUT_PATH/fish-$VERSION.app"
|
|
||||||
cd "$OUTPUT_PATH"
|
|
||||||
|
|
||||||
# Maybe notarize.
|
|
||||||
if test -n "$NOTARIZE"; then
|
|
||||||
echo "Notarizing"
|
|
||||||
rcodesign notarize --staple --wait --max-wait-seconds 1800 --api-key-file "$API_KEY_FILE" "$OUTPUT_PATH/fish-$VERSION.pkg"
|
|
||||||
rcodesign notarize --staple --wait --max-wait-seconds 1800 --api-key-file "$API_KEY_FILE" "$OUTPUT_PATH/fish-$VERSION.app"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Zip it up.
|
|
||||||
zip -r "fish-$VERSION.app.zip" "fish-$VERSION.app" && rm -Rf "fish-$VERSION.app"
|
|
||||||
|
|
||||||
rm -rf "$PKGDIR"
|
|
||||||
|
|||||||
@@ -14,14 +14,6 @@ set -e
|
|||||||
# but to get the documentation in, we need to make a symlink called "fish-VERSION"
|
# but to get the documentation in, we need to make a symlink called "fish-VERSION"
|
||||||
# and tar from that, so that the documentation gets the right prefix
|
# and tar from that, so that the documentation gets the right prefix
|
||||||
|
|
||||||
# Use Ninja if available, as it automatically paralellises
|
|
||||||
BUILD_TOOL="make"
|
|
||||||
BUILD_GENERATOR="Unix Makefiles"
|
|
||||||
if command -v ninja >/dev/null; then
|
|
||||||
BUILD_TOOL="ninja"
|
|
||||||
BUILD_GENERATOR="Ninja"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# We need GNU tar as that supports the --mtime and --transform options
|
# We need GNU tar as that supports the --mtime and --transform options
|
||||||
TAR=notfound
|
TAR=notfound
|
||||||
for try in tar gtar gnutar; do
|
for try in tar gtar gnutar; do
|
||||||
@@ -59,8 +51,8 @@ git archive --format=tar --prefix="$prefix"/ HEAD > "$path"
|
|||||||
PREFIX_TMPDIR=$(mktemp -d)
|
PREFIX_TMPDIR=$(mktemp -d)
|
||||||
cd "$PREFIX_TMPDIR"
|
cd "$PREFIX_TMPDIR"
|
||||||
echo "$VERSION" > version
|
echo "$VERSION" > version
|
||||||
cmake -G "$BUILD_GENERATOR" "$wd"
|
cmake "$wd"
|
||||||
$BUILD_TOOL doc
|
make doc
|
||||||
|
|
||||||
TAR_APPEND="$TAR --append --file=$path --mtime=now --owner=0 --group=0 \
|
TAR_APPEND="$TAR --append --file=$path --mtime=now --owner=0 --group=0 \
|
||||||
--mode=g+w,a+rX --transform s/^/$prefix\//"
|
--mode=g+w,a+rX --transform s/^/$prefix\//"
|
||||||
@@ -74,6 +66,6 @@ rm -r "$PREFIX_TMPDIR"
|
|||||||
# xz it
|
# xz it
|
||||||
xz "$path"
|
xz "$path"
|
||||||
|
|
||||||
# Output what we did, and the sha256 hash
|
# Output what we did, and the sha1 hash
|
||||||
echo "Tarball written to $path".xz
|
echo "Tarball written to $path".xz
|
||||||
openssl dgst -sha256 "$path".xz
|
openssl dgst -sha256 "$path".xz
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Script to generate a tarball of vendored (downloaded) Rust dependencies
|
|
||||||
# and the cargo configuration to ensure they are used
|
|
||||||
# This tarball should be unpacked into a fish source directory
|
|
||||||
# Outputs to $FISH_ARTEFACT_PATH or ~/fish_built by default
|
|
||||||
|
|
||||||
# Exit on error
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# We need GNU tar as that supports the --mtime and --transform options
|
|
||||||
TAR=notfound
|
|
||||||
for try in tar gtar gnutar; do
|
|
||||||
if $try -Pcf /dev/null --mtime now /dev/null >/dev/null 2>&1; then
|
|
||||||
TAR=$try
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "$TAR" = "notfound" ]; then
|
|
||||||
echo 'No suitable tar (supporting --mtime) found as tar/gtar/gnutar in PATH'
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get the current directory, which we'll use for telling Cargo where to find the sources
|
|
||||||
wd="$PWD"
|
|
||||||
|
|
||||||
# Get the version from git-describe
|
|
||||||
VERSION=$(git describe --dirty 2>/dev/null)
|
|
||||||
|
|
||||||
# The name of the prefix, which is the directory that you get when you untar
|
|
||||||
prefix="fish-$VERSION"
|
|
||||||
|
|
||||||
# The path where we will output the tar file
|
|
||||||
# Defaults to ~/fish_built
|
|
||||||
path=${FISH_ARTEFACT_PATH:-~/fish_built}/$prefix-vendor.tar
|
|
||||||
|
|
||||||
# Clean up stuff we've written before
|
|
||||||
rm -f "$path" "$path".xz
|
|
||||||
|
|
||||||
# Work in a temporary directory to avoid clobbering the source directory
|
|
||||||
PREFIX_TMPDIR=$(mktemp -d)
|
|
||||||
cd "$PREFIX_TMPDIR"
|
|
||||||
|
|
||||||
mkdir .cargo
|
|
||||||
cargo vendor --manifest-path "$wd/Cargo.toml" > .cargo/config.toml
|
|
||||||
|
|
||||||
tar cfvJ $path.xz vendor .cargo
|
|
||||||
|
|
||||||
cd -
|
|
||||||
rm -r "$PREFIX_TMPDIR"
|
|
||||||
|
|
||||||
# Output what we did, and the sha256 hash
|
|
||||||
echo "Tarball written to $path".xz
|
|
||||||
openssl dgst -sha256 "$path".xz
|
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
<installer-gui-script minSpecVersion="1">
|
<installer-gui-script minSpecVersion="1">
|
||||||
<title>fish shell</title>
|
<title>fish shell</title>
|
||||||
<welcome file="welcome.html" mime-type="text/html"/>
|
<welcome file="welcome.rtf"/>
|
||||||
<background file="terminal_logo.png" scaling="proportional" alignment="bottomleft"/>
|
<background file="terminal_logo.png" scaling="proportional" alignment="bottomleft"/>
|
||||||
<pkg-ref id="com.ridiculousfish.fish-shell-pkg"/>
|
<pkg-ref id="com.ridiculousfish.fish-shell-pkg"/>
|
||||||
<options hostArchitectures="arm64,x86_64" rootVolumeOnly="true"/>
|
<options customize="never" require-scripts="false"/>
|
||||||
<options customize="never" require-scripts="true"/>
|
|
||||||
<choices-outline>
|
<choices-outline>
|
||||||
<line choice="default">
|
<line choice="default">
|
||||||
<line choice="com.ridiculousfish.fish-shell-pkg"/>
|
<line choice="com.ridiculousfish.fish-shell-pkg"/>
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-family: system-ui, -apple-system, "Helvetica Neue", sans-serif;
|
|
||||||
font-size: 10pt;
|
|
||||||
}
|
|
||||||
code, tt {
|
|
||||||
font-family: ui-monospace, Menlo, monospace;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p>
|
|
||||||
<strong>fish</strong> is a smart and user-friendly command line shell. For more information, visit <a href="https://fishshell.com">fishshell.com</a>.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<strong>fish</strong> will be installed into <tt>/usr/local/</tt>, and its path will be added to <wbr><tt>/etc/shells</tt> if necessary.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Your default shell will <em>not</em> be changed. To make <strong>fish</strong> your login shell after the installation, run:
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<code>chsh -s /usr/local/bin/fish</code>
|
|
||||||
</p>
|
|
||||||
<p>Enjoy! Bugs can be reported on <a href="https://github.org/fish-shell/fish-shell/">GitHub</a>.</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
26
build_tools/osx_package_resources/welcome.rtf
Normal file
26
build_tools/osx_package_resources/welcome.rtf
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{\rtf1\ansi\ansicpg1252\cocoartf1485\cocoasubrtf410
|
||||||
|
{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;\f1\fnil\fcharset0 Menlo-Regular;}
|
||||||
|
{\colortbl;\red255\green255\blue255;}
|
||||||
|
{\*\expandedcolortbl;\csgenericrgb\c100000\c100000\c100000;}
|
||||||
|
{\info
|
||||||
|
{\author dlkfjslfjsfdlkfk}}\margl1440\margr1440\vieww10800\viewh8400\viewkind0
|
||||||
|
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
|
||||||
|
|
||||||
|
\f0\fs30 \cf0 Fish is a smart and user friendly command line shell. For more information, visit {\field{\*\fldinst{HYPERLINK "https://fishshell.com"}}{\fldrslt https://fishshell.com}}\
|
||||||
|
\
|
||||||
|
fish will be installed into
|
||||||
|
\f1\fs26 /usr/local/
|
||||||
|
\f0\fs30 , and fish will be added to
|
||||||
|
\f1\fs26 /etc/shells
|
||||||
|
\f0\fs30 if necessary.\
|
||||||
|
\
|
||||||
|
Your default shell will
|
||||||
|
\i not
|
||||||
|
\i0 be changed. To make fish your default, run:\
|
||||||
|
\
|
||||||
|
|
||||||
|
\f1 chsh -s /usr/local/bin/fish
|
||||||
|
\f0 \
|
||||||
|
\
|
||||||
|
Enjoy!\
|
||||||
|
}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
#!/bin/sh -x
|
#!/bin/sh -x
|
||||||
|
|
||||||
./add-shell ${DSTVOLUME}usr/local/bin/fish
|
./add-shell /usr/local/bin/fish > /tmp/fish_postinstall_output.log
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/sh -x
|
|
||||||
|
|
||||||
echo "Removing any previous installation"
|
|
||||||
pkgutil --pkg-info ${INSTALL_PKG_SESSION_ID} && pkgutil --only-files --files ${INSTALL_PKG_SESSION_ID} | while read installed
|
|
||||||
do rm -v ${DSTVOLUME}${installed}
|
|
||||||
done
|
|
||||||
echo "... removed"
|
|
||||||
@@ -22,51 +22,33 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import pexpect
|
import pexpect
|
||||||
from signal import Signals
|
|
||||||
|
|
||||||
# Default timeout for failing to match.
|
# Default timeout for failing to match.
|
||||||
TIMEOUT_SECS = 5
|
TIMEOUT_SECS = 5
|
||||||
|
|
||||||
UNEXPECTED_SUCCESS = object()
|
|
||||||
|
|
||||||
# When rendering fish's output, remove the control sequences that modify terminal state,
|
|
||||||
# to avoid confusing the calling terminal. No need to replace things like colors and cursor
|
|
||||||
# movement that are harmless and/or will not leak anyway.
|
|
||||||
SANITIZE_FOR_PRINTING_RE = re.compile(
|
|
||||||
r"""
|
|
||||||
\x1b\[\?1004[hl]
|
|
||||||
| \x1b\[\?2004[hl]
|
|
||||||
| \x1b\[>4;[10]m
|
|
||||||
| \x1b\[>5u
|
|
||||||
| \x1b\[<1u
|
|
||||||
| \x1b=
|
|
||||||
| \x1b>
|
|
||||||
| \x1b\].*?\x07
|
|
||||||
""",
|
|
||||||
re.VERBOSE)
|
|
||||||
|
|
||||||
|
|
||||||
def get_prompt_re(counter):
|
def get_prompt_re(counter):
|
||||||
"""Return a regular expression for matching a with a given prompt counter."""
|
""" Return a regular expression for matching a with a given prompt counter. """
|
||||||
return re.compile("prompt %d>" % counter)
|
return re.compile(
|
||||||
|
r"""(?:\r\n?|^) # beginning of line
|
||||||
|
(?:\[.\]\ )? # optional vi mode prompt
|
||||||
|
"""
|
||||||
|
+ (r"prompt\ %d>" % counter), # prompt with counter
|
||||||
|
re.VERBOSE,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_callsite():
|
def get_callsite():
|
||||||
"""Return a triple (filename, line_number, line_text) of the call site location."""
|
""" Return a triple (filename, line_number, line_text) of the call site location. """
|
||||||
callstack = inspect.getouterframes(inspect.currentframe())
|
callstack = inspect.getouterframes(inspect.currentframe())
|
||||||
for f in callstack:
|
for f in callstack:
|
||||||
# Skip call sites from this file.
|
if inspect.getmodule(f.frame) is not Message.MODULE:
|
||||||
if inspect.getmodule(f.frame) is Message.MODULE:
|
return (os.path.basename(f.filename), f.lineno, f.code_context)
|
||||||
continue
|
|
||||||
# Skip functions which have a truthy callsite_skip attribute.
|
|
||||||
if getattr(f.function, "callsite_skip", False):
|
|
||||||
continue
|
|
||||||
return (os.path.basename(f.filename), f.lineno, f.code_context)
|
|
||||||
return ("Unknown", -1, "")
|
return ("Unknown", -1, "")
|
||||||
|
|
||||||
|
|
||||||
def escape(s):
|
def escape(s):
|
||||||
"""Escape the string 's' to make it human-understandable."""
|
""" Escape the string 's' to make it human-understandable. """
|
||||||
res = []
|
res = []
|
||||||
for c in s:
|
for c in s:
|
||||||
if c == "\n":
|
if c == "\n":
|
||||||
@@ -83,19 +65,17 @@ def escape(s):
|
|||||||
|
|
||||||
|
|
||||||
def pexpect_error_type(err):
|
def pexpect_error_type(err):
|
||||||
"""Return a human-readable description of a pexpect error type."""
|
""" Return a human-readable description of a pexpect error type. """
|
||||||
if isinstance(err, pexpect.EOF):
|
if isinstance(err, pexpect.EOF):
|
||||||
return "EOF"
|
return "EOF"
|
||||||
elif isinstance(err, pexpect.TIMEOUT):
|
elif isinstance(err, pexpect.TIMEOUT):
|
||||||
return "timeout"
|
return "timeout"
|
||||||
elif err is UNEXPECTED_SUCCESS:
|
|
||||||
return "unexpected success"
|
|
||||||
else:
|
else:
|
||||||
return "unknown error"
|
return "unknown error"
|
||||||
|
|
||||||
|
|
||||||
class Message(object):
|
class Message(object):
|
||||||
"""Some text either sent-to or received-from the spawned proc.
|
""" Some text either sent-to or received-from the spawned proc.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
dir: the message direction, either DIR_INPUT or DIR_OUTPUT
|
dir: the message direction, either DIR_INPUT or DIR_OUTPUT
|
||||||
@@ -113,7 +93,7 @@ class Message(object):
|
|||||||
MODULE = sys.modules[__name__]
|
MODULE = sys.modules[__name__]
|
||||||
|
|
||||||
def __init__(self, dir, text, when):
|
def __init__(self, dir, text, when):
|
||||||
"""Construct from a direction, message text and timestamp."""
|
""" Construct from a direction, message text and timestamp. """
|
||||||
self.dir = dir
|
self.dir = dir
|
||||||
self.filename, self.lineno, _ = get_callsite()
|
self.filename, self.lineno, _ = get_callsite()
|
||||||
self.text = text
|
self.text = text
|
||||||
@@ -121,17 +101,17 @@ class Message(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sent_input(text, when):
|
def sent_input(text, when):
|
||||||
"""Return an input message with the given text."""
|
""" Return an input message with the given text. """
|
||||||
return Message(Message.DIR_INPUT, text, when)
|
return Message(Message.DIR_INPUT, text, when)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def received_output(text, when):
|
def received_output(text, when):
|
||||||
"""Return a output message with the given text."""
|
""" Return a output message with the given text. """
|
||||||
return Message(Message.DIR_OUTPUT, text, when)
|
return Message(Message.DIR_OUTPUT, text, when)
|
||||||
|
|
||||||
|
|
||||||
class SpawnedProc(object):
|
class SpawnedProc(object):
|
||||||
"""A process, talking to our ptty. This wraps pexpect.spawn.
|
""" A process, talking to our ptty. This wraps pexpect.spawn.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
colorize: whether error messages should have ANSI color escapes
|
colorize: whether error messages should have ANSI color escapes
|
||||||
@@ -142,41 +122,37 @@ class SpawnedProc(object):
|
|||||||
function to ensure that each printed prompt is distinct.
|
function to ensure that each printed prompt is distinct.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, name="fish", timeout=TIMEOUT_SECS, env=os.environ.copy()):
|
||||||
self, name="fish", timeout=TIMEOUT_SECS, env=os.environ.copy(), **kwargs
|
""" Construct from a name, timeout, and environment.
|
||||||
):
|
|
||||||
"""Construct from a name, timeout, and environment.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
name: the name of the executable to launch, as a key into the
|
name: the name of the executable to launch, as a key into the
|
||||||
environment dictionary. By default this is 'fish' but may be
|
environment dictionary. By default this is 'fish' but may be
|
||||||
other executables.
|
other executables.
|
||||||
timeout: A timeout to pass to pexpect. This indicates how long to wait
|
timeout: A timeout to pass to pexpect. This indicates how long to wait
|
||||||
before giving up on some expected output.
|
before giving up on some expected output.
|
||||||
env: a string->string dictionary, describing the environment variables.
|
env: a string->string dictionary, describing the environment variables.
|
||||||
"""
|
"""
|
||||||
if name not in env:
|
if name not in env:
|
||||||
raise ValueError("'%s' variable not found in environment" % name)
|
raise ValueError("'name' variable not found in environment" % name)
|
||||||
exe_path = env.get(name)
|
exe_path = env.get(name)
|
||||||
self.colorize = sys.stdout.isatty() or env.get("FISH_FORCE_COLOR", "0") == "1"
|
self.colorize = sys.stdout.isatty()
|
||||||
self.messages = []
|
self.messages = []
|
||||||
self.start_time = None
|
self.start_time = None
|
||||||
self.spawn = pexpect.spawn(
|
self.spawn = pexpect.spawn(exe_path, env=env, encoding="utf-8", timeout=timeout)
|
||||||
exe_path, env=env, encoding="utf-8", timeout=timeout, **kwargs
|
|
||||||
)
|
|
||||||
self.spawn.delaybeforesend = None
|
self.spawn.delaybeforesend = None
|
||||||
self.prompt_counter = 0
|
self.prompt_counter = 1
|
||||||
|
|
||||||
def time_since_first_message(self):
|
def time_since_first_message(self):
|
||||||
"""Return a delta in seconds since the first message, or 0 if this is the first."""
|
""" Return a delta in seconds since the first message, or 0 if this is the first. """
|
||||||
now = time.monotonic()
|
now = time.monotonic()
|
||||||
if not self.start_time:
|
if not self.start_time:
|
||||||
self.start_time = now
|
self.start_time = now
|
||||||
return now - self.start_time
|
return now - self.start_time
|
||||||
|
|
||||||
def send(self, s):
|
def send(self, s):
|
||||||
"""Cover over pexpect.spawn.send().
|
""" Cover over pexpect.spawn.send().
|
||||||
Send the given string to the tty, returning the number of bytes written.
|
Send the given string to the tty, returning the number of bytes written.
|
||||||
"""
|
"""
|
||||||
res = self.spawn.send(s)
|
res = self.spawn.send(s)
|
||||||
when = self.time_since_first_message()
|
when = self.time_since_first_message()
|
||||||
@@ -184,91 +160,71 @@ class SpawnedProc(object):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
def sendline(self, s):
|
def sendline(self, s):
|
||||||
"""Cover over pexpect.spawn.sendline().
|
""" Cover over pexpect.spawn.sendline().
|
||||||
Send the given string + linesep to the tty, returning the number of bytes written.
|
Send the given string + linesep to the tty, returning the number of bytes written.
|
||||||
"""
|
"""
|
||||||
return self.send(s + os.linesep)
|
return self.send(s + os.linesep)
|
||||||
|
|
||||||
def expect_re(self, pat, pat_desc=None, unmatched=None, shouldfail=False, **kwargs):
|
def expect_re(self, pat, pat_desc=None, unmatched=None, **kwargs):
|
||||||
"""Cover over pexpect.spawn.expect().
|
""" Cover over pexpect.spawn.expect().
|
||||||
Consume all "new" output of self.spawn until the given pattern is matched, or
|
Consume all "new" output of self.spawn until the given pattern is matched, or
|
||||||
the timeout is reached.
|
the timeout is reached.
|
||||||
Note that output between the current position and the location of the match is
|
Note that output between the current position and the location of the match is
|
||||||
consumed as well.
|
consumed as well.
|
||||||
The pattern is typically a regular expression in string form, but may also be
|
The pattern is typically a regular expression in string form, but may also be
|
||||||
any of the types accepted by pexpect.spawn.expect().
|
any of the types accepted by pexpect.spawn.expect().
|
||||||
If the 'unmatched' parameter is given, it is printed as part of the error message
|
If the 'unmatched' parameter is given, it is printed as part of the error message
|
||||||
of any failure.
|
of any failure.
|
||||||
On failure, this prints an error and exits.
|
On failure, this prints an error and exits.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.spawn.expect(pat, **kwargs)
|
res = self.spawn.expect(pat, **kwargs)
|
||||||
when = self.time_since_first_message()
|
when = self.time_since_first_message()
|
||||||
self.messages.append(
|
self.messages.append(
|
||||||
Message.received_output(self.spawn.match.group(), when)
|
Message.received_output(self.spawn.match.group(), when)
|
||||||
)
|
)
|
||||||
# When a match is found,
|
return res
|
||||||
# spawn.match is the MatchObject that produced it.
|
|
||||||
# This can be used to check what exactly was matched.
|
|
||||||
if shouldfail:
|
|
||||||
err = UNEXPECTED_SUCCESS
|
|
||||||
if not pat_desc:
|
|
||||||
pat_desc = str(pat)
|
|
||||||
self.report_exception_and_exit(pat_desc, unmatched, err)
|
|
||||||
return self.spawn.match
|
|
||||||
except pexpect.ExceptionPexpect as err:
|
except pexpect.ExceptionPexpect as err:
|
||||||
if shouldfail:
|
|
||||||
return True
|
|
||||||
if not pat_desc:
|
if not pat_desc:
|
||||||
pat_desc = str(pat)
|
pat_desc = str(pat)
|
||||||
self.report_exception_and_exit(pat_desc, unmatched, err)
|
self.report_exception_and_exit(pat_desc, unmatched, err)
|
||||||
|
|
||||||
def expect_str(self, s, **kwargs):
|
def expect_str(self, s, **kwargs):
|
||||||
"""Cover over expect_re() which accepts a literal string."""
|
""" Cover over expect_re() which accepts a literal string. """
|
||||||
return self.expect_re(re.escape(s), **kwargs)
|
return self.expect_re(re.escape(s), **kwargs)
|
||||||
|
|
||||||
def expect_prompt(self, *args, increment=True, **kwargs):
|
def expect_prompt(self, *args, **kwargs):
|
||||||
"""Convenience function which matches some text and then a prompt.
|
""" Convenience function which matches some text and then a prompt.
|
||||||
Match the given positional arguments as expect_re, and then look
|
Match the given positional arguments as expect_re, and then look
|
||||||
for a prompt.
|
for a prompt, bumping the prompt counter.
|
||||||
If increment is set, then this should be a new prompt and the prompt counter
|
Returns None on success, and exits on failure.
|
||||||
should be bumped; otherwise this is not a new prompt.
|
Example:
|
||||||
Returns None on success, and exits on failure.
|
sp.sendline("echo hello world")
|
||||||
Example:
|
sp.expect_prompt("hello world")
|
||||||
sp.sendline("echo hello world")
|
|
||||||
sp.expect_prompt("hello world")
|
|
||||||
"""
|
"""
|
||||||
if args:
|
if args:
|
||||||
self.expect_re(*args, **kwargs)
|
self.expect_re(*args, **kwargs)
|
||||||
if increment:
|
|
||||||
self.prompt_counter += 1
|
|
||||||
self.expect_re(
|
self.expect_re(
|
||||||
get_prompt_re(self.prompt_counter),
|
get_prompt_re(self.prompt_counter),
|
||||||
pat_desc="prompt %d" % self.prompt_counter,
|
pat_desc="prompt %d" % self.prompt_counter,
|
||||||
)
|
)
|
||||||
|
self.prompt_counter += 1
|
||||||
|
|
||||||
def report_exception_and_exit(self, pat, unmatched, err):
|
def report_exception_and_exit(self, pat, unmatched, err):
|
||||||
"""Things have gone badly.
|
""" Things have gone badly.
|
||||||
We have an exception 'err', some pexpect.ExceptionPexpect.
|
We have an exception 'err', some pexpect.ExceptionPexpect.
|
||||||
Report it to stdout, along with the offending call site.
|
Report it to stdout, along with the offending call site.
|
||||||
If 'unmatched' is set, print it to stdout.
|
If 'unmatched' is set, print it to stdout.
|
||||||
"""
|
"""
|
||||||
# Close the process so we can get the status
|
|
||||||
self.spawn.close()
|
|
||||||
colors = self.colors()
|
colors = self.colors()
|
||||||
failtype = pexpect_error_type(err)
|
failtype = pexpect_error_type(err)
|
||||||
# If we get an EOF, we check if the process exited with a signal.
|
|
||||||
# This shows us e.g. if it crashed
|
|
||||||
if failtype == 'EOF' and self.spawn.signalstatus is not None and self.spawn.signalstatus != 0:
|
|
||||||
failtype = "SIGNAL " + Signals(self.spawn.signalstatus).name
|
|
||||||
|
|
||||||
fmtkeys = {"failtype": failtype, "pat": escape(pat)}
|
fmtkeys = {"failtype": failtype, "pat": escape(pat)}
|
||||||
fmtkeys.update(**colors)
|
fmtkeys.update(**colors)
|
||||||
|
|
||||||
filename, lineno, code_context = get_callsite()
|
filename, lineno, code_context = get_callsite()
|
||||||
fmtkeys["filename"] = filename
|
fmtkeys["filename"] = filename
|
||||||
fmtkeys["lineno"] = lineno
|
fmtkeys["lineno"] = lineno
|
||||||
fmtkeys["code"] = "\n".join([n.strip() for n in code_context if n])
|
fmtkeys["code"] = "\n".join(code_context)
|
||||||
|
|
||||||
if unmatched:
|
if unmatched:
|
||||||
print(
|
print(
|
||||||
@@ -287,21 +243,23 @@ class SpawnedProc(object):
|
|||||||
print("{CYAN}Escaped buffer:{RESET}".format(**colors))
|
print("{CYAN}Escaped buffer:{RESET}".format(**colors))
|
||||||
print(escape(self.spawn.before))
|
print(escape(self.spawn.before))
|
||||||
print("")
|
print("")
|
||||||
print("{CYAN}When written to the tty, this looks like:{RESET}".format(**colors))
|
if sys.stdout.isatty():
|
||||||
print("{CYAN}<-------{RESET}".format(**colors))
|
print(
|
||||||
sys.stdout.write(SANITIZE_FOR_PRINTING_RE.sub('', self.spawn.before))
|
"{CYAN}When written to the tty, this looks like:{RESET}".format(
|
||||||
sys.stdout.flush()
|
**colors
|
||||||
maybe_nl=""
|
)
|
||||||
if not self.spawn.before.endswith("\n"):
|
)
|
||||||
maybe_nl="\n{CYAN}(no trailing newline)".format(**colors)
|
print("{CYAN}<-------{RESET}".format(**colors))
|
||||||
print("{RESET}{maybe_nl}{CYAN}------->{RESET}".format(maybe_nl=maybe_nl, **colors))
|
sys.stdout.write(self.spawn.before)
|
||||||
|
sys.stdout.flush()
|
||||||
|
print("{RESET}\n{CYAN}------->{RESET}".format(**colors))
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
# Show the last 10 messages.
|
# Show the last 5 messages.
|
||||||
print("Last 10 messages:")
|
print("Last 5 messages:")
|
||||||
delta = None
|
delta = None
|
||||||
for m in self.messages[-10:]:
|
for m in self.messages[-5:]:
|
||||||
etext = escape(m.text)
|
etext = escape(m.text)
|
||||||
timestamp = m.when * 1000.0
|
timestamp = m.when * 1000.0
|
||||||
# Use relative timestamps and add a sign.
|
# Use relative timestamps and add a sign.
|
||||||
@@ -313,6 +271,7 @@ class SpawnedProc(object):
|
|||||||
else:
|
else:
|
||||||
timestampstr = "{timestamp:10.2f} ms".format(timestamp=timestamp)
|
timestampstr = "{timestamp:10.2f} ms".format(timestamp=timestamp)
|
||||||
delta = m.when * 1000.0
|
delta = m.when * 1000.0
|
||||||
|
dir = m.dir
|
||||||
print(
|
print(
|
||||||
"{dir} {timestampstr} (Line {lineno}): {BOLD}{etext}{RESET}".format(
|
"{dir} {timestampstr} (Line {lineno}): {BOLD}{etext}{RESET}".format(
|
||||||
dir=m.dir,
|
dir=m.dir,
|
||||||
@@ -327,14 +286,14 @@ class SpawnedProc(object):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def sleep(self, secs):
|
def sleep(self, secs):
|
||||||
"""Cover over time.sleep()."""
|
""" Cover over time.sleep(). """
|
||||||
time.sleep(secs)
|
time.sleep(secs)
|
||||||
|
|
||||||
def colors(self):
|
def colors(self):
|
||||||
"""Return a dictionary mapping color names to ANSI escapes"""
|
""" Return a dictionary mapping color names to ANSI escapes """
|
||||||
|
|
||||||
def ansic(n):
|
def ansic(n):
|
||||||
"""Return either an ANSI escape sequence for a color, or empty string."""
|
""" Return either an ANSI escape sequence for a color, or empty string. """
|
||||||
return "\033[%dm" % n if self.colorize else ""
|
return "\033[%dm" % n if self.colorize else ""
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -358,25 +317,3 @@ class SpawnedProc(object):
|
|||||||
"LIGHTCYAN": ansic(96),
|
"LIGHTCYAN": ansic(96),
|
||||||
"WHITE": ansic(97),
|
"WHITE": ansic(97),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def control(char: str) -> str:
|
|
||||||
""" Returns the char sent when control is pressed along the given key. """
|
|
||||||
assert len(char) == 1
|
|
||||||
char = char.lower()
|
|
||||||
if ord("a") <= ord(char) <= ord("z"):
|
|
||||||
return chr(ord(char) - ord("a") + 1)
|
|
||||||
return chr({
|
|
||||||
"@": 0,
|
|
||||||
"`": 0,
|
|
||||||
"[": 27,
|
|
||||||
"{": 27,
|
|
||||||
"\\": 28,
|
|
||||||
"|": 28,
|
|
||||||
"]": 29,
|
|
||||||
"}": 29,
|
|
||||||
"^": 30,
|
|
||||||
"~": 30,
|
|
||||||
"_": 31,
|
|
||||||
"?": 127,
|
|
||||||
}[char])
|
|
||||||
|
|||||||
@@ -1,176 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
version=$1
|
|
||||||
repository_owner=fish-shell
|
|
||||||
remote=origin
|
|
||||||
if [ -n "$2" ]; then
|
|
||||||
set -u
|
|
||||||
repository_owner=$2
|
|
||||||
remote=$3
|
|
||||||
set +u
|
|
||||||
[ $# -eq 3 ]
|
|
||||||
fi
|
|
||||||
|
|
||||||
[ -n "$version" ]
|
|
||||||
|
|
||||||
for tool in \
|
|
||||||
bundle \
|
|
||||||
gh \
|
|
||||||
ruby \
|
|
||||||
timeout \
|
|
||||||
; do
|
|
||||||
if ! command -v "$tool" >/dev/null; then
|
|
||||||
echo >&2 "$0: missing command: $1"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
repo_root="$(dirname "$0")/.."
|
|
||||||
fish_site=$repo_root/../fish-site
|
|
||||||
|
|
||||||
for path in . "$fish_site"
|
|
||||||
do
|
|
||||||
if ! git -C "$path" diff HEAD --quiet; then
|
|
||||||
echo >&2 "$0: index and worktree must be clean"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if git tag | grep -qxF "$version"; then
|
|
||||||
echo >&2 "$0: tag $version already exists"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
sed -n 1p CHANGELOG.rst | grep -q '^fish .*(released ???)$'
|
|
||||||
sed -n 2p CHANGELOG.rst | grep -q '^===*$'
|
|
||||||
|
|
||||||
changelog_title="fish $version (released $(date +'%B %d, %Y'))"
|
|
||||||
sed -i \
|
|
||||||
-e "1c$changelog_title" \
|
|
||||||
-e "2c$(printf %s "$changelog_title" | sed s/./=/g)" \
|
|
||||||
CHANGELOG.rst
|
|
||||||
|
|
||||||
CommitVersion() {
|
|
||||||
sed -i "s/^version = \".*\"/version = \"$1\"/g" Cargo.toml
|
|
||||||
cargo fetch --offline
|
|
||||||
git add CHANGELOG.rst Cargo.toml Cargo.lock
|
|
||||||
git commit -m "$2
|
|
||||||
|
|
||||||
Created by ./build_tools/release.sh $version"
|
|
||||||
}
|
|
||||||
|
|
||||||
CommitVersion "$version" "Release $version"
|
|
||||||
|
|
||||||
# N.B. this is not GPG-signed.
|
|
||||||
git tag --annotate --message="Release $version" $version
|
|
||||||
|
|
||||||
git push $remote $version
|
|
||||||
|
|
||||||
gh() {
|
|
||||||
command gh --repo "$repository_owner/fish-shell" "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
run_id=
|
|
||||||
while [ -z "$run_id" ] && sleep 5
|
|
||||||
do
|
|
||||||
run_id=$(gh run list \
|
|
||||||
--json=databaseId --jq=.[].databaseId \
|
|
||||||
--workflow=release.yml --limit=1 \
|
|
||||||
--commit="$(git rev-parse "$version^{commit}")")
|
|
||||||
done
|
|
||||||
|
|
||||||
# Update fishshell.com
|
|
||||||
tag_oid=$(git rev-parse "$version")
|
|
||||||
tmpdir=$(mktemp -d)
|
|
||||||
while ! \
|
|
||||||
gh release download "$version" --dir="$tmpdir" \
|
|
||||||
--pattern="fish-$version.tar.xz"
|
|
||||||
do
|
|
||||||
timeout 30 gh run watch "$run_id" ||:
|
|
||||||
done
|
|
||||||
actual_tag_oid=$(git ls-remote "$remote" |
|
|
||||||
awk '$2 == "refs/tags/'"$version"'" { print $1 }')
|
|
||||||
[ "$tag_oid" = "$actual_tag_oid" ]
|
|
||||||
tar -C "$tmpdir" xf fish-$version.tar.xz
|
|
||||||
minor_version=${version%.*}
|
|
||||||
CopyDocs() {
|
|
||||||
rm -rf "fish-site/site/docs/$1"
|
|
||||||
cp -r "$tmpdir/fish-$version/user_doc/html" "fish-site/site/docs/$1"
|
|
||||||
git -C fish-site add "site/docs/$1"
|
|
||||||
}
|
|
||||||
CopyDocs "$minor_version"
|
|
||||||
latest_release=$(
|
|
||||||
releases=$(git tag | grep '^[0-9]*\.[0-9]*\.[0-9]*.*' |
|
|
||||||
sed $(: "De-prioritize release candidates (1.2.3-rc0)") \
|
|
||||||
's/-/~/g' | LC_ALL=C sort --version-sort)
|
|
||||||
printf %s\\n "$releases" | tail -1
|
|
||||||
)
|
|
||||||
if [ "$version" = "$latest_release" ]; then
|
|
||||||
CopyDocs current
|
|
||||||
fi
|
|
||||||
rm -rf "$tmpdir"
|
|
||||||
(
|
|
||||||
cd "$fish_site"
|
|
||||||
make new-release
|
|
||||||
git add -u
|
|
||||||
git commit --message="$(printf %s "\
|
|
||||||
| Release $version
|
|
||||||
|
|
|
||||||
| Created by ../fish-shell/build_tools/release.sh
|
|
||||||
" | sed 's,^\s*| ,,')"
|
|
||||||
)
|
|
||||||
|
|
||||||
# N.B. --exit-status doesn't fail reliably.
|
|
||||||
gh run view "$run_id" --verbose --log-failed --exit-status
|
|
||||||
|
|
||||||
while {
|
|
||||||
! draft=$(gh release view "$version" --json=isDraft --jq=.isDraft) \
|
|
||||||
|| [ "$draft" = true ]
|
|
||||||
}
|
|
||||||
do
|
|
||||||
sleep 20
|
|
||||||
done
|
|
||||||
|
|
||||||
(
|
|
||||||
cd "$fish_site"
|
|
||||||
git push git@github.com:$repository_owner/fish-site
|
|
||||||
)
|
|
||||||
|
|
||||||
if git merge-base --is-ancestor $remote/master $version
|
|
||||||
then
|
|
||||||
git push $remote $version:master
|
|
||||||
else
|
|
||||||
# Probably on an integration branch.
|
|
||||||
# TODO Maybe push when that's safe (or move this to CI).
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$repository_owner" = fish-shell ]; then {
|
|
||||||
mail=$(mktemp)
|
|
||||||
cat >$mail <<EOF
|
|
||||||
From: $(git var GIT_AUTHOR_IDENT | sed 's/ [0-9]* +[0-9]*$//')
|
|
||||||
To: fish-users Mailing List <fish-users@lists.sourceforge.net>
|
|
||||||
Subject: fish $version released
|
|
||||||
|
|
||||||
See https://github.com/fish-shell/fish-shell/releases/tag/$version
|
|
||||||
EOF
|
|
||||||
git send-email --suppress-cc=all $mail
|
|
||||||
rm $mail
|
|
||||||
} fi
|
|
||||||
|
|
||||||
changelog=$(cat - CHANGELOG.rst <<EOF
|
|
||||||
fish ?.?.? (released ???)
|
|
||||||
=========================
|
|
||||||
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
printf %s\\n "$changelog" >CHANGELOG.rst
|
|
||||||
CommitVersion ${version}-snapshot "start new cycle"
|
|
||||||
|
|
||||||
exit
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -3,9 +3,10 @@
|
|||||||
# This runs C++ files and fish scripts (*.fish) through their respective code
|
# This runs C++ files and fish scripts (*.fish) through their respective code
|
||||||
# formatting programs.
|
# formatting programs.
|
||||||
#
|
#
|
||||||
|
set -l git_clang_format no
|
||||||
|
set -l c_files
|
||||||
set -l fish_files
|
set -l fish_files
|
||||||
set -l python_files
|
set -l python_files
|
||||||
set -l rust_files
|
|
||||||
set -l all no
|
set -l all no
|
||||||
|
|
||||||
if test "$argv[1]" = --all
|
if test "$argv[1]" = --all
|
||||||
@@ -22,20 +23,33 @@ if test $all = yes
|
|||||||
set -l files (git status --porcelain --short --untracked-files=all | sed -e 's/^ *[^ ]* *//')
|
set -l files (git status --porcelain --short --untracked-files=all | sed -e 's/^ *[^ ]* *//')
|
||||||
if set -q files[1]
|
if set -q files[1]
|
||||||
echo
|
echo
|
||||||
echo 'You have uncommitted changes. Are you sure you want to restyle?'
|
echo You have uncommitted changes. Cowardly refusing to restyle the entire code base.
|
||||||
read -P 'y/N? ' -n1 -l ans
|
echo
|
||||||
if not string match -qi y -- $ans
|
exit 1
|
||||||
exit 1
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
set fish_files share/**.fish
|
set c_files src/*.h src/*.cpp src/*.c
|
||||||
set python_files {doc_src,share,tests}/**.py
|
set fish_files (printf '%s\n' share/***.fish)
|
||||||
set rust_files fish-rust/src/**.rs
|
set python_files **.py
|
||||||
else
|
else
|
||||||
|
# We haven't been asked to reformat all the source. If there are uncommitted changes reformat
|
||||||
|
# those using `git clang-format`. Else reformat the files in the most recent commit.
|
||||||
|
# Select (cached files) (modified but not cached, and untracked files)
|
||||||
|
set -l files (git diff-index --cached HEAD --name-only) (git ls-files --exclude-standard --others --modified)
|
||||||
|
if set -q files[1]
|
||||||
|
set git_clang_format yes
|
||||||
|
else
|
||||||
|
# No pending changes so lint the files in the most recent commit.
|
||||||
|
set files (git diff-tree --no-commit-id --name-only -r HEAD)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Extract just the C/C++ files that exist.
|
||||||
|
set c_files
|
||||||
|
for file in (string match -r '^.*\.(?:c|cpp|h)$' -- $files)
|
||||||
|
test -f $file; and set c_files $c_files $file
|
||||||
|
end
|
||||||
# Extract just the fish files.
|
# Extract just the fish files.
|
||||||
set fish_files (string match -r '^.*\.fish$' -- $files)
|
set fish_files (string match -r '^.*\.fish$' -- $files)
|
||||||
set python_files (string match -r '^.*\.py$' -- $files)
|
set python_files (string match -r '^.*\.py$' -- $files)
|
||||||
set rust_files (string match -r '^.*\.rs$' -- $files)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
set -l red (set_color red)
|
set -l red (set_color red)
|
||||||
@@ -43,6 +57,37 @@ set -l green (set_color green)
|
|||||||
set -l blue (set_color blue)
|
set -l blue (set_color blue)
|
||||||
set -l normal (set_color normal)
|
set -l normal (set_color normal)
|
||||||
|
|
||||||
|
# Run the C++ reformatter if we have any C++ files.
|
||||||
|
if set -q c_files[1]
|
||||||
|
if test $git_clang_format = yes
|
||||||
|
if type -q git-clang-format
|
||||||
|
echo === Running "$red"git-clang-format"$normal"
|
||||||
|
git add $c_files
|
||||||
|
git-clang-format
|
||||||
|
else
|
||||||
|
echo
|
||||||
|
echo 'WARNING: Cannot find git-clang-format command'
|
||||||
|
echo
|
||||||
|
end
|
||||||
|
else if type -q clang-format
|
||||||
|
echo === Running "$red"clang-format"$normal"
|
||||||
|
for file in $c_files
|
||||||
|
cp $file $file.new # preserves mode bits
|
||||||
|
clang-format $file >$file.new
|
||||||
|
if cmp --quiet $file $file.new
|
||||||
|
rm $file.new
|
||||||
|
else
|
||||||
|
echo $file was NOT correctly formatted
|
||||||
|
mv $file.new $file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
echo
|
||||||
|
echo 'WARNING: Cannot find clang-format command'
|
||||||
|
echo
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Run the fish reformatter if we have any fish files.
|
# Run the fish reformatter if we have any fish files.
|
||||||
if set -q fish_files[1]
|
if set -q fish_files[1]
|
||||||
if not type -q fish_indent
|
if not type -q fish_indent
|
||||||
@@ -63,14 +108,3 @@ if set -q python_files[1]
|
|||||||
black $python_files
|
black $python_files
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if set -q rust_files[1]
|
|
||||||
if not type -q rustfmt
|
|
||||||
echo
|
|
||||||
echo Please install "`rustfmt`" to style rust
|
|
||||||
echo
|
|
||||||
else
|
|
||||||
echo === Running "$blue"rustfmt"$normal"
|
|
||||||
rustfmt $rust_files
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|||||||
3
build_tools/ubsan.blacklist
Normal file
3
build_tools/ubsan.blacklist
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Ubuntu Xenial (used for Travis CI builds) ships libstdc++ 5.4.0 which contains undefined behaviour
|
||||||
|
# See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63345
|
||||||
|
object-size:*bits/stl_tree.h
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
# Support for benchmarking fish.
|
# Support for benchmarking fish.
|
||||||
|
|
||||||
add_custom_target(benchmark
|
add_custom_target(benchmark
|
||||||
COMMAND ${CMAKE_SOURCE_DIR}/benchmarks/driver.sh ${CMAKE_BINARY_DIR}/fish
|
COMMAND ${CMAKE_SOURCE_DIR}/benchmarks/driver.sh $<TARGET_FILE:fish>
|
||||||
DEPENDS fish
|
|
||||||
USES_TERMINAL
|
USES_TERMINAL
|
||||||
)
|
)
|
||||||
|
|||||||
123
cmake/CheckIncludeFiles.cmake
Normal file
123
cmake/CheckIncludeFiles.cmake
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
# Distributed under the OSI-approved BSD 3-Clause License. See full license information in
|
||||||
|
# doc_src/license.hdr or https://cmake.org/licensing for details.
|
||||||
|
|
||||||
|
#.rst:
|
||||||
|
# CheckIncludeFiles
|
||||||
|
# -----------------
|
||||||
|
#
|
||||||
|
# Provides a macro to check if a list of one or more header files can
|
||||||
|
# be included together in ``C``.
|
||||||
|
#
|
||||||
|
# .. command:: CHECK_INCLUDE_FILES
|
||||||
|
#
|
||||||
|
# ::
|
||||||
|
#
|
||||||
|
# CHECK_INCLUDE_FILES("<includes>" <variable> [LANGUAGE <language>])
|
||||||
|
#
|
||||||
|
# Check if the given ``<includes>`` list may be included together
|
||||||
|
# in a ``C`` source file and store the result in an internal cache
|
||||||
|
# entry named ``<variable>``. Specify the ``<includes>`` argument
|
||||||
|
# as a :ref:`;-list <CMake Language Lists>` of header file names.
|
||||||
|
#
|
||||||
|
# If LANGUAGE is set, the specified compiler will be used to perform the
|
||||||
|
# check. Acceptable values are C and CXX.
|
||||||
|
#
|
||||||
|
# The following variables may be set before calling this macro to modify
|
||||||
|
# the way the check is run:
|
||||||
|
#
|
||||||
|
# ``CMAKE_REQUIRED_FLAGS``
|
||||||
|
# string of compile command line flags
|
||||||
|
# ``CMAKE_REQUIRED_DEFINITIONS``
|
||||||
|
# list of macros to define (-DFOO=bar)
|
||||||
|
# ``CMAKE_REQUIRED_INCLUDES``
|
||||||
|
# list of include directories
|
||||||
|
# ``CMAKE_REQUIRED_QUIET``
|
||||||
|
# execute quietly without messages
|
||||||
|
#
|
||||||
|
# See modules :module:`CheckIncludeFile` and :module:`CheckIncludeFileCXX`
|
||||||
|
# to check for a single header file in ``C`` or ``CXX`` languages.
|
||||||
|
|
||||||
|
macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE)
|
||||||
|
if(NOT DEFINED "${VARIABLE}")
|
||||||
|
set(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n")
|
||||||
|
|
||||||
|
if("x${ARGN}" STREQUAL "x")
|
||||||
|
if(CMAKE_C_COMPILER_LOADED)
|
||||||
|
set(_lang C)
|
||||||
|
elseif(CMAKE_CXX_COMPILER_LOADED)
|
||||||
|
set(_lang CXX)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "CHECK_INCLUDE_FILES needs either C or CXX language enabled")
|
||||||
|
endif()
|
||||||
|
elseif("x${ARGN}" MATCHES "^xLANGUAGE;([a-zA-Z]+)$")
|
||||||
|
set(_lang "${CMAKE_MATCH_1}")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Unknown arguments:\n ${ARGN}\n")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(_lang STREQUAL "C")
|
||||||
|
set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckIncludeFiles/${var}.c)
|
||||||
|
elseif(_lang STREQUAL "CXX")
|
||||||
|
set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckIncludeFiles/${var}.cpp)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Unknown language:\n ${_lang}\nSupported languages: C, CXX.\n")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_REQUIRED_INCLUDES)
|
||||||
|
set(CHECK_INCLUDE_FILES_INCLUDE_DIRS "-DINCLUDE_DIRECTORIES=${CMAKE_REQUIRED_INCLUDES}")
|
||||||
|
else()
|
||||||
|
set(CHECK_INCLUDE_FILES_INCLUDE_DIRS)
|
||||||
|
endif()
|
||||||
|
set(CHECK_INCLUDE_FILES_CONTENT "/* */\n")
|
||||||
|
set(MACRO_CHECK_INCLUDE_FILES_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||||
|
foreach(FILE ${INCLUDE})
|
||||||
|
string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
|
||||||
|
"#include <${FILE}>\n")
|
||||||
|
endforeach()
|
||||||
|
string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
|
||||||
|
"\n\nint main(void){return 0;}\n")
|
||||||
|
configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
|
||||||
|
"${src}" @ONLY)
|
||||||
|
|
||||||
|
set(_INCLUDE ${INCLUDE}) # remove empty elements
|
||||||
|
if("${_INCLUDE}" MATCHES "^([^;]+);.+;([^;]+)$")
|
||||||
|
list(LENGTH _INCLUDE _INCLUDE_LEN)
|
||||||
|
set(_description "${_INCLUDE_LEN} include files ${CMAKE_MATCH_1}, ..., ${CMAKE_MATCH_2}")
|
||||||
|
elseif("${_INCLUDE}" MATCHES "^([^;]+);([^;]+)$")
|
||||||
|
set(_description "include files ${CMAKE_MATCH_1}, ${CMAKE_MATCH_2}")
|
||||||
|
else()
|
||||||
|
set(_description "include file ${_INCLUDE}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_REQUIRED_QUIET)
|
||||||
|
message(STATUS "Looking for ${_description}")
|
||||||
|
endif()
|
||||||
|
try_compile(${VARIABLE}
|
||||||
|
${CMAKE_BINARY_DIR}
|
||||||
|
${src}
|
||||||
|
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
|
||||||
|
CMAKE_FLAGS
|
||||||
|
-DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_INCLUDE_FILES_FLAGS}
|
||||||
|
"${CHECK_INCLUDE_FILES_INCLUDE_DIRS}"
|
||||||
|
OUTPUT_VARIABLE OUTPUT)
|
||||||
|
if(${VARIABLE})
|
||||||
|
if(NOT CMAKE_REQUIRED_QUIET)
|
||||||
|
message(STATUS "Looking for ${_description} - found")
|
||||||
|
endif()
|
||||||
|
set(${VARIABLE} 1 CACHE INTERNAL "Have include ${INCLUDE}")
|
||||||
|
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
|
||||||
|
"Determining if files ${INCLUDE} "
|
||||||
|
"exist passed with the following output:\n"
|
||||||
|
"${OUTPUT}\n\n")
|
||||||
|
else()
|
||||||
|
if(NOT CMAKE_REQUIRED_QUIET)
|
||||||
|
message(STATUS "Looking for ${_description} - not found")
|
||||||
|
endif()
|
||||||
|
set(${VARIABLE} "" CACHE INTERNAL "Have includes ${INCLUDE}")
|
||||||
|
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||||
|
"Determining if files ${INCLUDE} "
|
||||||
|
"exist failed with the following output:\n"
|
||||||
|
"${OUTPUT}\nSource:\n${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
209
cmake/ConfigureChecks.cmake
Normal file
209
cmake/ConfigureChecks.cmake
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
# The following defines affect the environment configuration tests are run in:
|
||||||
|
# CMAKE_REQUIRED_DEFINITIONS, CMAKE_REQUIRED_FLAGS, CMAKE_REQUIRED_LIBRARIES,
|
||||||
|
# and CMAKE_REQUIRED_INCLUDES
|
||||||
|
# `wcstod_l` is a GNU-extension, sometimes hidden behind GNU-related defines.
|
||||||
|
# This is the case for at least Cygwin and Newlib.
|
||||||
|
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE=1)
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
include(CheckCXXCompilerFlag)
|
||||||
|
check_cxx_compiler_flag("-Werror=unguarded-availability" REQUIRES_UNGUARDED_AVAILABILITY)
|
||||||
|
if(REQUIRES_UNGUARDED_AVAILABILITY)
|
||||||
|
list(APPEND CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-Werror=unguarded-availability")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Try using CMake's own logic to locate curses/ncurses
|
||||||
|
find_package(Curses)
|
||||||
|
if(NOT ${CURSES_FOUND})
|
||||||
|
# CMake has trouble finding platform-specific system libraries
|
||||||
|
# installed to multiarch paths (e.g. /usr/lib/x86_64-linux-gnu)
|
||||||
|
# if not symlinked or passed in as a manual define.
|
||||||
|
message("Falling back to pkg-config for (n)curses detection")
|
||||||
|
include(FindPkgConfig)
|
||||||
|
pkg_search_module(CURSES REQUIRED ncurses curses)
|
||||||
|
set(CURSES_CURSES_LIBRARY ${CURSES_LIBRARIES})
|
||||||
|
set(CURSES_LIBRARY ${CURSES_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Get threads.
|
||||||
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
|
# FindThreads < 3.4.0 doesn't work for C++-only projects
|
||||||
|
if(CMAKE_VERSION VERSION_LESS 3.4.0)
|
||||||
|
enable_language(C)
|
||||||
|
endif()
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
|
# Detect WSL. Does not match against native Windows/WIN32.
|
||||||
|
if (CMAKE_HOST_SYSTEM_VERSION MATCHES ".*-Microsoft")
|
||||||
|
set(WSL 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Set up the config.h file.
|
||||||
|
set(PACKAGE_NAME "fish")
|
||||||
|
set(PACKAGE_TARNAME "fish")
|
||||||
|
include(CheckCXXSymbolExists)
|
||||||
|
include(CheckIncludeFileCXX)
|
||||||
|
include(CheckIncludeFiles)
|
||||||
|
include(CheckStructHasMember)
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
include(CheckTypeSize)
|
||||||
|
include(CMakePushCheckState)
|
||||||
|
check_cxx_symbol_exists(backtrace_symbols execinfo.h HAVE_BACKTRACE_SYMBOLS)
|
||||||
|
check_cxx_symbol_exists(clock_gettime time.h HAVE_CLOCK_GETTIME)
|
||||||
|
check_cxx_symbol_exists(ctermid_r stdio.h HAVE_CTERMID_R)
|
||||||
|
check_struct_has_member("struct dirent" d_type dirent.h HAVE_STRUCT_DIRENT_D_TYPE LANGUAGE CXX)
|
||||||
|
check_cxx_symbol_exists(dirfd "sys/types.h;dirent.h" HAVE_DIRFD)
|
||||||
|
check_include_file_cxx(execinfo.h HAVE_EXECINFO_H)
|
||||||
|
check_cxx_symbol_exists(flock sys/file.h HAVE_FLOCK)
|
||||||
|
# futimens is new in OS X 10.13 but is a weak symbol.
|
||||||
|
# Don't assume it exists just because we can link - it may be null.
|
||||||
|
check_cxx_symbol_exists(futimens sys/stat.h HAVE_FUTIMENS)
|
||||||
|
check_cxx_symbol_exists(futimes sys/time.h HAVE_FUTIMES)
|
||||||
|
check_cxx_symbol_exists(getifaddrs ifaddrs.h HAVE_GETIFADDRS)
|
||||||
|
check_cxx_symbol_exists(getpwent pwd.h HAVE_GETPWENT)
|
||||||
|
check_cxx_symbol_exists(getrusage sys/resource.h HAVE_GETRUSAGE)
|
||||||
|
check_cxx_symbol_exists(gettext libintl.h HAVE_GETTEXT)
|
||||||
|
check_cxx_symbol_exists(killpg "sys/types.h;signal.h" HAVE_KILLPG)
|
||||||
|
check_cxx_symbol_exists(lrand48_r stdlib.h HAVE_LRAND48_R)
|
||||||
|
# mkostemp is in stdlib in glibc and FreeBSD, but unistd on macOS
|
||||||
|
check_cxx_symbol_exists(mkostemp "stdlib.h;unistd.h" HAVE_MKOSTEMP)
|
||||||
|
set(HAVE_CURSES_H ${CURSES_HAVE_CURSES_H})
|
||||||
|
set(HAVE_NCURSES_CURSES_H ${CURSES_HAVE_NCURSES_CURSES_H})
|
||||||
|
set(HAVE_NCURSES_H ${CURSES_HAVE_NCURSES_H})
|
||||||
|
if(HAVE_CURSES_H)
|
||||||
|
check_include_files("curses.h;term.h" HAVE_TERM_H)
|
||||||
|
endif()
|
||||||
|
if(NOT HAVE_TERM_H)
|
||||||
|
check_include_file_cxx("ncurses/term.h" HAVE_NCURSES_TERM_H)
|
||||||
|
endif()
|
||||||
|
check_include_file_cxx(siginfo.h HAVE_SIGINFO_H)
|
||||||
|
check_include_file_cxx(spawn.h HAVE_SPAWN_H)
|
||||||
|
check_struct_has_member("struct stat" st_ctime_nsec "sys/stat.h" HAVE_STRUCT_STAT_ST_CTIME_NSEC
|
||||||
|
LANGUAGE CXX)
|
||||||
|
check_struct_has_member("struct stat" st_mtimespec.tv_nsec "sys/stat.h"
|
||||||
|
HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC LANGUAGE CXX)
|
||||||
|
check_struct_has_member("struct stat" st_mtim.tv_nsec "sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
|
||||||
|
LANGUAGE CXX)
|
||||||
|
check_cxx_symbol_exists(sys_errlist stdio.h HAVE_SYS_ERRLIST)
|
||||||
|
check_include_file_cxx(sys/ioctl.h HAVE_SYS_IOCTL_H)
|
||||||
|
check_include_file_cxx(sys/select.h HAVE_SYS_SELECT_H)
|
||||||
|
check_include_files("sys/types.h;sys/sysctl.h" HAVE_SYS_SYSCTL_H)
|
||||||
|
check_include_file_cxx(termios.h HAVE_TERMIOS_H) # Needed for TIOCGWINSZ
|
||||||
|
|
||||||
|
check_cxx_symbol_exists(wcscasecmp wchar.h HAVE_WCSCASECMP)
|
||||||
|
check_cxx_symbol_exists(wcsdup wchar.h HAVE_WCSDUP)
|
||||||
|
check_cxx_symbol_exists(wcslcpy wchar.h HAVE_WCSLCPY)
|
||||||
|
check_cxx_symbol_exists(wcsncasecmp wchar.h HAVE_WCSNCASECMP)
|
||||||
|
check_cxx_symbol_exists(wcsndup wchar.h HAVE_WCSNDUP)
|
||||||
|
|
||||||
|
# These are for compatibility with Solaris 10, which places the following
|
||||||
|
# in the std namespace.
|
||||||
|
if(NOT HAVE_WCSNCASECMP)
|
||||||
|
check_cxx_symbol_exists(std::wcscasecmp wchar.h HAVE_STD__WCSCASECMP)
|
||||||
|
endif()
|
||||||
|
if(NOT HAVE_WCSDUP)
|
||||||
|
check_cxx_symbol_exists(std::wcsdup wchar.h HAVE_STD__WCSDUP)
|
||||||
|
endif()
|
||||||
|
if(NOT HAVE_WCSNCASECMP)
|
||||||
|
check_cxx_symbol_exists(std::wcsncasecmp wchar.h HAVE_STD__WCSNCASECMP)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# `xlocale.h` is required to find `wcstod_l` in `wchar.h` under FreeBSD,
|
||||||
|
# but it's not present under Linux.
|
||||||
|
check_include_files("xlocale.h" HAVE_XLOCALE_H)
|
||||||
|
if(HAVE_XLOCALE_H)
|
||||||
|
list(APPEND WCSTOD_L_INCLUDES "xlocale.h")
|
||||||
|
endif()
|
||||||
|
list(APPEND WCSTOD_L_INCLUDES "wchar.h")
|
||||||
|
check_cxx_symbol_exists(wcstod_l "${WCSTOD_L_INCLUDES}" HAVE_WCSTOD_L)
|
||||||
|
|
||||||
|
check_cxx_symbol_exists(_sys_errs stdlib.h HAVE__SYS__ERRS)
|
||||||
|
|
||||||
|
cmake_push_check_state()
|
||||||
|
set(CMAKE_EXTRA_INCLUDE_FILES termios.h sys/ioctl.h)
|
||||||
|
check_type_size("struct winsize" STRUCT_WINSIZE LANGUAGE CXX)
|
||||||
|
check_cxx_symbol_exists("TIOCGWINSZ" "termios.h;sys/ioctl.h" HAVE_TIOCGWINSZ)
|
||||||
|
if(STRUCT_WINSIZE GREATER -1 AND HAVE_TIOCGWINSZ EQUAL 1)
|
||||||
|
set(HAVE_WINSIZE 1)
|
||||||
|
endif()
|
||||||
|
cmake_pop_check_state()
|
||||||
|
|
||||||
|
check_type_size("wchar_t[8]" WCHAR_T_BITS LANGUAGE CXX)
|
||||||
|
|
||||||
|
set(TPARM_INCLUDES)
|
||||||
|
if(HAVE_NCURSES_H)
|
||||||
|
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <ncurses.h>\n")
|
||||||
|
elseif(HAVE_NCURSES_CURSES_H)
|
||||||
|
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <ncurses/curses.h>\n")
|
||||||
|
else()
|
||||||
|
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <curses.h>\n")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_TERM_H)
|
||||||
|
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <term.h>\n")
|
||||||
|
elseif(HAVE_NCURSES_TERM_H)
|
||||||
|
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <ncurses/term.h>\n")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Solaris and X/Open-conforming systems have a fixed-args tparm
|
||||||
|
cmake_push_check_state()
|
||||||
|
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARY})
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#define TPARM_VARARGS
|
||||||
|
${TPARM_INCLUDES}
|
||||||
|
|
||||||
|
int main () {
|
||||||
|
tparm( \"\" );
|
||||||
|
}
|
||||||
|
"
|
||||||
|
TPARM_TAKES_VARARGS
|
||||||
|
)
|
||||||
|
|
||||||
|
if(TPARM_TAKES_VARARGS)
|
||||||
|
set(TPARM_VARARGS 1)
|
||||||
|
else()
|
||||||
|
set(TPARM_SOLARIS_KLUDGE 1)
|
||||||
|
endif()
|
||||||
|
cmake_pop_check_state()
|
||||||
|
|
||||||
|
# Work around the fact that cmake does not propagate the language standard flag into
|
||||||
|
# the CHECK_CXX_SOURCE_COMPILES function. See CMake issue #16456.
|
||||||
|
# Ensure we do this after the FIND_PACKAGE calls which use C, and will error on a C++
|
||||||
|
# standards flag.
|
||||||
|
# Also see https://github.com/fish-shell/fish-shell/issues/5865
|
||||||
|
if(NOT POLICY CMP0067)
|
||||||
|
list(APPEND CMAKE_REQUIRED_FLAGS "${CMAKE_CXX${CMAKE_CXX_STANDARD}_EXTENSION_COMPILE_OPTION}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
int main () {
|
||||||
|
std::unique_ptr<int> foo = std::make_unique<int>();
|
||||||
|
}
|
||||||
|
"
|
||||||
|
HAVE_STD__MAKE_UNIQUE
|
||||||
|
)
|
||||||
|
|
||||||
|
# Detect support for thread_local.
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
int main () {
|
||||||
|
static thread_local int x = 3;
|
||||||
|
(void)x;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
HAVE_CX11_THREAD_LOCAL
|
||||||
|
)
|
||||||
|
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <atomic>
|
||||||
|
#include <cstdint>
|
||||||
|
std::atomic<uint64_t> x;
|
||||||
|
int main() {
|
||||||
|
return x;
|
||||||
|
}"
|
||||||
|
LIBATOMIC_NOT_NEEDED)
|
||||||
|
IF (NOT LIBATOMIC_NOT_NEEDED)
|
||||||
|
set(ATOMIC_LIBRARY "atomic")
|
||||||
|
endif()
|
||||||
@@ -9,6 +9,7 @@ include(FeatureSummary)
|
|||||||
set(SPHINX_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/doc_src")
|
set(SPHINX_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/doc_src")
|
||||||
set(SPHINX_ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}/user_doc")
|
set(SPHINX_ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}/user_doc")
|
||||||
set(SPHINX_BUILD_DIR "${SPHINX_ROOT_DIR}/build")
|
set(SPHINX_BUILD_DIR "${SPHINX_ROOT_DIR}/build")
|
||||||
|
set(SPHINX_CACHE_DIR "${SPHINX_ROOT_DIR}/doctrees")
|
||||||
set(SPHINX_HTML_DIR "${SPHINX_ROOT_DIR}/html")
|
set(SPHINX_HTML_DIR "${SPHINX_ROOT_DIR}/html")
|
||||||
set(SPHINX_MANPAGE_DIR "${SPHINX_ROOT_DIR}/man")
|
set(SPHINX_MANPAGE_DIR "${SPHINX_ROOT_DIR}/man")
|
||||||
|
|
||||||
@@ -16,12 +17,13 @@ set(SPHINX_MANPAGE_DIR "${SPHINX_ROOT_DIR}/man")
|
|||||||
# Prepend the output dir of fish_indent to PATH.
|
# Prepend the output dir of fish_indent to PATH.
|
||||||
add_custom_target(sphinx-docs
|
add_custom_target(sphinx-docs
|
||||||
mkdir -p ${SPHINX_HTML_DIR}/_static/
|
mkdir -p ${SPHINX_HTML_DIR}/_static/
|
||||||
COMMAND env PATH="${CMAKE_BINARY_DIR}:$$PATH"
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SPHINX_SRC_DIR}/_static/pygments.css ${SPHINX_HTML_DIR}/_static/
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SPHINX_SRC_DIR}/_static/custom.css ${SPHINX_HTML_DIR}/_static/
|
||||||
|
COMMAND env PATH="$<TARGET_FILE_DIR:fish_indent>:$$PATH"
|
||||||
${SPHINX_EXECUTABLE}
|
${SPHINX_EXECUTABLE}
|
||||||
-j auto
|
|
||||||
-q -b html
|
-q -b html
|
||||||
-c "${SPHINX_SRC_DIR}"
|
-c "${SPHINX_SRC_DIR}"
|
||||||
-d "${SPHINX_ROOT_DIR}/.doctrees-html"
|
-d "${SPHINX_CACHE_DIR}"
|
||||||
"${SPHINX_SRC_DIR}"
|
"${SPHINX_SRC_DIR}"
|
||||||
"${SPHINX_HTML_DIR}"
|
"${SPHINX_HTML_DIR}"
|
||||||
DEPENDS ${SPHINX_SRC_DIR}/fish_indent_lexer.py fish_indent
|
DEPENDS ${SPHINX_SRC_DIR}/fish_indent_lexer.py fish_indent
|
||||||
@@ -29,16 +31,15 @@ add_custom_target(sphinx-docs
|
|||||||
|
|
||||||
# sphinx-manpages needs the fish_indent binary for the version number
|
# sphinx-manpages needs the fish_indent binary for the version number
|
||||||
add_custom_target(sphinx-manpages
|
add_custom_target(sphinx-manpages
|
||||||
env FISH_BUILD_VERSION_FILE="${CMAKE_CURRENT_BINARY_DIR}/${FBVF}"
|
env PATH="$<TARGET_FILE_DIR:fish_indent>:$$PATH"
|
||||||
${SPHINX_EXECUTABLE}
|
${SPHINX_EXECUTABLE}
|
||||||
-j auto
|
|
||||||
-q -b man
|
-q -b man
|
||||||
-c "${SPHINX_SRC_DIR}"
|
-c "${SPHINX_SRC_DIR}"
|
||||||
-d "${SPHINX_ROOT_DIR}/.doctrees-man"
|
-d "${SPHINX_CACHE_DIR}"
|
||||||
"${SPHINX_SRC_DIR}"
|
"${SPHINX_SRC_DIR}"
|
||||||
# TODO: This only works if we only have section 1 manpages.
|
# TODO: This only works if we only have section 1 manpages.
|
||||||
"${SPHINX_MANPAGE_DIR}/man1"
|
"${SPHINX_MANPAGE_DIR}/man1"
|
||||||
DEPENDS CHECK-FISH-BUILD-VERSION-FILE
|
DEPENDS fish_indent
|
||||||
COMMENT "Building man pages with Sphinx")
|
COMMENT "Building man pages with Sphinx")
|
||||||
|
|
||||||
if(SPHINX_EXECUTABLE)
|
if(SPHINX_EXECUTABLE)
|
||||||
|
|||||||
@@ -1,805 +0,0 @@
|
|||||||
#[=======================================================================[.rst:
|
|
||||||
FindRust
|
|
||||||
--------
|
|
||||||
|
|
||||||
Find Rust
|
|
||||||
|
|
||||||
This module finds an installed rustc compiler and the cargo build tool. If Rust
|
|
||||||
is managed by rustup it determines the available toolchains and returns a
|
|
||||||
concrete Rust version, not a rustup proxy.
|
|
||||||
|
|
||||||
Imported from Corrosion https://github.com/corrosion-rs/corrosion/
|
|
||||||
|
|
||||||
Copyright (c) 2018 Andrew Gaspar
|
|
||||||
|
|
||||||
Licensed under the MIT license
|
|
||||||
|
|
||||||
#]=======================================================================]
|
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.12)
|
|
||||||
|
|
||||||
# search for Cargo here and set up a bunch of cool flags and stuff
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
|
|
||||||
list(APPEND CMAKE_MESSAGE_CONTEXT "FindRust")
|
|
||||||
|
|
||||||
# Print error message and return.
|
|
||||||
macro(_findrust_failed)
|
|
||||||
if("${Rust_FIND_REQUIRED}")
|
|
||||||
message(FATAL_ERROR ${ARGN})
|
|
||||||
elseif(NOT "${Rust_FIND_QUIETLY}")
|
|
||||||
message(WARNING ${ARGN})
|
|
||||||
endif()
|
|
||||||
# Note: PARENT_SCOPE is the scope of the caller of the caller of this macro.
|
|
||||||
set(Rust_FOUND "" PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
# Checks if the actual version of a Rust toolchain matches the VERSION requirements specified in find_package.
|
|
||||||
function(_findrust_version_ok ACTUAL_VERSION OUT_IS_OK)
|
|
||||||
if(DEFINED Rust_FIND_VERSION_RANGE)
|
|
||||||
if(Rust_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE")
|
|
||||||
set(COMPARSION_OPERATOR "VERSION_LESS_EQUAL")
|
|
||||||
elseif(Rust_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE")
|
|
||||||
set(COMPARSION_OPERATOR "VERSION_LESS")
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "Unexpected value in `<PackageName>_FIND_VERSION_RANGE_MAX`: "
|
|
||||||
"`${Rust_FIND_VERSION_RANGE_MAX}`.")
|
|
||||||
endif()
|
|
||||||
if(("${ACTUAL_VERSION}" VERSION_GREATER_EQUAL "${Rust_FIND_VERSION_RANGE_MIN}")
|
|
||||||
AND
|
|
||||||
( "${ACTUAL_VERSION}" ${COMPARSION_OPERATOR} "${Rust_FIND_VERSION_RANGE_MAX}" )
|
|
||||||
)
|
|
||||||
set("${OUT_IS_OK}" TRUE PARENT_SCOPE)
|
|
||||||
else()
|
|
||||||
set("${OUT_IS_OK}" FALSE PARENT_SCOPE)
|
|
||||||
endif()
|
|
||||||
elseif(DEFINED Rust_FIND_VERSION)
|
|
||||||
if(Rust_VERSION_EXACT)
|
|
||||||
set(COMPARISON_OPERATOR VERSION_EQUAL)
|
|
||||||
else()
|
|
||||||
set(COMPARISON_OPERATOR VERSION_GREATER_EQUAL)
|
|
||||||
endif()
|
|
||||||
if(_TOOLCHAIN_${_TOOLCHAIN_SELECTED}_VERSION "${COMPARISON_OPERATOR}" Rust_FIND_VERSION)
|
|
||||||
set("${OUT_IS_OK}" TRUE PARENT_SCOPE)
|
|
||||||
else()
|
|
||||||
set("${OUT_IS_OK}" FALSE PARENT_SCOPE)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
# if no VERSION requirement was specified, the version is always okay.
|
|
||||||
set("${OUT_IS_OK}" TRUE PARENT_SCOPE)
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
function(_corrosion_strip_target_triple input_triple_or_path output_triple)
|
|
||||||
# If the target_triple is a path to a custom target specification file, then strip everything
|
|
||||||
# except the filename from `target_triple`.
|
|
||||||
get_filename_component(target_triple_ext "${input_triple_or_path}" EXT)
|
|
||||||
set(target_triple "${input_triple_or_path}")
|
|
||||||
if(target_triple_ext)
|
|
||||||
if(target_triple_ext STREQUAL ".json")
|
|
||||||
get_filename_component(target_triple "${input_triple_or_path}" NAME_WE)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
set(${output_triple} "${target_triple}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
function(_corrosion_parse_target_triple target_triple out_arch out_vendor out_os out_env)
|
|
||||||
_corrosion_strip_target_triple(${target_triple} target_triple)
|
|
||||||
|
|
||||||
# The vendor part may be left out from the target triple, and since `env` is also optional,
|
|
||||||
# we determine if vendor is present by matching against a list of known vendors.
|
|
||||||
set(known_vendors
|
|
||||||
"apple"
|
|
||||||
"esp[a-z0-9]*" # espressif, e.g. riscv32imc-esp-espidf or xtensa-esp32s3-none-elf
|
|
||||||
"fortanix"
|
|
||||||
"kmc"
|
|
||||||
"pc"
|
|
||||||
"nintendo"
|
|
||||||
"nvidia"
|
|
||||||
"openwrt"
|
|
||||||
"alpine"
|
|
||||||
"chimera"
|
|
||||||
"unikraft"
|
|
||||||
"unknown"
|
|
||||||
"uwp" # aarch64-uwp-windows-msvc
|
|
||||||
"wrs" # e.g. aarch64-wrs-vxworks
|
|
||||||
"sony"
|
|
||||||
"sun"
|
|
||||||
)
|
|
||||||
# todo: allow users to add additional vendors to the list via a cmake variable.
|
|
||||||
list(JOIN known_vendors "|" known_vendors_joined)
|
|
||||||
# vendor is optional - We detect if vendor is present by matching against a known list of
|
|
||||||
# vendors. The next field is the OS, which we assume to always be present, while the last field
|
|
||||||
# is again optional and contains the environment.
|
|
||||||
string(REGEX MATCH
|
|
||||||
"^([a-z0-9_\.]+)-((${known_vendors_joined})-)?([a-z0-9_]+)(-([a-z0-9_]+))?$"
|
|
||||||
whole_match
|
|
||||||
"${target_triple}"
|
|
||||||
)
|
|
||||||
if((NOT whole_match) AND (NOT CORROSION_NO_WARN_PARSE_TARGET_TRIPLE_FAILED))
|
|
||||||
message(WARNING "Failed to parse target-triple `${target_triple}`."
|
|
||||||
"Corrosion determines some information about the output artifacts based on OS "
|
|
||||||
"specified in the Rust target-triple.\n"
|
|
||||||
"Currently this is relevant for windows and darwin (mac) targets, since file "
|
|
||||||
"extensions differ.\n"
|
|
||||||
"Note: If you are targeting a different OS you can suppress this warning by"
|
|
||||||
" setting the CMake cache variable "
|
|
||||||
"`CORROSION_NO_WARN_PARSE_TARGET_TRIPLE_FAILED`."
|
|
||||||
"Please consider opening an issue on github if you you need to add a new vendor to the list."
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
message(DEBUG "Parsed Target triple: arch: ${CMAKE_MATCH_1}, vendor: ${CMAKE_MATCH_3}, "
|
|
||||||
"OS: ${CMAKE_MATCH_4}, env: ${CMAKE_MATCH_6}")
|
|
||||||
|
|
||||||
set("${out_arch}" "${CMAKE_MATCH_1}" PARENT_SCOPE)
|
|
||||||
set("${out_vendor}" "${CMAKE_MATCH_3}" PARENT_SCOPE)
|
|
||||||
set("${out_os}" "${CMAKE_MATCH_4}" PARENT_SCOPE)
|
|
||||||
set("${out_env}" "${CMAKE_MATCH_6}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
function(_corrosion_determine_libs_new target_triple out_libs)
|
|
||||||
set(package_dir "${CMAKE_BINARY_DIR}/corrosion/required_libs")
|
|
||||||
# Cleanup on reconfigure to get a cleans state (in case we change something in the future)
|
|
||||||
file(REMOVE_RECURSE "${package_dir}")
|
|
||||||
file(MAKE_DIRECTORY "${package_dir}")
|
|
||||||
set(manifest "[package]\nname = \"required_libs\"\nedition = \"2018\"\nversion = \"0.1.0\"\n")
|
|
||||||
string(APPEND manifest "\n[lib]\ncrate-type=[\"staticlib\"]\npath = \"lib.rs\"\n")
|
|
||||||
string(APPEND manifest "\n[workspace]\n")
|
|
||||||
file(WRITE "${package_dir}/Cargo.toml" "${manifest}")
|
|
||||||
file(WRITE "${package_dir}/lib.rs" "pub fn add(left: usize, right: usize) -> usize {left + right}\n")
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E env
|
|
||||||
"CARGO_BUILD_RUSTC=${Rust_COMPILER_CACHED}"
|
|
||||||
${Rust_CARGO_CACHED} rustc --verbose --color never --target=${target_triple} -- --print=native-static-libs
|
|
||||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/corrosion/required_libs"
|
|
||||||
RESULT_VARIABLE cargo_build_result
|
|
||||||
ERROR_VARIABLE cargo_build_error_message
|
|
||||||
)
|
|
||||||
if(cargo_build_result)
|
|
||||||
message(DEBUG "Determining required native libraries - failed: ${cargo_build_result}.")
|
|
||||||
message(TRACE "The cargo build error was: ${cargo_build_error_message}")
|
|
||||||
message(DEBUG "Note: This is expected for Rust targets without std support")
|
|
||||||
return()
|
|
||||||
else()
|
|
||||||
# The pattern starts with `native-static-libs:` and goes to the end of the line.
|
|
||||||
if(cargo_build_error_message MATCHES "native-static-libs: ([^\r\n]+)\r?\n")
|
|
||||||
string(REPLACE " " ";" "libs_list" "${CMAKE_MATCH_1}")
|
|
||||||
set(stripped_lib_list "")
|
|
||||||
|
|
||||||
set(was_last_framework OFF)
|
|
||||||
foreach(lib ${libs_list})
|
|
||||||
# merge -framework;lib -> "-framework lib" as CMake does de-duplication of link libraries, and -framework prefix is required
|
|
||||||
if (lib STREQUAL "-framework")
|
|
||||||
set(was_last_framework ON)
|
|
||||||
continue()
|
|
||||||
endif()
|
|
||||||
if (was_last_framework)
|
|
||||||
list(APPEND stripped_lib_list "-framework ${lib}")
|
|
||||||
set(was_last_framework OFF)
|
|
||||||
continue()
|
|
||||||
endif()
|
|
||||||
# Strip leading `-l` (unix) and potential .lib suffix (windows)
|
|
||||||
string(REGEX REPLACE "^-l" "" "stripped_lib" "${lib}")
|
|
||||||
string(REGEX REPLACE "\.lib$" "" "stripped_lib" "${stripped_lib}")
|
|
||||||
list(APPEND stripped_lib_list "${stripped_lib}")
|
|
||||||
endforeach()
|
|
||||||
set(libs_list "${stripped_lib_list}")
|
|
||||||
# Special case `msvcrt` to link with the debug version in Debug mode.
|
|
||||||
list(TRANSFORM libs_list REPLACE "^msvcrt$" "\$<\$<CONFIG:Debug>:msvcrtd>")
|
|
||||||
else()
|
|
||||||
message(DEBUG "Determining required native libraries - failed: Regex match failure.")
|
|
||||||
message(DEBUG "`native-static-libs` not found in: `${cargo_build_error_message}`")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
set("${out_libs}" "${libs_list}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
if (NOT "${Rust_TOOLCHAIN}" STREQUAL "$CACHE{Rust_TOOLCHAIN}")
|
|
||||||
# Promote Rust_TOOLCHAIN to a cache variable if it is not already a cache variable
|
|
||||||
set(Rust_TOOLCHAIN ${Rust_TOOLCHAIN} CACHE STRING "Requested rustup toolchain" FORCE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(_RESOLVE_RUSTUP_TOOLCHAINS_DESC "Indicates whether to descend into the toolchain pointed to by rustup")
|
|
||||||
set(Rust_RESOLVE_RUSTUP_TOOLCHAINS ON CACHE BOOL ${_RESOLVE_RUSTUP_TOOLCHAINS_DESC})
|
|
||||||
|
|
||||||
# This block checks to see if we're prioritizing a rustup-managed toolchain.
|
|
||||||
if (DEFINED Rust_TOOLCHAIN)
|
|
||||||
# If the user specifies `Rust_TOOLCHAIN`, then look for `rustup` first, rather than `rustc`.
|
|
||||||
find_program(Rust_RUSTUP rustup PATHS "$ENV{HOME}/.cargo/bin")
|
|
||||||
if(NOT Rust_RUSTUP)
|
|
||||||
if(NOT "${Rust_FIND_QUIETLY}")
|
|
||||||
message(
|
|
||||||
WARNING "CMake variable `Rust_TOOLCHAIN` specified, but `rustup` was not found. "
|
|
||||||
"Ignoring toolchain and looking for a Rust toolchain not managed by rustup.")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
# If we aren't definitely using a rustup toolchain, look for rustc first - the user may have
|
|
||||||
# a toolchain installed via a method other than rustup higher in the PATH, which should be
|
|
||||||
# preferred. However, if the first-found rustc is a rustup proxy, then we'll revert to
|
|
||||||
# finding the preferred toolchain via rustup.
|
|
||||||
|
|
||||||
# Uses `Rust_COMPILER` to let user-specified `rustc` win. But we will still "override" the
|
|
||||||
# user's setting if it is pointing to `rustup`. Default rustup install path is provided as a
|
|
||||||
# backup if a toolchain cannot be found in the user's PATH.
|
|
||||||
|
|
||||||
if (DEFINED Rust_COMPILER)
|
|
||||||
set(_Rust_COMPILER_TEST "${Rust_COMPILER}")
|
|
||||||
set(_USER_SPECIFIED_RUSTC ON)
|
|
||||||
if(NOT (EXISTS "${_Rust_COMPILER_TEST}" AND NOT IS_DIRECTORY "${_Rust_COMPILER_TEST}"))
|
|
||||||
set(_ERROR_MESSAGE "Rust_COMPILER was set to `${Rust_COMPILER}`, but this file does "
|
|
||||||
"not exist."
|
|
||||||
)
|
|
||||||
_findrust_failed(${_ERROR_MESSAGE})
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
find_program(_Rust_COMPILER_TEST rustc PATHS "$ENV{HOME}/.cargo/bin")
|
|
||||||
if(NOT EXISTS "${_Rust_COMPILER_TEST}")
|
|
||||||
set(_ERROR_MESSAGE "`rustc` not found in PATH or `$ENV{HOME}/.cargo/bin`.\n"
|
|
||||||
"Hint: Check if `rustc` is in PATH or manually specify the location "
|
|
||||||
"by setting `Rust_COMPILER` to the path to `rustc`.")
|
|
||||||
_findrust_failed(${_ERROR_MESSAGE})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Check if the discovered rustc is actually a "rustup" proxy.
|
|
||||||
execute_process(
|
|
||||||
COMMAND
|
|
||||||
${CMAKE_COMMAND} -E env
|
|
||||||
RUSTUP_FORCE_ARG0=rustup
|
|
||||||
"${_Rust_COMPILER_TEST}" --version
|
|
||||||
OUTPUT_VARIABLE _RUSTC_VERSION_RAW
|
|
||||||
ERROR_VARIABLE _RUSTC_VERSION_STDERR
|
|
||||||
RESULT_VARIABLE _RUSTC_VERSION_RESULT
|
|
||||||
)
|
|
||||||
|
|
||||||
if(NOT (_RUSTC_VERSION_RESULT EQUAL "0"))
|
|
||||||
_findrust_failed("`${_Rust_COMPILER_TEST} --version` failed with ${_RUSTC_VERSION_RESULT}\n"
|
|
||||||
"rustc stderr:\n${_RUSTC_VERSION_STDERR}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (_RUSTC_VERSION_RAW MATCHES "rustup [0-9\\.]+")
|
|
||||||
# Get `rustup` next to the `rustc` proxy
|
|
||||||
get_filename_component(_RUST_PROXIES_PATH "${_Rust_COMPILER_TEST}" DIRECTORY)
|
|
||||||
find_program(Rust_RUSTUP rustup HINTS "${_RUST_PROXIES_PATH}" NO_DEFAULT_PATH)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
unset(_Rust_COMPILER_TEST CACHE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# At this point, the only thing we should have evaluated is a path to `rustup` _if that's what the
|
|
||||||
# best source for a Rust toolchain was determined to be_.
|
|
||||||
if (NOT Rust_RUSTUP)
|
|
||||||
set(Rust_RESOLVE_RUSTUP_TOOLCHAINS OFF CACHE BOOL ${_RESOLVE_RUSTUP_TOOLCHAINS_DESC} FORCE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# List of user variables that will override any toolchain-provided setting
|
|
||||||
set(_Rust_USER_VARS Rust_COMPILER Rust_CARGO Rust_CARGO_TARGET Rust_CARGO_HOST_TARGET)
|
|
||||||
foreach(_VAR ${_Rust_USER_VARS})
|
|
||||||
if (DEFINED "${_VAR}")
|
|
||||||
set(${_VAR}_CACHED "${${_VAR}}" CACHE INTERNAL "Internal cache of ${_VAR}")
|
|
||||||
else()
|
|
||||||
unset(${_VAR}_CACHED CACHE)
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Discover what toolchains are installed by rustup, if the discovered `rustc` is a proxy from
|
|
||||||
# `rustup` and the user hasn't explicitly requested to override this behavior, then select either
|
|
||||||
# the default toolchain, or the requested toolchain Rust_TOOLCHAIN
|
|
||||||
if (Rust_RESOLVE_RUSTUP_TOOLCHAINS)
|
|
||||||
execute_process(
|
|
||||||
COMMAND
|
|
||||||
"${Rust_RUSTUP}" toolchain list --verbose
|
|
||||||
OUTPUT_VARIABLE _TOOLCHAINS_RAW
|
|
||||||
)
|
|
||||||
|
|
||||||
string(REPLACE "\n" ";" _TOOLCHAINS_RAW "${_TOOLCHAINS_RAW}")
|
|
||||||
set(_DISCOVERED_TOOLCHAINS "")
|
|
||||||
set(_DISCOVERED_TOOLCHAINS_RUSTC_PATH "")
|
|
||||||
set(_DISCOVERED_TOOLCHAINS_CARGO_PATH "")
|
|
||||||
set(_DISCOVERED_TOOLCHAINS_VERSION "")
|
|
||||||
|
|
||||||
foreach(_TOOLCHAIN_RAW ${_TOOLCHAINS_RAW})
|
|
||||||
# We're going to try to parse the output of `rustup toolchain list --verbose`.
|
|
||||||
# We expect output like this:
|
|
||||||
# stable-random-toolchain-junk (parenthesized-random-stuff-like-active-or-default) /path/to/toolchain/blah/more-blah
|
|
||||||
# In the following regex, we capture the toolchain name, any parenthesized stuff, and then the path.
|
|
||||||
message(STATUS "Parsing toolchain: ${_TOOLCHAIN_RAW}")
|
|
||||||
if (_TOOLCHAIN_RAW MATCHES "([^\t ]+)[\t ]*(\\(.*\\))?[\t ]*(.+)")
|
|
||||||
set(_TOOLCHAIN "${CMAKE_MATCH_1}")
|
|
||||||
set(_TOOLCHAIN_TYPE "${CMAKE_MATCH_2}")
|
|
||||||
|
|
||||||
set(_TOOLCHAIN_PATH "${CMAKE_MATCH_3}")
|
|
||||||
set(_TOOLCHAIN_${_TOOLCHAIN}_PATH "${CMAKE_MATCH_3}")
|
|
||||||
|
|
||||||
if (_TOOLCHAIN_TYPE MATCHES "default")
|
|
||||||
set(_TOOLCHAIN_DEFAULT "${_TOOLCHAIN}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (_TOOLCHAIN_TYPE MATCHES "override")
|
|
||||||
set(_TOOLCHAIN_OVERRIDE "${_TOOLCHAIN}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND
|
|
||||||
"${_TOOLCHAIN_PATH}/bin/rustc" --version
|
|
||||||
OUTPUT_VARIABLE _TOOLCHAIN_RAW_VERSION
|
|
||||||
)
|
|
||||||
if (_TOOLCHAIN_RAW_VERSION MATCHES "rustc ([0-9]+)\\.([0-9]+)\\.([0-9]+)(-nightly)?")
|
|
||||||
list(APPEND _DISCOVERED_TOOLCHAINS "${_TOOLCHAIN}")
|
|
||||||
list(APPEND _DISCOVERED_TOOLCHAINS_RUSTC_PATH "${_TOOLCHAIN_PATH}/bin/rustc")
|
|
||||||
list(APPEND _DISCOVERED_TOOLCHAINS_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
|
|
||||||
|
|
||||||
# We need this variable to determine the default toolchain, since `foreach(... IN ZIP_LISTS ...)`
|
|
||||||
# requires CMake 3.17. As a workaround we define this variable to lookup the version when iterating
|
|
||||||
# through the `_DISCOVERED_TOOLCHAINS` lists.
|
|
||||||
set(_TOOLCHAIN_${_TOOLCHAIN}_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
|
|
||||||
if(CMAKE_MATCH_4)
|
|
||||||
set(_TOOLCHAIN_${_TOOLCHAIN}_IS_NIGHTLY "TRUE")
|
|
||||||
else()
|
|
||||||
set(_TOOLCHAIN_${_TOOLCHAIN}_IS_NIGHTLY "FALSE")
|
|
||||||
endif()
|
|
||||||
if(EXISTS "${_TOOLCHAIN_PATH}/bin/cargo")
|
|
||||||
list(APPEND _DISCOVERED_TOOLCHAINS_CARGO_PATH "${_TOOLCHAIN_PATH}/bin/cargo")
|
|
||||||
else()
|
|
||||||
list(APPEND _DISCOVERED_TOOLCHAINS_CARGO_PATH "NOTFOUND")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(AUTHOR_WARNING "Unexpected output from `rustc --version` for Toolchain `${_TOOLCHAIN}`: "
|
|
||||||
"`${_TOOLCHAIN_RAW_VERSION}`.\n"
|
|
||||||
"Ignoring this toolchain."
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(AUTHOR_WARNING "Didn't recognize toolchain: ${_TOOLCHAIN_RAW}. Ignoring this toolchain.\n"
|
|
||||||
"Rustup toolchain list output( `${Rust_RUSTUP} toolchain list --verbose`):\n"
|
|
||||||
"${_TOOLCHAINS_RAW}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Expose a list of available rustup toolchains.
|
|
||||||
list(LENGTH _DISCOVERED_TOOLCHAINS _toolchain_len)
|
|
||||||
list(LENGTH _DISCOVERED_TOOLCHAINS_RUSTC_PATH _toolchain_rustc_len)
|
|
||||||
list(LENGTH _DISCOVERED_TOOLCHAINS_CARGO_PATH _toolchain_cargo_len)
|
|
||||||
list(LENGTH _DISCOVERED_TOOLCHAINS_VERSION _toolchain_version_len)
|
|
||||||
if(NOT
|
|
||||||
(_toolchain_len EQUAL _toolchain_rustc_len
|
|
||||||
AND _toolchain_cargo_len EQUAL _toolchain_version_len
|
|
||||||
AND _toolchain_len EQUAL _toolchain_cargo_len)
|
|
||||||
)
|
|
||||||
message(FATAL_ERROR "Internal error - list length mismatch."
|
|
||||||
"List lengths: ${_toolchain_len} toolchains, ${_toolchain_rustc_len} rustc, ${_toolchain_cargo_len} cargo,"
|
|
||||||
" ${_toolchain_version_len} version. The lengths should be the same."
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(Rust_RUSTUP_TOOLCHAINS CACHE INTERNAL "List of available Rustup toolchains" "${_DISCOVERED_TOOLCHAINS}")
|
|
||||||
set(Rust_RUSTUP_TOOLCHAINS_RUSTC_PATH
|
|
||||||
CACHE INTERNAL
|
|
||||||
"List of the rustc paths corresponding to the toolchain at the same index in `Rust_RUSTUP_TOOLCHAINS`."
|
|
||||||
"${_DISCOVERED_TOOLCHAINS_RUSTC_PATH}"
|
|
||||||
)
|
|
||||||
set(Rust_RUSTUP_TOOLCHAINS_CARGO_PATH
|
|
||||||
CACHE INTERNAL
|
|
||||||
"List of the cargo paths corresponding to the toolchain at the same index in `Rust_RUSTUP_TOOLCHAINS`. \
|
|
||||||
May also be `NOTFOUND` if the toolchain does not have a cargo executable."
|
|
||||||
"${_DISCOVERED_TOOLCHAINS_CARGO_PATH}"
|
|
||||||
)
|
|
||||||
set(Rust_RUSTUP_TOOLCHAINS_VERSION
|
|
||||||
CACHE INTERNAL
|
|
||||||
"List of the rust toolchain version corresponding to the toolchain at the same index in \
|
|
||||||
`Rust_RUSTUP_TOOLCHAINS`."
|
|
||||||
"${_DISCOVERED_TOOLCHAINS_VERSION}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Rust_TOOLCHAIN is preferred over a requested version if it is set.
|
|
||||||
if (NOT DEFINED Rust_TOOLCHAIN)
|
|
||||||
if (NOT DEFINED _TOOLCHAIN_OVERRIDE)
|
|
||||||
set(_TOOLCHAIN_SELECTED "${_TOOLCHAIN_DEFAULT}")
|
|
||||||
else()
|
|
||||||
set(_TOOLCHAIN_SELECTED "${_TOOLCHAIN_OVERRIDE}")
|
|
||||||
endif()
|
|
||||||
# Check default toolchain first.
|
|
||||||
_findrust_version_ok("_TOOLCHAIN_${_TOOLCHAIN_SELECTED}_VERSION" _VERSION_OK)
|
|
||||||
if(NOT "${_VERSION_OK}")
|
|
||||||
foreach(_TOOLCHAIN "${_DISCOVERED_TOOLCHAINS}")
|
|
||||||
_findrust_version_ok("_TOOLCHAIN_${_TOOLCHAIN}_VERSION" _VERSION_OK)
|
|
||||||
if("${_VERSION_OK}")
|
|
||||||
set(_TOOLCHAIN_SELECTED "${_TOOLCHAIN}")
|
|
||||||
break()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
# Check if we found a suitable version in the for loop.
|
|
||||||
if(NOT "${_VERSION_OK}")
|
|
||||||
string(REPLACE ";" "\n" _DISCOVERED_TOOLCHAINS "${_DISCOVERED_TOOLCHAINS}")
|
|
||||||
_findrust_failed("Failed to find a Rust toolchain matching the version requirements of "
|
|
||||||
"${Rust_FIND_VERSION}. Available toolchains: ${_DISCOVERED_TOOLCHAINS}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(Rust_TOOLCHAIN "${_TOOLCHAIN_SELECTED}" CACHE STRING "The rustup toolchain to use")
|
|
||||||
set_property(CACHE Rust_TOOLCHAIN PROPERTY STRINGS "${_DISCOVERED_TOOLCHAINS}")
|
|
||||||
|
|
||||||
if(NOT Rust_FIND_QUIETLY)
|
|
||||||
message(STATUS "Rust Toolchain: ${Rust_TOOLCHAIN}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT Rust_TOOLCHAIN IN_LIST _DISCOVERED_TOOLCHAINS)
|
|
||||||
# If the precise toolchain wasn't found, try appending the default host
|
|
||||||
execute_process(
|
|
||||||
COMMAND
|
|
||||||
"${Rust_RUSTUP}" show
|
|
||||||
RESULT_VARIABLE _SHOW_RESULT
|
|
||||||
OUTPUT_VARIABLE _SHOW_RAW
|
|
||||||
)
|
|
||||||
if(NOT "${_SHOW_RESULT}" EQUAL "0")
|
|
||||||
_findrust_failed("Command `${Rust_RUSTUP} show` failed")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (_SHOW_RAW MATCHES "Default host: ([a-zA-Z0-9_\\-]*)\n")
|
|
||||||
set(_DEFAULT_HOST "${CMAKE_MATCH_1}")
|
|
||||||
else()
|
|
||||||
_findrust_failed("Failed to parse \"Default host\" from `${Rust_RUSTUP} show`. Got: ${_SHOW_RAW}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT "${Rust_TOOLCHAIN}-${_DEFAULT_HOST}" IN_LIST _DISCOVERED_TOOLCHAINS)
|
|
||||||
set(_NOT_FOUND_MESSAGE "Could not find toolchain '${Rust_TOOLCHAIN}'\n"
|
|
||||||
"Available toolchains:\n"
|
|
||||||
)
|
|
||||||
foreach(_TOOLCHAIN ${_DISCOVERED_TOOLCHAINS})
|
|
||||||
list(APPEND _NOT_FOUND_MESSAGE " `${_TOOLCHAIN}`\n")
|
|
||||||
endforeach()
|
|
||||||
_findrust_failed(${_NOT_FOUND_MESSAGE})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(_RUSTUP_TOOLCHAIN_FULL "${Rust_TOOLCHAIN}-${_DEFAULT_HOST}")
|
|
||||||
else()
|
|
||||||
set(_RUSTUP_TOOLCHAIN_FULL "${Rust_TOOLCHAIN}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(_RUST_TOOLCHAIN_PATH "${_TOOLCHAIN_${_RUSTUP_TOOLCHAIN_FULL}_PATH}")
|
|
||||||
if(NOT "${Rust_FIND_QUIETLY}")
|
|
||||||
message(VERBOSE "Rust toolchain ${_RUSTUP_TOOLCHAIN_FULL}")
|
|
||||||
message(VERBOSE "Rust toolchain path ${_RUST_TOOLCHAIN_PATH}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Is overridden if the user specifies `Rust_COMPILER` explicitly.
|
|
||||||
find_program(
|
|
||||||
Rust_COMPILER_CACHED
|
|
||||||
rustc
|
|
||||||
HINTS "${_RUST_TOOLCHAIN_PATH}/bin"
|
|
||||||
NO_DEFAULT_PATH)
|
|
||||||
elseif (Rust_RUSTUP)
|
|
||||||
get_filename_component(_RUST_TOOLCHAIN_PATH "${Rust_RUSTUP}" DIRECTORY)
|
|
||||||
get_filename_component(_RUST_TOOLCHAIN_PATH "${_RUST_TOOLCHAIN_PATH}" DIRECTORY)
|
|
||||||
find_program(
|
|
||||||
Rust_COMPILER_CACHED
|
|
||||||
rustc
|
|
||||||
HINTS "${_RUST_TOOLCHAIN_PATH}/bin"
|
|
||||||
NO_DEFAULT_PATH)
|
|
||||||
else()
|
|
||||||
find_program(Rust_COMPILER_CACHED rustc)
|
|
||||||
if (EXISTS "${Rust_COMPILER_CACHED}")
|
|
||||||
# rustc is expected to be at `<toolchain_path>/bin/rustc`.
|
|
||||||
get_filename_component(_RUST_TOOLCHAIN_PATH "${Rust_COMPILER_CACHED}" DIRECTORY)
|
|
||||||
get_filename_component(_RUST_TOOLCHAIN_PATH "${_RUST_TOOLCHAIN_PATH}" DIRECTORY)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT EXISTS "${Rust_COMPILER_CACHED}")
|
|
||||||
set(_NOT_FOUND_MESSAGE "The rustc executable was not found. "
|
|
||||||
"Rust not installed or ~/.cargo/bin not added to path?\n"
|
|
||||||
"Hint: Consider setting `Rust_COMPILER` to the absolute path of `rustc`."
|
|
||||||
)
|
|
||||||
_findrust_failed(${_NOT_FOUND_MESSAGE})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (Rust_RESOLVE_RUSTUP_TOOLCHAINS)
|
|
||||||
set(_NOT_FOUND_MESSAGE "Rust was detected to be managed by rustup, but failed to find `cargo` "
|
|
||||||
"next to `rustc` in `${_RUST_TOOLCHAIN_PATH}/bin`. This can happen for custom toolchains, "
|
|
||||||
"if cargo was not built. "
|
|
||||||
"Please manually specify the path to a compatible `cargo` by setting `Rust_CARGO`."
|
|
||||||
)
|
|
||||||
find_program(
|
|
||||||
Rust_CARGO_CACHED
|
|
||||||
cargo
|
|
||||||
HINTS "${_RUST_TOOLCHAIN_PATH}/bin"
|
|
||||||
NO_DEFAULT_PATH
|
|
||||||
)
|
|
||||||
# note: maybe can use find_package_handle_standard_args here, if we remove the _CACHED postfix.
|
|
||||||
# not sure why that is here...
|
|
||||||
if(NOT EXISTS "${Rust_CARGO_CACHED}")
|
|
||||||
_findrust_failed(${_NOT_FOUND_MESSAGE})
|
|
||||||
endif()
|
|
||||||
set(Rust_TOOLCHAIN_IS_RUSTUP_MANAGED TRUE CACHE INTERNAL "" FORCE)
|
|
||||||
else()
|
|
||||||
set(_NOT_FOUND_MESSAGE "Failed to find `cargo` in PATH and `${_RUST_TOOLCHAIN_PATH}/bin`.\n"
|
|
||||||
"Please ensure cargo is in PATH or manually specify the path to a compatible `cargo` by "
|
|
||||||
"setting `Rust_CARGO`."
|
|
||||||
)
|
|
||||||
# On some systems (e.g. NixOS) cargo is not managed by rustup and also not next to rustc.
|
|
||||||
find_program(
|
|
||||||
Rust_CARGO_CACHED
|
|
||||||
cargo
|
|
||||||
HINTS "${_RUST_TOOLCHAIN_PATH}/bin"
|
|
||||||
)
|
|
||||||
# note: maybe can use find_package_handle_standard_args here, if we remove the _CACHED postfix.
|
|
||||||
# not sure why that is here...
|
|
||||||
if(NOT EXISTS "${Rust_CARGO_CACHED}")
|
|
||||||
_findrust_failed(${_NOT_FOUND_MESSAGE})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND "${Rust_CARGO_CACHED}" --version --verbose
|
|
||||||
OUTPUT_VARIABLE _CARGO_VERSION_RAW
|
|
||||||
RESULT_VARIABLE _CARGO_VERSION_RESULT
|
|
||||||
)
|
|
||||||
# todo: check if cargo is a required component!
|
|
||||||
if(NOT ( "${_CARGO_VERSION_RESULT}" EQUAL "0" ))
|
|
||||||
_findrust_failed("Failed to get cargo version.\n"
|
|
||||||
"`${Rust_CARGO_CACHED} --version` failed with error: `${_CARGO_VERSION_RESULT}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# todo: don't set cache variables here, but let find_package_handle_standard_args do the promotion
|
|
||||||
# later.
|
|
||||||
if (_CARGO_VERSION_RAW MATCHES "cargo ([0-9]+)\\.([0-9]+)\\.([0-9]+)")
|
|
||||||
set(Rust_CARGO_VERSION_MAJOR "${CMAKE_MATCH_1}" CACHE INTERNAL "" FORCE)
|
|
||||||
set(Rust_CARGO_VERSION_MINOR "${CMAKE_MATCH_2}" CACHE INTERNAL "" FORCE)
|
|
||||||
set(Rust_CARGO_VERSION_PATCH "${CMAKE_MATCH_3}" CACHE INTERNAL "" FORCE)
|
|
||||||
set(Rust_CARGO_VERSION "${Rust_CARGO_VERSION_MAJOR}.${Rust_CARGO_VERSION_MINOR}.${Rust_CARGO_VERSION_PATCH}" CACHE INTERNAL "" FORCE)
|
|
||||||
# Workaround for the version strings where the `cargo ` prefix is missing.
|
|
||||||
elseif(_CARGO_VERSION_RAW MATCHES "([0-9]+)\\.([0-9]+)\\.([0-9]+)")
|
|
||||||
set(Rust_CARGO_VERSION_MAJOR "${CMAKE_MATCH_1}" CACHE INTERNAL "" FORCE)
|
|
||||||
set(Rust_CARGO_VERSION_MINOR "${CMAKE_MATCH_2}" CACHE INTERNAL "" FORCE)
|
|
||||||
set(Rust_CARGO_VERSION_PATCH "${CMAKE_MATCH_3}" CACHE INTERNAL "" FORCE)
|
|
||||||
set(Rust_CARGO_VERSION "${Rust_CARGO_VERSION_MAJOR}.${Rust_CARGO_VERSION_MINOR}.${Rust_CARGO_VERSION_PATCH}" CACHE INTERNAL "" FORCE)
|
|
||||||
else()
|
|
||||||
_findrust_failed(
|
|
||||||
"Failed to parse cargo version. `cargo --version` evaluated to (${_CARGO_VERSION_RAW}). "
|
|
||||||
"Expected a <Major>.<Minor>.<Patch> version triple."
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND "${Rust_COMPILER_CACHED}" --version --verbose
|
|
||||||
OUTPUT_VARIABLE _RUSTC_VERSION_RAW
|
|
||||||
RESULT_VARIABLE _RUSTC_VERSION_RESULT
|
|
||||||
)
|
|
||||||
|
|
||||||
if(NOT ( "${_RUSTC_VERSION_RESULT}" EQUAL "0" ))
|
|
||||||
_findrust_failed("Failed to get rustc version.\n"
|
|
||||||
"${Rust_COMPILER_CACHED} --version failed with error: `${_RUSTC_VERSION_RESULT}`")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (_RUSTC_VERSION_RAW MATCHES "rustc ([0-9]+)\\.([0-9]+)\\.([0-9]+)(-nightly)?")
|
|
||||||
set(Rust_VERSION_MAJOR "${CMAKE_MATCH_1}" CACHE INTERNAL "" FORCE)
|
|
||||||
set(Rust_VERSION_MINOR "${CMAKE_MATCH_2}" CACHE INTERNAL "" FORCE)
|
|
||||||
set(Rust_VERSION_PATCH "${CMAKE_MATCH_3}" CACHE INTERNAL "" FORCE)
|
|
||||||
set(Rust_VERSION "${Rust_VERSION_MAJOR}.${Rust_VERSION_MINOR}.${Rust_VERSION_PATCH}" CACHE INTERNAL "" FORCE)
|
|
||||||
if(CMAKE_MATCH_4)
|
|
||||||
set(Rust_IS_NIGHTLY 1 CACHE INTERNAL "" FORCE)
|
|
||||||
else()
|
|
||||||
set(Rust_IS_NIGHTLY 0 CACHE INTERNAL "" FORCE)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
_findrust_failed("Failed to parse rustc version. `${Rust_COMPILER_CACHED} --version --verbose` "
|
|
||||||
"evaluated to:\n`${_RUSTC_VERSION_RAW}`"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (_RUSTC_VERSION_RAW MATCHES "host: ([a-zA-Z0-9_\\-]*)\n")
|
|
||||||
set(Rust_DEFAULT_HOST_TARGET "${CMAKE_MATCH_1}")
|
|
||||||
set(Rust_CARGO_HOST_TARGET_CACHED "${Rust_DEFAULT_HOST_TARGET}" CACHE STRING "Host triple")
|
|
||||||
else()
|
|
||||||
_findrust_failed(
|
|
||||||
"Failed to parse rustc host target. `rustc --version --verbose` evaluated to:\n${_RUSTC_VERSION_RAW}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (_RUSTC_VERSION_RAW MATCHES "LLVM version: ([0-9]+)\\.([0-9]+)(\\.([0-9]+))?")
|
|
||||||
set(Rust_LLVM_VERSION_MAJOR "${CMAKE_MATCH_1}" CACHE INTERNAL "" FORCE)
|
|
||||||
set(Rust_LLVM_VERSION_MINOR "${CMAKE_MATCH_2}" CACHE INTERNAL "" FORCE)
|
|
||||||
# With the Rust toolchain 1.44.1 the reported LLVM version is 9.0, i.e. without a patch version.
|
|
||||||
# Since cmake regex does not support non-capturing groups, just ignore Match 3.
|
|
||||||
set(Rust_LLVM_VERSION_PATCH "${CMAKE_MATCH_4}" CACHE INTERNAL "" FORCE)
|
|
||||||
set(Rust_LLVM_VERSION "${Rust_LLVM_VERSION_MAJOR}.${Rust_LLVM_VERSION_MINOR}.${Rust_LLVM_VERSION_PATCH}" CACHE INTERNAL "" FORCE)
|
|
||||||
elseif(NOT Rust_FIND_QUIETLY)
|
|
||||||
message(
|
|
||||||
WARNING
|
|
||||||
"Failed to parse rustc LLVM version. `rustc --version --verbose` evaluated to:\n${_RUSTC_VERSION_RAW}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT Rust_CARGO_TARGET_CACHED)
|
|
||||||
unset(_CARGO_ARCH)
|
|
||||||
unset(_CARGO_ABI)
|
|
||||||
if (WIN32)
|
|
||||||
if (CMAKE_VS_PLATFORM_NAME)
|
|
||||||
string(TOLOWER "${CMAKE_VS_PLATFORM_NAME}" LOWER_VS_PLATFORM_NAME)
|
|
||||||
if ("${LOWER_VS_PLATFORM_NAME}" STREQUAL "win32")
|
|
||||||
set(_CARGO_ARCH i686)
|
|
||||||
elseif("${LOWER_VS_PLATFORM_NAME}" STREQUAL "x64")
|
|
||||||
set(_CARGO_ARCH x86_64)
|
|
||||||
elseif("${LOWER_VS_PLATFORM_NAME}" STREQUAL "arm64")
|
|
||||||
set(_CARGO_ARCH aarch64)
|
|
||||||
else()
|
|
||||||
message(WARNING "VS Platform '${CMAKE_VS_PLATFORM_NAME}' not recognized")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
# Fallback path
|
|
||||||
if(NOT DEFINED _CARGO_ARCH)
|
|
||||||
# Possible values for windows when not cross-compiling taken from here:
|
|
||||||
# https://learn.microsoft.com/en-us/windows/win32/winprog64/wow64-implementation-details
|
|
||||||
# When cross-compiling the user is expected to supply the value, so we match more variants.
|
|
||||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(AMD64|amd64|x86_64)$")
|
|
||||||
set(_CARGO_ARCH x86_64)
|
|
||||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(ARM64|arm64|aarch64)$")
|
|
||||||
set(_CARGO_ARCH aarch64)
|
|
||||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(X86|x86|i686)$")
|
|
||||||
set(_CARGO_ARCH i686)
|
|
||||||
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "i586")
|
|
||||||
set(_CARGO_ARCH i586)
|
|
||||||
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "IA64")
|
|
||||||
message(FATAL_ERROR "No rust target for Intel Itanium.")
|
|
||||||
elseif(NOT "${CMAKE_SYSTEM_PROCESSOR}")
|
|
||||||
message(WARNING "Failed to detect target architecture. Please set `CMAKE_SYSTEM_PROCESSOR`"
|
|
||||||
" to your target architecture or set `Rust_CARGO_TARGET` to your cargo target triple."
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
message(WARNING "Failed to detect target architecture. Please set "
|
|
||||||
"`Rust_CARGO_TARGET` to your cargo target triple."
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(_CARGO_VENDOR "pc-windows")
|
|
||||||
|
|
||||||
# The MSVC Generators will always target the msvc ABI.
|
|
||||||
# For other generators we check the compiler ID and compiler target (if present)
|
|
||||||
# If no compiler is set and we are not cross-compiling then we just choose the
|
|
||||||
# default rust host target.
|
|
||||||
if(DEFINED MSVC
|
|
||||||
OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC"
|
|
||||||
OR "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC"
|
|
||||||
OR "${CMAKE_CXX_COMPILER_TARGET}" MATCHES "-msvc$"
|
|
||||||
OR "${CMAKE_C_COMPILER_TARGET}" MATCHES "-msvc$"
|
|
||||||
)
|
|
||||||
set(_CARGO_ABI msvc)
|
|
||||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU"
|
|
||||||
OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU"
|
|
||||||
OR "${CMAKE_CXX_COMPILER_TARGET}" MATCHES "-gnu$"
|
|
||||||
OR "${CMAKE_C_COMPILER_TARGET}" MATCHES "-gnu$"
|
|
||||||
OR (NOT CMAKE_CROSSCOMPILING AND "${Rust_DEFAULT_HOST_TARGET}" MATCHES "-gnu$")
|
|
||||||
)
|
|
||||||
set(_CARGO_ABI gnu)
|
|
||||||
elseif(NOT "${CMAKE_CROSSCOMPILING}" AND "${Rust_DEFAULT_HOST_TARGET}" MATCHES "-msvc$")
|
|
||||||
# We first check if the gnu branch matches to ensure this fallback is only used
|
|
||||||
# if no compiler is enabled.
|
|
||||||
set(_CARGO_ABI msvc)
|
|
||||||
else()
|
|
||||||
message(WARNING "Could not determine the target ABI. Please specify `Rust_CARGO_TARGET` manually.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(DEFINED _CARGO_ARCH AND DEFINED _CARGO_VENDOR AND DEFINED _CARGO_ABI)
|
|
||||||
set(Rust_CARGO_TARGET_CACHED "${_CARGO_ARCH}-${_CARGO_VENDOR}-${_CARGO_ABI}"
|
|
||||||
CACHE STRING "Target triple")
|
|
||||||
endif()
|
|
||||||
elseif (ANDROID)
|
|
||||||
if (CMAKE_ANDROID_ARCH_ABI STREQUAL armeabi-v7a)
|
|
||||||
if (CMAKE_ANDROID_ARM_MODE)
|
|
||||||
set(_Rust_ANDROID_TARGET armv7-linux-androideabi)
|
|
||||||
else ()
|
|
||||||
set(_Rust_ANDROID_TARGET thumbv7neon-linux-androideabi)
|
|
||||||
endif()
|
|
||||||
elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL arm64-v8a)
|
|
||||||
set(_Rust_ANDROID_TARGET aarch64-linux-android)
|
|
||||||
elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL x86)
|
|
||||||
set(_Rust_ANDROID_TARGET i686-linux-android)
|
|
||||||
elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL x86_64)
|
|
||||||
set(_Rust_ANDROID_TARGET x86_64-linux-android)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (_Rust_ANDROID_TARGET)
|
|
||||||
set(Rust_CARGO_TARGET_CACHED "${_Rust_ANDROID_TARGET}" CACHE STRING "Target triple")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
# Fallback to the default host target
|
|
||||||
if(NOT Rust_CARGO_TARGET_CACHED)
|
|
||||||
if(CMAKE_CROSSCOMPILING)
|
|
||||||
message(WARNING "CMake is in cross-compiling mode, but the cargo target-triple could not be inferred."
|
|
||||||
"Falling back to the default host target. Please consider manually setting `Rust_CARGO_TARGET`."
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
set(Rust_CARGO_TARGET_CACHED "${Rust_DEFAULT_HOST_TARGET}" CACHE STRING "Target triple")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
message(STATUS "Rust Target: ${Rust_CARGO_TARGET_CACHED}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(Rust_CARGO_TARGET_CACHED STREQUAL Rust_DEFAULT_HOST_TARGET)
|
|
||||||
set(Rust_CROSSCOMPILING FALSE CACHE INTERNAL "Rust is configured for cross-compiling")
|
|
||||||
else()
|
|
||||||
set(Rust_CROSSCOMPILING TRUE CACHE INTERNAL "Rust is configured for cross-compiling")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
_corrosion_parse_target_triple("${Rust_CARGO_TARGET_CACHED}" rust_arch rust_vendor rust_os rust_env)
|
|
||||||
_corrosion_parse_target_triple("${Rust_CARGO_HOST_TARGET_CACHED}" rust_host_arch rust_host_vendor rust_host_os rust_host_env)
|
|
||||||
|
|
||||||
set(Rust_CARGO_TARGET_ARCH "${rust_arch}" CACHE INTERNAL "Target architecture")
|
|
||||||
set(Rust_CARGO_TARGET_VENDOR "${rust_vendor}" CACHE INTERNAL "Target vendor")
|
|
||||||
set(Rust_CARGO_TARGET_OS "${rust_os}" CACHE INTERNAL "Target Operating System")
|
|
||||||
set(Rust_CARGO_TARGET_ENV "${rust_env}" CACHE INTERNAL "Target environment")
|
|
||||||
|
|
||||||
set(Rust_CARGO_HOST_ARCH "${rust_host_arch}" CACHE INTERNAL "Host architecture")
|
|
||||||
set(Rust_CARGO_HOST_VENDOR "${rust_host_vendor}" CACHE INTERNAL "Host vendor")
|
|
||||||
set(Rust_CARGO_HOST_OS "${rust_host_os}" CACHE INTERNAL "Host Operating System")
|
|
||||||
set(Rust_CARGO_HOST_ENV "${rust_host_env}" CACHE INTERNAL "Host environment")
|
|
||||||
|
|
||||||
if(NOT DEFINED CACHE{Rust_CARGO_TARGET_LINK_NATIVE_LIBS})
|
|
||||||
message(STATUS "Determining required link libraries for target ${Rust_CARGO_TARGET_CACHED}")
|
|
||||||
unset(required_native_libs)
|
|
||||||
_corrosion_determine_libs_new("${Rust_CARGO_TARGET_CACHED}" required_native_libs)
|
|
||||||
if(DEFINED required_native_libs)
|
|
||||||
message(STATUS "Required static libs for target ${Rust_CARGO_TARGET_CACHED}: ${required_native_libs}" )
|
|
||||||
endif()
|
|
||||||
# In very recent corrosion versions it is possible to override the rust compiler version
|
|
||||||
# per target, so to be totally correct we would need to determine the libraries for
|
|
||||||
# every installed Rust version, that the user could choose from.
|
|
||||||
# In practice there aren't likely going to be any major differences, so we just do it once
|
|
||||||
# for the target and once for the host target (if cross-compiling).
|
|
||||||
set(Rust_CARGO_TARGET_LINK_NATIVE_LIBS "${required_native_libs}" CACHE INTERNAL
|
|
||||||
"Required native libraries when linking Rust static libraries")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(Rust_CROSSCOMPILING AND NOT DEFINED CACHE{Rust_CARGO_HOST_TARGET_LINK_NATIVE_LIBS})
|
|
||||||
message(STATUS "Determining required link libraries for target ${Rust_CARGO_HOST_TARGET_CACHED}")
|
|
||||||
unset(host_libs)
|
|
||||||
_corrosion_determine_libs_new("${Rust_CARGO_HOST_TARGET_CACHED}" host_libs)
|
|
||||||
if(DEFINED host_libs)
|
|
||||||
message(STATUS "Required static libs for host target ${Rust_CARGO_HOST_TARGET_CACHED}: ${host_libs}" )
|
|
||||||
endif()
|
|
||||||
set(Rust_CARGO_HOST_TARGET_LINK_NATIVE_LIBS "${host_libs}" CACHE INTERNAL
|
|
||||||
"Required native libraries when linking Rust static libraries for the host target")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Set the input variables as non-cache variables so that the variables are available after
|
|
||||||
# `find_package`, even if the values were evaluated to defaults.
|
|
||||||
foreach(_VAR ${_Rust_USER_VARS})
|
|
||||||
set(${_VAR} "${${_VAR}_CACHED}")
|
|
||||||
# Ensure cached variables have type INTERNAL
|
|
||||||
set(${_VAR}_CACHED "${${_VAR}_CACHED}" CACHE INTERNAL "Internal cache of ${_VAR}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
find_package_handle_standard_args(
|
|
||||||
Rust
|
|
||||||
REQUIRED_VARS Rust_COMPILER Rust_VERSION Rust_CARGO Rust_CARGO_VERSION Rust_CARGO_TARGET Rust_CARGO_HOST_TARGET
|
|
||||||
VERSION_VAR Rust_VERSION
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if(NOT TARGET Rust::Rustc)
|
|
||||||
add_executable(Rust::Rustc IMPORTED GLOBAL)
|
|
||||||
set_property(
|
|
||||||
TARGET Rust::Rustc
|
|
||||||
PROPERTY IMPORTED_LOCATION "${Rust_COMPILER_CACHED}"
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(Rust::Cargo IMPORTED GLOBAL)
|
|
||||||
set_property(
|
|
||||||
TARGET Rust::Cargo
|
|
||||||
PROPERTY IMPORTED_LOCATION "${Rust_CARGO_CACHED}"
|
|
||||||
)
|
|
||||||
set(Rust_FOUND true)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
list(POP_BACK CMAKE_MESSAGE_CONTEXT)
|
|
||||||
@@ -1,17 +1,29 @@
|
|||||||
|
# -DLOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}"
|
||||||
|
# -DPREFIX=L"${CMAKE_INSTALL_PREFIX}"
|
||||||
|
# -DDATADIR=L"${CMAKE_INSTALL_FULL_DATADIR}"
|
||||||
|
# -DSYSCONFDIR=L"${CMAKE_INSTALL_FULL_SYSCONFDIR}"
|
||||||
|
# -DBINDIR=L"${CMAKE_INSTALL_FULL_BINDIR}"
|
||||||
|
# -DDOCDIR=L"${CMAKE_INSTALL_FULL_DOCDIR}")
|
||||||
|
|
||||||
set(CMAKE_INSTALL_MESSAGE NEVER)
|
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(PROGRAMS fish fish_indent fish_key_reader)
|
||||||
|
|
||||||
set(prefix ${CMAKE_INSTALL_PREFIX})
|
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||||
set(bindir ${CMAKE_INSTALL_BINDIR})
|
set(bindir ${CMAKE_INSTALL_BINDIR})
|
||||||
set(sysconfdir ${CMAKE_INSTALL_SYSCONFDIR})
|
set(sysconfdir ${CMAKE_INSTALL_SYSCONFDIR})
|
||||||
set(mandir ${CMAKE_INSTALL_MANDIR})
|
set(mandir ${CMAKE_INSTALL_MANDIR})
|
||||||
|
|
||||||
|
set(rel_datadir ${CMAKE_INSTALL_DATADIR})
|
||||||
set(datadir ${CMAKE_INSTALL_FULL_DATADIR})
|
set(datadir ${CMAKE_INSTALL_FULL_DATADIR})
|
||||||
file(RELATIVE_PATH rel_datadir ${CMAKE_INSTALL_PREFIX} ${datadir})
|
|
||||||
|
|
||||||
set(docdir ${CMAKE_INSTALL_DOCDIR})
|
set(docdir ${CMAKE_INSTALL_DOCDIR})
|
||||||
|
|
||||||
|
# Comment at the top of some .in files
|
||||||
|
set(configure_input
|
||||||
|
"This file was generated from a corresponding .in file.\
|
||||||
|
DO NOT MANUALLY EDIT THIS FILE!")
|
||||||
|
|
||||||
set(rel_completionsdir "fish/vendor_completions.d")
|
set(rel_completionsdir "fish/vendor_completions.d")
|
||||||
set(rel_functionsdir "fish/vendor_functions.d")
|
set(rel_functionsdir "fish/vendor_functions.d")
|
||||||
set(rel_confdir "fish/vendor_conf.d")
|
set(rel_confdir "fish/vendor_conf.d")
|
||||||
@@ -28,19 +40,10 @@ set(extra_confdir
|
|||||||
"${datadir}/${rel_confdir}"
|
"${datadir}/${rel_confdir}"
|
||||||
CACHE STRING "Path for extra configuration")
|
CACHE STRING "Path for extra configuration")
|
||||||
|
|
||||||
|
|
||||||
# These are the man pages that go in system manpath; all manpages go in the fish-specific manpath.
|
# 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
|
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_indent.1
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish_key_reader.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-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.
|
# 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
|
# On OS X, don't install a man page for open, since we defeat fish's open
|
||||||
@@ -73,7 +76,7 @@ function(FISH_TRY_CREATE_DIRS)
|
|||||||
endforeach()
|
endforeach()
|
||||||
endfunction(FISH_TRY_CREATE_DIRS)
|
endfunction(FISH_TRY_CREATE_DIRS)
|
||||||
|
|
||||||
install(PROGRAMS ${PROGRAMS}
|
install(TARGETS ${PROGRAMS}
|
||||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
|
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
|
||||||
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
||||||
DESTINATION ${bindir})
|
DESTINATION ${bindir})
|
||||||
@@ -87,9 +90,8 @@ fish_create_dirs(${rel_datadir}/fish ${rel_datadir}/fish/completions
|
|||||||
${rel_datadir}/fish/man/man1 ${rel_datadir}/fish/tools
|
${rel_datadir}/fish/man/man1 ${rel_datadir}/fish/tools
|
||||||
${rel_datadir}/fish/tools/web_config
|
${rel_datadir}/fish/tools/web_config
|
||||||
${rel_datadir}/fish/tools/web_config/js
|
${rel_datadir}/fish/tools/web_config/js
|
||||||
${rel_datadir}/fish/tools/web_config/sample_prompts
|
${rel_datadir}/fish/tools/web_config/partials
|
||||||
${rel_datadir}/fish/tools/web_config/themes
|
${rel_datadir}/fish/tools/web_config/sample_prompts)
|
||||||
)
|
|
||||||
|
|
||||||
configure_file(share/__fish_build_paths.fish.in share/__fish_build_paths.fish)
|
configure_file(share/__fish_build_paths.fish.in share/__fish_build_paths.fish)
|
||||||
install(FILES share/config.fish
|
install(FILES share/config.fish
|
||||||
@@ -106,9 +108,9 @@ configure_file(fish.pc.in fish.pc.noversion @ONLY)
|
|||||||
add_custom_command(OUTPUT fish.pc
|
add_custom_command(OUTPUT fish.pc
|
||||||
COMMAND sed '/Version/d' fish.pc.noversion > fish.pc
|
COMMAND sed '/Version/d' fish.pc.noversion > fish.pc
|
||||||
COMMAND printf "Version: " >> fish.pc
|
COMMAND printf "Version: " >> fish.pc
|
||||||
COMMAND cat ${FBVF} >> fish.pc
|
COMMAND sed 's/FISH_BUILD_VERSION=//\;s/\"//g' ${FBVF} >> fish.pc
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
DEPENDS CHECK-FISH-BUILD-VERSION-FILE ${CMAKE_CURRENT_BINARY_DIR}/fish.pc.noversion)
|
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${FBVF} ${CMAKE_CURRENT_BINARY_DIR}/fish.pc.noversion)
|
||||||
|
|
||||||
add_custom_target(build_fish_pc ALL DEPENDS fish.pc)
|
add_custom_target(build_fish_pc ALL DEPENDS fish.pc)
|
||||||
|
|
||||||
@@ -145,7 +147,6 @@ install(DIRECTORY share/tools/web_config
|
|||||||
PATTERN "*.html"
|
PATTERN "*.html"
|
||||||
PATTERN "*.py"
|
PATTERN "*.py"
|
||||||
PATTERN "*.js"
|
PATTERN "*.js"
|
||||||
PATTERN "*.theme"
|
|
||||||
PATTERN "*.fish")
|
PATTERN "*.fish")
|
||||||
|
|
||||||
# Building the man pages is optional: if Sphinx isn't installed, they're not built
|
# Building the man pages is optional: if Sphinx isn't installed, they're not built
|
||||||
@@ -154,6 +155,8 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/user_doc/html/ # Trailing slash is
|
|||||||
DESTINATION ${docdir} OPTIONAL)
|
DESTINATION ${docdir} OPTIONAL)
|
||||||
install(FILES CHANGELOG.rst DESTINATION ${docdir})
|
install(FILES CHANGELOG.rst DESTINATION ${docdir})
|
||||||
|
|
||||||
|
install(FILES share/lynx.lss DESTINATION ${rel_datadir}/fish/)
|
||||||
|
|
||||||
# These files are built by cmake/gettext.cmake, but using GETTEXT_PROCESS_PO_FILES's
|
# These files are built by cmake/gettext.cmake, but using GETTEXT_PROCESS_PO_FILES's
|
||||||
# INSTALL_DESTINATION leads to them being installed as ${lang}.gmo, not fish.mo
|
# INSTALL_DESTINATION leads to them being installed as ${lang}.gmo, not fish.mo
|
||||||
# The ${languages} array comes from cmake/gettext.cmake
|
# The ${languages} array comes from cmake/gettext.cmake
|
||||||
@@ -164,14 +167,13 @@ if(GETTEXT_FOUND)
|
|||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT APPLE)
|
install(FILES fish.desktop DESTINATION ${rel_datadir}/applications)
|
||||||
install(FILES fish.desktop DESTINATION ${rel_datadir}/applications)
|
install(FILES fish.png DESTINATION ${rel_datadir}/pixmaps)
|
||||||
install(FILES ${SPHINX_SRC_DIR}/python_docs_theme/static/fish.png DESTINATION ${rel_datadir}/pixmaps)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Group install targets into a InstallTargets folder
|
# Group install targets into a InstallTargets folder
|
||||||
set_property(TARGET build_fish_pc CHECK-FISH-BUILD-VERSION-FILE
|
set_property(TARGET build_fish_pc CHECK-FISH-BUILD-VERSION-FILE
|
||||||
tests_buildroot_target
|
test_fishscript
|
||||||
|
test_prep tests_buildroot_target
|
||||||
PROPERTY FOLDER cmake/InstallTargets)
|
PROPERTY FOLDER cmake/InstallTargets)
|
||||||
|
|
||||||
# Make a target build_root that installs into the buildroot directory, for testing.
|
# Make a target build_root that installs into the buildroot directory, for testing.
|
||||||
|
|||||||
36
cmake/Mac.cmake
Normal file
36
cmake/Mac.cmake
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version")
|
||||||
|
|
||||||
|
# Code signing ID on Mac. A default '-' is ad-hoc codesign.
|
||||||
|
# If this is falsey, codesigning is disabled.
|
||||||
|
set(MAC_CODESIGN_ID "-" CACHE STRING "Mac code-signing identity")
|
||||||
|
|
||||||
|
# Whether to inject the "get-task-allow" entitlement, which permits debugging
|
||||||
|
# on the Mac.
|
||||||
|
set(MAC_INJECT_GET_TASK_ALLOW ON CACHE BOOL "Inject get-task-allow on Mac")
|
||||||
|
|
||||||
|
function(CODESIGN_ON_MAC target)
|
||||||
|
if((APPLE) AND (MAC_CODESIGN_ID))
|
||||||
|
execute_process(COMMAND sw_vers "-productVersion" OUTPUT_VARIABLE OSX_VERSION)
|
||||||
|
if(MAC_INJECT_GET_TASK_ALLOW)
|
||||||
|
set(ENTITLEMENTS "--entitlements" "${CMAKE_SOURCE_DIR}/osx/fish_debug.entitlements")
|
||||||
|
else()
|
||||||
|
set(ENTITLEMENTS "")
|
||||||
|
endif(MAC_INJECT_GET_TASK_ALLOW)
|
||||||
|
if(OSX_VERSION VERSION_LESS "10.13.6")
|
||||||
|
# `-options runtime` is only available in OS X from 10.13.6 and up
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ${target}
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND codesign --force --deep ${ENTITLEMENTS} --sign "${MAC_CODESIGN_ID}" $<TARGET_FILE:${target}>
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ${target}
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND codesign --force --deep --options runtime ${ENTITLEMENTS} --sign "${MAC_CODESIGN_ID}" $<TARGET_FILE:${target}>
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endfunction(CODESIGN_ON_MAC target)
|
||||||
@@ -6,9 +6,6 @@ endif (NOT APPLE)
|
|||||||
# The source tree containing certain macOS resources.
|
# The source tree containing certain macOS resources.
|
||||||
set(OSX_DIR ${CMAKE_CURRENT_SOURCE_DIR}/osx)
|
set(OSX_DIR ${CMAKE_CURRENT_SOURCE_DIR}/osx)
|
||||||
|
|
||||||
# 10.9 is the minimum supported version.
|
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9")
|
|
||||||
|
|
||||||
set(RESOURCE_FILES
|
set(RESOURCE_FILES
|
||||||
${OSX_DIR}/launch_fish.scpt
|
${OSX_DIR}/launch_fish.scpt
|
||||||
${OSX_DIR}/fish_term_icon.icns
|
${OSX_DIR}/fish_term_icon.icns
|
||||||
@@ -24,7 +21,7 @@ add_executable(fish_macapp EXCLUDE_FROM_ALL
|
|||||||
|
|
||||||
# Compute the version. Note this is done at generation time, not build time,
|
# Compute the version. Note this is done at generation time, not build time,
|
||||||
# so cmake must be re-run after version changes for the app to be updated. But
|
# so cmake must be re-run after version changes for the app to be updated. But
|
||||||
# generally this will be run by make_macos_pkg.sh which always re-runs cmake.
|
# generally this will be run by make_pkg.sh which always re-runs cmake.
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_tools/git_version_gen.sh --stdout
|
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_tools/git_version_gen.sh --stdout
|
||||||
COMMAND cut -d- -f1
|
COMMAND cut -d- -f1
|
||||||
@@ -32,7 +29,7 @@ execute_process(
|
|||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
|
||||||
|
|
||||||
# Note CMake appends .app, so the real output name will be fish.app.
|
# Note CMake appends .app, so the real output name will be fish.app.
|
||||||
# This target does not include the 'base' resource.
|
# This target does not include the 'base' resource.
|
||||||
set_target_properties(fish_macapp PROPERTIES OUTPUT_NAME "fish")
|
set_target_properties(fish_macapp PROPERTIES OUTPUT_NAME "fish")
|
||||||
|
|
||||||
@@ -64,5 +61,15 @@ add_custom_command(TARGET fish_macapp POST_BUILD
|
|||||||
# The entitlements file.
|
# The entitlements file.
|
||||||
set(MACAPP_ENTITLEMENTS "${CMAKE_SOURCE_DIR}/osx/MacApp.entitlements")
|
set(MACAPP_ENTITLEMENTS "${CMAKE_SOURCE_DIR}/osx/MacApp.entitlements")
|
||||||
|
|
||||||
# Group our targets in a folder.
|
# Target to sign the macapp.
|
||||||
set_property(TARGET fish_macapp PROPERTY FOLDER macapp)
|
# Note that a POST_BUILD step happens before resources are copied,
|
||||||
|
# and therefore would be too early.
|
||||||
|
add_custom_target(signed_fish_macapp
|
||||||
|
DEPENDS fish_macapp "${MACAPP_ENTITLEMENTS}"
|
||||||
|
COMMAND codesign --force --deep
|
||||||
|
--options runtime
|
||||||
|
--entitlements "${MACAPP_ENTITLEMENTS}"
|
||||||
|
--sign "${MAC_CODESIGN_ID}"
|
||||||
|
$<TARGET_BUNDLE_DIR:fish_macapp>
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,9 +1,43 @@
|
|||||||
set(FISH_USE_SYSTEM_PCRE2 ON CACHE BOOL
|
# PCRE2 needs some settings.
|
||||||
"Try to use PCRE2 from the system, instead of the pcre2-sys version")
|
set(PCRE2_WIDTH ${WCHAR_T_BITS})
|
||||||
|
set(PCRE2_BUILD_PCRE2_8 OFF CACHE BOOL "Build 8bit PCRE2 library")
|
||||||
|
set(PCRE2_BUILD_PCRE2_${PCRE2_WIDTH} ON CACHE BOOL "Build ${PCRE2_WIDTH}bit PCRE2 library")
|
||||||
|
set(PCRE2_SHOW_REPORT OFF CACHE BOOL "Show the final configuration report")
|
||||||
|
set(PCRE2_BUILD_TESTS OFF CACHE BOOL "Build tests")
|
||||||
|
set(PCRE2_BUILD_PCRE2GREP OFF CACHE BOOL "Build pcre2grep")
|
||||||
|
|
||||||
|
set(PCRE2_MIN_VERSION 10.21)
|
||||||
|
|
||||||
|
# Look for a system-installed PCRE2.
|
||||||
|
find_library(SYS_PCRE2_LIB pcre2-${PCRE2_WIDTH})
|
||||||
|
find_path(SYS_PCRE2_INCLUDE_DIR pcre2.h)
|
||||||
|
|
||||||
|
# We can either use the system-installed PCRE or our bundled version.
|
||||||
|
# This is controlled by the cache variable FISH_USE_SYSTEM_PCRE2.
|
||||||
|
# Here we compute the default value for that variable.
|
||||||
|
if ((APPLE) AND (MAC_CODESIGN_ID))
|
||||||
|
# On Mac, a codesigned fish will refuse to load a non-codesigned PCRE2
|
||||||
|
# (e.g. from Homebrew) so default to bundled PCRE2.
|
||||||
|
set(USE_SYS_PCRE2_DEFAULT OFF)
|
||||||
|
elseif((NOT SYS_PCRE2_LIB) OR (NOT SYS_PCRE2_INCLUDE_DIR))
|
||||||
|
# We did not find system PCRE2, so default to bundled.
|
||||||
|
set(USE_SYS_PCRE2_DEFAULT OFF)
|
||||||
|
else()
|
||||||
|
# Default to using the system PCRE2, which was found.
|
||||||
|
set(USE_SYS_PCRE2_DEFAULT ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(FISH_USE_SYSTEM_PCRE2 ${USE_SYS_PCRE2_DEFAULT} CACHE BOOL
|
||||||
|
"Use PCRE2 from the system, instead of bundled with fish")
|
||||||
|
|
||||||
if(FISH_USE_SYSTEM_PCRE2)
|
if(FISH_USE_SYSTEM_PCRE2)
|
||||||
message(STATUS "Trying to use PCRE2 from the system")
|
set(PCRE2_LIB "${SYS_PCRE2_LIB}")
|
||||||
|
set(PCRE2_INCLUDE_DIR "${SYS_PCRE2_INCLUDE_DIR}")
|
||||||
|
message(STATUS "Using system PCRE2 library ${PCRE2_INCLUDE_DIR}")
|
||||||
else()
|
else()
|
||||||
message(STATUS "Forcing static build of PCRE2")
|
message(STATUS "Using bundled PCRE2 library")
|
||||||
set(FISH_PCRE2_BUILDFLAG "PCRE2_SYS_STATIC=1")
|
add_subdirectory(pcre2 EXCLUDE_FROM_ALL)
|
||||||
|
set(PCRE2_INCLUDE_DIR ${CMAKE_BINARY_DIR}/pcre2)
|
||||||
|
set(PCRE2_LIB pcre2-${PCRE2_WIDTH})
|
||||||
endif(FISH_USE_SYSTEM_PCRE2)
|
endif(FISH_USE_SYSTEM_PCRE2)
|
||||||
|
include_directories(${PCRE2_INCLUDE_DIR})
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
# Trying to build using the resolved toolchain causes all kinds of weird errors
|
|
||||||
# Just let rustup do its job
|
|
||||||
set(Rust_RESOLVE_RUSTUP_TOOLCHAINS Off)
|
|
||||||
|
|
||||||
include(FindRust)
|
|
||||||
find_package(Rust REQUIRED)
|
|
||||||
|
|
||||||
set(FISH_RUST_BUILD_DIR "${CMAKE_BINARY_DIR}/cargo/build")
|
|
||||||
|
|
||||||
if(DEFINED ASAN)
|
|
||||||
list(APPEND CARGO_FLAGS "-Z" "build-std")
|
|
||||||
list(APPEND FISH_CRATE_FEATURES "asan")
|
|
||||||
endif()
|
|
||||||
if(DEFINED TSAN)
|
|
||||||
list(APPEND CARGO_FLAGS "-Z" "build-std")
|
|
||||||
list(APPEND FISH_CRATE_FEATURES "tsan")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (Rust_CARGO_TARGET)
|
|
||||||
set(rust_target_dir "${FISH_RUST_BUILD_DIR}/${Rust_CARGO_TARGET}")
|
|
||||||
else()
|
|
||||||
set(rust_target_dir "${FISH_RUST_BUILD_DIR}/${Rust_CARGO_HOST_TARGET}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(rust_profile $<IF:$<CONFIG:Debug>,debug,$<IF:$<CONFIG:RelWithDebInfo>,release-with-debug,release>>)
|
|
||||||
set(rust_debugflags "$<$<CONFIG:Debug>:-g>$<$<CONFIG:RelWithDebInfo>:-g>")
|
|
||||||
|
|
||||||
|
|
||||||
# Temporary hack to propogate CMake flags/options to build.rs. We need to get CMake to evaluate the
|
|
||||||
# truthiness of the strings if they are set.
|
|
||||||
set(CMAKE_WITH_GETTEXT "1")
|
|
||||||
if(DEFINED WITH_GETTEXT AND NOT "${WITH_GETTEXT}")
|
|
||||||
set(CMAKE_WITH_GETTEXT "0")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(FISH_CRATE_FEATURES)
|
|
||||||
set(FEATURES_ARG ${FISH_CRATE_FEATURES})
|
|
||||||
list(PREPEND FEATURES_ARG "--features")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
get_property(
|
|
||||||
RUSTC_EXECUTABLE
|
|
||||||
TARGET Rust::Rustc PROPERTY IMPORTED_LOCATION
|
|
||||||
)
|
|
||||||
|
|
||||||
# Tell Cargo where our build directory is so it can find Cargo.toml.
|
|
||||||
set(VARS_FOR_CARGO
|
|
||||||
"FISH_BUILD_DIR=${CMAKE_BINARY_DIR}"
|
|
||||||
"PREFIX=${CMAKE_INSTALL_PREFIX}"
|
|
||||||
# Temporary hack to propogate CMake flags/options to build.rs.
|
|
||||||
"CMAKE_WITH_GETTEXT=${CMAKE_WITH_GETTEXT}"
|
|
||||||
# Cheesy so we can tell cmake was used to build
|
|
||||||
"CMAKE=1"
|
|
||||||
"DOCDIR=${CMAKE_INSTALL_FULL_DOCDIR}"
|
|
||||||
"DATADIR=${CMAKE_INSTALL_FULL_DATADIR}"
|
|
||||||
"SYSCONFDIR=${CMAKE_INSTALL_FULL_SYSCONFDIR}"
|
|
||||||
"BINDIR=${CMAKE_INSTALL_FULL_BINDIR}"
|
|
||||||
"LOCALEDIR=${CMAKE_INSTALL_FULL_LOCALEDIR}"
|
|
||||||
"CARGO_TARGET_DIR=${FISH_RUST_BUILD_DIR}"
|
|
||||||
"CARGO_BUILD_RUSTC=${RUSTC_EXECUTABLE}"
|
|
||||||
"${FISH_PCRE2_BUILDFLAG}"
|
|
||||||
"RUSTFLAGS=$ENV{RUSTFLAGS} ${rust_debugflags}"
|
|
||||||
)
|
|
||||||
@@ -1,34 +1,7 @@
|
|||||||
# This adds ctest support to the project
|
# Define fish_tests.
|
||||||
enable_testing()
|
add_executable(fish_tests EXCLUDE_FROM_ALL
|
||||||
|
src/fish_tests.cpp)
|
||||||
# Put in a tests folder to reduce the top level targets in IDEs.
|
fish_link_deps_and_sign(fish_tests)
|
||||||
set(CMAKE_FOLDER tests)
|
|
||||||
|
|
||||||
# We will use 125 as a reserved exit code to indicate that a test has been skipped, i.e. it did not
|
|
||||||
# pass but it should not be considered a failed test run, either.
|
|
||||||
set(SKIP_RETURN_CODE 125)
|
|
||||||
|
|
||||||
# Even though we are using CMake's ctest for testing, we still define our own `make fish_run_tests` target
|
|
||||||
# rather than use its default for many reasons:
|
|
||||||
# * CMake doesn't run tests in-proc or even add each tests as an individual node in the ninja
|
|
||||||
# dependency tree, instead it just bundles all tests into a target called `test` that always just
|
|
||||||
# shells out to `ctest`, so there are no build-related benefits to not doing that ourselves.
|
|
||||||
# * The only way to have a test depend on a binary is to add a fake test with a name like
|
|
||||||
# "build_fish" that executes CMake recursively to build the `fish` target.
|
|
||||||
# * Circling back to the point about individual tests not being actual Makefile targets, CMake does
|
|
||||||
# not offer any way to execute a named test via the `make`/`ninja`/whatever interface; the only
|
|
||||||
# way to manually invoke test `foo` is to to manually run `ctest` and specify a regex matching
|
|
||||||
# `foo` as an argument, e.g. `ctest -R ^foo$`... which is really crazy.
|
|
||||||
|
|
||||||
# The top-level test target is "fish_run_tests".
|
|
||||||
add_custom_target(fish_run_tests
|
|
||||||
COMMAND env FISH_FORCE_COLOR=1
|
|
||||||
FISH_SOURCE_DIR=${CMAKE_SOURCE_DIR}
|
|
||||||
${CMAKE_CTEST_COMMAND} --force-new-ctest-process # --verbose
|
|
||||||
--output-on-failure --progress
|
|
||||||
DEPENDS tests_dir funcs_dir tests_buildroot_target
|
|
||||||
USES_TERMINAL
|
|
||||||
)
|
|
||||||
|
|
||||||
# The "test" directory.
|
# The "test" directory.
|
||||||
set(TEST_DIR ${CMAKE_CURRENT_BINARY_DIR}/test)
|
set(TEST_DIR ${CMAKE_CURRENT_BINARY_DIR}/test)
|
||||||
@@ -39,25 +12,18 @@ set(TEST_INSTALL_DIR ${TEST_DIR}/buildroot)
|
|||||||
# The directory where the tests expect to find the fish root (./bin, etc)
|
# The directory where the tests expect to find the fish root (./bin, etc)
|
||||||
set(TEST_ROOT_DIR ${TEST_DIR}/root)
|
set(TEST_ROOT_DIR ${TEST_DIR}/root)
|
||||||
|
|
||||||
# Copy needed directories for out-of-tree builds
|
# Copy tests files.
|
||||||
if(NOT FISH_IN_TREE_BUILD)
|
file(GLOB TESTS_FILES tests/*)
|
||||||
add_custom_target(funcs_dir)
|
add_custom_target(tests_dir DEPENDS tests)
|
||||||
add_custom_command(TARGET funcs_dir
|
|
||||||
POST_BUILD
|
|
||||||
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/share
|
|
||||||
# Don't run ln twice or it will create a new link in the link.
|
|
||||||
COMMAND test -e ${CMAKE_BINARY_DIR}/share/functions || ln -sf
|
|
||||||
${CMAKE_SOURCE_DIR}/share/functions/ ${CMAKE_BINARY_DIR}/share/functions
|
|
||||||
COMMENT "Symlinking fish functions to binary dir"
|
|
||||||
VERBATIM)
|
|
||||||
|
|
||||||
add_custom_target(tests_dir DEPENDS tests)
|
if(NOT FISH_IN_TREE_BUILD)
|
||||||
add_custom_command(TARGET tests_dir
|
add_custom_command(TARGET tests_dir
|
||||||
POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
${CMAKE_SOURCE_DIR}/tests/ ${CMAKE_BINARY_DIR}/tests/
|
${CMAKE_SOURCE_DIR}/tests/ ${CMAKE_BINARY_DIR}/tests/
|
||||||
COMMENT "Copying test files to binary dir"
|
COMMENT "Copying test files to binary dir"
|
||||||
VERBATIM)
|
VERBATIM)
|
||||||
|
|
||||||
|
add_dependencies(fish_tests tests_dir)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Copy littlecheck.py
|
# Copy littlecheck.py
|
||||||
@@ -66,86 +32,94 @@ configure_file(build_tools/littlecheck.py littlecheck.py COPYONLY)
|
|||||||
# Copy pexpect_helper.py
|
# Copy pexpect_helper.py
|
||||||
configure_file(build_tools/pexpect_helper.py pexpect_helper.py COPYONLY)
|
configure_file(build_tools/pexpect_helper.py pexpect_helper.py COPYONLY)
|
||||||
|
|
||||||
# Suppress generating Xcode schemes for all tests, there's too many.
|
# Make the directory in which to run tests.
|
||||||
set(CMAKE_XCODE_GENERATE_SCHEME 0)
|
# Also symlink fish to where the tests expect it to be.
|
||||||
|
# Lastly put fish_test_helper there too.
|
||||||
# CMake being CMake, you can't just add a DEPENDS argument to add_test to make it depend on any of
|
|
||||||
# your binaries actually being built before `make fish_run_tests` is executed (requiring `make all` first),
|
|
||||||
# and the only dependency a test can have is on another test. So we make building fish
|
|
||||||
# prerequisites to our entire top-level `test` target.
|
|
||||||
function(add_test_target NAME)
|
|
||||||
string(REPLACE "/" "-" NAME ${NAME})
|
|
||||||
add_custom_target("test_${NAME}" COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -R "^${NAME}$$"
|
|
||||||
DEPENDS tests_dir funcs_dir tests_buildroot_target USES_TERMINAL )
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
add_custom_target(tests_buildroot_target
|
add_custom_target(tests_buildroot_target
|
||||||
# Make the directory in which to run tests:
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${TEST_INSTALL_DIR}
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${TEST_INSTALL_DIR}
|
||||||
COMMAND env DESTDIR=${TEST_INSTALL_DIR} ${CMAKE_COMMAND}
|
COMMAND DESTDIR=${TEST_INSTALL_DIR} ${CMAKE_COMMAND}
|
||||||
--build ${CMAKE_CURRENT_BINARY_DIR} --target install
|
--build ${CMAKE_CURRENT_BINARY_DIR} --target install
|
||||||
# Put fish_test_helper there too:
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/fish_test_helper
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/fish_test_helper
|
||||||
${TEST_INSTALL_DIR}/${CMAKE_INSTALL_PREFIX}/bin
|
${TEST_INSTALL_DIR}/${CMAKE_INSTALL_PREFIX}/bin
|
||||||
# Also symlink fish to where the tests expect it to be:
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||||
${TEST_INSTALL_DIR}/${CMAKE_INSTALL_PREFIX}
|
${TEST_INSTALL_DIR}/${CMAKE_INSTALL_PREFIX}
|
||||||
${TEST_ROOT_DIR}
|
${TEST_ROOT_DIR}
|
||||||
DEPENDS fish fish_test_helper)
|
DEPENDS fish fish_test_helper)
|
||||||
|
|
||||||
FILE(GLOB FISH_CHECKS CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/tests/checks/*.fish)
|
if(NOT FISH_IN_TREE_BUILD)
|
||||||
foreach(CHECK ${FISH_CHECKS})
|
# We need to symlink share/functions for the tests.
|
||||||
get_filename_component(CHECK_NAME ${CHECK} NAME)
|
# This should be simplified.
|
||||||
get_filename_component(CHECK ${CHECK} NAME_WE)
|
add_custom_target(symlink_functions
|
||||||
add_test(NAME ${CHECK_NAME}
|
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||||
COMMAND sh ${CMAKE_CURRENT_BINARY_DIR}/tests/test_driver.sh
|
${CMAKE_CURRENT_SOURCE_DIR}/share/functions
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/tests/test.fish ${CHECK}
|
${CMAKE_CURRENT_BINARY_DIR}/share/functions)
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tests
|
add_dependencies(tests_buildroot_target symlink_functions)
|
||||||
)
|
else()
|
||||||
set_tests_properties(${CHECK_NAME} PROPERTIES SKIP_RETURN_CODE ${SKIP_RETURN_CODE})
|
add_custom_target(symlink_functions)
|
||||||
set_tests_properties(${CHECK_NAME} PROPERTIES ENVIRONMENT FISH_FORCE_COLOR=1)
|
|
||||||
add_test_target("${CHECK_NAME}")
|
|
||||||
endforeach(CHECK)
|
|
||||||
|
|
||||||
FILE(GLOB PEXPECTS CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/tests/pexpects/*.py)
|
|
||||||
foreach(PEXPECT ${PEXPECTS})
|
|
||||||
get_filename_component(PEXPECT ${PEXPECT} NAME)
|
|
||||||
add_test(NAME ${PEXPECT}
|
|
||||||
COMMAND sh ${CMAKE_CURRENT_BINARY_DIR}/tests/test_driver.sh
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/tests/interactive.fish ${PEXPECT}
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tests
|
|
||||||
)
|
|
||||||
set_tests_properties(${PEXPECT} PROPERTIES SKIP_RETURN_CODE ${SKIP_RETURN_CODE})
|
|
||||||
set_tests_properties(${PEXPECT} PROPERTIES ENVIRONMENT FISH_FORCE_COLOR=1)
|
|
||||||
add_test_target("${PEXPECT}")
|
|
||||||
endforeach(PEXPECT)
|
|
||||||
|
|
||||||
set(cargo_test_flags)
|
|
||||||
# Rust stuff.
|
|
||||||
if(DEFINED ASAN)
|
|
||||||
# Rust w/ -Zsanitizer=address requires explicitly specifying the --target triple or else linker
|
|
||||||
# errors pertaining to asan symbols will ensue.
|
|
||||||
if(NOT DEFINED Rust_CARGO_TARGET)
|
|
||||||
message(FATAL_ERROR "ASAN requires defining the CMake variable Rust_CARGO_TARGET to the
|
|
||||||
intended target triple")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
if(DEFINED TSAN)
|
|
||||||
if(NOT DEFINED Rust_CARGO_TARGET)
|
|
||||||
message(FATAL_ERROR "TSAN requires defining the CMake variable Rust_CARGO_TARGET to the
|
|
||||||
intended target triple")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(DEFINED Rust_CARGO_TARGET)
|
# Prep the environment for running the unit tests.
|
||||||
list(APPEND cargo_test_flags "--target" ${Rust_CARGO_TARGET})
|
add_custom_target(test_prep
|
||||||
list(APPEND cargo_test_flags "--lib")
|
COMMAND ${CMAKE_COMMAND} -E remove_directory ${TEST_DIR}/data
|
||||||
endif()
|
COMMAND ${CMAKE_COMMAND} -E remove_directory ${TEST_DIR}/home
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E remove_directory ${TEST_DIR}/temp
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||||
|
${TEST_DIR}/data ${TEST_DIR}/home ${TEST_DIR}/temp
|
||||||
|
DEPENDS tests_buildroot_target tests_dir
|
||||||
|
USES_TERMINAL)
|
||||||
|
|
||||||
add_test(
|
# Define our individual tests.
|
||||||
NAME "cargo-test"
|
# Each test is conceptually independent.
|
||||||
COMMAND env ${VARS_FOR_CARGO} cargo test --no-default-features ${CARGO_FLAGS} --workspace --target-dir ${rust_target_dir} ${cargo_test_flags}
|
# However when running all tests, we want to run them serially for sanity's sake.
|
||||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
# So define both a normal target, and a serial variant which enforces ordering.
|
||||||
)
|
foreach(TESTTYPE test serial_test)
|
||||||
set_tests_properties("cargo-test" PROPERTIES SKIP_RETURN_CODE ${SKIP_RETURN_CODE})
|
add_custom_target(${TESTTYPE}_low_level
|
||||||
add_test_target("cargo-test")
|
COMMAND env XDG_DATA_HOME=test/data XDG_CONFIG_HOME=test/home ./fish_tests
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
DEPENDS fish_tests
|
||||||
|
USES_TERMINAL)
|
||||||
|
|
||||||
|
add_custom_target(${TESTTYPE}_fishscript
|
||||||
|
COMMAND cd tests && ${TEST_ROOT_DIR}/bin/fish test.fish
|
||||||
|
DEPENDS test_prep
|
||||||
|
USES_TERMINAL)
|
||||||
|
|
||||||
|
add_custom_target(${TESTTYPE}_interactive
|
||||||
|
COMMAND cd tests && ${TEST_ROOT_DIR}/bin/fish interactive.fish
|
||||||
|
DEPENDS test_prep
|
||||||
|
USES_TERMINAL)
|
||||||
|
endforeach(TESTTYPE)
|
||||||
|
|
||||||
|
# Now add a dependency chain between the serial versions.
|
||||||
|
# This ensures they run in order.
|
||||||
|
add_dependencies(serial_test_fishscript serial_test_low_level)
|
||||||
|
add_dependencies(serial_test_interactive serial_test_fishscript)
|
||||||
|
|
||||||
|
|
||||||
|
add_custom_target(serial_test_high_level
|
||||||
|
DEPENDS serial_test_interactive serial_test_fishscript)
|
||||||
|
|
||||||
|
# Create the 'test' target.
|
||||||
|
# Set a policy so CMake stops complaining about the name 'test'.
|
||||||
|
cmake_policy(PUSH)
|
||||||
|
|
||||||
|
if(${CMAKE_VERSION} VERSION_LESS 3.11.0 AND POLICY CMP0037)
|
||||||
|
cmake_policy(SET CMP0037 OLD)
|
||||||
|
endif()
|
||||||
|
add_custom_target(test)
|
||||||
|
cmake_policy(POP)
|
||||||
|
add_dependencies(test serial_test_high_level)
|
||||||
|
|
||||||
|
# Group test targets into a TestTargets folder
|
||||||
|
set_property(TARGET test tests_dir
|
||||||
|
test_low_level
|
||||||
|
test_fishscript
|
||||||
|
test_interactive
|
||||||
|
test_fishscript test_prep
|
||||||
|
tests_buildroot_target
|
||||||
|
serial_test_high_level
|
||||||
|
serial_test_low_level
|
||||||
|
serial_test_fishscript
|
||||||
|
serial_test_interactive
|
||||||
|
symlink_functions
|
||||||
|
PROPERTY FOLDER cmake/TestTargets)
|
||||||
|
|||||||
@@ -1,22 +1,43 @@
|
|||||||
set(languages de en fr pl pt_BR sv zh_CN)
|
set(languages de en fr nb nn pl pt_BR sv zh_CN)
|
||||||
|
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
|
|
||||||
option(WITH_GETTEXT "translate messages if gettext is available" ON)
|
option(WITH_GETTEXT "translate messages if gettext is available" ON)
|
||||||
if(WITH_GETTEXT)
|
if(WITH_GETTEXT)
|
||||||
|
find_package(Intl QUIET)
|
||||||
find_package(Gettext)
|
find_package(Gettext)
|
||||||
|
if(GETTEXT_FOUND)
|
||||||
|
set(HAVE_GETTEXT 1)
|
||||||
|
include_directories(${Intl_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
add_feature_info(gettext GETTEXT_FOUND "translate messages with gettext")
|
add_feature_info(gettext GETTEXT_FOUND "translate messages with gettext")
|
||||||
|
|
||||||
# Define translations
|
# Define translations
|
||||||
if(GETTEXT_FOUND)
|
if(GETTEXT_FOUND)
|
||||||
# Group pofile targets into their own folder, as there's a lot of them.
|
|
||||||
set(CMAKE_FOLDER pofiles)
|
|
||||||
foreach(lang ${languages})
|
foreach(lang ${languages})
|
||||||
# Our translations aren't set up entirely as CMake expects, so installation is done in
|
# Our translations aren't set up entirely as CMake expects, so installation is done in
|
||||||
# cmake/Install.cmake instead of using INSTALL_DESTINATION
|
# cmake/Install.cmake instead of using INSTALL_DESTINATION
|
||||||
gettext_process_po_files(${lang} ALL
|
gettext_process_po_files(${lang} ALL
|
||||||
PO_FILES po/${lang}.po)
|
PO_FILES po/${lang}.po)
|
||||||
endforeach()
|
endforeach()
|
||||||
set(CMAKE_FOLDER)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
cmake_push_check_state()
|
||||||
|
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${Intl_INCLUDE_DIR})
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${Intl_LIBRARIES})
|
||||||
|
# libintl.h can be compiled into the stdlib on some GLibC systems
|
||||||
|
if(Intl_FOUND AND Intl_LIBRARIES)
|
||||||
|
set(LIBINTL_INCLUDE "#include <libintl.h>")
|
||||||
|
endif()
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
${LIBINTL_INCLUDE}
|
||||||
|
#include <stdlib.h>
|
||||||
|
int main () {
|
||||||
|
extern int _nl_msg_cat_cntr;
|
||||||
|
int tmp = _nl_msg_cat_cntr;
|
||||||
|
exit(tmp);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
HAVE__NL_MSG_CAT_CNTR)
|
||||||
|
cmake_pop_check_state()
|
||||||
|
|||||||
179
config_cmake.h.in
Normal file
179
config_cmake.h.in
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
/* Define to 1 if you have the `backtrace_symbols' function. */
|
||||||
|
#cmakedefine HAVE_BACKTRACE_SYMBOLS 1
|
||||||
|
|
||||||
|
/* Define to 1 if compiled on WSL */
|
||||||
|
#cmakedefine WSL 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `clock_gettime' function. */
|
||||||
|
#cmakedefine HAVE_CLOCK_GETTIME 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `ctermid_r' function. */
|
||||||
|
#cmakedefine HAVE_CTERMID_R 1
|
||||||
|
|
||||||
|
/* Define to 1 if C++11 thread_local is supported. */
|
||||||
|
#cmakedefine HAVE_CX11_THREAD_LOCAL 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `dirfd' function. */
|
||||||
|
#cmakedefine HAVE_DIRFD 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <execinfo.h> header file. */
|
||||||
|
#cmakedefine HAVE_EXECINFO_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `flock' function. */
|
||||||
|
#cmakedefine HAVE_FLOCK 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `futimens' function. */
|
||||||
|
#cmakedefine HAVE_FUTIMENS 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `futimes' function. */
|
||||||
|
#cmakedefine HAVE_FUTIMES 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getifaddrs' function. */
|
||||||
|
#cmakedefine HAVE_GETIFADDRS 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getpwent' function. */
|
||||||
|
#cmakedefine HAVE_GETPWENT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the 'getrusage' function. */
|
||||||
|
#cmakedefine HAVE_GETRUSAGE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `gettext' function. */
|
||||||
|
#cmakedefine HAVE_GETTEXT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `killpg' function. */
|
||||||
|
#cmakedefine HAVE_KILLPG 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `lrand48_r' function. */
|
||||||
|
#cmakedefine HAVE_LRAND48_R 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `mkostemp' function. */
|
||||||
|
#cmakedefine HAVE_MKOSTEMP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <curses.h> header file. */
|
||||||
|
#cmakedefine HAVE_CURSES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ncurses/curses.h> header file. */
|
||||||
|
#cmakedefine HAVE_NCURSES_CURSES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ncurses.h> header file. */
|
||||||
|
#cmakedefine HAVE_NCURSES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ncurses/term.h> header file. */
|
||||||
|
#cmakedefine HAVE_NCURSES_TERM_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <siginfo.h> header file. */
|
||||||
|
#cmakedefine HAVE_SIGINFO_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <spawn.h> header file. */
|
||||||
|
#cmakedefine HAVE_SPAWN_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `std::wcscasecmp' function. */
|
||||||
|
#cmakedefine HAVE_STD__WCSCASECMP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `std::wcsdup' function. */
|
||||||
|
#cmakedefine HAVE_STD__WCSDUP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `std::wcsncasecmp' function. */
|
||||||
|
#cmakedefine HAVE_STD__WCSNCASECMP 1
|
||||||
|
|
||||||
|
/* Define to 1 if `d_type' is a member of `struct dirent'. */
|
||||||
|
#cmakedefine HAVE_STRUCT_DIRENT_D_TYPE 1
|
||||||
|
|
||||||
|
/* Define to 1 if `st_ctime_nsec' is a member of `struct stat'. */
|
||||||
|
#cmakedefine HAVE_STRUCT_STAT_ST_CTIME_NSEC 1
|
||||||
|
|
||||||
|
/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */
|
||||||
|
#cmakedefine HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1
|
||||||
|
|
||||||
|
/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
|
||||||
|
#cmakedefine HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
|
||||||
|
|
||||||
|
/* Define to 1 if the sys_errlist array is available. */
|
||||||
|
#cmakedefine HAVE_SYS_ERRLIST 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||||
|
#cmakedefine HAVE_SYS_IOCTL_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||||
|
#cmakedefine HAVE_SYS_SELECT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/sysctl.h> header file. */
|
||||||
|
#cmakedefine HAVE_SYS_SYSCTL_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <termios.h> header file. */
|
||||||
|
#cmakedefine HAVE_TERMIOS_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <term.h> header file. */
|
||||||
|
#cmakedefine HAVE_TERM_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `wcscasecmp' function. */
|
||||||
|
#cmakedefine HAVE_WCSCASECMP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `wcsdup' function. */
|
||||||
|
#cmakedefine HAVE_WCSDUP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `wcslcpy' function. */
|
||||||
|
#cmakedefine HAVE_WCSLCPY 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `wcsncasecmp' function. */
|
||||||
|
#cmakedefine HAVE_WCSNCASECMP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `wcsndup' function. */
|
||||||
|
#cmakedefine HAVE_WCSNDUP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `wcstod_l' function. */
|
||||||
|
#cmakedefine HAVE_WCSTOD_L 1
|
||||||
|
|
||||||
|
/* Define to 1 if the winsize struct and TIOCGWINSZ macro exist */
|
||||||
|
#cmakedefine HAVE_WINSIZE 1
|
||||||
|
|
||||||
|
/* Define to 1 if the _nl_msg_cat_cntr symbol is exported. */
|
||||||
|
#cmakedefine HAVE__NL_MSG_CAT_CNTR 1
|
||||||
|
|
||||||
|
/* Define to 1 if std::make_unique is available. */
|
||||||
|
#cmakedefine HAVE_STD__MAKE_UNIQUE 1
|
||||||
|
|
||||||
|
/* Define to 1 if the _sys_errs array is available. */
|
||||||
|
#cmakedefine HAVE__SYS__ERRS 1
|
||||||
|
|
||||||
|
/* Define to 1 to disable ncurses macros that conflict with the STL */
|
||||||
|
#define NCURSES_NOMACROS 1
|
||||||
|
|
||||||
|
/* Define to 1 to disable curses macros that conflict with the STL */
|
||||||
|
#define NOMACROS 1
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#define PACKAGE_BUGREPORT "https://github.com/fish-shell/fish-shell/issues"
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#define PACKAGE_NAME "fish"
|
||||||
|
|
||||||
|
/* Use a variadic tparm on NetBSD curses. */
|
||||||
|
#cmakedefine TPARM_VARARGS 1
|
||||||
|
|
||||||
|
/* Define to 1 if tparm accepts a fixed amount of parameters. */
|
||||||
|
#cmakedefine TPARM_SOLARIS_KLUDGE 1
|
||||||
|
|
||||||
|
/* Enable GNU extensions on systems that have them. */
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
|
# define _GNU_SOURCE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The size of wchar_t in bits. */
|
||||||
|
#define WCHAR_T_BITS ${WCHAR_T_BITS}
|
||||||
|
|
||||||
|
/* Define if xlocale.h is required for locale_t or wide character support */
|
||||||
|
#cmakedefine HAVE_XLOCALE_H 1
|
||||||
|
|
||||||
|
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||||
|
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||||
|
# define _DARWIN_USE_64_BIT_INODE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __GNUC__ >= 3
|
||||||
|
#ifndef __warn_unused
|
||||||
|
#define __warn_unused __attribute__ ((warn_unused_result))
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define __warn_unused
|
||||||
|
#endif
|
||||||
2
debian/compat
vendored
2
debian/compat
vendored
@@ -1 +1 @@
|
|||||||
12
|
9
|
||||||
|
|||||||
51
debian/control
vendored
51
debian/control
vendored
@@ -3,16 +3,10 @@ Section: shells
|
|||||||
Priority: optional
|
Priority: optional
|
||||||
Maintainer: ridiculous_fish <corydoras@ridiculousfish.com>
|
Maintainer: ridiculous_fish <corydoras@ridiculousfish.com>
|
||||||
Uploaders: David Adam <zanchey@ucc.gu.uwa.edu.au>
|
Uploaders: David Adam <zanchey@ucc.gu.uwa.edu.au>
|
||||||
Build-Depends: debhelper (>= 12),
|
Build-Depends: debhelper (>= 9.20151004), libncurses5-dev, cmake (>= 3.2.0), gettext,
|
||||||
cargo (>= 0.66) | cargo-mozilla (>= 0.66),
|
|
||||||
cmake (>= 3.15.0) | cmake-mozilla (>= 3.15.0),
|
|
||||||
gettext,
|
|
||||||
libpcre2-dev,
|
|
||||||
rustc (>= 1.70),
|
|
||||||
# Test dependencies
|
# Test dependencies
|
||||||
locales-all,
|
locales-all, python3
|
||||||
ncurses-base,
|
# When libpcre2-dev is available on all supported Debian versions, add a dependency on that.
|
||||||
python3
|
|
||||||
Standards-Version: 4.1.5
|
Standards-Version: 4.1.5
|
||||||
Homepage: https://fishshell.com/
|
Homepage: https://fishshell.com/
|
||||||
Vcs-Git: https://github.com/fish-shell/fish-shell.git
|
Vcs-Git: https://github.com/fish-shell/fish-shell.git
|
||||||
@@ -20,21 +14,34 @@ Vcs-Browser: https://github.com/fish-shell/fish-shell
|
|||||||
|
|
||||||
Package: fish
|
Package: fish
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: bsdextrautils,
|
Depends: ${shlibs:Depends}, ${misc:Depends}, fish-common (= ${source:Version}), passwd (>= 4.0.3-10), gettext-base, man-db
|
||||||
Depends: bsdextrautils | bsdmainutils,
|
|
||||||
file,
|
|
||||||
gettext-base,
|
|
||||||
groff-base,
|
|
||||||
man-db,
|
|
||||||
ncurses-base,
|
|
||||||
procps,
|
|
||||||
python3 (>=3.5),
|
|
||||||
${misc:Depends},
|
|
||||||
${shlibs:Depends}
|
|
||||||
Conflicts: fish-common
|
|
||||||
Recommends: xsel (>=1.2.0)
|
Recommends: xsel (>=1.2.0)
|
||||||
Suggests: xdg-utils
|
|
||||||
Description: friendly interactive shell
|
Description: friendly interactive shell
|
||||||
Fish is a command-line shell for modern systems, focusing on user-friendliness,
|
Fish is a command-line shell for modern systems, focusing on user-friendliness,
|
||||||
sensibility and discoverability in interactive use. The syntax is simple, but
|
sensibility and discoverability in interactive use. The syntax is simple, but
|
||||||
not POSIX compliant.
|
not POSIX compliant.
|
||||||
|
|
||||||
|
Package: fish-common
|
||||||
|
Architecture: all
|
||||||
|
Multi-Arch: foreign
|
||||||
|
Depends: ${misc:Depends}
|
||||||
|
Recommends: fish, python3 (>= 3.5), python3-distutils
|
||||||
|
Suggests: xdg-utils
|
||||||
|
Replaces: fish (<= 2.1.1.dfsg-2)
|
||||||
|
Description: friendly interactive shell (architecture-independent files)
|
||||||
|
Fish is a command-line shell for modern systems, focusing on user-friendliness,
|
||||||
|
sensibility and discoverability in interactive use. The syntax is simple, but
|
||||||
|
not POSIX compliant.
|
||||||
|
.
|
||||||
|
This package contains the common fish files shared by all architectures.
|
||||||
|
|
||||||
|
Package: fish-dbg
|
||||||
|
Architecture: any
|
||||||
|
Section: debug
|
||||||
|
Depends: fish (= ${binary:Version}), ${misc:Depends}
|
||||||
|
Description: debugging symbols for friendly interactive shell
|
||||||
|
Fish is a command-line shell for modern systems, focusing on user-friendliness,
|
||||||
|
sensibility and discoverability in interactive use. The syntax is simple, but
|
||||||
|
not POSIX compliant.
|
||||||
|
.
|
||||||
|
This package contains the debugging symbols for fish.
|
||||||
|
|||||||
236
debian/copyright
vendored
236
debian/copyright
vendored
@@ -1,165 +1,101 @@
|
|||||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
This work was packaged for Debian by David Adam <zanchey@ucc.gu.uwa.edu.au>
|
||||||
Upstream-Name: fish
|
on Thu, 14 Jun 2012 20:33:34 +0800, based on work by James Vega
|
||||||
Upstream-Contact: corydoras@ridiculousfish.com
|
<jamessan@jamessan.com>. Modifications from the downstream Debian maintainer,
|
||||||
Source: https://fishshell.com/
|
Tristan Seligmann <mithrandi@debian.org>, have also been included.
|
||||||
|
|
||||||
Files: *
|
It was downloaded from:
|
||||||
Copyright: 2005-2009 Axel Liljencrantz <axel@liljencrantz.se>
|
|
||||||
2009-2024 fish-shell contributors
|
|
||||||
License: GPL-2
|
|
||||||
|
|
||||||
Files: doc_src/python_docs_theme/*
|
https://github.com/fish-shell/fish-shell
|
||||||
Copyright: 2001-2017 Python Software Foundation
|
|
||||||
2020-2024 fish-shell contributors
|
|
||||||
License: Python
|
|
||||||
|
|
||||||
Files: share/tools/web_config/js/alpine.js
|
Upstream Authors:
|
||||||
Copyright: 2019-2021 Caleb Porzio and contributors
|
|
||||||
License: MIT
|
|
||||||
|
|
||||||
Files: share/tools/web_config/themes/Dracula.theme
|
Axel Liljencrantz
|
||||||
Copyright: 2018 Dracula Team
|
ridiculous_fish
|
||||||
License: MIT
|
|
||||||
|
|
||||||
Files: share/tools/web_config/themes/Nord.theme
|
Copyright:
|
||||||
Copyright: 2016-2024 Sven Greb
|
|
||||||
License: MIT
|
|
||||||
|
|
||||||
Files: cmake/FindRust.cmake
|
Copyright (C) 2005-2008 Axel Liljencrantz
|
||||||
Copyright: 2018 Andrew Gaspar
|
Copyright (C) 2011-2012 ridiculous_fish
|
||||||
License: MIT
|
|
||||||
|
|
||||||
Files: src/builtins/printf.rs
|
License:
|
||||||
Copyright: 1990-2007 Free Software Foundation, Inc.
|
|
||||||
2022 fish-shell contributors
|
|
||||||
License: GPL-2+
|
|
||||||
|
|
||||||
Files: src/wgetopt.rs
|
Copyright (C) 2005-2008 Axel Liljencrantz
|
||||||
Copyright: 1989-1994 Free Software Foundation, Inc.
|
|
||||||
License: LGPL-2+
|
|
||||||
|
|
||||||
Files: printf/*
|
This program is free software; you can redistribute it and/or modify
|
||||||
Copyright: 2024 fish-shell contributors
|
it under the terms of the GNU General Public License version 2 as
|
||||||
2005-2020 Rich Felker
|
published by the Free Software Foundation.
|
||||||
License: MIT
|
|
||||||
|
|
||||||
Files: debian/*
|
This program is distributed in the hope that it will be useful,
|
||||||
Copyright: 2005-2009 James Vega <jamessan@jamessan.com>
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
2012 David Adam <zanchey@ucc.gu.uwa.edu.au>
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
2015 Tristan Seligmann <mithrandi@debian.org>
|
GNU General Public License for more details.
|
||||||
2019-2022 Mo Zhou <lumin@debian.org>
|
|
||||||
License: GPL-2
|
|
||||||
|
|
||||||
License: GPL-2
|
You should have received a copy of the GNU General Public License
|
||||||
Most of fish is licensed under the GNU General Public License version 2, and
|
along with this program; if not, write to the Free Software
|
||||||
you can redistribute it and/or modify it under the terms of the GNU GPL as
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
||||||
published by the Free Software Foundation.
|
MA 02110-1301, USA.
|
||||||
.
|
|
||||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
more details.
|
|
||||||
.
|
|
||||||
On Debian systems, the complete text of the GNU General Public License can be
|
|
||||||
found in `/usr/share/common-licenses/GPL-2'.
|
|
||||||
|
|
||||||
License: GPL-2+
|
On Debian systems, the complete text of the GNU General
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
|
||||||
Foundation; either version 2, or (at your option) any later version.
|
|
||||||
.
|
|
||||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
details.
|
|
||||||
.
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
|
|
||||||
Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
.
|
|
||||||
On Debian systems, the complete text of the GNU General Public License can be
|
|
||||||
found in `/usr/share/common-licenses/GPL-2'.
|
|
||||||
|
|
||||||
License: LGPL-2+
|
Fish contains code from the PCRE2 library to support regular expressions. This
|
||||||
This package is free software; you can redistribute it and/or
|
code, created by Philip Hazel, is distributed under the terms of the BSD
|
||||||
modify it under the terms of the GNU Library General Public
|
license. Copyright © 1997-2015 University of Cambridge.
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2 of the License, or (at your option) any later version.
|
|
||||||
.
|
|
||||||
This package is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
.
|
|
||||||
You should have received a copy of the GNU Library General Public
|
|
||||||
License along with this package; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
.
|
|
||||||
On Debian systems, the complete text of the GNU Library General
|
|
||||||
Public License can be found in `/usr/share/common-licenses/LGPL-2'.
|
|
||||||
|
|
||||||
License: MIT
|
Redistribution and use in source and binary forms, with or without
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
modification, are permitted provided that the following conditions are met:
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
subject to the following conditions:
|
|
||||||
.
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
.
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
License: Python
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
1. This LICENSE AGREEMENT is between the Python Software Foundation
|
this list of conditions and the following disclaimer.
|
||||||
("PSF"), and the Individual or Organization ("Licensee") accessing and
|
|
||||||
otherwise using this software ("Python") in source or binary form and
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
its associated documentation.
|
this list of conditions and the following disclaimer in the documentation
|
||||||
.
|
and/or other materials provided with the distribution.
|
||||||
2. Subject to the terms and conditions of this License Agreement, PSF
|
|
||||||
hereby grants Licensee a nonexclusive, royalty-free, world-wide
|
- Neither the name of the University of Cambridge nor the names of any
|
||||||
license to reproduce, analyze, test, perform and/or display publicly,
|
contributors may be used to endorse or promote products derived from this
|
||||||
prepare derivative works, distribute, and otherwise use Python alone
|
software without specific prior written permission.
|
||||||
or in any derivative version, provided, however, that PSF's License
|
|
||||||
Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001,
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012,
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
2013, 2014 Python Software Foundation; All Rights Reserved" are
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
retained in Python alone or in any derivative version prepared by
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
Licensee.
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
.
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
3. In the event Licensee prepares a derivative work that is based on
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
or incorporates Python or any part thereof, and wants to make
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
the derivative work available to others as provided herein, then
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
Licensee hereby agrees to include in any such work a brief summary of
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
the changes made to Python.
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
.
|
|
||||||
4. PSF is making Python available to Licensee on an "AS IS"
|
Fish also contains small amounts of code under the OpenBSD license, namely a
|
||||||
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
version of the function strlcpy, modified for use with wide character strings.
|
||||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
|
This code is copyrighted by Todd C. Miller (1998). It also contains code from
|
||||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
tmux, copyrighted by Nicholas Marriott <nicm@users.sourceforge.net> (2007), and
|
||||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
|
made available under an identical license.
|
||||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
|
||||||
.
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
copyright notice and this permission notice appear in all copies.
|
||||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
|
||||||
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
.
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
6. This License Agreement will automatically terminate upon a material
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
breach of its terms and conditions.
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
.
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
7. Nothing in this License Agreement shall be deemed to create any
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
relationship of agency, partnership, or joint venture between PSF and
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
Licensee. This License Agreement does not grant permission to use PSF
|
|
||||||
trademarks or trade name in a trademark sense to endorse or promote
|
Fish contains code from the glibc library, namely the wcstok function
|
||||||
products or services of Licensee, or any third party.
|
in fallback.c. This code is licensed under the LGPL.
|
||||||
.
|
|
||||||
8. By copying, installing or otherwise using Python, Licensee
|
On Debian systems, the complete text of the GNU Lesser General
|
||||||
agrees to be bound by the terms and conditions of this License
|
Public License can be found in `/usr/share/common-licenses/LGPL'.
|
||||||
Agreement.
|
|
||||||
|
The Debian packaging is:
|
||||||
|
|
||||||
|
Copyright (C) 2005 James Vega <jamessan@jamessan.com>
|
||||||
|
Copyright (C) 2012 David Adam <zanchey@ucc.gu.uwa.edu.au>
|
||||||
|
Copyright (C) 2015 Tristan Seligmann <mithrandi@debian.org>
|
||||||
|
|
||||||
|
and is licensed under the GPL version 2, see above.
|
||||||
|
|||||||
0
debian/docs → debian/fish-common.docs
vendored
0
debian/docs → debian/fish-common.docs
vendored
2
debian/fish-common.install
vendored
Normal file
2
debian/fish-common.install
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
debian/tmp/etc
|
||||||
|
debian/tmp/usr/share
|
||||||
4
debian/fish-common.lintian-overrides
vendored
Normal file
4
debian/fish-common.lintian-overrides
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# These directories are intentionally empty.
|
||||||
|
fish-common: package-contains-empty-directory usr/share/fish/vendor_completions.d/
|
||||||
|
fish-common: package-contains-empty-directory usr/share/fish/vendor_conf.d/
|
||||||
|
fish-common: package-contains-empty-directory usr/share/fish/vendor_functions.d/
|
||||||
1
debian/fish.install
vendored
Normal file
1
debian/fish.install
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
debian/tmp/usr/bin
|
||||||
0
debian/postinst → debian/fish.postinst
vendored
0
debian/postinst → debian/fish.postinst
vendored
37
debian/fish.postrm
vendored
Normal file
37
debian/fish.postrm
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# postrm script for fish
|
||||||
|
#
|
||||||
|
# see: dh_installdeb(1)
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# summary of how this script can be called:
|
||||||
|
# * <postrm> `remove'
|
||||||
|
# * <postrm> `purge'
|
||||||
|
# * <old-postrm> `upgrade' <new-version>
|
||||||
|
# * <new-postrm> `failed-upgrade' <old-version>
|
||||||
|
# * <new-postrm> `abort-install'
|
||||||
|
# * <new-postrm> `abort-install' <old-version>
|
||||||
|
# * <new-postrm> `abort-upgrade' <old-version>
|
||||||
|
# * <disappearer's-postrm> `disappear' <overwriter>
|
||||||
|
# <overwriter-version>
|
||||||
|
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||||
|
# the debian-policy package
|
||||||
|
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "postrm called with unknown argument \`$1'" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# dh_installdeb will replace this with shell code automatically
|
||||||
|
# generated by other debhelper scripts.
|
||||||
|
|
||||||
|
#DEBHELPER#
|
||||||
|
|
||||||
|
exit 0
|
||||||
0
debian/prerm → debian/fish.prerm
vendored
0
debian/prerm → debian/fish.prerm
vendored
4
debian/lintian-overrides
vendored
4
debian/lintian-overrides
vendored
@@ -1,4 +0,0 @@
|
|||||||
# These directories are intentionally empty.
|
|
||||||
fish: package-contains-empty-directory usr/share/fish/vendor_completions.d/
|
|
||||||
fish: package-contains-empty-directory usr/share/fish/vendor_conf.d/
|
|
||||||
fish: package-contains-empty-directory usr/share/fish/vendor_functions.d/
|
|
||||||
18
debian/rules
vendored
18
debian/rules
vendored
@@ -3,20 +3,18 @@
|
|||||||
|
|
||||||
# Uncomment this to turn on verbose mode.
|
# Uncomment this to turn on verbose mode.
|
||||||
export DH_VERBOSE=1
|
export DH_VERBOSE=1
|
||||||
# The LTO profile sets CFLAGS/CXXFLAGS which confuse the compilation process; disable it
|
|
||||||
# LTO is still performed by rustc based on Cargo.toml
|
|
||||||
export DEB_BUILD_MAINT_OPTIONS=optimize=-lto
|
|
||||||
|
|
||||||
%:
|
%:
|
||||||
dh $@
|
dh $@
|
||||||
|
|
||||||
# Setting the build system is still required, because otherwise the GNUmakefile gets picked up
|
# Setting the build system is still required, because otherwise the GNUmakefile gets picked up
|
||||||
override_dh_auto_configure:
|
override_dh_auto_configure:
|
||||||
ln -s cargo-vendor/vendor vendor
|
dh_auto_configure --buildsystem=cmake --parallel
|
||||||
ln -s cargo-vendor/.cargo .cargo
|
|
||||||
dh_auto_configure --buildsystem=cmake -- -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
|
||||||
|
|
||||||
override_dh_clean:
|
override_dh_installdocs:
|
||||||
dh_clean
|
dh_installdocs --link-doc=fish
|
||||||
-unlink .cargo
|
|
||||||
-unlink vendor
|
# Still needed until all platforms have debhelper 9.20151219
|
||||||
|
# Consider transitioning https://wiki.debian.org/DebugPackage
|
||||||
|
override_dh_strip:
|
||||||
|
dh_strip --dbg-package=fish-dbg
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user