Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Distributable binaries #165

Merged
merged 58 commits into from
Jul 20, 2020
Merged
Show file tree
Hide file tree
Changes from 54 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
69b4f07
WIP
lukel97 Jun 12, 2020
0e30291
WIP 2
lukel97 Jun 12, 2020
43c8076
WIP 3
lukel97 Jun 12, 2020
8ba974b
WIP 4
lukel97 Jun 12, 2020
cde25d7
WIP 5
lukel97 Jun 12, 2020
c328c80
WIP 6
lukel97 Jun 12, 2020
2a5b400
WIP 7
lukel97 Jun 12, 2020
ffe3d4e
WIP 8
lukel97 Jun 12, 2020
7c7c207
WIP 9 Use patched hie-bios to get libdir dynamically
lukel97 Jun 13, 2020
bf59f29
Try building the wrapper
lukel97 Jun 13, 2020
0ace84b
Try to fix build_wrapper env variable not being picked up
lukel97 Jun 13, 2020
32c5937
Try again
lukel97 Jun 13, 2020
1a66953
Give up on the env var idea
lukel97 Jun 13, 2020
5d3fed7
Try out static optimised builds?
lukel97 Jun 13, 2020
191272a
Try squashing the working dir
lukel97 Jun 15, 2020
a3b309c
Woops
lukel97 Jun 15, 2020
a626ffc
Try squashing the builddir
lukel97 Jun 15, 2020
4219d51
Try going into the parent directory
lukel97 Jun 15, 2020
dc99a50
Radical approach - don't use such a long name for the wrapper
lukel97 Jun 15, 2020
277f20e
Use dist-binary flag
lukel97 Jun 15, 2020
4feadad
Debug why floskell fails to build on windows
lukel97 Jun 16, 2020
f4a7fb8
haskell-language-server => hls on CI
lukel97 Jun 16, 2020
a91ae03
Employ extreme path saving measures
lukel97 Jun 16, 2020
d53fb6e
sed time :(
lukel97 Jun 16, 2020
7e0402b
Try making sed command portable
lukel97 Jun 16, 2020
505ee0a
Compress artefacts
lukel97 Jun 17, 2020
304f4c3
Tidy up wrapper logging
lukel97 Jun 17, 2020
0c48be8
Use version checking logic in hie-bios
lukel97 Jun 18, 2020
65eb6c4
Add documentation on the releases process
lukel97 Jun 18, 2020
c1a1228
Remove unused code
lukel97 Jun 19, 2020
d0aa2fa
Append .exe to windows binaries
lukel97 Jun 23, 2020
edf2cc5
Try out building remaining supported ghc configurations
lukel97 Jun 23, 2020
322e6ad
Add wrapper tests and update hie-bios
lukel97 Jun 25, 2020
8063c33
Merge remote-tracking branch 'origin/master' into github-action-builds
lukel97 Jun 26, 2020
997e6b0
Use index timestamp that exists on hackage
lukel97 Jun 26, 2020
0df1168
Update hie-bios
lukel97 Jun 29, 2020
74468f7
Update hie-bios
lukel97 Jun 29, 2020
06abcf4
Try building windows jobs on -j1
lukel97 Jun 30, 2020
f84d4a7
Skip windows 8.8.2
lukel97 Jun 30, 2020
dc3a61a
Update ghc-check to use hie-bios runtime ghc libdir
lukel97 Jul 1, 2020
c76a69e
Upload binaries as an artifact too
lukel97 Jul 1, 2020
18c4082
Try flicking on enable-executable-static
lukel97 Jul 7, 2020
90b286e
Fix artifact upload
lukel97 Jul 7, 2020
b24390f
Merge remote-tracking branch 'origin/master' into github-action-builds
lukel97 Jul 14, 2020
1e9b6e7
Merge remote-tracking branch 'origin/master' into github-action-builds
lukel97 Jul 14, 2020
a5c5608
Update to latest ghcide and reuse loadSession
lukel97 Jul 15, 2020
cf05aa9
Check if the tool is installed in --project-ghc-version in the wrapper
lukel97 Jul 16, 2020
773ec86
Fix wrapper tests by copying to temporary directory
lukel97 Jul 16, 2020
bcfa908
Try caching
lukel97 Jul 16, 2020
53c3676
Tidy up and switch back to cabal helper implicit cradle
lukel97 Jul 16, 2020
54ce0ec
use split sections
amesgen Jul 16, 2020
c162fca
Merge pull request #1 from amesgen/use-split-sections
lukel97 Jul 16, 2020
7156e45
Remove cabal-helper and replace it with hie-bios implicit logic
lukel97 Jul 17, 2020
72abb71
Merge branch 'github-action-builds' of github.com:bubba/haskell-langu…
lukel97 Jul 17, 2020
1cd5016
Merge remote-tracking branch 'origin/master' into github-action-builds
lukel97 Jul 17, 2020
9238ced
Undo agpl common stanza change
lukel97 Jul 17, 2020
ebe5ef1
Add release number
lukel97 Jul 17, 2020
3e2ac6f
Merge remote-tracking branch 'origin/master' into github-action-builds
lukel97 Jul 20, 2020
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
116 changes: 116 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
name: Builds

on:
release:
types: [created]
jobs:

build:
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
ghc: ['8.10.1', '8.8.3', '8.8.2', '8.6.5', '8.6.4']
os: [ubuntu-latest, macOS-latest, windows-latest]
exclude:
- os: windows-latest
ghc: '8.8.3' # fails due to segfault
- os: windows-latest
ghc: '8.8.2' # fails due to error with Cabal

steps:
- uses: actions/checkout@v2
with:
submodules: true
- uses: actions/[email protected]
with:
ghc-version: ${{ matrix.ghc }}
cabal-version: '3.2'

- name: Cache Cabal
uses: actions/[email protected]
with:
path: ~/.cabal
key: ${{ runner.OS }}-${{ matrix.ghc }}-${{ hashFiles('**/*.cabal') }}

- name: Shorten binary names
shell: bash
run: |
sed -i.bak -e 's/haskell-language-server/hls/g' \
-e 's/haskell_language_server/hls/g' \
haskell-language-server.cabal
sed -i.bak -e 's/Paths_haskell_language_server/Paths_hls/g' \
src/**/*.hs exe/*.hs

- name: Set some window specific things
if: matrix.os == 'windows-latest'
shell: bash
run: |
echo '::set-env name=EXE_EXT::.exe'

- name: Set some linux specific things
if: matrix.os == 'ubuntu-latest'
run: |
echo '::set-env name=LINUX_CABAL_ARGS::--enable-executable-static --ghc-options=-split-sections'

- name: Build Server
shell: bash
# Try building it twice in case of flakey builds on Windows
run: |
cabal build exe:hls -O2 --disable-documentation $LINUX_CABAL_ARGS || \
cabal build exe:hls -O2 --disable-documentation $LINUX_CABAL_ARGS

- name: Find Server Binary
id: find_server_binary
shell: bash
run: |
HLS=$(find dist-newstyle \( -name 'hls' -o -name 'hls.exe' \) -type f)
gzip --best $HLS
echo ::set-output name=hls_binary::$HLS.gz

- name: Upload Server Binary
uses: actions/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: ${{ steps.find_server_binary.outputs.hls_binary }}
asset_name: haskell-language-server-${{ runner.OS }}-${{ matrix.ghc }}${{env.EXE_EXT}}.gz
asset_content_type: application/gzip

- uses: actions/upload-artifact@v2
with:
name: haskell-language-server-${{ runner.OS }}-${{ matrix.ghc }}${{env.EXE_EXT}}.gz
path: ${{ steps.find_server_binary.outputs.hls_binary }}

- name: Build Wrapper
if: matrix.ghc == '8.10.1'
run: cabal build exe:hls-wrapper -O2 --disable-documentation $WIN_CABAL_ARGS $LINUX_CABAL_ARGS

- name: Find Wrapper Binary
if: matrix.ghc == '8.10.1'
id: find_wrapper_binary
shell: bash
run: |
HLS_WRAPPER=$(find dist-newstyle \( -name 'hls-wrapper' -o -name 'hls-wrapper.exe' \) -type f)
gzip --best $HLS_WRAPPER
echo ::set-output name=hls_wrapper_binary::$HLS_WRAPPER.gz

- name: Upload Wrapper
if: matrix.ghc == '8.10.1'
uses: actions/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: ${{ steps.find_wrapper_binary.outputs.hls_wrapper_binary }}
asset_name: haskell-language-server-wrapper-${{ runner.OS }}${{env.EXE_EXT}}.gz
asset_content_type: application/gzip

- uses: actions/upload-artifact@v2
if: matrix.ghc == '8.10.1'
with:
name: haskell-language-server-wrapper-${{ runner.OS }}${{env.EXE_EXT}}.gz
path: ${{ steps.find_wrapper_binary.outputs.hls_wrapper_binary }}

2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ stack*.yaml.lock
shake.yaml.lock

# ignore hie.yaml's for testdata
test/**/*.yaml
test/testdata/**/hie.yaml

# metadata files on macOS
.DS_Store
3 changes: 2 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
# url = https://github.com/digital-asset/ghcide.git
# url = https://github.com/alanz/ghcide.git
# url = https://github.com/wz1000/ghcide.git
url = https://github.com/fendor/ghcide.git
# url = https://github.com/fendor/ghcide.git
url = https://github.com/bubba/ghcide.git
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the correct upstream repo?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Until those other PRs and @wz1000s PRs get merged into ghcide, I think so. This checkout is just @fendor's previous submodule + my patches cherry-picked on top

2 changes: 1 addition & 1 deletion cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ package ghcide

write-ghc-environment-files: never

index-state: 2020-07-13T21:29:04Z
index-state: 2020-07-13T21:03:06Z
72 changes: 72 additions & 0 deletions docs/releases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Releases and distributable binaries
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome Documentation!


Starting with 0.X.0.0 haskell-language-server provides pre-built binaries on
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine 0.3.0.0, if we merge soon.

each [GitHub
release](https://github.com/haskell/haskell-language-server/releases). These
binaries are used by the [vscode-hie-server
extension](https://github.com/alanz/vscode-hie-server) to provide automatic
installation for users on VS Code, but they can also be installed manually
when added to the path.

## Making a new release of haskell-language-server

Go to the [GitHub releases
page](https://github.com/haskell/haskell-language-server/releases) for
haskell-language-server and start to create a new release. Choose or create a
tag, fill out the release notes etc., but before you create it
**make sure to check the pre-release checkbox**. This will prevent VS Code
*extension
users from attempting to install this version before the binaries are
created.

Once the release is created the [GitHub Actions
workflow](https://github.com/haskell/haskell-language-server/actions) will be
kicked off and will start creating binaries. They will be gzipped and
uploaded to the release.

It creates a `haskell-language-server-OS-GHC` binary for each platform
(Linux, macOS, Windows) and each GHC version that we currently support, as well
as a `haskell-language-server-wrapper-OS` binary for each platform. Note that
only one wrapper binary is created per platform, and it should be built with the
most recent GHC version.

Once all these binaries are present

## Distributable binaries
In order to compile a hls binary on one machine and have it run on another, you
need to make sure there are **no hardcoded paths or data-files**.

### ghc libdir
One noteable thing which cannot be hardcoded is the **GHC libdir** – this is
a path to `/usr/local/lib/ghc` or something like that, which was previously
baked in at compile-time with ghc-paths. Note that with static binaries we
can no longer use this because the GHC libdir of the GitHub Actions machine
will most almost certainly not exist on the end user's machine.
Therefore, hie-bios provides `getGhcRuntimeLibDir` to obtain this path on the fly
by consulting the cradle.

### Static binaries
We use the word "distributable" here because technically only the Linux builds
are static. They are built by passing `--enable-executable-static` to cabal.
Static binaries don't really exist on macOS, and there are issues with
proprietary code being linked in on Windows. However, the `.dylib`s linked on
macOS are all already provided by the system:

```
$ objdump -macho --dylibs-used haskell-language-server
haskell-language-server:
/usr/lib/libncurses.5.4.dylib (compatibility version 5.4.0, current version 5.4.0)
/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1)
/usr/lib/libcharset.1.dylib (compatibility version 2.0.0, current version 2.0.0)
```

## The GitHub Actions workflow
It just kicks off a matrix of jobs varying across GHC versions and OSs, building
the binaries with Cabal and extracting them from the dist-newstyle directory.
The binaries are built with -O2.

One caveat is that we need to rename the binaries from
haskell-language-server/haskell-language-server-wrapper to hls/hls-wrapper due to
path length limitations on windows. But whenever we upload them to the release,
we make sure to upload them as their full name variant.
18 changes: 7 additions & 11 deletions exe/Arguments.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,11 @@
module Arguments
( Arguments(..)
, getArguments
, ghcideVersion
, getLibdir
, haskellLanguageServerVersion
) where

import Data.Maybe
import Data.Version
import Development.GitRev
import qualified GHC.Paths
import Options.Applicative
import Paths_haskell_language_server
import System.Environment
Expand All @@ -37,6 +34,7 @@ data Arguments = Arguments
, argsDebugOn :: Bool
, argsLogFile :: Maybe String
, argsThreads :: Int
, argsProjectGhcVersion :: Bool
} deriving Show

getArguments :: String -> IO Arguments
Expand Down Expand Up @@ -80,21 +78,19 @@ arguments exeName = Arguments
<> value 0
<> showDefault
)
<*> switch (long "project-ghc-version"
<> help "Work out the project GHC version and print it")

-- ---------------------------------------------------------------------
-- Set the GHC libdir to the nix libdir if it's present.
getLibdir :: IO FilePath
getLibdir = fromMaybe GHC.Paths.libdir <$> lookupEnv "NIX_GHC_LIBDIR"

ghcideVersion :: IO String
ghcideVersion = do
haskellLanguageServerVersion :: IO String
haskellLanguageServerVersion = do
path <- getExecutablePath
let gitHashSection = case $(gitHash) of
x | x == "UNKNOWN" -> ""
x -> " (GIT hash: " <> x <> ")"
return $ "ghcide version: " <> showVersion version
return $ "haskell-language-server version: " <> showVersion version
<> " (GHC: " <> VERSION_ghc
<> ") (PATH: " <> path <> ")"
<> gitHashSection

-- ---------------------------------------------------------------------
Loading