Skip to content

Commit 6ec16e1

Browse files
authored
Build a separate print-api executable for each supported GHC versions (#16)
* Build print-api tool for all supported GHC versions The `print-api` executable is a simple wrapper that detects the used GHC version and calls the appropriate `print-api-VERSION` executable which does the actual work.
1 parent 0f9c200 commit 6ec16e1

File tree

11 files changed

+459
-97
lines changed

11 files changed

+459
-97
lines changed

.github/workflows/ci.yml

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,14 @@ jobs:
4343
strategy:
4444
matrix: ${{ fromJSON(needs.generate-matrix.outputs.matrix) }}
4545
steps:
46-
- name: Checkout base repo
47-
uses: actions/checkout@v4
4846
- name: "Install tools"
47+
if: ${{ matrix.os == 'ubuntu-latest' }}
4948
run: |
50-
.github/workflows/install-tools.sh
49+
sudo apt install upx-ucl
50+
51+
- name: Checkout base repo
52+
uses: actions/checkout@v4
53+
5154
- name: Set up Haskell
5255
id: setup-haskell
5356
uses: haskell-actions/setup@v2
@@ -74,23 +77,34 @@ jobs:
7477

7578
- name: Install
7679
run: |
77-
bin=$(cabal -v0 --project-file=cabal.release.project list-bin print-api)
7880
mkdir distribution
79-
cp ${bin} distribution/print-api
81+
for executable in 'print-api' 'print-api-${{ matrix.ghc }}'; do
82+
path=$(cabal -v0 --project-file=cabal.release.project list-bin "print-api:exe:${executable}")
83+
cp "${path}" distribution
84+
done
85+
echo "$GITHUB_WORKSPACE/distribution" >> "$GITHUB_PATH"
8086
8187
- name: File type
82-
run: file distribution/print-api
88+
run: file distribution/*
8389

84-
- name: Package the print-api executable
90+
- name: Post-process executables
91+
if: ${{ matrix.os == 'ubuntu-latest' }}
8592
run: |
86-
PRINTAPI_EXEC=distribution/print-api
87-
.github/workflows/process-binaries.sh
88-
DIR=$(dirname $PRINTAPI_EXEC)
89-
FILE=$(basename $PRINTAPI_EXEC)
90-
PRINTAPI_EXEC_TAR=print-api-head-${{ runner.os }}-${{ matrix.ghc }}-${{ env.ARCH }}.tar.gz
91-
tar -czvf $PRINTAPI_EXEC_TAR -C $DIR $FILE
92-
echo PRINTAPI_EXEC_TAR=$PRINTAPI_EXEC_TAR >> $GITHUB_ENV
93-
- name: Upload the print-api executable
93+
for executable in distribution/*; do
94+
strip "${executable}"
95+
upx -9 "${executable}"
96+
done
97+
98+
- name: Package the executables
99+
shell: bash
100+
run: |
101+
executables=( $(ls distribution) )
102+
version=$(./distribution/print-api --version)
103+
archive="print-api-${version}-${{ runner.os }}-${{ env.ARCH }}-ghc-${{ matrix.ghc }}.tar.gz"
104+
tar -czvf "${archive}" -C distribution "${executables[@]}"
105+
echo "PRINTAPI_EXEC_TAR=${archive}" >> $GITHUB_ENV
106+
107+
- name: Upload the executables archive
94108
uses: actions/upload-artifact@v3
95109
with:
96110
name: artifact
@@ -142,9 +156,11 @@ jobs:
142156

143157
- name: Install
144158
run: |
145-
bin=$(cabal -v0 --project-file=cabal.static.project list-bin print-api)
146159
mkdir distribution
147-
cp ${bin} distribution/print-api
160+
for executable in 'print-api' 'print-api-${{ matrix.ghc }}'; do
161+
path=$(cabal -v0 --project-file=cabal.static.project list-bin "print-api:exe:${executable}")
162+
cp "${path}" distribution
163+
done
148164
echo "$GITHUB_WORKSPACE/distribution" >> "$GITHUB_PATH"
149165
150166
- name: Test
@@ -157,19 +173,26 @@ jobs:
157173
report_paths: "report.xml"
158174

159175
- name: File type
160-
run: file distribution/print-api
176+
run: file distribution/*
161177

162-
- name: Tar print-api executable
178+
- name: Post-process executables
179+
if: ${{ matrix.os == 'ubuntu-latest' }}
163180
run: |
164-
PRINTAPI_EXEC=distribution/print-api
165-
.github/workflows/process-binaries.sh
166-
DIR=$(dirname $PRINTAPI_EXEC)
167-
FILE=$(basename $PRINTAPI_EXEC)
168-
PRINTAPI_EXEC_TAR=print-api-head-${{ runner.os }}-static-${{ matrix.ghc }}-${{ env.ARCH }}.tar.gz
169-
tar -czvf $PRINTAPI_EXEC_TAR -C $DIR $FILE
170-
echo PRINTAPI_EXEC_TAR=$PRINTAPI_EXEC_TAR >> $GITHUB_ENV
171-
172-
- name: Upload print-api executable to workflow artifacts
181+
for executable in distribution/*; do
182+
strip "${executable}"
183+
upx -9 "${executable}"
184+
done
185+
186+
- name: Package the executables
187+
shell: bash
188+
run: |
189+
executables=( $(ls distribution) )
190+
version=$(./distribution/print-api --version)
191+
archive="print-api-${version}-${{ runner.os }}-${{ env.ARCH }}-static-ghc-${{ matrix.ghc }}.tar.gz"
192+
tar -c -z -v -f "${archive}" -C distribution "${executables[@]}"
193+
echo "PRINTAPI_EXEC_TAR=${archive}" >> $GITHUB_ENV
194+
195+
- name: Upload the executables archive
173196
uses: actions/upload-artifact@v3
174197
with:
175198
name: artifact

.github/workflows/install-tools.sh

Lines changed: 0 additions & 6 deletions
This file was deleted.

.github/workflows/process-binaries.sh

Lines changed: 0 additions & 12 deletions
This file was deleted.

.github/workflows/release.yml

Lines changed: 79 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,13 @@ jobs:
4444
strategy:
4545
matrix: ${{ fromJSON(needs.generate-matrix.outputs.matrix) }}
4646
steps:
47-
- name: Checkout base repo
48-
uses: actions/checkout@v4
4947
- name: "Install tools"
48+
if: ${{ matrix.os == 'ubuntu-latest' }}
5049
run: |
51-
.github/workflows/install-tools.sh
50+
sudo apt install upx-ucl
51+
52+
- name: Checkout base repo
53+
uses: actions/checkout@v4
5254
- name: Set up Haskell
5355
id: setup-haskell
5456
uses: haskell-actions/setup@v2
@@ -75,9 +77,11 @@ jobs:
7577

7678
- name: Install
7779
run: |
78-
bin=$(cabal -v0 --project-file=cabal.release.project list-bin print-api)
7980
mkdir distribution
80-
cp ${bin} distribution/print-api
81+
for executable in 'print-api' 'print-api-${{ matrix.ghc }}'; do
82+
path=$(cabal -v0 --project-file=cabal.release.project list-bin "print-api:exe:${executable}")
83+
cp "${path}" distribution
84+
done
8185
echo "$GITHUB_WORKSPACE/distribution" >> "$GITHUB_PATH"
8286
8387
- name: Test
@@ -90,19 +94,25 @@ jobs:
9094
report_paths: "report.xml"
9195

9296
- name: File type
93-
run: file distribution/print-api
97+
run: file distribution/*
98+
99+
- name: Post-process executables
100+
if: ${{ matrix.os == 'ubuntu-latest' }}
101+
run: |
102+
for executable in distribution/*; do
103+
strip "${executable}"
104+
upx -9 "${executable}"
105+
done
94106
95-
- name: Package the print-api executable
107+
- name: Package the executables
96108
run: |
97-
PRINTAPI_EXEC=distribution/print-api
98-
.github/workflows/process-binaries.sh
99-
DIR=$(dirname $PRINTAPI_EXEC)
100-
FILE=$(basename $PRINTAPI_EXEC)
109+
executables=( $(ls distribution) )
101110
version=$(./distribution/print-api --version)
102-
PRINTAPI_EXEC_TAR=print-api-${version}-${{ runner.os }}-${{ matrix.ghc }}-${{ env.ARCH }}.tar.gz
103-
tar -czvf $PRINTAPI_EXEC_TAR -C $DIR $FILE
104-
echo PRINTAPI_EXEC_TAR=$PRINTAPI_EXEC_TAR >> $GITHUB_ENV
105-
- name: Upload the print-api executable
111+
archive="print-api-${version}-${{ runner.os }}-${{ env.ARCH }}-ghc-${{ matrix.ghc }}.tar.gz"
112+
tar -czvf "${archive}" -C distribution "${executables[@]}"
113+
echo "PRINTAPI_EXEC_TAR=${archive}" >> $GITHUB_ENV
114+
115+
- name: Upload the executables archive
106116
uses: actions/upload-artifact@v3
107117
with:
108118
name: artifact
@@ -154,9 +164,11 @@ jobs:
154164

155165
- name: Install
156166
run: |
157-
bin=$(cabal -v0 --project-file=cabal.static.project list-bin print-api)
158167
mkdir distribution
159-
cp ${bin} distribution/print-api
168+
for executable in 'print-api' 'print-api-${{ matrix.ghc }}'; do
169+
path=$(cabal -v0 --project-file=cabal.static.project list-bin "print-api:exe:${executable}")
170+
cp "${path}" distribution
171+
done
160172
echo "$GITHUB_WORKSPACE/distribution" >> "$GITHUB_PATH"
161173
162174
- name: Test
@@ -169,40 +181,76 @@ jobs:
169181
report_paths: "report.xml"
170182

171183
- name: File type
172-
run: file distribution/print-api
184+
run: file distribution/*
185+
186+
- name: Post-process executables
187+
if: ${{ matrix.os == 'ubuntu-latest' }}
188+
run: |
189+
for executable in distribution/*; do
190+
strip "${executable}"
191+
upx -9 "${executable}"
192+
done
173193
174-
- name: Package the print-api executable
194+
- name: Package the executables
195+
shell: bash
175196
run: |
176-
PRINTAPI_EXEC=distribution/print-api
177-
.github/workflows/process-binaries.sh
178-
DIR=$(dirname $PRINTAPI_EXEC)
179-
FILE=$(basename $PRINTAPI_EXEC)
197+
executables=( $(ls distribution) )
180198
version=$(./distribution/print-api --version)
181-
PRINTAPI_EXEC_TAR=print-api-${version}-${{ runner.os }}-static-${{ matrix.ghc }}-${{ env.ARCH }}.tar.gz
182-
tar -czvf $PRINTAPI_EXEC_TAR -C $DIR $FILE
183-
echo PRINTAPI_EXEC_TAR=$PRINTAPI_EXEC_TAR >> $GITHUB_ENV
199+
archive="print-api-${version}-${{ runner.os }}-${{ env.ARCH }}-static-ghc-${{ matrix.ghc }}.tar.gz"
200+
tar -czvf "${archive}" -C distribution "${executables[@]}"
201+
echo "PRINTAPI_EXEC_TAR=${archive}" >> $GITHUB_ENV
184202
185-
- name: Upload print-api executable to workflow artifacts
203+
- name: Upload the executables archive
186204
uses: actions/upload-artifact@v3
187205
with:
188206
name: artifact
189207
path: ${{ env.PRINTAPI_EXEC_TAR }}
190208

209+
# NOTE: We run upx on the executables in every linux job to compress them.
210+
# That means, the assets that are linked dynamically _appear_ to be statically
211+
# linked after that, despite not being compiled statically in Alpine with
212+
# musl. They are still dynamically-linked once they are decompresed.
213+
# See: https://stackoverflow.com/questions/20740625/does-upx-magically-transform-binaries-from-dynamically-linked-into-statically-li
191214
release:
192215
name: Create a GitHub Release with the binary artifacts
193216
runs-on: ubuntu-latest
194-
if: startsWith(github.ref, 'refs/tags/v')
195217
needs: ['tests', 'build-alpine']
196218

197219
steps:
198220
- uses: actions/download-artifact@v3
199221
with:
200222
name: artifact
201-
path: ./out
223+
path: ./artifacts
224+
225+
- name: Prepare release
226+
shell: bash
227+
run: |
228+
create-tarball() {
229+
local name="${1}"
230+
local pattern="${2}"
231+
232+
echo "::group::Creating release tarball ${name}.tar.gz"
233+
mkdir "${name}"
234+
find artifacts -type f -name "${pattern}" -exec tar -x -z -f {} -C "${name}" \;
235+
local files=( $(find "${name}" -type f -printf '%P\n') )
236+
if [[ ${#files[@]} > 0 ]]; then
237+
echo "Packaging ${#files[@]} files"
238+
tar -c -z -v -f "release/${name}.tar.gz" -C "${name}" "${files[@]}"
239+
else
240+
echo "No files to package"
241+
fi
242+
echo '::endgroup::'
243+
}
244+
245+
mkdir release
246+
for base in $(ls artifacts | cut -d - -f -5 | sort --uniq); do
247+
create-tarball "${base}" "${base}-ghc-*.tar.gz"
248+
create-tarball "${base}-static" "${base}-static-ghc-*.tar.gz"
249+
done
202250
203251
- name: Release
204252
uses: softprops/action-gh-release@v2
205-
if: startsWith(github.ref, 'refs/tags/')
206253
with:
254+
prerelease: ${{ startsWith(github.ref, 'refs/tags/v') }}
207255
draft: true
208-
files: ./out/*
256+
files: ./release/*

README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ The tool can be used with the following GHC versions:
1919

2020
Pick the one that matches your operating system *and* GHC version.
2121

22+
If you have the GitHub CLI installed, (something like) the following does work:
23+
24+
```
25+
$ gh release download --repo Kleidukos/print-api --pattern "print-api-*-$(uname -s)-$(uname -m).tar.gz" --output - | tar -x -z -C <INSTALL_DIRECTORY>
26+
```
27+
2228
## Usage
2329

2430
Go in your project and build it with the GHC environment files enabled:
@@ -27,7 +33,21 @@ Go in your project and build it with the GHC environment files enabled:
2733
$ cabal build --write-ghc-environment-files=always
2834
```
2935

30-
Then run the `print-api` binary from within the same directory:
36+
You need the appropriate `print-api-<GHC_VERSION>` in your `PATH`. That means,
37+
if you did not obtain the executables from the GitHub Releases as described
38+
above but build and installed `print-api` yourself, then you need to install it
39+
for the GHC version you intend to use; For example:
40+
41+
```
42+
$ git clone https://github.com/Kleidukos/print-api.git
43+
$ cd print-api
44+
$ cabal install --with-compiler ghc-<GHC_VERSION>
45+
```
46+
47+
(There is also an `install-for-ghcup-compilers.sh` script in the `print-api`
48+
repository that installs `print-api` for GHCs currently installed by GHCup.)
49+
50+
Then run the `print-api` binary from within the source tree of your project:
3151

3252
```
3353
$ print-api -p <my-package>

app/print-api-wrapper/Main.hs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
module Main (main) where
2+
3+
import Data.ByteString.Lazy.Char8 qualified as ByteString
4+
import Data.Char (isSpace)
5+
import Options.Applicative
6+
import PrintApi.CLI.Types
7+
import PrintApi.Utils (readCabalizedProcess, runCabalizedProcess)
8+
import System.Environment (getArgs)
9+
import System.IO (hPutStrLn, stderr)
10+
11+
main :: IO ()
12+
main = do
13+
args <- getArgs
14+
-- We parse the command line arguments here in order to detect flags like
15+
-- @--help@ or @--version@.
16+
_ <- execParser (parseOptions `withInfo` "Export the declarations of a Haskell package")
17+
ghcVersion <- getGhcVersion
18+
hPutStrLn stderr $ "Detected GHC version: " <> ghcVersion
19+
runCabalizedProcess (Just ghcVersion) ("print-api-" <> ghcVersion) args
20+
21+
getGhcVersion :: IO String
22+
getGhcVersion =
23+
ByteString.unpack . ByteString.dropWhileEnd isSpace
24+
<$> readCabalizedProcess Nothing "ghc" ["--numeric-version"]
File renamed without changes.

0 commit comments

Comments
 (0)