Add script for circumventing MacOS SIP and using nix-built grpc; upda… (#85)

* Add script for circumventing MacOS SIP and using nix-built grpc; update README.md

* Guard destructive /usr/local and brew updates with a user prompt
This commit is contained in:
Joel Stanley 2016-12-20 11:37:46 -06:00 committed by GitHub Enterprise
parent 8a6a7c3715
commit 89a5547dc0
2 changed files with 112 additions and 41 deletions

View file

@ -1,14 +1,15 @@
Building and testing Building and testing
-------------------- --------------------
You will need to have GRPC installed already. See the "Installing GRPC" section If you want to use `stack` on MacOS, you will need to have GRPC installed
below for more information. already -- see the [Installing GRPC for `stack`](#stackgrpc) section below. Any
example build and test recipes below which use `stack` assume you have already
performed the steps described in that section.
`nix-build release.nix -A grpc-haskell` will build and test the whole thing and Without `stack`, `nix-build release.nix -A grpc-haskell` will build and test the
put the completed package into the nix store. whole thing and put the completed package into the nix store. `nix-shell` can be
used to give you a development environment where you can use the `cabal` and
`nix-shell` can be used to give you a development environment where you can use `stack` toolchains for development and testing:
the `cabal` and `stack test` toolchains for development and testing iteration.
```bash ```bash
$ nix-shell release-nix -A grpc-haskell.env $ nix-shell release-nix -A grpc-haskell.env
@ -20,39 +21,71 @@ $ nix-shell release-nix -A grpc-haskell.env
[nix-shell]$ stack build --fast && stack test --fast [nix-shell]$ stack build --fast && stack test --fast
``` ```
Note that, for `stack`, the `nix-shell` environment only needed to run the Note that, for `stack`, the `nix-shell` environment is only needed to run the
tests, because it uses some custom python tooling (for grpc interop tests, because it uses some custom python tooling (for grpc interop
testing). You should still be able to `stack build` without using the testing). You should still be able to `stack build` without using the
`nix-shell` environment at all. See the section below on installing GRPC for use `nix-shell` environment at all.
by `stack`.
NB: You can also instruct `stack` to run the tests inside the `nix-shell` NB: You can also instruct `stack` to run the tests inside the `nix-shell`
environment directly, via `stack --nix test --fast`. However, this will environment directly, via `stack --nix test --fast`. However, this will
frequently rebuild the custom ghc that is used by the `nix` tooling so is not frequently rebuild the custom ghc that is used in `release.nix`, so is not
recommended for development iterations. recommended during develop-debug cycles (use the `cabal` path for that, or
iterate within a `nix-shell`).
Finally, since `stack` does not use `nix` for any Haskell dependencies, Finally, since `stack` does not use `nix` for any Haskell package dependencies,
repository references for dependent packages such as `protobuf-wire` must be be sure to update repository references for dependent packages such as
updated both in `nix/<pkg>.nix` AND in the `stack.yaml`. `protobuf-wire` in both `nix/<pkg>.nix` AND in `stack.yaml`.
Installing GRPC for `stack` <a name="stackgrpc"></a>Installing GRPC for `stack` (MacOS)
--------------------------- -----------------------------------------------------------
If you want to use the `stack` tooling, you will need a working installation of If you want to use `stack` in a relatively natural and painless manner, you will
the GRPC C core libraries. need a working installation of the GRPC C core libraries.
On MacOS, because On MacOS, because of
of [this](https://github.com/commercialhaskell/stack/issues/1161), dependencies issues [related](https://github.com/commercialhaskell/stack/issues/1161) to
on the nix-built `grpc` don't work properly, so the library needs to be System Integrity Protection, dependencies on the nix-built `grpc` don't seem to
installed somewhere the linker will pick it up without `DYLD_LIBRARY_PATH` set. work properly in the stack toolflow when `DYLD_LIBRARY_PATH` refers to the
`nix`-built `grpc` library in the nix store, so the library needs to be
installed somewhere that the loader can pick it up without `DYLD_LIBRARY_PATH`
set (e.g., in `/usr/local/lib`).
We suggest that use `brew` to do this: There are basically two methods to accomplish this:
1. Run `bin/install-macos-nix-grpc.sh`.
This script will build the same version of `grpc` used in `release.nix`, which
is what is used in the end-to-end system and in our CI testing flows. It then
pretends to be an impoverished version of `brew` and installs symlinks from
the nix store into `/usr/local/include/grpc` and
`/usr/local/lib/libgrpc.dylib`. It should be run manually whenever the `grpc`
dependency is updated. Note that it is intentionally destructive to any
existing `brew` installs of `grpc`.
Is it an ugly hack? Yes, but it's better than having either a rootless system
to circumvent SIP or building atop a version of `grpc` which may differ from
CI and production environments (which may be the case with `brew`-installed
grpc).
After running this script, you should be able to use `stack` normally, in
combination with a `nix-shell` environment for running the tests:
```bash
$ bin/install-macos-nix-grpc.sh
$ stack build --fast
$ stack --nix test --fast
``` ```
brew tap grpc/grpc
brew edit grpc 1. Use `brew`
...
brew install grpc If you don't want to hack the global pathing yourself using the above script,
you can rely on homebrew to do this for you instead. However, you will need to
specify the version of the `grpc` release that you want to use.
```bash
$ brew tap grpc/grpc
$ brew edit grpc
$ brew install grpc
``` ```
Make sure you select a release version that is reasonably close to our grpc Make sure you select a release version that is reasonably close to our grpc

38
bin/install-macos-nix-grpc.sh Executable file
View file

@ -0,0 +1,38 @@
#!/bin/bash
set -e
function purge_grpc {
echo "Purging old grpc references in /usr/local..."
if brew list grpc; then
echo "Removing brew-installed grpc..."
brew uninstall grpc
else
echo "No brew-installed grpc detected."
fi
rm -rf /usr/local/include/grpc
rm -f /usr/local/lib/libgrpc.dylib
}
read -p "This script nukes brew-installed grpc libs and destructively updates /usr/local. Cool? [yN] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
echo "Okay, aborting."
exit 1
fi
purge_grpc
echo "Building grpc from release.nix..."
grpc=$(nix-build release.nix -A grpc)
echo "Nix store path for grpc is ${grpc}."
echo "Creating symlinks into /usr/local/include and /usr/local/lib..."
ln -sf "${grpc}/include/grpc" /usr/local/include/grpc
ln -sf "${grpc}/lib/libgrpc.dylib" /usr/local/lib/libgrpc.dylib
echo "Creating the following symlinks:"
ls -ld /usr/local/include/grpc
ls -l /usr/local/lib/libgrpc.dylib
echo "All done."