Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 0 additions & 103 deletions .cirrus.yml

This file was deleted.

92 changes: 92 additions & 0 deletions .github/workflows/freebsd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# FreeBSD CI
#
# FreeBSD is not a native GitHub Actions runner, so this workflow runs
# the build inside a VM via vmactions/freebsd-vm. It is kept separate
# from haskell.yml because the cache/restore step model in that
# workflow (hackage index, ghcup, deps caches) does not apply inside
# the VM.

name: FREEBSD

on:
workflow_dispatch:
pull_request:
push:
branches:
- master

jobs:
build:
name: >-
freebsd-${{ matrix.release }}
${{ matrix.command }}
${{ matrix.ghc_version }}
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.ignore_error }}
strategy:
fail-fast: false
matrix:
include:
- release: "14.5"
command: cabal
ghc_version: 9.14.1
ignore_error: true

steps:
- uses: actions/checkout@v4

- name: Build on FreeBSD
uses: vmactions/freebsd-vm@v1
env:
PACKCHECK_COMMAND: ${{ matrix.command }}
GHCVER: ${{ matrix.ghc_version }}
# For updating see: https://downloads.haskell.org/~ghcup/
GHCUP_VERSION: 0.1.50.2
LC_ALL: C.UTF-8
CABAL_REINIT_CONFIG: y
CABAL_CHECK_RELAX: y
CABAL_PROJECT: cabal.project
# With the default -j (4 CPUs) the VM (6 GB) killed cabal while it
# built fusion-plugin and other dependencies in parallel.
CABAL_BUILD_OPTIONS: "-j2"
DISABLE_BENCH: "y"
DISABLE_DOCS: "y"
DISABLE_SDIST_BUILD: "y"
DISABLE_DIST_CHECKS: "y"
PACKCHECK: "./packcheck.sh"
PACKCHECK_GITHUB_URL: "https://raw.githubusercontent.com/composewell/packcheck"
PACKCHECK_GITHUB_COMMIT: "20514de6ae27035b0406b4ed46d628c806e40b49"
with:
release: ${{ matrix.release }}
usesh: true
copyback: false
envs: >-
PACKCHECK_COMMAND GHCVER GHCUP_VERSION LC_ALL
CABAL_REINIT_CONFIG CABAL_CHECK_RELAX CABAL_PROJECT CABAL_BUILD_OPTIONS
DISABLE_BENCH DISABLE_DOCS DISABLE_SDIST_BUILD DISABLE_DIST_CHECKS
PACKCHECK PACKCHECK_GITHUB_URL PACKCHECK_GITHUB_COMMIT
prepare: |
pkg update
pkg install -y gmake
pkg install -y bash
pkg install -y git
pkg install -y gmp
run: |
if test ! -e "$PACKCHECK"
then
if test -z "$PACKCHECK_GITHUB_COMMIT"
then
echo "PACKCHECK_GITHUB_COMMIT is not specified." >&2
exit 1
fi
PACKCHECK_URL=${PACKCHECK_GITHUB_URL}/${PACKCHECK_GITHUB_COMMIT}/packcheck.sh
curl --fail -sL -o "$PACKCHECK" $PACKCHECK_URL || exit 1
chmod +x $PACKCHECK
elif test ! -x "$PACKCHECK"
then
chmod +x $PACKCHECK
fi
# Use "bash -c" instead of invoking directly to preserve quoted
# arguments in PACKCHECK_COMMAND e.g. DOCSPEC_OPTIONS="--timeout 60".
# Direct invocation would word-split on spaces inside quoted values.
bash -c "$PACKCHECK $PACKCHECK_COMMAND"
58 changes: 47 additions & 11 deletions .github/workflows/haskell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ jobs:
# If you have not committed packcheck.sh in your repo at PACKCHECK
# then it is automatically pulled from this URL.
PACKCHECK_GITHUB_URL: "https://raw.githubusercontent.com/composewell/packcheck"
PACKCHECK_GITHUB_COMMIT: "74a50fd9bcb06907b822e910938dae795d0f23cc"
PACKCHECK_GITHUB_COMMIT: "20514de6ae27035b0406b4ed46d628c806e40b49"

# ubuntu seems to have better support than debian on CI systems
runs-on: ${{ matrix.runner }}
Expand Down Expand Up @@ -255,11 +255,13 @@ jobs:
- name: ci
runner: ubuntu-latest
command: hlint
# Bump to invalidate the cached hlint binary in ~/.local/bin.
ghc_salt: 1
# WARNING! cannot use # comments inside pack_options.
pack_options: >-
HLINT_VERSION=3.6.1
HLINT_VERSION=3.10
HLINT_OPTIONS="lint"
HLINT_TARGETS="src test Benchmark"
HLINT_TARGETS="src test benchmark"

- name: docspec
runner: ubuntu-latest
Expand Down Expand Up @@ -300,6 +302,38 @@ jobs:

- uses: actions/checkout@v4

# The macOS image may ship Command Line Tools newer than the default
# Xcode (e.g. CLT 27.0 with Xcode 26.6). Linking against the CLT SDK then
# fails with "tapi error: malformed file ... unknown architecture
# arm64e.x1-macos". Select the default Xcode so that the compiler, linker
# and SDK come from the same toolchain. packcheck clears the environment,
# so SDKROOT or DEVELOPER_DIR cannot be used instead.
#
# The GHC bindists for macOS hardcode the CLT SDK path from their build
# machine, e.g. the rts and ghci package confs of GHC 9.14.1 have
# /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib in
# library-dirs, so the linker uses the CLT SDK even when Xcode is
# selected. Point the CLT MacOSX.sdk symlink at the Xcode SDK.
#
# The GHC and dependency cache keys include the Xcode version and build,
# so a runner image with a different Xcode installs GHC afresh.
- name: Select default Xcode (macOS)
id: xcode
if: runner.os == 'macOS'
run: |
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
xcode-select -p
sdk=$(xcrun --show-sdk-path)
echo "$sdk"
clt=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
if test -L "$clt"; then
ls -ld "$clt"
sudo ln -sfn "$sdk" "$clt"
ls -ld "$clt"
fi
ver=$(xcodebuild -version | awk 'NR==1{v=$2} /Build version/{b=$3} END{print v "-" b}')
echo "toolchain=-xcode-$ver" >> "$GITHUB_OUTPUT"

# This should happen before cache restore.
- name: Remove ~/.ghcup symlink (non-Windows)
if: runner.os != 'Windows'
Expand All @@ -309,15 +343,16 @@ jobs:
# See the "cabal path" output in the CI logs to tweak the cache
# locations.

# Shared by all tests, all platforms
# Shared by all tests, all platforms. Other workflows can restore it
# with the same key.
- name: Restore hackage package index (non-Windows)
id: restore-hackage
uses: actions/cache/restore@v4
if: runner.os != 'Windows'
with:
path: |
~/.cache/cabal/packages
key: cabal-hackage-index-non-windows
key: cabal-hackage-index

# GHC is not test/options specific
- name: Restore ghcup and ghc (non-Windows)
Expand All @@ -327,7 +362,7 @@ jobs:
with:
path: |
~/.ghcup
key: ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }}
key: ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }}${{ steps.xcode.outputs.toolchain }}

# GHC is not test/options specific
#- name: Restore ghcup and ghc (Windows)
Expand Down Expand Up @@ -358,7 +393,7 @@ jobs:
~/.local/bin
~/.local/state/cabal
~/.stack
key: ${{ matrix.command }}-deps-ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }}-${{ matrix.name }}
key: ${{ matrix.command }}-deps-ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }}-${{ matrix.name }}${{ steps.xcode.outputs.toolchain }}

# Deps are test/options specific
- name: Restore build dependencies, hackage index, local/bin (Windows)
Expand Down Expand Up @@ -429,7 +464,8 @@ jobs:
ARGS="$ARGS CABAL_BUILDDIR=\"/c/b\" WINVER=$WINVER"
ARGS="$ARGS NUMBER_OF_PROCESSORS=$NUMBER_OF_PROCESSORS"
ARGS="$ARGS PROCESSOR_IDENTIFIER=\"$PROCESSOR_IDENTIFIER\""
PATH_VAR="$PATH_VAR:/c/ghcup:/c/Program Files/7-Zip:/mingw64/bin"
# Git for Windows 2.56 moved /mingw64 to /ucrt64
PATH_VAR="$PATH_VAR:/c/ghcup:/c/Program Files/7-Zip:/ucrt64/bin:/mingw64/bin"
;;
esac
ARGS="$ARGS PATH=\"$PATH_VAR\""
Expand Down Expand Up @@ -457,14 +493,14 @@ jobs:
if: always() && steps.deps-only.outcome == 'success' && runner.os != 'Windows' && steps.restore-hackage.outputs.cache-hit != 'true'
with:
path: ~/.cache/cabal/packages
key: cabal-hackage-index-non-windows
key: cabal-hackage-index

- name: Save ghcup and ghc (non-Windows)
uses: actions/cache/save@v4
if: always() && steps.deps-only.outcome == 'success' && runner.os != 'Windows' && steps.restore-ghcup.outputs.cache-hit != 'true'
with:
path: ~/.ghcup
key: ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }}
key: ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }}${{ steps.xcode.outputs.toolchain }}

# On Windows, ghc restore step takes 2-3 minutes whereas installing
# GHC takes less than 2 minutes. On top of this saving the ghc cache
Expand All @@ -486,7 +522,7 @@ jobs:
~/.local/bin
~/.local/state/cabal
~/.stack
key: ${{ matrix.command }}-deps-ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }}-${{ matrix.name }}
key: ${{ matrix.command }}-deps-ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }}-${{ matrix.name }}${{ steps.xcode.outputs.toolchain }}

# hackage package index is part of C:/cabal
# Deps are test/options specific, hence, matrix.name in the key
Expand Down
4 changes: 3 additions & 1 deletion .packcheck.ignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.cirrus.yml
.github/workflows/freebsd.yml
.packcheck.ignore
.github/workflows/haskell.yml
.gitignore
Expand All @@ -12,3 +12,5 @@ flake.nix
packages.nix
stack.yaml
test/Main.hs
cabal.project
sources.nix
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ shell, or instead of assembling the same behaviour from `directory`,
Where a function differs from GNU, for example `rm -r` on a symbolic
link with a trailing slash, which here deletes only the link, the
difference is documented.
* No subprocesses: no quoting of arguments, no parsing of text output.
Errors are Haskell exceptions, and the code also runs on Windows, where
the commands are not installed.
* The utilities run no subprocesses: no quoting of arguments, no parsing
of text output. Errors are Haskell exceptions, and the code also runs on
Windows, where the commands are not installed. `Streamly.Coreutils.Sh` is
the exception: it runs shell commands.
* `ls`, `find` and `tail` return [streamly](https://github.com/composewell/streamly)
streams. You can filter, map, take the first few entries or fold them as
they are produced, in constant memory, even for a directory tree with
Expand All @@ -35,7 +36,8 @@ shell, or instead of assembling the same behaviour from `directory`,
* File tests compose like the operands of `test`, and a combined test
makes a single `stat` call: ``test p (isFile `and_` size (> 10240))``.
* When you do need a shell command, `Streamly.Coreutils.Sh` runs it and
connects its input and output to Haskell streams.
connects its input and output to Haskell streams. It uses `/bin/sh`, and
on Windows `sh` from the `PATH`, e.g. from Git for Windows.

## Example

Expand Down
Loading
Loading