Skip to content

Commit

Permalink
add missing mainPackage attr in the config for the ghci runner
Browse files Browse the repository at this point in the history
  • Loading branch information
tek committed Sep 26, 2023
1 parent 3fd0396 commit 74fffdf
Show file tree
Hide file tree
Showing 16 changed files with 171 additions and 67 deletions.
6 changes: 6 additions & 0 deletions lib/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ let
else o
;

cabalDepPackage = dep:
if isAttrs dep
then dep.name
else dep;

in {
inherit
flake-utils
Expand Down Expand Up @@ -148,6 +153,7 @@ in {
empty
evalModules
overridesVia
cabalDepPackage
;

ghcOverlay = import ./ghc-overlay.nix;
Expand Down
1 change: 1 addition & 0 deletions lib/with-config.nix
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ let
# - restarts
# - cwd
ghci = {
mainPackage = config.main;
inherit packages;
setup = config.ghci.setup;
run = config.ghci.run;
Expand Down
56 changes: 46 additions & 10 deletions modules/basic.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,36 @@ let
cabalOptionsModule = import ./cabal-options.nix { inherit global util; };

baseFromPackages = let
pkg = head (attrValues config.internal.packagePaths);
paths = attrValues config.internal.packagePaths;
pkg = head paths;
next = p:
if p == "/"
then throw "Could not determine base dir: Invalid package path ${pkg}"
then throw "Could not determine project root dir: Invalid package path ${pkg}"
else if isStorePath p || pathExists "${p}/flake.nix"
then p
else next (dirOf p);
in
if length (attrNames config.internal.packagePaths) == 0
then throw "You have to specify either the 'base' option, pointing to the project root, or an entry in [](#opt-general-packages)."
if length paths == 0
then throw ''
Could not determine project root dir.
Either specify `base = ./.;` or add entries to `packages`.
See https://tryp.io/hix/index.html#packages for more.
''
else next pkg;

autoMain = let
ps = attrValues config.packages;

inDeps = target: thing: any (dep: util.cabalDepPackage dep == target) thing.dependencies;

hasDepOn = dep: pkg:
pkg.name != dep &&
any (inDeps dep) (attrValues pkg.internal.componentsSet);

isNoDep = pkg: ! (any (hasDepOn pkg.name) ps);

in findFirst isNoDep null (attrValues config.packages);

in {
options = {

Expand All @@ -40,7 +58,6 @@ in {
description = mdDoc ''
The project's Cabal packages, with Cabal package names as keys and package config as values.
The config is processed with [HPack](https://github.com/sol/hpack).
Consult the docs for the package options to learn how this is translated.
'';
example = literalExpression ''
{
Expand All @@ -57,6 +74,8 @@ in {
The name of a key in `packages` that is considered to be the main package.
This package will be assigned to the `defaultPackage` flake output that is built by a plain
`nix build`.
If this option is undefined, Hix will choose one of the packages that are not in the dependencies of any other
package.
'';
type = str;
};
Expand Down Expand Up @@ -250,12 +269,29 @@ in {
config = {
base = mkDefault baseFromPackages;

main = mkDefault (
if (length config.internal.packageNames == 1)
then head config.internal.packageNames
main = mkDefault (let
names = config.internal.packageNames;
count = length names;
in
if count == 1
then head names
else if count == 0
then ''
This action requires at least one package to be defined, as in:
{
packages.my-project = { src = ./.; };
}
''
else if autoMain != null
then autoMain.name
else throw ''
The config option 'main' must name one of the 'packages' if more than one is defined.
See https://tryp.io/hix/index.html#opt-general-main
Could not determine the main package.
This should only happen if all packages depend on each other cyclically.
If that is not the case, please report a bug at: https://github.com/tek/hix/issues
You can specify the main package explicitly:
{
main = "my-package";
}
''
);

Expand Down
30 changes: 20 additions & 10 deletions modules/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ let

anyEnabled = set: any (a: a.enable) (attrValues set);

# excludes `pkgConfig.executable` because it's used to determine whether the default executable should be enabled.
hasComponents =
pkgConfig.library.enable || anyEnabled pkgConfig.executables ||
pkgConfig.library.enable || anyEnabled pkgConfig.libraries ||
anyEnabled pkgConfig.executables ||
pkgConfig.test.enable || anyEnabled pkgConfig.tests ||
pkgConfig.benchmark.enable || anyEnabled pkgConfig.benchmarks;

Expand Down Expand Up @@ -73,13 +75,13 @@ let

};

config = optionalAttrs default {
enable = mkDefault (!hasComponents);
} // {
dependencies = optional (config.dependOnLibrary && pkgConfig.library.enable) pkgName;

ghc-options = mkIf (sort != "benchmark") config.ghc-options-exe;
};
config =
optionalAttrs default { enable = mkDefault (!hasComponents); }
//
{
dependencies = optional (config.dependOnLibrary && pkgConfig.library.enable) pkgName;
ghc-options = mkIf (sort != "benchmark") config.ghc-options-exe;
};

};

Expand Down Expand Up @@ -115,9 +117,10 @@ in {
options = with types; {

name = mkOption {
description = mdDoc "The name of the package, defaulting to the attribute name in the config.";
description = mdDoc "The name of the package, determined by the attribute name in the config.";
type = str;
default = name;
readOnly = true;
};

src = mkOption {
Expand All @@ -135,7 +138,13 @@ in {
};

libraries = mkOption {
description = mdDoc "";
description = mdDoc ''
The sublibraries of this package.
Unlike [](#opt-package-library), these are treated specially by cabal.
To depend on them, use `<pkg>:<lib>`.
If [](#opt-package-libraries._name_.public) is set to `false`, you can only depend on them from other components
in the same package (this is then called an internal library – default is `true`).
'';
type = attrsOf (libSubmodule false);
default = {};
};
Expand Down Expand Up @@ -352,6 +361,7 @@ in {

internal.componentsSet =
optionalAttrs config.library.enable { library = config.library; } //
config.libraries //
optionalAttrs config.executable.enable { ${config.executable.name} = config.executable; } //
config.executables //
optionalAttrs config.test.enable { ${config.test.name} = config.test; } //
Expand Down
3 changes: 2 additions & 1 deletion test/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ let
basic = test "basic";
deps = test "deps";
ghci = test "ghci";
ghci-vm = test "ghci-vm";
packages = test "packages";
hackage = test "hackage";
cross = test "cross";
Expand All @@ -28,7 +29,7 @@ let

testsA = concatStringsSep " " (mapAttrsToList testA tests);

ciSkipTests = "ghci service postgres hackage";
ciSkipTests = "ghci-vm service postgres hackage";

in {
main = pkgs.writeScript "hix-tests" ''
Expand Down
1 change: 1 addition & 0 deletions test/ghci-vm/root/cabal.project
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
packages: .
26 changes: 26 additions & 0 deletions test/ghci-vm/root/flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
description = "hix test project";

inputs.hix.url = "path:HIX";

outputs = { hix, ... }: hix.lib.flake ({config, ...}: {
packages.root = {
src = ./pkg;
library.enable = true;
library.dependencies = ["http-client" "bytestring" "path" "path-io"];
library.default-extensions = ["OverloadedStrings"];
executable.enable = true;
test.enable = true;
test.env = "hix-ghci-test";
};
envs.hix-ghci-test.services.test.enable = true;
services.test = {
nixos.services.nginx = {
enable = true;
virtualHosts.localhost.locations."/test".return = "200 test-endpoint";
};
ports.nginx = { host = 2; guest = 80; };
};
internal.hixCli.dev = true;
});
}
7 changes: 7 additions & 0 deletions test/ghci-vm/root/pkg/app/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Main where

import Root.Lib (string)

main :: IO ()
main =
putStrLn string
25 changes: 25 additions & 0 deletions test/ghci-vm/root/pkg/lib/Root/Lib.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module Root.Lib where

import Control.Exception
import Control.Concurrent
import qualified Data.ByteString.Lazy.Char8 as ByteString
import Network.HTTP.Client

tryRequest :: Manager -> IO (Response ByteString.ByteString)
tryRequest man =
spin 10
where
spin 0 = req
spin n = catch req (err n)
err :: Int -> SomeException -> IO (Response ByteString.ByteString)
err n _ = do
threadDelay 1000000
spin (n - 1)
req =
httpLbs "http://localhost:20002/test" man

test :: IO ()
test = do
man <- newManager defaultManagerSettings
res <- tryRequest man
ByteString.putStrLn (responseBody res)
6 changes: 6 additions & 0 deletions test/ghci-vm/root/pkg/test/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Main where

import Root.Lib (test)

main :: IO ()
main = test
12 changes: 12 additions & 0 deletions test/ghci-vm/test.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{ pkgs }:
{
test = builtins.toFile "ghci-vm-test" ''
cd ./root
nix flake update
nix run .#gen-cabal
ghci_match '.#ghci -- -p root -t main' 'test-endpoint' "ghci service output with component env does not contain 'test-endpoint'"
ghci_match '.#env.hix-ghci-test.ghci -- -t main' 'test-endpoint' "ghci service output with explicit env does not contain 'test-endpoint'"
'';
}
4 changes: 4 additions & 0 deletions test/ghci/root/core/lib/Root/Lib.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Root.Lib where

test :: IO ()
test = putStrLn "core-lib-test"
29 changes: 13 additions & 16 deletions test/ghci/root/flake.nix
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
{
description = "hix test project";

inputs.hix.url = path:HIX;
inputs.hix.url = "path:HIX";

outputs = { hix, ... }: hix.lib.flake ({config, ...}: {
packages.root = {
src = ./pkg;
library.enable = true;
library.dependencies = ["http-client" "bytestring" "path" "path-io"];
library.default-extensions = ["OverloadedStrings"];
executable.enable = true;
test.enable = true;
test.env = "hix-ghci-test";
};
envs.hix-ghci-test.services.test.enable = true;
services.test = {
nixos.services.nginx = {
enable = true;
virtualHosts.localhost.locations."/test".return = "200 test-endpoint";
packages = {
core = {
src = ./core;
library.enable = true;
};
root = {
src = ./pkg;
library.enable = true;
executable.enable = true;
test.enable = true;
library.dependencies = ["path" "path-io" "core"];
# library.default-extensions = ["OverloadedStrings"];
};
ports.nginx = { host = 2; guest = 80; };
};
ghci.run.print = ''putStrLn "print success"'';
ghci.run.cwd = ''putStrLn . toFilePath =<< getCurrentDir'';
Expand Down
5 changes: 1 addition & 4 deletions test/ghci/root/pkg/app/Main.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
module Main where

import Root.Lib (string)

main :: IO ()
main =
putStrLn string
main = putStrLn "app-main"
23 changes: 1 addition & 22 deletions test/ghci/root/pkg/lib/Root/Lib.hs
Original file line number Diff line number Diff line change
@@ -1,25 +1,4 @@
module Root.Lib where

import Control.Exception
import Control.Concurrent
import qualified Data.ByteString.Lazy.Char8 as ByteString
import Network.HTTP.Client

tryRequest :: Manager -> IO (Response ByteString.ByteString)
tryRequest man =
spin 10
where
spin 0 = req
spin n = catch req (err n)
err :: Int -> SomeException -> IO (Response ByteString.ByteString)
err n _ = do
threadDelay 1000000
spin (n - 1)
req =
httpLbs "http://localhost:20002/test" man

test :: IO ()
test = do
man <- newManager defaultManagerSettings
res <- tryRequest man
ByteString.putStrLn (responseBody res)
test = putStrLn "lib-test"
4 changes: 0 additions & 4 deletions test/ghci/test.nix
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@
ghci_match '.#ghci -- -p root -c lib -m Root.Lib -r print' 'print success' "ghci output for 'print' runner does not contain 'print success'"
ghci_match '.#ghci -- -p root -t main' 'test-endpoint' "ghci service output with component env does not contain 'test-endpoint'"
ghci_match '.#env.hix-ghci-test.ghci -- -t main' 'test-endpoint' "ghci service output with explicit env does not contain 'test-endpoint'"
ghci_match '.#ghci-app' 'print success' "ghci-app did not output 'print success'"
'';
}

0 comments on commit 74fffdf

Please sign in to comment.