diff --git a/.gitignore b/.gitignore index e349535d..f1a50793 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,7 @@ examples/echo/echo-cpp/echo-server benchmarks.html result *~ -cabal.project.local +cabal.project.local* dist-newstyle/ tests/py-tmp tests/tmp diff --git a/README.md b/README.md index 820fb8c6..e363981e 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ have extended and released under the same [`LICENSE`](./LICENSE) Installation ------------ -**The current version of this library requires gRPC version 1.34.1. Newer versions may work but have not been tested.** +**The current version of this library requires gRPC version 1.46.3. Newer versions may work but have not been tested.** Usage ----- @@ -22,7 +22,7 @@ put the completed package into the nix store. `nix-shell` can be used to give you a development environment where you can use `cabal` for development and testing: -```bash +``` console $ nix-shell [nix-shell]$ cabal configure --enable-tests && cabal build && cabal test ``` diff --git a/core/grpc-haskell-core.cabal b/core/grpc-haskell-core.cabal index dabc5b46..71ce861e 100644 --- a/core/grpc-haskell-core.cabal +++ b/core/grpc-haskell-core.cabal @@ -22,7 +22,7 @@ Flag Debug library build-depends: base >=4.8 && <5.0 - , clock >=0.6.0 && <0.8.0 + , clock >=0.6.0 && <0.9 , bytestring ==0.10.* , stm >=2.4 && <2.6 , containers >=0.5 && <0.7 @@ -94,7 +94,7 @@ test-suite tests , proto3-suite , transformers , safe - , clock >=0.6.0 && <0.8.0 + , clock >=0.6.0 && <0.9 , turtle >= 1.2.0 , text , QuickCheck >=2.8 && <3.0 diff --git a/core/src/Network/GRPC/LowLevel/Client.hs b/core/src/Network/GRPC/LowLevel/Client.hs index 4d684518..8f7ac506 100644 --- a/core/src/Network/GRPC/LowLevel/Client.hs +++ b/core/src/Network/GRPC/LowLevel/Client.hs @@ -88,19 +88,21 @@ addMetadataCreds c (Just create) = do createChannel :: ClientConfig -> C.GrpcChannelArgs -> IO C.Channel createChannel conf@ClientConfig{..} chanargs = case clientSSLConfig of - Nothing -> C.grpcInsecureChannelCreate e chanargs C.reserved + Nothing -> + C.withInsecureChannelCredentials $ \creds -> + C.grpcChannelCreate e creds chanargs Just (ClientSSLConfig rootCertPath Nothing plugin) -> do rootCert <- mapM B.readFile rootCertPath C.withChannelCredentials rootCert Nothing Nothing $ \creds -> do creds' <- addMetadataCreds creds plugin - C.secureChannelCreate creds' e chanargs C.reserved + C.grpcChannelCreate e creds' chanargs Just (ClientSSLConfig x (Just (ClientSSLKeyCertPair y z)) plugin) -> do rootCert <- mapM B.readFile x privKey <- Just <$> B.readFile y clientCert <- Just <$> B.readFile z C.withChannelCredentials rootCert privKey clientCert $ \creds -> do creds' <- addMetadataCreds creds plugin - C.secureChannelCreate creds' e chanargs C.reserved + C.grpcChannelCreate e creds' chanargs where (Endpoint e) = clientEndpoint conf createClient :: GRPC -> ClientConfig -> IO Client diff --git a/core/src/Network/GRPC/LowLevel/Server.hs b/core/src/Network/GRPC/LowLevel/Server.hs index fc718a4c..10948970 100644 --- a/core/src/Network/GRPC/LowLevel/Server.hs +++ b/core/src/Network/GRPC/LowLevel/Server.hs @@ -143,7 +143,8 @@ serverEndpoint ServerConfig{..} = endpoint host port addPort :: C.Server -> ServerConfig -> IO Int addPort server conf@ServerConfig{..} = case sslConfig of - Nothing -> C.grpcServerAddInsecureHttp2Port server e + Nothing -> + C.withInsecureServerCredentials $ C.grpcServerAddHttp2Port server e Just ServerSSLConfig{..} -> do crc <- mapM B.readFile clientRootCert spk <- B.readFile serverPrivateKey @@ -152,7 +153,7 @@ addPort server conf@ServerConfig{..} = case customMetadataProcessor of Just p -> C.setMetadataProcessor creds p Nothing -> return () - C.serverAddSecureHttp2Port server e creds + C.grpcServerAddHttp2Port server e creds where e = unEndpoint $ serverEndpoint conf startServer :: GRPC -> ServerConfig -> IO Server diff --git a/core/src/Network/GRPC/Unsafe.chs b/core/src/Network/GRPC/Unsafe.chs index 8967537e..f80f7355 100644 --- a/core/src/Network/GRPC/Unsafe.chs +++ b/core/src/Network/GRPC/Unsafe.chs @@ -44,6 +44,19 @@ deriving instance Show Channel -- | Represents a server. Created on the server side. {#pointer *grpc_server as Server newtype #} +deriving instance Show Server + +-- | A server credentials object that represents a way to authenticate a server. +{#pointer *grpc_server_credentials as ServerCredentials newtype #} + +deriving instance Show ServerCredentials + +-- | A channel credentials object represents a way to authenticate a client on a +-- channel. +{#pointer *grpc_channel_credentials as ChannelCredentials newtype #} + +deriving instance Show ChannelCredentials + -- | Represents a pointer to a call. To users of the gRPC core library, this -- type is abstract; we have no access to its fields. {#pointer *grpc_call as Call newtype #} @@ -194,8 +207,8 @@ castPeek p = do -- are expected to pass a 'nullPtr' for the 'ChannelArgsPtr'. We currently don't -- expose any functions for creating channel args, since they are entirely -- undocumented. -{#fun grpc_insecure_channel_create as ^ - {useAsCString* `ByteString', `GrpcChannelArgs', unReserved `Reserved'} -> `Channel'#} +{#fun grpc_channel_create as ^ + {useAsCString* `ByteString', `ChannelCredentials', `GrpcChannelArgs'} -> `Channel'#} {#fun grpc_channel_register_call as ^ {`Channel', useAsCString* `ByteString',useAsCString* `ByteString',unReserved `Reserved'} @@ -258,8 +271,8 @@ getPeerPeek cstr = do {#fun grpc_server_register_completion_queue as ^ {`Server', `CompletionQueue', unReserved `Reserved'} -> `()'#} -{#fun grpc_server_add_insecure_http2_port as ^ - {`Server', useAsCString* `ByteString'} -> `Int'#} +{#fun grpc_server_add_http2_port as ^ + {`Server', useAsCString* `ByteString', `ServerCredentials'} -> `Int'#} -- | Starts a server. To shut down the server, call these in order: -- 'grpcServerShutdownAndNotify', 'grpcServerCancelAllCalls', diff --git a/core/src/Network/GRPC/Unsafe/Security.chs b/core/src/Network/GRPC/Unsafe/Security.chs index 7de77f18..b6368773 100644 --- a/core/src/Network/GRPC/Unsafe/Security.chs +++ b/core/src/Network/GRPC/Unsafe/Security.chs @@ -20,7 +20,6 @@ import Network.GRPC.LowLevel.GRPC.MetadataMap (MetadataMap) #include {#import Network.GRPC.Unsafe#} -{#import Network.GRPC.Unsafe.ChannelArgs#} {#import Network.GRPC.Unsafe.Metadata#} {#import Network.GRPC.Unsafe.Op#} @@ -49,10 +48,6 @@ instance Storable AuthContext where {#pointer *call_credentials as ^ newtype#} -{#pointer *channel_credentials as ^ newtype#} - -{#pointer *server_credentials as ^ newtype#} - withAuthPropertyIterator :: AuthContext -> (AuthPropertyIterator -> IO a) -> IO a @@ -169,6 +164,8 @@ getAuthProperties ctx = withAuthPropertyIterator ctx $ \i -> do {#fun unsafe ssl_credentials_create_internal as ^ {`CString', `CString', `CString'} -> `ChannelCredentials'#} +{#fun insecure_credentials_create as ^ {} -> `ChannelCredentials'#} + sslChannelCredentialsCreate :: Maybe ByteString -> Maybe ByteString -> Maybe ByteString @@ -195,6 +192,10 @@ withChannelCredentials :: Maybe ByteString withChannelCredentials x y z = bracket (sslChannelCredentialsCreate x y z) channelCredentialsRelease +withInsecureChannelCredentials :: (ChannelCredentials -> IO a) -> IO a +withInsecureChannelCredentials = + bracket (insecureCredentialsCreate) channelCredentialsRelease + -- * Call Credentials {#fun call_set_credentials as ^ @@ -219,6 +220,8 @@ withChannelCredentials x y z = bracket (sslChannelCredentialsCreate x y z) `SslClientCertificateRequestType'} -> `ServerCredentials'#} +{#fun insecure_server_credentials_create as ^ {} -> `ServerCredentials'#} + sslServerCredentialsCreate :: Maybe ByteString -- ^ PEM encoding of the client root certificates. -- Can be 'Nothing' if SSL authentication of @@ -250,14 +253,9 @@ withServerCredentials :: Maybe ByteString withServerCredentials a b c d = bracket (sslServerCredentialsCreate a b c d) serverCredentialsRelease --- * Creating Secure Clients/Servers - -{#fun server_add_secure_http2_port as ^ - {`Server',useAsCString* `ByteString', `ServerCredentials'} -> `Int'#} - -{#fun secure_channel_create as ^ - {`ChannelCredentials',useAsCString* `ByteString', `GrpcChannelArgs', unReserved `Reserved'} - -> `Channel'#} +withInsecureServerCredentials :: (ServerCredentials -> IO a) -> IO a +withInsecureServerCredentials = + bracket (insecureServerCredentialsCreate) serverCredentialsRelease -- * Custom metadata processing -- server side diff --git a/grpc-haskell.cabal b/grpc-haskell.cabal index 4863c9fa..36ca99cc 100644 --- a/grpc-haskell.cabal +++ b/grpc-haskell.cabal @@ -204,7 +204,7 @@ test-suite tests , proto3-suite , transformers , safe - , clock >=0.6.0 && <0.8.0 + , clock >=0.6.0 && <0.9 , turtle >= 1.2.0 , text , QuickCheck >=2.10 && <3.0 diff --git a/nix/data-diverse.nix b/nix/data-diverse.nix new file mode 100644 index 00000000..1681ab8e --- /dev/null +++ b/nix/data-diverse.nix @@ -0,0 +1,16 @@ +{ mkDerivation, base, containers, criterion, deepseq, ghc-prim +, hspec, lib, tagged +}: +mkDerivation { + pname = "data-diverse"; + version = "4.7.0.0"; + sha256 = "sha256-w82WWNWbShoYYtDFvJHgQUb1vxEehGmgUOpq4SZaizE="; + libraryHaskellDepends = [ + base containers deepseq ghc-prim tagged + ]; + testHaskellDepends = [ base hspec tagged ]; + benchmarkHaskellDepends = [ base criterion ]; + homepage = "https://github.com/louispan/data-diverse#readme"; + description = "Extensible records and polymorphic variants"; + license = lib.licenses.bsd3; +} diff --git a/nix/grpc-pin/grpc.nix b/nix/grpc-pin/grpc.nix new file mode 100644 index 00000000..267450f1 --- /dev/null +++ b/nix/grpc-pin/grpc.nix @@ -0,0 +1,108 @@ +# Copy-paste from nixpkgs “release-22.05” branch + +{ lib +, stdenv +, fetchFromGitHub +, fetchpatch +, buildPackages +, cmake +, zlib +, c-ares +, pkg-config +, re2 +, openssl +, protobuf +, grpc +, abseil-cpp +, libnsl + +# tests +, python3 +}: + +stdenv.mkDerivation rec { + pname = "grpc"; + version = "1.46.3"; # N.B: if you change this, please update: + # pythonPackages.grpcio-tools + # pythonPackages.grpcio-status + + src = fetchFromGitHub { + owner = "grpc"; + repo = "grpc"; + rev = "v${version}"; + sha256 = "sha256-RiXtKlRtlbqwrSxI904dgSu3da0A6Fwk+/hWHIG7A5E="; + fetchSubmodules = true; + }; + + patches = [ + # Fix build on armv6l (https://github.com/grpc/grpc/pull/21341) + (fetchpatch { + url = "https://github.com/grpc/grpc/commit/2f4cf1d9265c8e10fb834f0794d0e4f3ec5ae10e.patch"; + sha256 = "0ams3jmgh9yzwmxcg4ifb34znamr7pb4qm0609kvil9xqvkqz963"; + }) + + # Revert gRPC C++ Mutex to be an alias of Abseil, because it breaks dependent packages + (fetchpatch { + url = "https://github.com/grpc/grpc/commit/931f91b745cd5b2864a0d1787815871d0bd844ae.patch"; + sha256 = "0vc93g2i4982ys4gzyaxdv9ni25yk10sxq3n7fkz8dypy8sylck7"; + revert = true; + }) + ]; + + nativeBuildInputs = [ cmake pkg-config ] + ++ lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) grpc; + propagatedBuildInputs = [ c-ares re2 zlib abseil-cpp ]; + buildInputs = [ c-ares.cmake-config openssl protobuf ] + ++ lib.optionals stdenv.isLinux [ libnsl ]; + + cmakeFlags = [ + "-DgRPC_ZLIB_PROVIDER=package" + "-DgRPC_CARES_PROVIDER=package" + "-DgRPC_RE2_PROVIDER=package" + "-DgRPC_SSL_PROVIDER=package" + "-DgRPC_PROTOBUF_PROVIDER=package" + "-DgRPC_ABSL_PROVIDER=package" + "-DBUILD_SHARED_LIBS=ON" + "-DCMAKE_SKIP_BUILD_RPATH=OFF" + ] ++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) [ + "-D_gRPC_PROTOBUF_PROTOC_EXECUTABLE=${buildPackages.protobuf}/bin/protoc" + ] ++ lib.optionals ((stdenv.hostPlatform.useLLVM or false) && lib.versionOlder stdenv.cc.cc.version "11.0") [ + # Needs to be compiled with -std=c++11 for clang < 11. Interestingly this is + # only an issue with the useLLVM stdenv, not the darwin stdenv… + # https://github.com/grpc/grpc/issues/26473#issuecomment-860885484 + "-DCMAKE_CXX_STANDARD=11" + ]; + + # CMake creates a build directory by default, this conflicts with the + # basel BUILD file on case-insensitive filesystems. + preConfigure = '' + rm -vf BUILD + ''; + + # When natively compiling, grpc_cpp_plugin is executed from the build directory, + # needing to load dynamic libraries from the build directory, so we set + # LD_LIBRARY_PATH to enable this. When cross compiling we need to avoid this, + # since it can cause the grpc_cpp_plugin executable from buildPackages to + # crash if build and host architecture are compatible (e. g. pkgsLLVM). + preBuild = lib.optionalString (stdenv.hostPlatform == stdenv.buildPlatform) '' + export LD_LIBRARY_PATH=$(pwd)''${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH + ''; + + NIX_CFLAGS_COMPILE = lib.optionalString stdenv.cc.isClang "-Wno-error=unknown-warning-option" + + lib.optionalString stdenv.isAarch64 "-Wno-error=format-security"; + + enableParallelBuilds = true; + + passthru.tests = { + inherit (python3.pkgs) grpcio-status grpcio-tools; + }; + + meta = with lib; { + description = "The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)"; + license = licenses.asl20; + maintainers = with maintainers; [ lnl7 marsam ]; + homepage = "https://grpc.io/"; + platforms = platforms.all; + changelog = "https://github.com/grpc/grpc/releases/tag/v${version}"; + }; +} diff --git a/nix/grpc-pin/grpcio-status.nix b/nix/grpc-pin/grpcio-status.nix new file mode 100644 index 00000000..d39f3c96 --- /dev/null +++ b/nix/grpc-pin/grpcio-status.nix @@ -0,0 +1,43 @@ +# Copy-paste from nixpkgs “release-22.05” branch + +{ lib +, buildPythonPackage +, fetchPypi +, googleapis-common-protos +, grpcio +, protobuf +, pythonOlder +}: + +buildPythonPackage rec { + pname = "grpcio-status"; + version = "1.46.3"; + format = "setuptools"; + + disabled = pythonOlder "3.6"; + + src = fetchPypi { + inherit pname version; + sha256 = "78442ac7d2813c56f9cc04f713efd7088596b10f88a4ddd09279211cc48402d5"; + }; + + propagatedBuildInputs = [ + googleapis-common-protos + grpcio + protobuf + ]; + + # Projec thas no tests + doCheck = false; + + pythonImportsCheck = [ + "grpc_status" + ]; + + meta = with lib; { + description = "GRPC Python status proto mapping"; + homepage = "https://github.com/grpc/grpc/tree/master/src/python/grpcio_status"; + license = licenses.asl20; + maintainers = with maintainers; [ fab ]; + }; +} diff --git a/nix/grpc-pin/grpcio-tools.nix b/nix/grpc-pin/grpcio-tools.nix new file mode 100644 index 00000000..fbab154f --- /dev/null +++ b/nix/grpc-pin/grpcio-tools.nix @@ -0,0 +1,31 @@ +# Copy-paste from nixpkgs “release-22.05” branch + +{ lib, buildPythonPackage, fetchPypi, protobuf, grpcio, setuptools }: + +buildPythonPackage rec { + pname = "grpcio-tools"; + version = "1.46.3"; + + src = fetchPypi { + inherit pname version; + sha256 = "31fee436ace5b3bd950cc3a8e68d6b84de1d6dc755959db7badc3470cdf22f70"; + }; + + outputs = [ "out" "dev" ]; + + enableParallelBuilding = true; + + propagatedBuildInputs = [ protobuf grpcio setuptools ]; + + # no tests in the package + doCheck = false; + + pythonImportsCheck = [ "grpc_tools" ]; + + meta = with lib; { + description = "Protobuf code generator for gRPC"; + license = licenses.asl20; + homepage = "https://grpc.io/grpc/python/"; + maintainers = with maintainers; [ ]; + }; +} diff --git a/nix/grpc.nix b/nix/grpc.nix deleted file mode 100644 index 92cf619a..00000000 --- a/nix/grpc.nix +++ /dev/null @@ -1,60 +0,0 @@ -{ lib, stdenv, fetchFromGitHub, fetchpatch, cmake, zlib, c-ares, pkg-config, openssl, protobuf -, gflags, abseil-cpp, libnsl -}: - -stdenv.mkDerivation rec { - version = "1.34.1"; # N.B: if you change this, change pythonPackages.grpcio-tools to a matching version too - pname = "grpc"; - src = fetchFromGitHub { - owner = "grpc"; - repo = "grpc"; - rev = "v${version}"; - sha256 = "0p6si9i0gg885ag2x87a7jyzhgd5lhx2bh2vjj2ra1jn6y3vg6qk"; - fetchSubmodules = true; - }; - patches = [ - # Fix build on armv6l (https://github.com/grpc/grpc/pull/21341) - (fetchpatch { - url = "https://github.com/grpc/grpc/commit/2f4cf1d9265c8e10fb834f0794d0e4f3ec5ae10e.patch"; - sha256 = "0ams3jmgh9yzwmxcg4ifb34znamr7pb4qm0609kvil9xqvkqz963"; - }) - ]; - - nativeBuildInputs = [ cmake pkg-config ]; - buildInputs = [ zlib c-ares c-ares.cmake-config openssl protobuf gflags abseil-cpp ] - ++ lib.optionals stdenv.isLinux [ libnsl ]; - - cmakeFlags = - [ "-DgRPC_ZLIB_PROVIDER=package" - "-DgRPC_CARES_PROVIDER=package" - "-DgRPC_SSL_PROVIDER=package" - "-DgRPC_PROTOBUF_PROVIDER=package" - "-DgRPC_GFLAGS_PROVIDER=package" - "-DgRPC_ABSL_PROVIDER=package" - "-DBUILD_SHARED_LIBS=ON" - "-DCMAKE_SKIP_BUILD_RPATH=OFF" - ]; - - # CMake creates a build directory by default, this conflicts with the - # basel BUILD file on case-insensitive filesystems. - preConfigure = '' - rm -vf BUILD - ''; - - preBuild = '' - export LD_LIBRARY_PATH=$(pwd)''${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH - ''; - - NIX_CFLAGS_COMPILE = lib.optionalString stdenv.cc.isClang "-Wno-error=unknown-warning-option"; - - enableParallelBuilds = true; - - meta = with lib; { - description = "The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)"; - license = licenses.asl20; - maintainers = [ maintainers.lnl7 maintainers.marsam ]; - homepage = "https://grpc.io/"; - platforms = platforms.all; - changelog = "https://github.com/grpc/grpc/releases/tag/v${version}"; - }; -} diff --git a/nix/parameterized.patch b/nix/parameterized.patch deleted file mode 100644 index 08e03e8f..00000000 --- a/nix/parameterized.patch +++ /dev/null @@ -1,44 +0,0 @@ -diff --git a/test/Parameterized/Control/Monad/Trans/Reader/ReaderSpec.hs b/test/Parameterized/Control/Monad/Trans/Reader/ReaderSpec.hs -index a39d181..1999e57 100644 ---- a/test/Parameterized/Control/Monad/Trans/Reader/ReaderSpec.hs -+++ b/test/Parameterized/Control/Monad/Trans/Reader/ReaderSpec.hs -@@ -91,7 +91,7 @@ whichIntBoolStringReader = do - manyIntMaybeReader :: ReaderT (Many '[Int]) Maybe String - manyIntMaybeReader = do - a <- ask -- let r = fetch @Int a -+ let r = grab @Int a - case r of - 0 -> empty - r' -> pure $ show r' -@@ -99,7 +99,7 @@ manyIntMaybeReader = do - manyBoolMaybeReader :: ReaderT (Many '[Bool]) Maybe String - manyBoolMaybeReader = do - a <- ask -- let r = fetch @Bool a -+ let r = grab @Bool a - case r of - False -> empty - r' -> pure $ show r' -diff --git a/test/Parameterized/Control/Monad/Trans/State/Strict/StateSpec.hs b/test/Parameterized/Control/Monad/Trans/State/Strict/StateSpec.hs -index 7dfd46c..4777c13 100644 ---- a/test/Parameterized/Control/Monad/Trans/State/Strict/StateSpec.hs -+++ b/test/Parameterized/Control/Monad/Trans/State/Strict/StateSpec.hs -@@ -26,7 +26,7 @@ main = hspec spec - manyIntMaybeState :: StateT (Many '[Int]) Maybe String - manyIntMaybeState= do - s <- get -- let r = fetch @Int s -+ let r = grab @Int s - case r of - 0 -> empty - r' -> do -@@ -36,7 +36,7 @@ manyIntMaybeState= do - manyBoolMaybeState :: StateT (Many '[Bool]) Maybe String - manyBoolMaybeState = do - s <- get -- let r = fetch @Bool s -+ let r = grab @Bool s - case r of - False -> empty - r' -> do diff --git a/nix/proto3-suite.nix b/nix/proto3-suite.nix index ce96ae4b..c2e5ff48 100644 --- a/nix/proto3-suite.nix +++ b/nix/proto3-suite.nix @@ -1,23 +1,18 @@ { mkDerivation, aeson, aeson-pretty, attoparsec, base , base64-bytestring, binary, bytestring, cereal, containers -, contravariant, deepseq, doctest, fetchgit, filepath, foldl -, generic-arbitrary, hashable, haskell-src +, contravariant, deepseq, doctest, filepath, foldl +, generic-arbitrary, hashable, haskell-src, hedgehog , insert-ordered-containers, lens, lib, mtl, neat-interpolation , optparse-applicative, optparse-generic, parsec, parsers, pretty , pretty-show, proto3-wire, QuickCheck, quickcheck-instances , range-set-list, safe, swagger2, system-filepath, tasty -, tasty-hunit, tasty-quickcheck, text, time, transformers, turtle -, vector +, tasty-hedgehog, tasty-hunit, tasty-quickcheck, text, time +, transformers, turtle, vector }: mkDerivation { pname = "proto3-suite"; - version = "0.4.3"; - src = fetchgit { - url = "https://github.com/awakesecurity/proto3-suite.git"; - sha256 = "0bjqczi6wddxv0n7qmfbrr19ajgq66xdkxx8vfcgbmv8ygma3vlw"; - rev = "7af7d76dcf9cc71ddada3aa4a38abf46f65550ca"; - fetchSubmodules = true; - }; + version = "0.5.0"; + sha256 = "sha256-lcm+En6esErjAvfycogkc7ixSXVpjdAz7dTJIIZPwCc="; isLibrary = true; isExecutable = true; enableSeparateDataOutput = true; @@ -35,9 +30,9 @@ mkDerivation { ]; testHaskellDepends = [ aeson attoparsec base base64-bytestring bytestring cereal - containers deepseq doctest generic-arbitrary mtl pretty-show - proto3-wire QuickCheck swagger2 tasty tasty-hunit tasty-quickcheck - text transformers turtle vector + containers deepseq doctest generic-arbitrary hedgehog mtl + pretty-show proto3-wire QuickCheck swagger2 tasty tasty-hedgehog + tasty-hunit tasty-quickcheck text transformers turtle vector ]; description = "A higher-level API to the proto3-wire library"; license = lib.licenses.asl20; diff --git a/nix/proto3-suite.patch b/nix/proto3-suite.patch new file mode 100644 index 00000000..a2f0f713 --- /dev/null +++ b/nix/proto3-suite.patch @@ -0,0 +1,13 @@ +diff --git a/proto3-suite.cabal b/proto3-suite.cabal +index 0898741..9959935 100644 +--- a/proto3-suite.cabal ++++ b/proto3-suite.cabal +@@ -48,7 +48,7 @@ library + if flag(swagger) + exposed-modules: Proto3.Suite.DotProto.Generate.Swagger + Proto3.Suite.DotProto.Generate.Swagger.Wrappers +- build-depends: swagger2 >=2.1.6 && <2.8 ++ build-depends: swagger2 >=2.1.6 && <3 + cpp-options: -DSWAGGER + if flag(swagger-wrapper-format) + hs-source-dirs: src/swagger-wrapper-format diff --git a/nix/proto3-wire.nix b/nix/proto3-wire.nix index 40179552..ab6c3a6b 100644 --- a/nix/proto3-wire.nix +++ b/nix/proto3-wire.nix @@ -6,7 +6,7 @@ mkDerivation { pname = "proto3-wire"; version = "1.2.2"; - sha256 = "8d409536a89a0187f0576711966d2ef45d43acab7b6a3a1c5ee12f6d01adbfb9"; + sha256 = "sha256-jUCVNqiaAYfwV2cRlm0u9F1DrKt7ajocXuEvbQGtv7k="; libraryHaskellDepends = [ base bytestring cereal containers deepseq ghc-prim hashable parameterized primitive QuickCheck safe text transformers diff --git a/nix/proto3-wire.patch b/nix/proto3-wire.patch new file mode 100644 index 00000000..7c88993d --- /dev/null +++ b/nix/proto3-wire.patch @@ -0,0 +1,13 @@ +diff --git a/proto3-wire.cabal b/proto3-wire.cabal +index 6db123a..9d7c958 100644 +--- a/proto3-wire.cabal ++++ b/proto3-wire.cabal +@@ -55,7 +55,7 @@ test-suite tests + build-depends: base >=4.9 && <=5.0, + bytestring >=0.10.6.0 && <0.11.0, + cereal >= 0.5.1 && <0.6, +- doctest >= 0.7.0 && <0.18, ++ doctest >= 0.7.0 && <0.19, + proto3-wire, + QuickCheck >=2.8 && <3.0, + tasty >= 0.11 && <1.5, diff --git a/nixpkgs.nix b/nixpkgs.nix index 1c22fafa..8993d8bb 100644 --- a/nixpkgs.nix +++ b/nixpkgs.nix @@ -1,12 +1,15 @@ # Given a Git revision hash ``, you get the new SHA256 by running: # -# ```bash -# $ nix-prefetch-url "https://github.com/NixOS/nixpkgs/archive/.tar.gz" +# ``` sh +# nix-prefetch-url --unpack 'https://github.com/NixOS/nixpkgs/archive/.tar.gz' # ``` # # The SHA256 will be printed as the last line of stdout. -import (builtins.fetchTarball { - url = "https://github.com/NixOS/nixpkgs/archive/dd9f73e7d34486b09b966738ace161e621a0480b.tar.gz"; - sha256 = "0s674386v5b24a9fia26439gw9wsyhif85k2nzpxkp61293v3n3h"; - }) +import (fetchTarball { + # Branch: release-22.05 + # Date: 2022-07-28 + # grpc.version: 1.46.3 + url = "https://github.com/NixOS/nixpkgs/archive/76e54678eb7fd4d9bfda9b13858a6a8df4501582.tar.gz"; + sha256 = "1zqjzdl9wy17v39nb7z7hsws4ydbqvjsm326x3cgh47m3d24kfhr"; +}) diff --git a/release.nix b/release.nix index 40df4637..8b12571e 100644 --- a/release.nix +++ b/release.nix @@ -1,7 +1,7 @@ # If you would like to test and build changes quickly using `cabal`, run: # # $ nix-shell -# [nix-shell]$ cabal configure --enable-tests && cabal test +# [nix-shell]$ cabal configure --enable-tests && cabal build && cabal test # # This will open up a Nix shell where all of your Haskell tools will work like # normal, except that all dependencies (including C libraries) are managed by @@ -30,7 +30,7 @@ # ... and then add this line below in the Haskell package overrides section: # # ${package-name} = -# haskellPackagesNew.callPackage ./nix/${package-name}.nix { }; +# hsPkgsSelf.callPackage ./nix/${package-name}.nix { }; # # ... replacing `${package-name}` with the name of the package that you would # like to upgrade and `${version}` with the version you want to upgrade to. @@ -41,7 +41,7 @@ # $ cabal2nix /${package-name}.git > ./nix/${package-name}.nix # # ...but also be sure to supply `fetchgit = pkgs.fetchgitPrivate` in the -# `haskellPackagesNew.callPackage` invocation for your private package. +# `hsPkgsSelf.callPackage` invocation for your private package. # # Note that `cabal2nix` also takes an optional `--revision` flag if you want to # pick a revision other than the latest to depend on. @@ -66,120 +66,130 @@ # };); let - overlay = pkgsNew: pkgsOld: { - - grpc = pkgsNew.callPackage ./nix/grpc.nix { }; - - haskellPackages = pkgsOld.haskellPackages.override { - overrides = haskellPackagesNew: haskellPackagesOld: rec { - parameterized = - pkgsNew.haskell.lib.overrideCabal - haskellPackagesOld.parameterized - (old: { - broken = false; - patches = (old.patches or [ ]) ++ [ ./nix/parameterized.patch ]; - }); - - haskell-src = - haskellPackagesNew.callHackage "haskell-src" "1.0.3.1" {}; - - proto3-wire = - haskellPackagesNew.callPackage ./nix/proto3-wire.nix { }; - - proto3-suite = - pkgsNew.haskell.lib.dontCheck - (haskellPackagesNew.callPackage ./nix/proto3-suite.nix {}); - - grpc-haskell-core = - pkgsNew.haskell.lib.buildFromSdist (pkgsNew.usesGRPC - (haskellPackagesNew.callCabal2nix "grpc-haskell-core" ./core { - gpr = pkgsNew.grpc; - } - ) - ); - - grpc-haskell-no-tests = - pkgsNew.haskell.lib.buildFromSdist (pkgsNew.usesGRPC - (pkgsNew.haskell.lib.dontCheck - (haskellPackagesNew.callCabal2nix "grpc-haskell" ./. { }) - )); - - grpc-haskell = - pkgsNew.usesGRPC - (pkgsNew.haskell.lib.overrideCabal - (pkgsNew.haskell.lib.buildFromSdist (haskellPackagesNew.callCabal2nix "grpc-haskell" ./. { })) - (oldDerivation: - let - ghc = - haskellPackagesNew.ghcWithPackages (pkgs: [ - pkgs.grpc-haskell-no-tests - # Include some additional packages in this custom ghc for - # running tests in the nix-shell environment. - pkgs.tasty-quickcheck - pkgs.turtle - ]); - - python = pkgsNew.python.withPackages (pkgs: [ - pkgs.grpcio-tools - ]); - - in { - configureFlags = (oldDerivation.configureFlags or []) ++ [ - "--flags=with-examples" - ]; - - buildDepends = (oldDerivation.buildDepends or [ ]) ++ [ - pkgsNew.makeWrapper - # Give our nix-shell its own cabal so we don't pick up one - # from the user's environment by accident. - haskellPackagesNew.cabal-install - - # And likewise for c2hs - haskellPackagesNew.c2hs - ]; - - patches = - (oldDerivation.patches or [ ]) ++ [ ./tests/tests.patch ]; - - postPatch = (oldDerivation.postPatch or "") + '' - patchShebangs tests - substituteInPlace tests/simple-client.sh \ - --replace @makeWrapper@ ${pkgsNew.makeWrapper} \ - --replace @grpc@ ${pkgsNew.grpc} - substituteInPlace tests/simple-server.sh \ - --replace @makeWrapper@ ${pkgsNew.makeWrapper} \ - --replace @grpc@ ${pkgsNew.grpc} - wrapProgram tests/protoc.sh \ - --prefix PATH : ${python}/bin - wrapProgram tests/test-client.sh \ - --prefix PATH : ${python}/bin - wrapProgram tests/test-server.sh \ - --prefix PATH : ${python}/bin - wrapProgram tests/simple-client.sh \ - --prefix PATH : ${ghc}/bin - wrapProgram tests/simple-server.sh \ - --prefix PATH : ${ghc}/bin - ''; - - shellHook = (oldDerivation.shellHook or "") + '' - # This lets us use our custom ghc and python environments in the shell. - export PATH=${ghc}/bin:${python}/bin''${PATH:+:}$PATH - ''; - }) - ); + # Taking specific Python version. + # + # N.B. Mind that some of the dependencies of gRPC Python packages + # (“grpcio-status” and “grpcio-tools”) do not support Python 2 anymore: + # “error: mox-0.7.8 not supported for interpreter python2.7”. + # So do not use “python” as a value since it defaults to Python 2. + pythonVer = "python3"; + overlay = pkgsSelf: pkgsSuper: { + # “grpc-haskell” is made for specific version of gRPC library. + # So this override makes sure it would still work against another nixpkgs + # pin where gRPC can have different version. + grpc = pkgsSelf.callPackage nix/grpc-pin/grpc.nix { + # grpc builds with c++14 so abseil must also be built that way + abseil-cpp = pkgsSelf.abseil-cpp_202111.override { + cxxStandard = "14"; }; }; + # As recommended for “grpc” derivation also overriding + # “grpcio-status” and “grpcio-tools” to the same version. + ${pythonVer} = pkgsSuper.${pythonVer}.override { + packageOverrides = pySelf: pySuper: { + grpcio-status = pySelf.callPackage nix/grpc-pin/grpcio-status.nix {}; + grpcio-tools = pySelf.callPackage nix/grpc-pin/grpcio-tools.nix {}; + }; + }; + + haskellPackages = (hsPkgsOverridden pkgsSuper).extend (hsSelf: hsSuper: { + + grpc-haskell-core = + pkgsSelf.lib.pipe ( + hsSelf.callCabal2nix "grpc-haskell-core" ./core { + gpr = pkgsSelf.grpc; + } + ) [ + pkgsSelf.usesGRPC + pkgsSelf.haskell.lib.buildFromSdist + ]; + + grpc-haskell-no-tests = + pkgsSelf.lib.pipe (hsSelf.callCabal2nix "grpc-haskell" ./. { }) [ + pkgsSelf.haskell.lib.dontCheck + pkgsSelf.usesGRPC + pkgsSelf.haskell.lib.buildFromSdist + ]; + + grpc-haskell = + let + ghc = + hsSelf.ghcWithPackages (pkgs: [ + pkgs.grpc-haskell-no-tests + # Include some additional packages in this custom ghc for + # running tests in the nix-shell environment. + pkgs.pipes + pkgs.tasty-hunit + pkgs.tasty-quickcheck + pkgs.turtle + ]); + + python = pkgsSelf.${pythonVer}.withPackages (pkgs: [ + pkgs.grpcio-tools + ]); + + override = old: { + configureFlags = (old.configureFlags or []) ++ [ + "--flags=with-examples" + ]; + + buildDepends = (old.buildDepends or [ ]) ++ [ + pkgsSelf.makeWrapper + + # Give our nix-shell its own cabal so we don't pick up one + # from the user's environment by accident. + hsSelf.cabal-install + + # And likewise for c2hs + hsSelf.c2hs + ]; + + patches = + (old.patches or [ ]) ++ [ ./tests/tests.patch ]; + + postPatch = (old.postPatch or "") + '' + patchShebangs tests + substituteInPlace tests/simple-client.sh \ + --replace @makeWrapper@ ${pkgsSelf.makeWrapper} \ + --replace @grpc@ ${pkgsSelf.grpc} + substituteInPlace tests/simple-server.sh \ + --replace @makeWrapper@ ${pkgsSelf.makeWrapper} \ + --replace @grpc@ ${pkgsSelf.grpc} + wrapProgram tests/protoc.sh \ + --prefix PATH : ${python}/bin + wrapProgram tests/test-client.sh \ + --prefix PATH : ${python}/bin + wrapProgram tests/test-server.sh \ + --prefix PATH : ${python}/bin + wrapProgram tests/simple-client.sh \ + --prefix PATH : ${ghc}/bin + wrapProgram tests/simple-server.sh \ + --prefix PATH : ${ghc}/bin + ''; + + shellHook = (old.shellHook or "") + '' + # This lets us use our custom ghc and python environments in the shell. + export PATH=${ghc}/bin:${python}/bin''${PATH:+:}$PATH + ''; + }; + in + pkgsSelf.lib.pipe (hsSelf.callCabal2nix "grpc-haskell" ./. { }) [ + pkgsSelf.haskell.lib.buildFromSdist + (pkgsSelf.haskell.lib.compose.overrideCabal override) + pkgsSelf.usesGRPC + ]; + + }); + test-grpc-haskell = - pkgsNew.mkShell { + pkgsSelf.mkShell { nativeBuildInputs = [ - (pkgsNew.haskellPackages.ghcWithPackages (pkgs: [ - pkgs.grpc-haskell - ] - ) - ) + (pkgsSelf.haskellPackages.ghcWithPackages (pkgs: [ + pkgs.grpc-haskell + ])) ]; }; @@ -188,27 +198,56 @@ let # grpc-haskell{-,core} code into `ghci` from within `nix-shell` # environments. # - # TODO: We might try using pkgsNew.fixDarwinDylibNames (see PR#129) + # TODO: We might try using pkgsSelf.fixDarwinDylibNames (see PR#129) # instead of setting DYLD_LIBRARY_PATH, but we might still need them # around for `ghci` as on Linux. - pkgsNew.haskell.lib.overrideCabal haskellPackage (oldAttributes: { - preBuild = (oldAttributes.preBuild or "") + - pkgsNew.lib.optionalString pkgsNew.stdenv.isDarwin '' - export DYLD_LIBRARY_PATH=${pkgsNew.grpc}/lib''${DYLD_LIBRARY_PATH:+:}$DYLD_LIBRARY_PATH - ''; + pkgsSelf.haskell.lib.overrideCabal haskellPackage (oldAttributes: { + preBuild = (oldAttributes.preBuild or "") + + pkgsSelf.lib.optionalString pkgsSelf.stdenv.isDarwin '' + export DYLD_LIBRARY_PATH=${pkgsSelf.grpc}/lib''${DYLD_LIBRARY_PATH:+:}$DYLD_LIBRARY_PATH + ''; - shellHook = (oldAttributes.shellHook or "") + - pkgsNew.lib.optionalString pkgsNew.stdenv.isDarwin '' - export DYLD_LIBRARY_PATH=${pkgsNew.grpc}/lib''${DYLD_LIBRARY_PATH:+:}$DYLD_LIBRARY_PATH - '' + - pkgsNew.lib.optionalString pkgsNew.stdenv.isLinux '' - export LD_LIBRARY_PATH=${pkgsNew.grpc}/lib''${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH - ''; - } - ); + shellHook = (oldAttributes.shellHook or "") + + pkgsSelf.lib.optionalString pkgsSelf.stdenv.isDarwin '' + export DYLD_LIBRARY_PATH=${pkgsSelf.grpc}/lib''${DYLD_LIBRARY_PATH:+:}$DYLD_LIBRARY_PATH + '' + + pkgsSelf.lib.optionalString pkgsSelf.stdenv.isLinux '' + export LD_LIBRARY_PATH=${pkgsSelf.grpc}/lib''${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH + ''; + }); }; + hsMarkUnbroken = pkgs: + pkgs.haskell.lib.compose.overrideCabal (old: { broken = false; }); + + # Overrides for Haskell packages this library depends on + hsPkgsOverridden = pkgs: + pkgs.haskellPackages.extend (self: super: { + data-diverse = + pkgs.lib.pipe (self.callPackage nix/data-diverse.nix {}) [ + # Patch for GHC 9.x support + (pkgs.haskell.lib.compose.appendPatch (pkgs.fetchpatch { + url = "https://github.com/louispan/data-diverse/commit/4033c90c44dab5824f76d64b7128bb6dea2b5dc7.patch"; + sha256 = "sha256-d6bC1Z7uCLtYF3FXGzo3XNdRPQgeAUjL1RW1Tiv7MnM="; + })) + + # The patch above makes it not to be broken anymore + (hsMarkUnbroken pkgs) + ]; + + proto3-wire = + pkgs.lib.pipe (self.callPackage nix/proto3-wire.nix {}) [ + (pkgs.haskell.lib.compose.appendPatch nix/proto3-wire.patch) + ]; + + proto3-suite = + pkgs.lib.pipe (self.callPackage nix/proto3-suite.nix {}) [ + (pkgs.haskell.lib.compose.appendPatch nix/proto3-suite.patch) + pkgs.haskell.lib.dontCheck # 4 out of 74 tests failed + ]; + }); + overlays = [ overlay ]; config = { }; @@ -218,6 +257,31 @@ let darwinPkgs = nixpkgs { inherit config overlays; system = "x86_64-darwin"; }; pkgs = nixpkgs { inherit config overlays; }; + shell = pkgs.haskellPackages.shellFor { + name = "gRPC-haskell-shell"; + withHoogle = true; + + packages = p: [ + p.grpc-haskell-core + p.grpc-haskell + ]; + + buildInputs = [ + pkgs.cabal-install + pkgs.grpc + ]; + }; + + # Stack build using Nix requires also “gmp” and “zlib” + stack-env = + pkgs.haskellPackages.grpc-haskell.env.overrideAttrs (old: { + propagatedBuildInputs = (old.propagatedBuildInputs or [ ]) ++ [ + pkgs.gmp + pkgs.zlib + pkgs.grpc + ]; + }); + in { grpc-haskell-core-linux = linuxPkgs.haskellPackages.grpc-haskell-core; @@ -234,6 +298,9 @@ in grpc = pkgs.grpc; - inherit pkgs config overlay; + inherit pkgs config overlay shell stack-env; inherit (pkgs) test-grpc-haskell; + + inherit hsPkgsOverridden; # Function :: nixpkgs -> new haskellPackages + inherit (hsPkgsOverridden (nixpkgs {})) data-diverse proto3-wire proto3-suite; } diff --git a/stack.yaml b/stack.yaml index 35110273..45ede7c6 100644 --- a/stack.yaml +++ b/stack.yaml @@ -2,7 +2,7 @@ # For more information, see: http://docs.haskellstack.org/en/stable/yaml_configuration/ # Specifies the GHC version and set of packages available (e.g., lts-3.5, nightly-2015-09-21, ghc-7.10.2) -resolver: lts-14.1 +resolver: lts-19.16 # Local packages, usually specified by relative directory name packages: @@ -18,10 +18,23 @@ extra-package-dbs: [] extra-deps: + - git: git@github.com:awakesecurity/proto3-suite.git - commit: 3f6dd6f612cf2eba3c05798926ff924b0d5ab4fa + # “v0.5.0” tag, as in nixpkgs pin + commit: 54662fa765afc4a581edc29e12ea3c5bf45da158 + - git: git@github.com:awakesecurity/proto3-wire.git - commit: 4f355bbac895d577d8a28f567ab4380f042ccc24 + # Trying to take “v1.2.2”, as in nixpkgs, but in this repo there’s only + # “1.4.0” tag. Found a commit with title “Version 1.2.1 → 1.2.2” assuming it’s + # the one I’m looking for. + commit: 25b378b8e663a9f5305a648b826200e88e5d11b8 + + +# Fix dependency bounds for “proto3-suite” and “proto3-wire”. +# It seems there is no way with Stack to apply a patch for a dependency +# as it’s done in Nix. +allow-newer: true + # Control whether we use the GHC we find on the path # @@ -58,4 +71,4 @@ nix: enable: false pure: false shell-file: release.nix - nix-shell-options: ["-A", "grpc-haskell.env"] + nix-shell-options: ["-A", "stack-env"] diff --git a/stack.yaml.lock b/stack.yaml.lock new file mode 100644 index 00000000..c55f4727 --- /dev/null +++ b/stack.yaml.lock @@ -0,0 +1,34 @@ +# This file was autogenerated by Stack. +# You should not edit this file by hand. +# For more information, please see the documentation at: +# https://docs.haskellstack.org/en/stable/lock_files + +packages: +- completed: + name: proto3-suite + pantry-tree: + sha256: 50149c07ce85634f4146456cb0268d2adf3e83d97c3230c188e8a19017673cda + size: 5538 + commit: 54662fa765afc4a581edc29e12ea3c5bf45da158 + git: git@github.com:awakesecurity/proto3-suite.git + version: 0.5.0 + original: + commit: 54662fa765afc4a581edc29e12ea3c5bf45da158 + git: git@github.com:awakesecurity/proto3-suite.git +- completed: + name: proto3-wire + pantry-tree: + sha256: 8cdd7b295da7e4270695b3c244177794ab99c65e3d8f23cef53104ab8e9dbb82 + size: 1260 + commit: 25b378b8e663a9f5305a648b826200e88e5d11b8 + git: git@github.com:awakesecurity/proto3-wire.git + version: 1.2.2 + original: + commit: 25b378b8e663a9f5305a648b826200e88e5d11b8 + git: git@github.com:awakesecurity/proto3-wire.git +snapshots: +- completed: + sha256: a27a5761890ade44d7dd21a5f5f93c87e60b9c063655fff835d69dd1071474f0 + size: 619163 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/16.yaml + original: lts-19.16