mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-10 01:21:16 -03:00
Compare commits
40 Commits
Integratio
...
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
|
||||
packages:
|
||||
- cargo
|
||||
- clang17-libclang
|
||||
- cmake
|
||||
- ninja
|
||||
- ncurses-dev
|
||||
- pcre2-dev
|
||||
- py3-pexpect
|
||||
- python3
|
||||
- rust
|
||||
- tmux
|
||||
- expect
|
||||
- python
|
||||
sources:
|
||||
- https://github.com/fish-shell/fish-shell
|
||||
- https://git.sr.ht/~faho/fish
|
||||
tasks:
|
||||
- build: |
|
||||
cd fish-shell
|
||||
mkdir build
|
||||
cd fish
|
||||
mkdir build || :
|
||||
cd build
|
||||
cmake -G Ninja .. \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCMAKE_INSTALL_DATADIR=share \
|
||||
-DCMAKE_INSTALL_DOCDIR=share/doc/fish \
|
||||
-DCMAKE_INSTALL_SYSCONFDIR=/etc
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCMAKE_INSTALL_DATADIR=share \
|
||||
-DCMAKE_INSTALL_DOCDIR=share/doc/fish \
|
||||
-DCMAKE_INSTALL_SYSCONFDIR=/etc
|
||||
ninja
|
||||
- test: |
|
||||
cd fish-shell/build
|
||||
env ninja test
|
||||
cd fish/build
|
||||
env SHOW_INTERACTIVE_LOG=1 ninja test
|
||||
|
||||
@@ -2,9 +2,8 @@ image: archlinux
|
||||
packages:
|
||||
- cmake
|
||||
- ninja
|
||||
- expect
|
||||
- python
|
||||
- python-pexpect
|
||||
- tmux
|
||||
sources:
|
||||
- https://git.sr.ht/~faho/fish
|
||||
tasks:
|
||||
@@ -20,4 +19,4 @@ tasks:
|
||||
ninja
|
||||
- test: |
|
||||
cd fish/build
|
||||
env ninja test
|
||||
env SHOW_INTERACTIVE_LOG=1 ninja test
|
||||
|
||||
@@ -1,30 +1,26 @@
|
||||
image: freebsd/latest
|
||||
packages:
|
||||
- cmake
|
||||
- ncurses
|
||||
- gcc
|
||||
- gettext
|
||||
- expect
|
||||
- cmake
|
||||
- gmake
|
||||
- llvm
|
||||
- terminfo-db
|
||||
- ninja
|
||||
- pcre2
|
||||
- py311-pexpect
|
||||
- python
|
||||
- rust
|
||||
- tmux
|
||||
sources:
|
||||
- https://github.com/fish-shell/fish-shell
|
||||
- https://git.sr.ht/~faho/fish
|
||||
tasks:
|
||||
- build: |
|
||||
cd fish-shell
|
||||
mkdir build
|
||||
cd fish
|
||||
mkdir build || :
|
||||
cd build
|
||||
cmake -GNinja .. \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCMAKE_INSTALL_DATADIR=share \
|
||||
-DCMAKE_INSTALL_DOCDIR=share/doc/fish \
|
||||
-DCMAKE_INSTALL_SYSCONFDIR=/etc
|
||||
ninja
|
||||
cmake .. \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCMAKE_INSTALL_DATADIR=share \
|
||||
-DCMAKE_INSTALL_DOCDIR=share/doc/fish \
|
||||
-DCMAKE_INSTALL_SYSCONFDIR=/etc
|
||||
gmake -j2
|
||||
- test: |
|
||||
cd fish-shell/build
|
||||
ninja test
|
||||
cd fish/build
|
||||
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
|
||||
ColumnLimit: 100
|
||||
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
|
||||
|
||||
[*.{md,rst}]
|
||||
max_line_length = unset
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.sh]
|
||||
indent_size = 4
|
||||
|
||||
[build_tools/release.sh]
|
||||
max_line_length = 72
|
||||
[*.{sh,ac}]
|
||||
indent_size = 2
|
||||
|
||||
[Dockerfile]
|
||||
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
|
||||
/.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
|
||||
pcre2/** linguist-vendored
|
||||
alpine.js linguist-vendored
|
||||
doc_src/** linguist-documentation
|
||||
/pcre2/* linguist-vendored
|
||||
angular.js linguist-vendored
|
||||
/doc_src/* linguist-documentation
|
||||
*.fish linguist-language=fish
|
||||
src/*.h linguist-language=c++
|
||||
src/builtins/*.h linguist-language=c++
|
||||
share/completions/*.fish linguist-documentation
|
||||
/tests/*.in linguist-language=fish
|
||||
|
||||
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:
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
**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. -->
|
||||
- [ ] Changes to fish usage are reflected in user documentation/manpages.
|
||||
- [ ] 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:
|
||||
schedule:
|
||||
- cron: '0 18 * * 1'
|
||||
# │ │ │ │ │
|
||||
# min 0-59 ┘ │ │ │ └ weekday 0-6
|
||||
# hour 0-23 ┘ │ └ month 1-12
|
||||
# └ day 1-31
|
||||
permissions:
|
||||
contents: read
|
||||
- cron: '0 * * * *'
|
||||
|
||||
jobs:
|
||||
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
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v4
|
||||
- uses: dessant/lock-threads@v2
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
issue-inactive-days: '365'
|
||||
pr-inactive-days: '365'
|
||||
exclude-any-issue-labels: 'question, needs more info'
|
||||
issue-lock-inactive-days: '90'
|
||||
pr-lock-inactive-days: '90'
|
||||
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]
|
||||
|
||||
env:
|
||||
CTEST_PARALLEL_LEVEL: "1"
|
||||
CMAKE_BUILD_PARALLEL_LEVEL: "4"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
ubuntu:
|
||||
@@ -15,152 +12,37 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@1.70
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo apt install gettext libpcre2-dev python3-pexpect tmux
|
||||
# Generate a locale that uses a comma as decimal separator.
|
||||
sudo locale-gen fr_FR.UTF-8
|
||||
sudo apt install expect gettext libncurses5-dev libpcre2-dev
|
||||
- name: cmake
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
cmake ..
|
||||
- name: make
|
||||
run: |
|
||||
make -C build VERBOSE=1
|
||||
- name: make fish_run_tests
|
||||
make
|
||||
- name: make test
|
||||
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:
|
||||
# - uses: actions/checkout@v4
|
||||
# - uses: dtolnay/rust-toolchain@1.70
|
||||
# - uses: actions/checkout@v2
|
||||
# - name: Install deps
|
||||
# run: |
|
||||
# sudo apt install gettext libpcre2-dev python3-pexpect tmux
|
||||
# brew install pcre2
|
||||
# - name: cmake
|
||||
# env:
|
||||
# FISH_CI_SAN: 1
|
||||
# CC: clang
|
||||
# run: |
|
||||
# mkdir build && cd build
|
||||
# cmake ..
|
||||
# cmake ..
|
||||
# - name: make
|
||||
# run: |
|
||||
# make
|
||||
# - name: make fish_run_tests
|
||||
# - name: make test
|
||||
# run: |
|
||||
# make -C build fish_run_tests
|
||||
|
||||
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
|
||||
# make test
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
.if $(GENERATOR) == "Ninja"
|
||||
BUILDFILE=build.ninja
|
||||
BUILDFILE=build/build.ninja
|
||||
.else
|
||||
BUILDFILE=Makefile
|
||||
BUILDFILE=build/Makefile
|
||||
.endif
|
||||
|
||||
PREFIX?=/usr/local
|
||||
|
||||
.PHONY: build/fish
|
||||
build/fish: build/$(BUILDFILE)
|
||||
$(CMAKE) --build build
|
||||
|
||||
# Don't split the mkdir into its own rule because that would cause CMake to regenerate the 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):
|
||||
build:
|
||||
mkdir -p build
|
||||
|
||||
build/$(BUILDFILE): build
|
||||
cd build; $(CMAKE) .. -G "$(GENERATOR)" -DCMAKE_INSTALL_PREFIX="$(PREFIX)" -DCMAKE_EXPORT_COMPILE_COMMANDS=1
|
||||
|
||||
.PHONY: install
|
||||
@@ -48,11 +46,7 @@ clean:
|
||||
|
||||
.PHONY: test
|
||||
test: build/fish
|
||||
$(CMAKE) --build build --target fish_run_tests
|
||||
|
||||
.PHONY: fish_run_tests
|
||||
fish_run_tests: build/fish
|
||||
$(CMAKE) --build build --target fish_run_tests
|
||||
$(CMAKE) --build build --target test
|
||||
|
||||
.PHONY: run
|
||||
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)
|
||||
|
||||
# We are C++11.
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(DEFAULT_BUILD_TYPE "RelWithDebInfo")
|
||||
|
||||
# Generate Xcode schemas (but not for tests).
|
||||
set(CMAKE_XCODE_GENERATE_SCHEME 1)
|
||||
# Use the default flags (#6296) but remove -DNDEBUG so that asserts remain enabled.
|
||||
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)
|
||||
message(STATUS "Setting build type to default '${DEFAULT_BUILD_TYPE}'")
|
||||
set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}")
|
||||
endif()
|
||||
|
||||
# Set up standard directories.
|
||||
include(GNUInstallDirs)
|
||||
add_definitions(-D_UNICODE=1)
|
||||
# Force colored warnings in Ninja's output, if the compiler has -fdiagnostics-color support.
|
||||
# Rationale in https://github.com/ninja-build/ninja/issues/814
|
||||
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
|
||||
# This sets an environment variable that needs to be available before the Rust stanzas
|
||||
include(cmake/PCRE2.cmake)
|
||||
# Prefer the gold linker because it doesn't emit useless warnings about sys_nerr and _sys_errlist.
|
||||
if (UNIX AND NOT APPLE)
|
||||
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.
|
||||
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)
|
||||
set(FISH_IN_TREE_BUILD TRUE)
|
||||
else()
|
||||
set(FISH_IN_TREE_BUILD FALSE)
|
||||
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
|
||||
# This defines the FBVF variable.
|
||||
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_SOURCE_DIR="${REAL_CMAKE_SOURCE_DIR}")
|
||||
|
||||
# Define a function to build and link dependencies.
|
||||
function(CREATE_TARGET target)
|
||||
add_custom_target(
|
||||
${target} ALL
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}" -E
|
||||
env ${VARS_FOR_CARGO}
|
||||
${Rust_CARGO}
|
||||
build --bin ${target}
|
||||
$<$<CONFIG:Release>:--release>
|
||||
$<$<CONFIG:RelWithDebInfo>:--profile=release-with-debug>
|
||||
--target ${Rust_CARGO_TARGET}
|
||||
--no-default-features
|
||||
${CARGO_FLAGS}
|
||||
${FEATURES_ARG}
|
||||
&&
|
||||
"${CMAKE_COMMAND}" -E
|
||||
copy "${rust_target_dir}/${rust_profile}/${target}" "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
USES_TERMINAL
|
||||
)
|
||||
endfunction(CREATE_TARGET)
|
||||
# Teach fish_version.o to rebuild when FBVF changes.
|
||||
# The standard C++ include detection machinery misses this.
|
||||
set_source_files_properties(src/fish_version.cpp
|
||||
PROPERTIES OBJECT_DEPENDS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${FBVF})
|
||||
|
||||
# Enable thread-safe errno on Solaris (#5611)
|
||||
add_definitions(-D_REENTRANT)
|
||||
|
||||
# Set up PCRE2
|
||||
include(cmake/PCRE2.cmake)
|
||||
|
||||
# Define a function to link dependencies.
|
||||
function(FISH_LINK_DEPS_AND_SIGN target)
|
||||
target_link_libraries(${target} fishlib)
|
||||
codesign_on_mac(${target})
|
||||
endfunction(FISH_LINK_DEPS_AND_SIGN)
|
||||
|
||||
# Define libfish.a.
|
||||
add_library(fishlib STATIC ${FISH_SRCS})
|
||||
target_sources(fishlib PRIVATE ${FISH_HEADERS})
|
||||
target_link_libraries(fishlib
|
||||
${CURSES_LIBRARY} ${CURSES_EXTRA_LIBRARY} Threads::Threads ${CMAKE_DL_LIBS}
|
||||
${PCRE2_LIB} ${Intl_LIBRARIES} ${ATOMIC_LIBRARY})
|
||||
|
||||
# Define fish.
|
||||
create_target(fish)
|
||||
add_executable(fish src/fish.cpp)
|
||||
fish_link_deps_and_sign(fish)
|
||||
|
||||
# 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.
|
||||
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.
|
||||
include(cmake/Docs.cmake)
|
||||
|
||||
# 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.
|
||||
include(cmake/Tests.cmake)
|
||||
|
||||
@@ -95,5 +211,20 @@ include(cmake/Install.cmake)
|
||||
# Mac app.
|
||||
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)
|
||||
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 @@
|
||||
####################
|
||||
Contributing To Fish
|
||||
####################
|
||||
Guidelines For Developers
|
||||
=========================
|
||||
|
||||
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,
|
||||
improve the documentation or translate something, this document will tell you how.
|
||||
Before introducing a new dependency, please make it optional with
|
||||
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.
|
||||
Fork it on Github and then run::
|
||||
Include What You Use
|
||||
--------------------
|
||||
|
||||
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.
|
||||
For that, you'll require:
|
||||
To install the tool on OS X you’ll need to add a
|
||||
`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,
|
||||
and if the change is very simple and obvious you can just send it in. Use your judgement!
|
||||
brew tap jasonmp85/iwyu
|
||||
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)
|
||||
- Use automated tools to help you (including ``make fish_run_tests`` and ``build_tools/style.fish``)
|
||||
Lint Free Code
|
||||
--------------
|
||||
|
||||
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.
|
||||
This means no private tools or personal scripts, and we do reserve the right to reject for other reasons.
|
||||
To make linting the code easy there are two make targets: ``lint`` and
|
||||
``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.
|
||||
Often that makes more sense, specifically because they can add new options to the script immediately once they add them,
|
||||
and don't have to maintain one completion script for multiple versions. If the authors no longer wish to maintain the script,
|
||||
they can of course always contact the fish maintainers to hand it over, preferably by opening a PR.
|
||||
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.
|
||||
Fish has custom cppcheck rules in the file ``.cppcheck.rule``. These
|
||||
help catch mistakes such as using ``wcwidth()`` rather than
|
||||
``fish_wcwidth()``. Please add a new rule if you find similar mistakes
|
||||
being made.
|
||||
|
||||
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``,
|
||||
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.
|
||||
Dealing With Lint Warnings
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
|
||||
before committing your change. That will run our autoformatters:
|
||||
|
||||
- ``rustfmt`` for Rust
|
||||
- ``fish_indent`` (shipped with fish) for fish script
|
||||
- ``black`` for python
|
||||
before committing your change. That will run ``git-clang-format`` to
|
||||
rewrite only the lines you’re modifying.
|
||||
|
||||
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
|
||||
@@ -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
|
||||
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*
|
||||
directories, should be formatted using the ``fish_indent`` command.
|
||||
ViM
|
||||
^^^
|
||||
|
||||
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.
|
||||
As of ViM 7.4 it does not recognize triple-slash comments as used by
|
||||
Doxygen and the OS X Xcode IDE to flag comments that explain the
|
||||
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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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``:
|
||||
|
||||
::
|
||||
@@ -171,46 +214,131 @@ made to run fish_indent via e.g.
|
||||
(add-hook 'fish-mode-hook (lambda ()
|
||||
(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
|
||||
=======
|
||||
-------
|
||||
|
||||
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
|
||||
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
|
||||
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).
|
||||
|
||||
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
|
||||
-------------
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The tests can be run on your local computer on all operating systems.
|
||||
|
||||
::
|
||||
|
||||
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
|
||||
---------
|
||||
~~~~~~~~~
|
||||
|
||||
Since developers sometimes forget to run the tests, it can be helpful to
|
||||
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
|
||||
if [ "x$isprotected" = x1 ]; then
|
||||
echo "Running tests before push to master"
|
||||
make fish_run_tests
|
||||
make test
|
||||
RESULT=$?
|
||||
if [ $RESULT -ne 0 ]; then
|
||||
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
|
||||
|
||||
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
|
||||
``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.
|
||||
|
||||
Coverity Scan
|
||||
-------------
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
We use Coverity’s static analysis tool which offers free access to open
|
||||
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
|
||||
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
|
||||
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
|
||||
translation. In Rust, this requires the use of the ``wgettext!`` or ``wgettext_fmt!``
|
||||
macros:
|
||||
translation. In C++, this requires the use of the ``_`` (underscore)
|
||||
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
|
||||
characters for our message extraction script to find them.
|
||||
They must also be translated via a command substitution. This means
|
||||
characters. They must also be translated via a subcommand. This means
|
||||
that the following are **not** valid:
|
||||
|
||||
::
|
||||
@@ -346,15 +466,34 @@ Above should be written like this instead:
|
||||
echo (_ "hello")
|
||||
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
|
||||
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*
|
||||
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``).
|
||||
To create a new translation, for example for German: \* 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``
|
||||
|
||||
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.
|
||||
|
||||
Copyright (C) 2005-2009 Axel Liljencrantz
|
||||
Copyright (C) 2009-2024 fish-shell contributors
|
||||
Copyright (C) 2009-2020 fish-shell contributors
|
||||
|
||||
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
|
||||
published by the Free Software Foundation.
|
||||
|
||||
fish also includes software licensed under the Python Software Foundation License version 2, the MIT
|
||||
license, and the GNU Library General Public License version 2.
|
||||
fish also includes software licensed under the GNU Lesser General Public
|
||||
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
|
||||
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
|
||||
RUN yum update -y &&\
|
||||
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
|
||||
|
||||
# Test dependency
|
||||
|
||||
15
GNUmakefile
15
GNUmakefile
@@ -31,19 +31,16 @@ else
|
||||
|
||||
all: .begin build/fish
|
||||
|
||||
.PHONY: .begin
|
||||
PHONY: .begin
|
||||
.begin:
|
||||
@which $(CMAKE) > /dev/null 2> /dev/null || \
|
||||
(echo 'Please install CMake and then re-run the `make` command!' 1>&2 && false)
|
||||
|
||||
.PHONY: build/fish
|
||||
build/fish: build/$(BUILDFILE)
|
||||
$(CMAKE) --build build
|
||||
|
||||
# Use build as an order-only dependency. This prevents the target from always being outdated
|
||||
# after a make run, and more importantly, doesn't clobber manually specified CMake options.
|
||||
build/$(BUILDFILE): | build
|
||||
cd build; $(CMAKE) .. -G "$(GENERATOR)" \
|
||||
build/$(BUILDFILE): build
|
||||
cd build; $(CMAKE) .. -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -G "$(GENERATOR)" \
|
||||
-DCMAKE_INSTALL_PREFIX="$(PREFIX)" -DCMAKE_EXPORT_COMPILE_COMMANDS=1
|
||||
|
||||
build:
|
||||
@@ -55,11 +52,7 @@ clean:
|
||||
|
||||
.PHONY: test
|
||||
test: build/fish
|
||||
$(CMAKE) --build build --target fish_run_tests
|
||||
|
||||
.PHONY: fish_run_tests
|
||||
fish_run_tests: build/fish
|
||||
$(CMAKE) --build build --target fish_run_tests
|
||||
$(CMAKE) --build build --target test
|
||||
|
||||
.PHONY: install
|
||||
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
|
||||
: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 <https://fishshell.com/>`__ - the friendly interactive shell |Build Status|
|
||||
=================================================================================
|
||||
|
||||
fish is a smart and user-friendly command line shell for macOS, Linux,
|
||||
and the rest of the family. fish includes features like syntax
|
||||
highlighting, autosuggest-as-you-type, and fancy tab completions that
|
||||
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
|
||||
-----------
|
||||
@@ -23,6 +20,11 @@ magic phrase “unlike other shells”.
|
||||
Detailed user documentation is available by running ``help`` within
|
||||
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
|
||||
------------
|
||||
|
||||
@@ -37,8 +39,6 @@ fish can be installed:
|
||||
- using the `installer 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
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -53,8 +53,8 @@ and can be installed using the following commands:
|
||||
::
|
||||
|
||||
sudo apt-add-repository ppa:fish-shell/release-3
|
||||
sudo apt update
|
||||
sudo apt install fish
|
||||
sudo apt-get update
|
||||
sudo apt-get install fish
|
||||
|
||||
Instructions for other distributions may be found at
|
||||
`fishshell.com <https://fishshell.com>`__.
|
||||
@@ -62,11 +62,12 @@ Instructions for other distributions may be found at
|
||||
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
|
||||
listed above under “Packages for Linux”, or from source with the
|
||||
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
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -75,7 +76,7 @@ If packages are not available for your platform, GPG-signed tarballs are
|
||||
available from `fishshell.com <https://fishshell.com/>`__ and
|
||||
`fish-shell on
|
||||
GitHub <https://github.com/fish-shell/fish-shell/releases>`__. See the
|
||||
`Building <#building>`__ section for instructions.
|
||||
*Building* section for instructions.
|
||||
|
||||
Running fish
|
||||
------------
|
||||
@@ -87,30 +88,56 @@ Dependencies
|
||||
|
||||
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.
|
||||
If this is unavailable, fish uses an included xterm-256color definition.
|
||||
- curses or ncurses (preinstalled on most \*nix systems)
|
||||
- some common \*nix system utilities (currently ``mktemp``), in
|
||||
addition to the basic POSIX utilities (``cat``, ``cut``, ``dirname``,
|
||||
``file``, ``ls``, ``mkdir``, ``mkfifo``, ``rm``, ``sort``, ``tee``, ``tr``,
|
||||
``uname`` and ``sed`` at least, but the full coreutils plus ``find`` and
|
||||
``awk`` is preferred)
|
||||
- The gettext library, if compiled with
|
||||
``ls``, ``mkdir``, ``mkfifo``, ``rm``, ``sort``, ``tee``, ``tr``,
|
||||
``uname`` and ``sed`` at least, but the full coreutils plus find, sed
|
||||
and awk is preferred)
|
||||
- gettext (library and ``gettext`` command), if compiled with
|
||||
translation support
|
||||
|
||||
The following optional features also have specific requirements:
|
||||
|
||||
- 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
|
||||
- automated completion generation from manual pages requires Python 3.5+
|
||||
- the ``fish_config`` web configuration tool requires Python 3.5+ and a web browser
|
||||
- automated completion generation from manual pages requires Python
|
||||
(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
|
||||
bindings) require either the ``xsel``, ``xclip``,
|
||||
``wl-copy``/``wl-paste`` or ``pbcopy``/``pbpaste`` utilities
|
||||
- full completions for ``yarn`` and ``npm`` require the
|
||||
``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
|
||||
--------
|
||||
@@ -122,25 +149,17 @@ Dependencies
|
||||
|
||||
Compiling fish requires:
|
||||
|
||||
- Rust (version 1.70 or later)
|
||||
- CMake (version 3.15 or later)
|
||||
- a C compiler (for system feature detection and the test helper binary)
|
||||
- PCRE2 (headers and libraries) - optional, this will be downloaded if missing
|
||||
- a C++11 compiler (g++ 4.8 or later, or clang 3.3 or later)
|
||||
- CMake (version 3.2 or later)
|
||||
- a curses implementation such as ncurses (headers and libraries)
|
||||
- PCRE2 (headers and libraries) - a copy is included with fish
|
||||
- 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
|
||||
cloned git repository.
|
||||
|
||||
Additionally, running the full test suite requires Python 3, tmux, and the pexpect package.
|
||||
|
||||
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>`__
|
||||
Building from source (all platforms) - Makefile generator
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To install into ``/usr/local``, run:
|
||||
|
||||
@@ -148,50 +167,49 @@ To install into ``/usr/local``, run:
|
||||
|
||||
mkdir build; cd build
|
||||
cmake ..
|
||||
cmake --build .
|
||||
sudo cmake --install .
|
||||
make
|
||||
sudo make install
|
||||
|
||||
The install directory can be changed using the
|
||||
``-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.
|
||||
- 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).
|
||||
- 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
|
||||
mkdir build; cd build
|
||||
cmake .. -G Xcode
|
||||
|
||||
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
|
||||
cargo install --git https://github.com/fish-shell/fish-shell --tag 4.0 # to build from git once 4.0 is released
|
||||
cargo install --git https://github.com/fish-shell/fish-shell # to build the current development snapshot without cloning
|
||||
If fish reports that it could not find curses, try installing a curses
|
||||
development package and build again.
|
||||
|
||||
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
|
||||
--------------------------------
|
||||
@@ -203,13 +221,18 @@ Contact Us
|
||||
|
||||
Questions, comments, rants and raves can be posted to the official fish
|
||||
mailing list at https://lists.sourceforge.net/lists/listinfo/fish-users
|
||||
or join us on our `matrix
|
||||
channel <https://matrix.to/#/#fish-shell:matrix.org>`__. Or use the `fish tag
|
||||
on Unix & Linux Stackexchange <https://unix.stackexchange.com/questions/tagged/fish>`__.
|
||||
There is also a fish tag on Stackoverflow, but it is typically a poor fit.
|
||||
or join us on our `gitter.im
|
||||
channel <https://gitter.im/fish-shell/fish-shell>`__. Or use the `fish
|
||||
tag on
|
||||
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
|
||||
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
|
||||
:target: https://github.com/fish-shell/fish-shell/actions
|
||||
.. |Build Status| image:: https://travis-ci.org/fish-shell/fish-shell.svg?branch=master
|
||||
: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 alias1022='something --arg1022'
|
||||
alias alias1023='something --arg1023'
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
for i in (seq 1000)
|
||||
for i in (seq 2000)
|
||||
command true
|
||||
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
|
||||
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
|
||||
|
||||
if [ "$#" -gt 2 -o "$#" -eq 0 ]; then
|
||||
echo "Usage: driver.sh /path/to/fish [/path/to/other/fish]"
|
||||
exit 1
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Usage: driver.sh /path/to/fish"
|
||||
fi
|
||||
|
||||
FISH_PATH=$1
|
||||
FISH2_PATH=$2
|
||||
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
|
||||
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
|
||||
cmd1="$(quote "${FISH_PATH}") --no-config $(quote "$benchmark")"
|
||||
if [ -n "$FISH2_PATH" ]; then
|
||||
cmd2="$(quote "${FISH2_PATH}") --no-config $(quote "$benchmark")"
|
||||
hyperfine --warmup 3 "$cmd1" "$cmd2"
|
||||
else
|
||||
hyperfine --warmup 3 "$cmd1"
|
||||
fi
|
||||
hyperfine "${FISH_PATH} $benchmark > /dev/null"
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
#
|
||||
# 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
|
||||
# works around that - based on share/functions/funced.fish.
|
||||
set -q TMPDIR
|
||||
or set -l TMPDIR /tmp
|
||||
set -l tmpdir (mktemp -d $TMPDIR/fish.XXXXXX)
|
||||
or exit 1
|
||||
# This script was originally motivated to work around a quirk (or bug depending on your viewpoint)
|
||||
# of the xgettext command. See https://lists.gnu.org/archive/html/bug-gettext/2014-11/msg00006.html.
|
||||
# However, it turns out that even if that quirk did not exist we would still need something like
|
||||
# this script to properly extract descriptions. That's because we need to normalize the strings to
|
||||
# a format that xgettext will handle correctly. Also, `xgettext -LShell` doesn't correctly extract
|
||||
# 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.
|
||||
# xgettext still does not support rust *at all*, so we use cargo-expand to get all our wgettext invocations.
|
||||
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
|
||||
# Start with the C++ source
|
||||
xgettext -k -k_ -kN_ -LC++ --no-wrap -o messages.pot src/*.cpp src/*.h
|
||||
|
||||
# This regex handles descriptions for `complete` and `function` statements. These messages are not
|
||||
# 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.
|
||||
set -l explicit_regex '.*\( *_ (([\'"]).+?(?<!\\\\)\\2) *\).*'
|
||||
|
||||
mkdir -p $tmpdir/implicit/share/completions $tmpdir/implicit/share/functions
|
||||
mkdir -p $tmpdir/explicit/share/completions $tmpdir/explicit/share/functions
|
||||
rm -r /tmp/fish
|
||||
|
||||
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
|
||||
# Extract explicit attempts to translate a message. That is, those that are of the form
|
||||
# `(_ "message")`.
|
||||
string replace --filter --regex $explicit_regex '$1' <$f | string unescape \
|
||||
| string replace --all '"' '\\"' | string replace -r '(.*)' 'N_ "$1"' >$tmpdir/explicit/$f
|
||||
string replace --filter --regex $explicit_regex 'echo $1' <$f | fish >/tmp/fish/explicit/$f.tmp ^/dev/null
|
||||
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
|
||||
# avoids the need to use `source` with a command substitution that could affect the current
|
||||
# shell.
|
||||
string replace --filter --regex $implicit_regex '$1' <$f | string unescape \
|
||||
| string replace --all '"' '\\"' | string replace -r '(.*)' 'N_ "$1"' >$tmpdir/implicit/$f
|
||||
string replace --filter --regex $implicit_regex 'echo $1' <$f | fish >/tmp/fish/implicit/$f.tmp ^/dev/null
|
||||
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
|
||||
|
||||
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
|
||||
sed -i 's_^#: /.*/share/_#: share/_' messages.pot
|
||||
|
||||
rm -r $tmpdir
|
||||
rm -r /tmp/fish
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/usr/bin/env sh
|
||||
# Originally from the git sources (GIT-VERSION-GEN)
|
||||
# Presumably (C) Junio C Hamano <junkio@cox.net>
|
||||
# Reused under GPL v2.0
|
||||
@@ -9,26 +9,14 @@ set -e
|
||||
# Find the fish directory as two levels up from script directory.
|
||||
FISH_BASE_DIR="$( cd "$( dirname "$( dirname "$0" )" )" && pwd )"
|
||||
DEF_VER=unknown
|
||||
git_permission_failed=0
|
||||
|
||||
# First see if there is a version file (included in release tarballs),
|
||||
# then try git-describe, then default.
|
||||
if test -f version
|
||||
then
|
||||
VN=$(cat version) || VN="$DEF_VER"
|
||||
else
|
||||
if VN=$(git -C "$FISH_BASE_DIR" describe --always --dirty 2>/dev/null); then
|
||||
:
|
||||
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
|
||||
elif ! VN=$(git -C "$FISH_BASE_DIR" describe --always --dirty 2>/dev/null); then
|
||||
VN="$DEF_VER"
|
||||
fi
|
||||
|
||||
# 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.
|
||||
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
|
||||
# HACK: Git failed, so we keep the current version file.
|
||||
# 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")
|
||||
VC=$(grep -v '^#' $FBVF | tr -d '"' | sed -e 's/^FISH_BUILD_VERSION=//')
|
||||
else
|
||||
VC="unset"
|
||||
fi
|
||||
|
||||
# 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" || {
|
||||
echo >&2 "$VN"
|
||||
echo "$VN" >"$FBVF"
|
||||
echo >&2 "FISH_BUILD_VERSION=$VN"
|
||||
echo "FISH_BUILD_VERSION=\"$VN\"" >${FBVF}
|
||||
}
|
||||
|
||||
# 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
|
||||
|
||||
set -l committers_to_tag (mktemp)
|
||||
or exit 1
|
||||
set -l committers_from_tag (mktemp)
|
||||
or exit 1
|
||||
|
||||
# You might think it would be better to case-insensitively sort/compare the names
|
||||
# to produce a more natural-looking list.
|
||||
|
||||
@@ -6,6 +6,7 @@ from __future__ import unicode_literals
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
from collections import deque
|
||||
import datetime
|
||||
import io
|
||||
import re
|
||||
@@ -13,39 +14,15 @@ import shlex
|
||||
import subprocess
|
||||
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.
|
||||
RUN_RE = re.compile(COMMENT_RE + r"RUN:\s+(.*)\n")
|
||||
REQUIRES_RE = re.compile(COMMENT_RE + r"REQUIRES:\s+(.*)\n")
|
||||
RUN_RE = re.compile(r"\s*#\s*RUN:\s+(.*)\n")
|
||||
|
||||
# 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.
|
||||
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):
|
||||
def __init__(self):
|
||||
@@ -55,6 +32,10 @@ class Config(object):
|
||||
self.colorize = False
|
||||
# Whether to show which file was tested.
|
||||
self.progress = False
|
||||
# How many after lines to print
|
||||
self.after = 5
|
||||
# How many before lines to print
|
||||
self.before = 5
|
||||
|
||||
def colors(self):
|
||||
""" Return a dictionary mapping color names to ANSI escapes """
|
||||
@@ -96,6 +77,8 @@ def esc(m):
|
||||
map = {
|
||||
"\n": "\\n",
|
||||
"\\": "\\\\",
|
||||
"'": "\\'",
|
||||
'"': '\\"',
|
||||
"\a": "\\a",
|
||||
"\b": "\\b",
|
||||
"\f": "\\f",
|
||||
@@ -135,26 +118,6 @@ class Line(object):
|
||||
self.number = number
|
||||
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):
|
||||
""" Return a substring of our line with the given text, preserving number and file. """
|
||||
return Line(text, self.number, self.file)
|
||||
@@ -166,16 +129,10 @@ class Line(object):
|
||||
def is_empty_space(self):
|
||||
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):
|
||||
"""A command to run on a given Checker.
|
||||
|
||||
""" A command to run on a given Checker.
|
||||
|
||||
Attributes:
|
||||
args: Unexpanded shell command as a string.
|
||||
"""
|
||||
@@ -192,17 +149,17 @@ class RunCmd(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.check = check
|
||||
self.testrun = testrun
|
||||
self.error_annotation_lines = None
|
||||
self.diff = diff
|
||||
self.lines = lines
|
||||
self.checks = checks
|
||||
self.signal = None
|
||||
self.error_annotation_line = None
|
||||
# The output that comes *after* the failure.
|
||||
self.after = after
|
||||
self.before = before
|
||||
|
||||
def message(self):
|
||||
afterlines = self.testrun.config.after
|
||||
fields = self.testrun.config.colors()
|
||||
fields["name"] = self.testrun.name
|
||||
fields["subbed_command"] = self.testrun.subbed_command
|
||||
@@ -211,7 +168,7 @@ class TestFailure(object):
|
||||
{
|
||||
"output_file": self.line.file,
|
||||
"output_lineno": self.line.number,
|
||||
"output_line": self.line.escaped_text(),
|
||||
"output_line": self.line.text.rstrip("\n"),
|
||||
}
|
||||
)
|
||||
if self.check:
|
||||
@@ -219,17 +176,12 @@ class TestFailure(object):
|
||||
{
|
||||
"input_file": self.check.line.file,
|
||||
"input_lineno": self.check.line.number,
|
||||
"input_line": self.check.line.escaped_text(),
|
||||
"input_line": self.check.line.text,
|
||||
"check_type": self.check.type,
|
||||
}
|
||||
)
|
||||
filemsg = "" if self.testrun.config.progress else " in {name}"
|
||||
fmtstrs = ["{RED}Failure{RESET}" + filemsg + ":", ""]
|
||||
if self.signal:
|
||||
fmtstrs += [
|
||||
" Process was killed by signal {BOLD}" + self.signal + "{RESET}",
|
||||
""
|
||||
]
|
||||
if self.line and self.check:
|
||||
fmtstrs += [
|
||||
" The {check_type} on line {input_lineno} wants:",
|
||||
@@ -254,97 +206,24 @@ class TestFailure(object):
|
||||
" {BOLD}{output_line}{RESET}",
|
||||
"",
|
||||
]
|
||||
if self.error_annotation_lines:
|
||||
fields["error_annotation"] = " ".join(
|
||||
[x.text for x in self.error_annotation_lines]
|
||||
)
|
||||
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
|
||||
)
|
||||
if self.error_annotation_line:
|
||||
fields["error_annotation"] = self.error_annotation_line.text
|
||||
fields["error_annotation_lineno"] = self.error_annotation_line.number
|
||||
fmtstrs += [
|
||||
" additional output on stderr:{error_annotation_lineno}:",
|
||||
" {BOLD}{error_annotation}{RESET}",
|
||||
]
|
||||
if self.diff:
|
||||
fmtstrs += [" Context:"]
|
||||
lasthi = 0
|
||||
lastcheckline = None
|
||||
for d in self.diff.get_grouped_opcodes():
|
||||
for op, alo, ahi, blo, bhi in d:
|
||||
color = "{BOLD}"
|
||||
if op == "replace" or op == "delete":
|
||||
color = "{RED}"
|
||||
# We got a new chunk, so we print a marker.
|
||||
if alo > lasthi:
|
||||
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("")
|
||||
if self.before:
|
||||
fields["before_output"] = " ".join(self.before)
|
||||
fields["additional_output"] = " ".join(self.after[:afterlines])
|
||||
fmtstrs += [
|
||||
" Context:",
|
||||
" {BOLD}{before_output} {RED}{output_line}{RESET} <= does not match '{LIGHTBLUE}{input_line}{RESET}'",
|
||||
" {BOLD}{additional_output}{RESET}",
|
||||
]
|
||||
elif self.after:
|
||||
fields["additional_output"] = " ".join(self.after[:afterlines])
|
||||
fmtstrs += [" additional output:", " {BOLD}{additional_output}{RESET}"]
|
||||
fmtstrs += [" when running command:", " {subbed_command}"]
|
||||
return "\n".join(fmtstrs).format(**fields)
|
||||
|
||||
@@ -354,8 +233,8 @@ class TestFailure(object):
|
||||
|
||||
|
||||
def perform_substitution(input_str, subs):
|
||||
"""Perform the substitutions described by subs to str
|
||||
Return the substituted string.
|
||||
""" Perform the substitutions described by subs to str
|
||||
Return the substituted string.
|
||||
"""
|
||||
# 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.
|
||||
@@ -375,20 +254,6 @@ def perform_substitution(input_str, subs):
|
||||
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):
|
||||
def __init__(self, name, runcmd, checker, subs, config):
|
||||
self.name = name
|
||||
@@ -402,95 +267,74 @@ class TestRun(object):
|
||||
# Reverse our lines and checks so we can pop off the end.
|
||||
lineq = lines[::-1]
|
||||
checkq = checks[::-1]
|
||||
usedlines = []
|
||||
usedchecks = []
|
||||
mismatches = []
|
||||
# We keep the last couple of lines in a deque so we can show context.
|
||||
before = deque(maxlen=self.config.before)
|
||||
while lineq and checkq:
|
||||
line = lineq[-1]
|
||||
check = checkq[-1]
|
||||
if check == line:
|
||||
if check.regex.match(line.text):
|
||||
# This line matched this checker, continue on.
|
||||
usedlines.append(line)
|
||||
usedchecks.append(check)
|
||||
lineq.pop()
|
||||
checkq.pop()
|
||||
before.append(line)
|
||||
elif line.is_empty_space():
|
||||
# Skip all whitespace input lines.
|
||||
lineq.pop()
|
||||
else:
|
||||
usedlines.append(line)
|
||||
usedchecks.append(check)
|
||||
mismatches.append((line, check))
|
||||
# Failed to match.
|
||||
lineq.pop()
|
||||
checkq.pop()
|
||||
|
||||
# Drain empties
|
||||
line.text = escape_string(line.text.strip()) + "\n"
|
||||
# Add context, ignoring empty lines.
|
||||
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():
|
||||
lineq.pop()
|
||||
|
||||
# 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.
|
||||
# If there's still lines or checkers, we have a failure.
|
||||
# Otherwise it's success.
|
||||
if mismatches:
|
||||
return TestFailure(
|
||||
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
|
||||
)
|
||||
if lineq:
|
||||
return TestFailure(lineq[-1], None, self)
|
||||
elif checkq:
|
||||
return TestFailure(
|
||||
None, checkq[-1], self, diff=diff, lines=usedlines, checks=usedchecks
|
||||
)
|
||||
return TestFailure(None, checkq[-1], self)
|
||||
else:
|
||||
# Success!
|
||||
return None
|
||||
|
||||
def run(self):
|
||||
""" Run the command. Return a TestFailure, or None. """
|
||||
|
||||
def split_by_newlines(s):
|
||||
"""Decode a string and split it by newlines only,
|
||||
retaining the newlines.
|
||||
""" Decode a string and split it by newlines only,
|
||||
retaining the newlines.
|
||||
"""
|
||||
return [s + "\n" for s in s.decode("utf-8").split("\n")]
|
||||
|
||||
PIPE = subprocess.PIPE
|
||||
if self.config.verbose:
|
||||
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()
|
||||
# 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,
|
||||
# most likely when the last command in a shell script doesn't exist.
|
||||
# So we check if the command *we execute* exists, and complain then.
|
||||
# Technically it's also possible to return it in other conditions.
|
||||
# Practically, that's *probably* not going to happen.
|
||||
status = proc.returncode
|
||||
cmd = shlex.split(self.subbed_command)[0]
|
||||
if status == 127 and not find_command(cmd):
|
||||
raise CheckerError("Command could not be found: " + cmd)
|
||||
if status == 126 and not find_command(cmd):
|
||||
raise CheckerError("Command is not executable: " + cmd)
|
||||
if status == 127:
|
||||
raise CheckerError("Command could not be found: " + self.subbed_command)
|
||||
|
||||
outlines = [
|
||||
Line(text, idx + 1, "stdout")
|
||||
@@ -507,38 +351,8 @@ class TestRun(object):
|
||||
# non-matching or unmatched stderr text, then annotate the outfail
|
||||
# with it.
|
||||
if outfail and errfail and errfail.line:
|
||||
outfail.error_annotation_lines = errlines[errfail.line.number - 1 :]
|
||||
# Trim a trailing newline
|
||||
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
|
||||
outfail.error_annotation_line = errfail.line
|
||||
return outfail if outfail else errfail
|
||||
|
||||
|
||||
class CheckCmd(object):
|
||||
@@ -547,28 +361,6 @@ class CheckCmd(object):
|
||||
self.type = checktype
|
||||
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
|
||||
def parse(line, checktype):
|
||||
# type: (Line) -> CheckCmd
|
||||
@@ -628,19 +420,14 @@ class Checker(object):
|
||||
|
||||
# Find run commands.
|
||||
self.runcmds = [RunCmd.parse(sl) for sl in group1s(RUN_RE)]
|
||||
self.shebang_cmd = None
|
||||
if not self.runcmds:
|
||||
# If no RUN command has been given, fall back to the shebang.
|
||||
if lines[0].text.startswith("#!"):
|
||||
# Remove the "#!" at the beginning, and the newline at the end.
|
||||
cmd = lines[0].text[2:-1]
|
||||
self.shebang_cmd = cmd
|
||||
self.runcmds = [RunCmd(cmd + " %s", lines[0])]
|
||||
self.runcmds = [RunCmd(lines[0].text[2:-1] + " %s", lines[0])]
|
||||
else:
|
||||
raise CheckerError("No runlines ('# RUN') found")
|
||||
|
||||
self.requirecmds = [RunCmd.parse(sl) for sl in group1s(REQUIRES_RE)]
|
||||
|
||||
# Find check cmds.
|
||||
self.outchecks = [
|
||||
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
|
||||
lines = Line.readfile(input_file, name)
|
||||
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:
|
||||
failure = TestRun(name, runcmd, checker, subs, config).run()
|
||||
if failure:
|
||||
@@ -684,8 +456,8 @@ def check_path(path, subs, config, failure_handler):
|
||||
|
||||
|
||||
def parse_subs(subs):
|
||||
"""Given a list of input substitutions like 'foo=bar',
|
||||
return a dictionary like {foo:bar}, or exit if invalid.
|
||||
""" Given a list of input substitutions like 'foo=bar',
|
||||
return a dictionary like {foo:bar}, or exit if invalid.
|
||||
"""
|
||||
result = {}
|
||||
for sub in subs:
|
||||
@@ -725,14 +497,23 @@ def get_argparse():
|
||||
help="Show the files to be checked",
|
||||
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(
|
||||
"-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
|
||||
|
||||
|
||||
@@ -742,16 +523,19 @@ def main():
|
||||
def_subs = {"%": "%"}
|
||||
def_subs.update(parse_subs(args.substitute))
|
||||
|
||||
tests_count = 0
|
||||
failed = False
|
||||
skip_count = 0
|
||||
failure_count = 0
|
||||
config = Config()
|
||||
config.colorize = args.force_color or sys.stdout.isatty()
|
||||
config.colorize = sys.stdout.isatty()
|
||||
config.progress = args.progress
|
||||
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:
|
||||
tests_count += 1
|
||||
fields["path"] = path
|
||||
if config.progress:
|
||||
print("Testing file {path} ... ".format(**fields), end="")
|
||||
@@ -759,33 +543,17 @@ def main():
|
||||
subs = def_subs.copy()
|
||||
subs["s"] = path
|
||||
starttime = datetime.datetime.now()
|
||||
ret = check_path(path, subs, config, TestFailure.print_message)
|
||||
if ret is SKIP:
|
||||
skip_count += 1
|
||||
if not ret:
|
||||
failed = True
|
||||
if not check_path(path, subs, config, TestFailure.print_message):
|
||||
failure_count += 1
|
||||
elif config.progress:
|
||||
endtime = datetime.datetime.now()
|
||||
duration_ms = round((endtime - starttime).total_seconds() * 1000)
|
||||
reason = "ok"
|
||||
color = "{GREEN}"
|
||||
if ret is SKIP:
|
||||
reason = "SKIPPED"
|
||||
color = "{BLUE}"
|
||||
print(
|
||||
(color + "{reason}{RESET} ({duration} ms)").format(
|
||||
duration=duration_ms, reason=reason, **fields
|
||||
"{GREEN}ok{RESET} ({duration} ms)".format(
|
||||
duration=duration_ms, **fields
|
||||
)
|
||||
)
|
||||
|
||||
# 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)
|
||||
sys.exit(failure_count)
|
||||
|
||||
|
||||
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
|
||||
|
||||
# Helper to notarize an .app.zip or .pkg file.
|
||||
# Based on https://www.logcg.com/en/archives/3222.html
|
||||
|
||||
set -e
|
||||
|
||||
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
|
||||
echo "Processing $INPUT"
|
||||
test -f "$INPUT" || die "Not a file: $INPUT"
|
||||
ext="${INPUT##*.}"
|
||||
(test "$ext" = "zip" || test "$ext" = "pkg") || die "Unrecognized extension: $ext"
|
||||
INPUT=$1
|
||||
AC_USER=$2
|
||||
|
||||
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
|
||||
TMPDIR=$(mktemp -d)
|
||||
echo "Extracting to $TMPDIR"
|
||||
@@ -37,9 +91,9 @@ for INPUT in "$@"; do
|
||||
cd "$(dirname "$STAPLE_TARGET")"
|
||||
zip -r -q "$INPUT_FULL" $(basename "$STAPLE_TARGET")
|
||||
fi
|
||||
echo "Processed $INPUT"
|
||||
fi
|
||||
echo "Processed $INPUT"
|
||||
|
||||
if test "$ext" = "zip"; then
|
||||
spctl -a -v "$STAPLE_TARGET"
|
||||
fi
|
||||
done
|
||||
if test "$ext" = "zip"; then
|
||||
spctl -a -v "$STAPLE_TARGET"
|
||||
fi
|
||||
|
||||
@@ -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)
|
||||
|
||||
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
|
||||
echo "Could not get version from git"
|
||||
if test -f version; then
|
||||
VERSION=$(cat version)
|
||||
fi
|
||||
fi
|
||||
|
||||
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)
|
||||
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
|
||||
|
||||
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; }
|
||||
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
|
||||
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"
|
||||
|
||||
# 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)
|
||||
{ cd "$PKGDIR/build" && make signed_fish_macapp && zip -r "$OUTPUT_PATH/fish-$VERSION.app.zip" fish.app; }
|
||||
|
||||
# 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"
|
||||
rm -r "$PKGDIR"
|
||||
|
||||
@@ -14,14 +14,6 @@ set -e
|
||||
# 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
|
||||
|
||||
# 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
|
||||
TAR=notfound
|
||||
for try in tar gtar gnutar; do
|
||||
@@ -59,8 +51,8 @@ git archive --format=tar --prefix="$prefix"/ HEAD > "$path"
|
||||
PREFIX_TMPDIR=$(mktemp -d)
|
||||
cd "$PREFIX_TMPDIR"
|
||||
echo "$VERSION" > version
|
||||
cmake -G "$BUILD_GENERATOR" "$wd"
|
||||
$BUILD_TOOL doc
|
||||
cmake "$wd"
|
||||
make doc
|
||||
|
||||
TAR_APPEND="$TAR --append --file=$path --mtime=now --owner=0 --group=0 \
|
||||
--mode=g+w,a+rX --transform s/^/$prefix\//"
|
||||
@@ -74,6 +66,6 @@ rm -r "$PREFIX_TMPDIR"
|
||||
# xz it
|
||||
xz "$path"
|
||||
|
||||
# Output what we did, and the sha256 hash
|
||||
# Output what we did, and the sha1 hash
|
||||
echo "Tarball written to $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"?>
|
||||
<installer-gui-script minSpecVersion="1">
|
||||
<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"/>
|
||||
<pkg-ref id="com.ridiculousfish.fish-shell-pkg"/>
|
||||
<options hostArchitectures="arm64,x86_64" rootVolumeOnly="true"/>
|
||||
<options customize="never" require-scripts="true"/>
|
||||
<options customize="never" require-scripts="false"/>
|
||||
<choices-outline>
|
||||
<line choice="default">
|
||||
<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
|
||||
|
||||
./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 time
|
||||
import pexpect
|
||||
from signal import Signals
|
||||
|
||||
# Default timeout for failing to match.
|
||||
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):
|
||||
"""Return a regular expression for matching a with a given prompt counter."""
|
||||
return re.compile("prompt %d>" % counter)
|
||||
""" Return a regular expression for matching a with a given prompt 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():
|
||||
"""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())
|
||||
for f in callstack:
|
||||
# Skip call sites from this file.
|
||||
if inspect.getmodule(f.frame) is Message.MODULE:
|
||||
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)
|
||||
if inspect.getmodule(f.frame) is not Message.MODULE:
|
||||
return (os.path.basename(f.filename), f.lineno, f.code_context)
|
||||
return ("Unknown", -1, "")
|
||||
|
||||
|
||||
def escape(s):
|
||||
"""Escape the string 's' to make it human-understandable."""
|
||||
""" Escape the string 's' to make it human-understandable. """
|
||||
res = []
|
||||
for c in s:
|
||||
if c == "\n":
|
||||
@@ -83,19 +65,17 @@ def escape(s):
|
||||
|
||||
|
||||
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):
|
||||
return "EOF"
|
||||
elif isinstance(err, pexpect.TIMEOUT):
|
||||
return "timeout"
|
||||
elif err is UNEXPECTED_SUCCESS:
|
||||
return "unexpected success"
|
||||
else:
|
||||
return "unknown error"
|
||||
|
||||
|
||||
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:
|
||||
dir: the message direction, either DIR_INPUT or DIR_OUTPUT
|
||||
@@ -113,7 +93,7 @@ class Message(object):
|
||||
MODULE = sys.modules[__name__]
|
||||
|
||||
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.filename, self.lineno, _ = get_callsite()
|
||||
self.text = text
|
||||
@@ -121,17 +101,17 @@ class Message(object):
|
||||
|
||||
@staticmethod
|
||||
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)
|
||||
|
||||
@staticmethod
|
||||
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)
|
||||
|
||||
|
||||
class SpawnedProc(object):
|
||||
"""A process, talking to our ptty. This wraps pexpect.spawn.
|
||||
""" A process, talking to our ptty. This wraps pexpect.spawn.
|
||||
|
||||
Attributes:
|
||||
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.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, name="fish", timeout=TIMEOUT_SECS, env=os.environ.copy(), **kwargs
|
||||
):
|
||||
"""Construct from a name, timeout, and environment.
|
||||
def __init__(self, name="fish", timeout=TIMEOUT_SECS, env=os.environ.copy()):
|
||||
""" Construct from a name, timeout, and environment.
|
||||
|
||||
Args:
|
||||
name: the name of the executable to launch, as a key into the
|
||||
environment dictionary. By default this is 'fish' but may be
|
||||
other executables.
|
||||
timeout: A timeout to pass to pexpect. This indicates how long to wait
|
||||
before giving up on some expected output.
|
||||
env: a string->string dictionary, describing the environment variables.
|
||||
Args:
|
||||
name: the name of the executable to launch, as a key into the
|
||||
environment dictionary. By default this is 'fish' but may be
|
||||
other executables.
|
||||
timeout: A timeout to pass to pexpect. This indicates how long to wait
|
||||
before giving up on some expected output.
|
||||
env: a string->string dictionary, describing the environment variables.
|
||||
"""
|
||||
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)
|
||||
self.colorize = sys.stdout.isatty() or env.get("FISH_FORCE_COLOR", "0") == "1"
|
||||
self.colorize = sys.stdout.isatty()
|
||||
self.messages = []
|
||||
self.start_time = None
|
||||
self.spawn = pexpect.spawn(
|
||||
exe_path, env=env, encoding="utf-8", timeout=timeout, **kwargs
|
||||
)
|
||||
self.spawn = pexpect.spawn(exe_path, env=env, encoding="utf-8", timeout=timeout)
|
||||
self.spawn.delaybeforesend = None
|
||||
self.prompt_counter = 0
|
||||
self.prompt_counter = 1
|
||||
|
||||
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()
|
||||
if not self.start_time:
|
||||
self.start_time = now
|
||||
return now - self.start_time
|
||||
|
||||
def send(self, s):
|
||||
"""Cover over pexpect.spawn.send().
|
||||
Send the given string to the tty, returning the number of bytes written.
|
||||
""" Cover over pexpect.spawn.send().
|
||||
Send the given string to the tty, returning the number of bytes written.
|
||||
"""
|
||||
res = self.spawn.send(s)
|
||||
when = self.time_since_first_message()
|
||||
@@ -184,91 +160,71 @@ class SpawnedProc(object):
|
||||
return res
|
||||
|
||||
def sendline(self, s):
|
||||
"""Cover over pexpect.spawn.sendline().
|
||||
Send the given string + linesep to the tty, returning the number of bytes written.
|
||||
""" Cover over pexpect.spawn.sendline().
|
||||
Send the given string + linesep to the tty, returning the number of bytes written.
|
||||
"""
|
||||
return self.send(s + os.linesep)
|
||||
|
||||
def expect_re(self, pat, pat_desc=None, unmatched=None, shouldfail=False, **kwargs):
|
||||
"""Cover over pexpect.spawn.expect().
|
||||
Consume all "new" output of self.spawn until the given pattern is matched, or
|
||||
the timeout is reached.
|
||||
Note that output between the current position and the location of the match is
|
||||
consumed as well.
|
||||
The pattern is typically a regular expression in string form, but may also be
|
||||
any of the types accepted by pexpect.spawn.expect().
|
||||
If the 'unmatched' parameter is given, it is printed as part of the error message
|
||||
of any failure.
|
||||
On failure, this prints an error and exits.
|
||||
def expect_re(self, pat, pat_desc=None, unmatched=None, **kwargs):
|
||||
""" Cover over pexpect.spawn.expect().
|
||||
Consume all "new" output of self.spawn until the given pattern is matched, or
|
||||
the timeout is reached.
|
||||
Note that output between the current position and the location of the match is
|
||||
consumed as well.
|
||||
The pattern is typically a regular expression in string form, but may also be
|
||||
any of the types accepted by pexpect.spawn.expect().
|
||||
If the 'unmatched' parameter is given, it is printed as part of the error message
|
||||
of any failure.
|
||||
On failure, this prints an error and exits.
|
||||
"""
|
||||
try:
|
||||
self.spawn.expect(pat, **kwargs)
|
||||
res = self.spawn.expect(pat, **kwargs)
|
||||
when = self.time_since_first_message()
|
||||
self.messages.append(
|
||||
Message.received_output(self.spawn.match.group(), when)
|
||||
)
|
||||
# When a match is found,
|
||||
# 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
|
||||
return res
|
||||
except pexpect.ExceptionPexpect as err:
|
||||
if shouldfail:
|
||||
return True
|
||||
if not pat_desc:
|
||||
pat_desc = str(pat)
|
||||
self.report_exception_and_exit(pat_desc, unmatched, err)
|
||||
|
||||
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)
|
||||
|
||||
def expect_prompt(self, *args, increment=True, **kwargs):
|
||||
"""Convenience function which matches some text and then a prompt.
|
||||
Match the given positional arguments as expect_re, and then look
|
||||
for a prompt.
|
||||
If increment is set, then this should be a new prompt and the prompt counter
|
||||
should be bumped; otherwise this is not a new prompt.
|
||||
Returns None on success, and exits on failure.
|
||||
Example:
|
||||
sp.sendline("echo hello world")
|
||||
sp.expect_prompt("hello world")
|
||||
def expect_prompt(self, *args, **kwargs):
|
||||
""" Convenience function which matches some text and then a prompt.
|
||||
Match the given positional arguments as expect_re, and then look
|
||||
for a prompt, bumping the prompt counter.
|
||||
Returns None on success, and exits on failure.
|
||||
Example:
|
||||
sp.sendline("echo hello world")
|
||||
sp.expect_prompt("hello world")
|
||||
"""
|
||||
if args:
|
||||
self.expect_re(*args, **kwargs)
|
||||
if increment:
|
||||
self.prompt_counter += 1
|
||||
self.expect_re(
|
||||
get_prompt_re(self.prompt_counter),
|
||||
pat_desc="prompt %d" % self.prompt_counter,
|
||||
)
|
||||
self.prompt_counter += 1
|
||||
|
||||
def report_exception_and_exit(self, pat, unmatched, err):
|
||||
"""Things have gone badly.
|
||||
We have an exception 'err', some pexpect.ExceptionPexpect.
|
||||
Report it to stdout, along with the offending call site.
|
||||
If 'unmatched' is set, print it to stdout.
|
||||
""" Things have gone badly.
|
||||
We have an exception 'err', some pexpect.ExceptionPexpect.
|
||||
Report it to stdout, along with the offending call site.
|
||||
If 'unmatched' is set, print it to stdout.
|
||||
"""
|
||||
# Close the process so we can get the status
|
||||
self.spawn.close()
|
||||
colors = self.colors()
|
||||
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.update(**colors)
|
||||
|
||||
filename, lineno, code_context = get_callsite()
|
||||
fmtkeys["filename"] = filename
|
||||
fmtkeys["lineno"] = lineno
|
||||
fmtkeys["code"] = "\n".join([n.strip() for n in code_context if n])
|
||||
fmtkeys["code"] = "\n".join(code_context)
|
||||
|
||||
if unmatched:
|
||||
print(
|
||||
@@ -287,21 +243,23 @@ class SpawnedProc(object):
|
||||
print("{CYAN}Escaped buffer:{RESET}".format(**colors))
|
||||
print(escape(self.spawn.before))
|
||||
print("")
|
||||
print("{CYAN}When written to the tty, this looks like:{RESET}".format(**colors))
|
||||
print("{CYAN}<-------{RESET}".format(**colors))
|
||||
sys.stdout.write(SANITIZE_FOR_PRINTING_RE.sub('', self.spawn.before))
|
||||
sys.stdout.flush()
|
||||
maybe_nl=""
|
||||
if not self.spawn.before.endswith("\n"):
|
||||
maybe_nl="\n{CYAN}(no trailing newline)".format(**colors)
|
||||
print("{RESET}{maybe_nl}{CYAN}------->{RESET}".format(maybe_nl=maybe_nl, **colors))
|
||||
if sys.stdout.isatty():
|
||||
print(
|
||||
"{CYAN}When written to the tty, this looks like:{RESET}".format(
|
||||
**colors
|
||||
)
|
||||
)
|
||||
print("{CYAN}<-------{RESET}".format(**colors))
|
||||
sys.stdout.write(self.spawn.before)
|
||||
sys.stdout.flush()
|
||||
print("{RESET}\n{CYAN}------->{RESET}".format(**colors))
|
||||
|
||||
print("")
|
||||
|
||||
# Show the last 10 messages.
|
||||
print("Last 10 messages:")
|
||||
# Show the last 5 messages.
|
||||
print("Last 5 messages:")
|
||||
delta = None
|
||||
for m in self.messages[-10:]:
|
||||
for m in self.messages[-5:]:
|
||||
etext = escape(m.text)
|
||||
timestamp = m.when * 1000.0
|
||||
# Use relative timestamps and add a sign.
|
||||
@@ -313,6 +271,7 @@ class SpawnedProc(object):
|
||||
else:
|
||||
timestampstr = "{timestamp:10.2f} ms".format(timestamp=timestamp)
|
||||
delta = m.when * 1000.0
|
||||
dir = m.dir
|
||||
print(
|
||||
"{dir} {timestampstr} (Line {lineno}): {BOLD}{etext}{RESET}".format(
|
||||
dir=m.dir,
|
||||
@@ -327,14 +286,14 @@ class SpawnedProc(object):
|
||||
sys.exit(1)
|
||||
|
||||
def sleep(self, secs):
|
||||
"""Cover over time.sleep()."""
|
||||
""" Cover over time.sleep(). """
|
||||
time.sleep(secs)
|
||||
|
||||
def colors(self):
|
||||
"""Return a dictionary mapping color names to ANSI escapes"""
|
||||
""" Return a dictionary mapping color names to ANSI escapes """
|
||||
|
||||
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 {
|
||||
@@ -358,25 +317,3 @@ class SpawnedProc(object):
|
||||
"LIGHTCYAN": ansic(96),
|
||||
"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
|
||||
# formatting programs.
|
||||
#
|
||||
set -l git_clang_format no
|
||||
set -l c_files
|
||||
set -l fish_files
|
||||
set -l python_files
|
||||
set -l rust_files
|
||||
set -l all no
|
||||
|
||||
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/^ *[^ ]* *//')
|
||||
if set -q files[1]
|
||||
echo
|
||||
echo 'You have uncommitted changes. Are you sure you want to restyle?'
|
||||
read -P 'y/N? ' -n1 -l ans
|
||||
if not string match -qi y -- $ans
|
||||
exit 1
|
||||
end
|
||||
echo You have uncommitted changes. Cowardly refusing to restyle the entire code base.
|
||||
echo
|
||||
exit 1
|
||||
end
|
||||
set fish_files share/**.fish
|
||||
set python_files {doc_src,share,tests}/**.py
|
||||
set rust_files fish-rust/src/**.rs
|
||||
set c_files src/*.h src/*.cpp src/*.c
|
||||
set fish_files (printf '%s\n' share/***.fish)
|
||||
set python_files **.py
|
||||
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.
|
||||
set fish_files (string match -r '^.*\.fish$' -- $files)
|
||||
set python_files (string match -r '^.*\.py$' -- $files)
|
||||
set rust_files (string match -r '^.*\.rs$' -- $files)
|
||||
end
|
||||
|
||||
set -l red (set_color red)
|
||||
@@ -43,6 +57,37 @@ set -l green (set_color green)
|
||||
set -l blue (set_color blue)
|
||||
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.
|
||||
if set -q fish_files[1]
|
||||
if not type -q fish_indent
|
||||
@@ -63,14 +108,3 @@ if set -q python_files[1]
|
||||
black $python_files
|
||||
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.
|
||||
|
||||
add_custom_target(benchmark
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/benchmarks/driver.sh ${CMAKE_BINARY_DIR}/fish
|
||||
DEPENDS fish
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/benchmarks/driver.sh $<TARGET_FILE:fish>
|
||||
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_ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}/user_doc")
|
||||
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_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.
|
||||
add_custom_target(sphinx-docs
|
||||
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}
|
||||
-j auto
|
||||
-q -b html
|
||||
-c "${SPHINX_SRC_DIR}"
|
||||
-d "${SPHINX_ROOT_DIR}/.doctrees-html"
|
||||
-d "${SPHINX_CACHE_DIR}"
|
||||
"${SPHINX_SRC_DIR}"
|
||||
"${SPHINX_HTML_DIR}"
|
||||
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
|
||||
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}
|
||||
-j auto
|
||||
-q -b man
|
||||
-c "${SPHINX_SRC_DIR}"
|
||||
-d "${SPHINX_ROOT_DIR}/.doctrees-man"
|
||||
-d "${SPHINX_CACHE_DIR}"
|
||||
"${SPHINX_SRC_DIR}"
|
||||
# TODO: This only works if we only have section 1 manpages.
|
||||
"${SPHINX_MANPAGE_DIR}/man1"
|
||||
DEPENDS CHECK-FISH-BUILD-VERSION-FILE
|
||||
DEPENDS fish_indent
|
||||
COMMENT "Building man pages with Sphinx")
|
||||
|
||||
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(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(bindir ${CMAKE_INSTALL_BINDIR})
|
||||
set(sysconfdir ${CMAKE_INSTALL_SYSCONFDIR})
|
||||
set(mandir ${CMAKE_INSTALL_MANDIR})
|
||||
|
||||
set(rel_datadir ${CMAKE_INSTALL_DATADIR})
|
||||
set(datadir ${CMAKE_INSTALL_FULL_DATADIR})
|
||||
file(RELATIVE_PATH rel_datadir ${CMAKE_INSTALL_PREFIX} ${datadir})
|
||||
|
||||
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_functionsdir "fish/vendor_functions.d")
|
||||
set(rel_confdir "fish/vendor_conf.d")
|
||||
@@ -28,19 +40,10 @@ set(extra_confdir
|
||||
"${datadir}/${rel_confdir}"
|
||||
CACHE STRING "Path for extra configuration")
|
||||
|
||||
|
||||
# These are the man pages that go in system manpath; all manpages go in the fish-specific manpath.
|
||||
set(MANUALS ${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish.1
|
||||
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish_indent.1
|
||||
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish_key_reader.1
|
||||
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish-doc.1
|
||||
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish-tutorial.1
|
||||
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish-language.1
|
||||
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish-interactive.1
|
||||
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish-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)
|
||||
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish_key_reader.1)
|
||||
|
||||
# Determine which man page we don't want to install.
|
||||
# On OS X, don't install a man page for open, since we defeat fish's open
|
||||
@@ -73,7 +76,7 @@ function(FISH_TRY_CREATE_DIRS)
|
||||
endforeach()
|
||||
endfunction(FISH_TRY_CREATE_DIRS)
|
||||
|
||||
install(PROGRAMS ${PROGRAMS}
|
||||
install(TARGETS ${PROGRAMS}
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
|
||||
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
||||
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/tools/web_config
|
||||
${rel_datadir}/fish/tools/web_config/js
|
||||
${rel_datadir}/fish/tools/web_config/sample_prompts
|
||||
${rel_datadir}/fish/tools/web_config/themes
|
||||
)
|
||||
${rel_datadir}/fish/tools/web_config/partials
|
||||
${rel_datadir}/fish/tools/web_config/sample_prompts)
|
||||
|
||||
configure_file(share/__fish_build_paths.fish.in share/__fish_build_paths.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
|
||||
COMMAND sed '/Version/d' fish.pc.noversion > 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}
|
||||
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)
|
||||
|
||||
@@ -145,7 +147,6 @@ install(DIRECTORY share/tools/web_config
|
||||
PATTERN "*.html"
|
||||
PATTERN "*.py"
|
||||
PATTERN "*.js"
|
||||
PATTERN "*.theme"
|
||||
PATTERN "*.fish")
|
||||
|
||||
# Building the man pages is optional: if Sphinx isn't installed, they're not built
|
||||
@@ -154,6 +155,8 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/user_doc/html/ # Trailing slash is
|
||||
DESTINATION ${docdir} OPTIONAL)
|
||||
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
|
||||
# INSTALL_DESTINATION leads to them being installed as ${lang}.gmo, not fish.mo
|
||||
# The ${languages} array comes from cmake/gettext.cmake
|
||||
@@ -164,14 +167,13 @@ if(GETTEXT_FOUND)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if (NOT APPLE)
|
||||
install(FILES fish.desktop DESTINATION ${rel_datadir}/applications)
|
||||
install(FILES ${SPHINX_SRC_DIR}/python_docs_theme/static/fish.png DESTINATION ${rel_datadir}/pixmaps)
|
||||
endif()
|
||||
install(FILES fish.desktop DESTINATION ${rel_datadir}/applications)
|
||||
install(FILES fish.png DESTINATION ${rel_datadir}/pixmaps)
|
||||
|
||||
# Group install targets into a InstallTargets folder
|
||||
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)
|
||||
|
||||
# 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.
|
||||
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
|
||||
${OSX_DIR}/launch_fish.scpt
|
||||
${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,
|
||||
# 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(
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_tools/git_version_gen.sh --stdout
|
||||
COMMAND cut -d- -f1
|
||||
@@ -32,7 +29,7 @@ execute_process(
|
||||
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.
|
||||
set_target_properties(fish_macapp PROPERTIES OUTPUT_NAME "fish")
|
||||
|
||||
@@ -64,5 +61,15 @@ add_custom_command(TARGET fish_macapp POST_BUILD
|
||||
# The entitlements file.
|
||||
set(MACAPP_ENTITLEMENTS "${CMAKE_SOURCE_DIR}/osx/MacApp.entitlements")
|
||||
|
||||
# Group our targets in a folder.
|
||||
set_property(TARGET fish_macapp PROPERTY FOLDER macapp)
|
||||
# Target to sign the 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
|
||||
"Try to use PCRE2 from the system, instead of the pcre2-sys version")
|
||||
# PCRE2 needs some settings.
|
||||
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)
|
||||
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()
|
||||
message(STATUS "Forcing static build of PCRE2")
|
||||
set(FISH_PCRE2_BUILDFLAG "PCRE2_SYS_STATIC=1")
|
||||
message(STATUS "Using bundled PCRE2 library")
|
||||
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)
|
||||
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
|
||||
enable_testing()
|
||||
|
||||
# Put in a tests folder to reduce the top level targets in IDEs.
|
||||
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
|
||||
)
|
||||
# Define fish_tests.
|
||||
add_executable(fish_tests EXCLUDE_FROM_ALL
|
||||
src/fish_tests.cpp)
|
||||
fish_link_deps_and_sign(fish_tests)
|
||||
|
||||
# The "test" directory.
|
||||
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)
|
||||
set(TEST_ROOT_DIR ${TEST_DIR}/root)
|
||||
|
||||
# Copy needed directories for out-of-tree builds
|
||||
if(NOT FISH_IN_TREE_BUILD)
|
||||
add_custom_target(funcs_dir)
|
||||
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)
|
||||
# Copy tests files.
|
||||
file(GLOB TESTS_FILES tests/*)
|
||||
add_custom_target(tests_dir DEPENDS tests)
|
||||
|
||||
add_custom_target(tests_dir DEPENDS tests)
|
||||
add_custom_command(TARGET tests_dir
|
||||
POST_BUILD
|
||||
if(NOT FISH_IN_TREE_BUILD)
|
||||
add_custom_command(TARGET tests_dir
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${CMAKE_SOURCE_DIR}/tests/ ${CMAKE_BINARY_DIR}/tests/
|
||||
COMMENT "Copying test files to binary dir"
|
||||
VERBATIM)
|
||||
|
||||
add_dependencies(fish_tests tests_dir)
|
||||
endif()
|
||||
|
||||
# Copy littlecheck.py
|
||||
@@ -66,86 +32,94 @@ configure_file(build_tools/littlecheck.py littlecheck.py COPYONLY)
|
||||
# Copy pexpect_helper.py
|
||||
configure_file(build_tools/pexpect_helper.py pexpect_helper.py COPYONLY)
|
||||
|
||||
# Suppress generating Xcode schemes for all tests, there's too many.
|
||||
set(CMAKE_XCODE_GENERATE_SCHEME 0)
|
||||
|
||||
# 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()
|
||||
|
||||
# Make the directory in which to run tests.
|
||||
# Also symlink fish to where the tests expect it to be.
|
||||
# Lastly put fish_test_helper there too.
|
||||
add_custom_target(tests_buildroot_target
|
||||
# Make the directory in which to run tests:
|
||||
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
|
||||
# Put fish_test_helper there too:
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/fish_test_helper
|
||||
${TEST_INSTALL_DIR}/${CMAKE_INSTALL_PREFIX}/bin
|
||||
# Also symlink fish to where the tests expect it to be:
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
${TEST_INSTALL_DIR}/${CMAKE_INSTALL_PREFIX}
|
||||
${TEST_ROOT_DIR}
|
||||
DEPENDS fish fish_test_helper)
|
||||
|
||||
FILE(GLOB FISH_CHECKS CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/tests/checks/*.fish)
|
||||
foreach(CHECK ${FISH_CHECKS})
|
||||
get_filename_component(CHECK_NAME ${CHECK} NAME)
|
||||
get_filename_component(CHECK ${CHECK} NAME_WE)
|
||||
add_test(NAME ${CHECK_NAME}
|
||||
COMMAND sh ${CMAKE_CURRENT_BINARY_DIR}/tests/test_driver.sh
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/test.fish ${CHECK}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tests
|
||||
)
|
||||
set_tests_properties(${CHECK_NAME} PROPERTIES SKIP_RETURN_CODE ${SKIP_RETURN_CODE})
|
||||
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()
|
||||
if(NOT FISH_IN_TREE_BUILD)
|
||||
# We need to symlink share/functions for the tests.
|
||||
# This should be simplified.
|
||||
add_custom_target(symlink_functions
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/share/functions
|
||||
${CMAKE_CURRENT_BINARY_DIR}/share/functions)
|
||||
add_dependencies(tests_buildroot_target symlink_functions)
|
||||
else()
|
||||
add_custom_target(symlink_functions)
|
||||
endif()
|
||||
|
||||
if(DEFINED Rust_CARGO_TARGET)
|
||||
list(APPEND cargo_test_flags "--target" ${Rust_CARGO_TARGET})
|
||||
list(APPEND cargo_test_flags "--lib")
|
||||
endif()
|
||||
# Prep the environment for running the unit tests.
|
||||
add_custom_target(test_prep
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${TEST_DIR}/data
|
||||
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(
|
||||
NAME "cargo-test"
|
||||
COMMAND env ${VARS_FOR_CARGO} cargo test --no-default-features ${CARGO_FLAGS} --workspace --target-dir ${rust_target_dir} ${cargo_test_flags}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
set_tests_properties("cargo-test" PROPERTIES SKIP_RETURN_CODE ${SKIP_RETURN_CODE})
|
||||
add_test_target("cargo-test")
|
||||
# Define our individual tests.
|
||||
# Each test is conceptually independent.
|
||||
# However when running all tests, we want to run them serially for sanity's sake.
|
||||
# So define both a normal target, and a serial variant which enforces ordering.
|
||||
foreach(TESTTYPE test serial_test)
|
||||
add_custom_target(${TESTTYPE}_low_level
|
||||
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)
|
||||
|
||||
option(WITH_GETTEXT "translate messages if gettext is available" ON)
|
||||
if(WITH_GETTEXT)
|
||||
find_package(Intl QUIET)
|
||||
find_package(Gettext)
|
||||
if(GETTEXT_FOUND)
|
||||
set(HAVE_GETTEXT 1)
|
||||
include_directories(${Intl_INCLUDE_DIR})
|
||||
endif()
|
||||
endif()
|
||||
add_feature_info(gettext GETTEXT_FOUND "translate messages with gettext")
|
||||
|
||||
# Define translations
|
||||
if(GETTEXT_FOUND)
|
||||
# Group pofile targets into their own folder, as there's a lot of them.
|
||||
set(CMAKE_FOLDER pofiles)
|
||||
foreach(lang ${languages})
|
||||
# Our translations aren't set up entirely as CMake expects, so installation is done in
|
||||
# cmake/Install.cmake instead of using INSTALL_DESTINATION
|
||||
gettext_process_po_files(${lang} ALL
|
||||
PO_FILES po/${lang}.po)
|
||||
endforeach()
|
||||
set(CMAKE_FOLDER)
|
||||
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
|
||||
Maintainer: ridiculous_fish <corydoras@ridiculousfish.com>
|
||||
Uploaders: David Adam <zanchey@ucc.gu.uwa.edu.au>
|
||||
Build-Depends: debhelper (>= 12),
|
||||
cargo (>= 0.66) | cargo-mozilla (>= 0.66),
|
||||
cmake (>= 3.15.0) | cmake-mozilla (>= 3.15.0),
|
||||
gettext,
|
||||
libpcre2-dev,
|
||||
rustc (>= 1.70),
|
||||
Build-Depends: debhelper (>= 9.20151004), libncurses5-dev, cmake (>= 3.2.0), gettext,
|
||||
# Test dependencies
|
||||
locales-all,
|
||||
ncurses-base,
|
||||
python3
|
||||
locales-all, python3
|
||||
# When libpcre2-dev is available on all supported Debian versions, add a dependency on that.
|
||||
Standards-Version: 4.1.5
|
||||
Homepage: https://fishshell.com/
|
||||
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
|
||||
Architecture: any
|
||||
Depends: bsdextrautils,
|
||||
Depends: bsdextrautils | bsdmainutils,
|
||||
file,
|
||||
gettext-base,
|
||||
groff-base,
|
||||
man-db,
|
||||
ncurses-base,
|
||||
procps,
|
||||
python3 (>=3.5),
|
||||
${misc:Depends},
|
||||
${shlibs:Depends}
|
||||
Conflicts: fish-common
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, fish-common (= ${source:Version}), passwd (>= 4.0.3-10), gettext-base, man-db
|
||||
Recommends: xsel (>=1.2.0)
|
||||
Suggests: xdg-utils
|
||||
Description: 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.
|
||||
|
||||
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/
|
||||
Upstream-Name: fish
|
||||
Upstream-Contact: corydoras@ridiculousfish.com
|
||||
Source: https://fishshell.com/
|
||||
This work was packaged for Debian by David Adam <zanchey@ucc.gu.uwa.edu.au>
|
||||
on Thu, 14 Jun 2012 20:33:34 +0800, based on work by James Vega
|
||||
<jamessan@jamessan.com>. Modifications from the downstream Debian maintainer,
|
||||
Tristan Seligmann <mithrandi@debian.org>, have also been included.
|
||||
|
||||
Files: *
|
||||
Copyright: 2005-2009 Axel Liljencrantz <axel@liljencrantz.se>
|
||||
2009-2024 fish-shell contributors
|
||||
License: GPL-2
|
||||
It was downloaded from:
|
||||
|
||||
Files: doc_src/python_docs_theme/*
|
||||
Copyright: 2001-2017 Python Software Foundation
|
||||
2020-2024 fish-shell contributors
|
||||
License: Python
|
||||
https://github.com/fish-shell/fish-shell
|
||||
|
||||
Files: share/tools/web_config/js/alpine.js
|
||||
Copyright: 2019-2021 Caleb Porzio and contributors
|
||||
License: MIT
|
||||
Upstream Authors:
|
||||
|
||||
Files: share/tools/web_config/themes/Dracula.theme
|
||||
Copyright: 2018 Dracula Team
|
||||
License: MIT
|
||||
Axel Liljencrantz
|
||||
ridiculous_fish
|
||||
|
||||
Files: share/tools/web_config/themes/Nord.theme
|
||||
Copyright: 2016-2024 Sven Greb
|
||||
License: MIT
|
||||
Copyright:
|
||||
|
||||
Files: cmake/FindRust.cmake
|
||||
Copyright: 2018 Andrew Gaspar
|
||||
License: MIT
|
||||
Copyright (C) 2005-2008 Axel Liljencrantz
|
||||
Copyright (C) 2011-2012 ridiculous_fish
|
||||
|
||||
Files: src/builtins/printf.rs
|
||||
Copyright: 1990-2007 Free Software Foundation, Inc.
|
||||
2022 fish-shell contributors
|
||||
License: GPL-2+
|
||||
License:
|
||||
|
||||
Files: src/wgetopt.rs
|
||||
Copyright: 1989-1994 Free Software Foundation, Inc.
|
||||
License: LGPL-2+
|
||||
Copyright (C) 2005-2008 Axel Liljencrantz
|
||||
|
||||
Files: printf/*
|
||||
Copyright: 2024 fish-shell contributors
|
||||
2005-2020 Rich Felker
|
||||
License: MIT
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2005-2009 James Vega <jamessan@jamessan.com>
|
||||
2012 David Adam <zanchey@ucc.gu.uwa.edu.au>
|
||||
2015 Tristan Seligmann <mithrandi@debian.org>
|
||||
2019-2022 Mo Zhou <lumin@debian.org>
|
||||
License: GPL-2
|
||||
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.
|
||||
|
||||
License: GPL-2
|
||||
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
|
||||
published by the Free Software Foundation.
|
||||
.
|
||||
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'.
|
||||
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 St, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
|
||||
License: GPL-2+
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
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'.
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
|
||||
|
||||
License: LGPL-2+
|
||||
This package is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
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'.
|
||||
Fish contains code from the PCRE2 library to support regular expressions. This
|
||||
code, created by Philip Hazel, is distributed under the terms of the BSD
|
||||
license. Copyright © 1997-2015 University of Cambridge.
|
||||
|
||||
License: MIT
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
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.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
License: Python
|
||||
1. This LICENSE AGREEMENT is between the Python Software Foundation
|
||||
("PSF"), and the Individual or Organization ("Licensee") accessing and
|
||||
otherwise using this software ("Python") in source or binary form and
|
||||
its associated documentation.
|
||||
.
|
||||
2. Subject to the terms and conditions of this License Agreement, PSF
|
||||
hereby grants Licensee a nonexclusive, royalty-free, world-wide
|
||||
license to reproduce, analyze, test, perform and/or display publicly,
|
||||
prepare derivative works, distribute, and otherwise use Python alone
|
||||
or in any derivative version, provided, however, that PSF's License
|
||||
Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012,
|
||||
2013, 2014 Python Software Foundation; All Rights Reserved" are
|
||||
retained in Python alone or in any derivative version prepared by
|
||||
Licensee.
|
||||
.
|
||||
3. In the event Licensee prepares a derivative work that is based on
|
||||
or incorporates Python or any part thereof, and wants to make
|
||||
the derivative work available to others as provided herein, then
|
||||
Licensee hereby agrees to include in any such work a brief summary of
|
||||
the changes made to Python.
|
||||
.
|
||||
4. PSF is making Python available to Licensee on an "AS IS"
|
||||
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
.
|
||||
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
||||
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
.
|
||||
6. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
.
|
||||
7. Nothing in this License Agreement shall be deemed to create any
|
||||
relationship of agency, partnership, or joint venture between PSF and
|
||||
Licensee. This License Agreement does not grant permission to use PSF
|
||||
trademarks or trade name in a trademark sense to endorse or promote
|
||||
products or services of Licensee, or any third party.
|
||||
.
|
||||
8. By copying, installing or otherwise using Python, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the University of Cambridge nor the names of any
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Fish also contains small amounts of code under the OpenBSD license, namely a
|
||||
version of the function strlcpy, modified for use with wide character strings.
|
||||
This code is copyrighted by Todd C. Miller (1998). It also contains code from
|
||||
tmux, copyrighted by Nicholas Marriott <nicm@users.sourceforge.net> (2007), and
|
||||
made available under an identical license.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
Fish contains code from the glibc library, namely the wcstok function
|
||||
in fallback.c. This code is licensed under the LGPL.
|
||||
|
||||
On Debian systems, the complete text of the GNU Lesser General
|
||||
Public License can be found in `/usr/share/common-licenses/LGPL'.
|
||||
|
||||
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.
|
||||
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 $@
|
||||
|
||||
# Setting the build system is still required, because otherwise the GNUmakefile gets picked up
|
||||
override_dh_auto_configure:
|
||||
ln -s cargo-vendor/vendor vendor
|
||||
ln -s cargo-vendor/.cargo .cargo
|
||||
dh_auto_configure --buildsystem=cmake -- -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
dh_auto_configure --buildsystem=cmake --parallel
|
||||
|
||||
override_dh_clean:
|
||||
dh_clean
|
||||
-unlink .cargo
|
||||
-unlink vendor
|
||||
override_dh_installdocs:
|
||||
dh_installdocs --link-doc=fish
|
||||
|
||||
# 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