Skip to content

Commit

Permalink
Try #427:
Browse files Browse the repository at this point in the history
  • Loading branch information
iohk-bors[bot] committed Mar 19, 2021
2 parents 4245567 + 8d3cd2e commit 94cec97
Show file tree
Hide file tree
Showing 11 changed files with 298 additions and 95 deletions.
62 changes: 51 additions & 11 deletions builder/comp-builder.nix
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ let self =
, preInstall ? component.preInstall , postInstall ? component.postInstall
, preHaddock ? component.preHaddock , postHaddock ? component.postHaddock
, shellHook ? ""
, configureAllComponents ? component.configureAllComponents ||
# When set, configure all the components in the package
# (not just the one we are building).
# Enable for tests in packages that use cabal-doctest.
( haskellLib.isTest componentId &&
lib.any (x: x.identifier.name or "" == "cabal-doctest") package.setup-depends
)
, allComponent # Used when `configureAllComponents` is set to get a suitable configuration.

, build-tools ? component.build-tools
, pkgconfig ? component.pkgconfig
Expand All @@ -47,7 +55,7 @@ let self =
, doHoogle ? component.doHoogle # Also build a hoogle index
, hyperlinkSource ? component.doHyperlinkSource # Link documentation to the source code
, quickjump ? component.doQuickjump # Generate an index for interactive documentation navigation
, keepSource ? component.keepSource # Build from `source` output in the store then delete `dist`
, keepSource ? component.keepSource || configureAllComponents # Build from `source` output in the store then delete `dist`
, setupHaddockFlags ? component.setupHaddockFlags

# Profiling
Expand Down Expand Up @@ -77,6 +85,11 @@ let self =
}@drvArgs:

let
componentForSetup =
if configureAllComponents
then allComponent
else component;

# Ignore attempts to include DWARF info when it is not possible
enableDWARF = drvArgs.enableDWARF or false
&& stdenv.hostPlatform.isLinux
Expand All @@ -96,7 +109,7 @@ let
# is the sub directory in that root path that contains the package.
# `cleanSrc.subDir` is used in `prePatch` and `lib/cover.nix`.
cleanSrc = haskellLib.rootAndSubDir (if canCleanSource
then haskellLib.cleanCabalComponent package component "${componentId.ctype}-${componentId.cname}" src
then haskellLib.cleanCabalComponent package componentForSetup "${componentId.ctype}-${componentId.cname}" src
else
# We can clean out the siblings though to at least avoid changes to other packages
# from triggering a rebuild of this one.
Expand All @@ -118,8 +131,9 @@ let
needsProfiling = enableExecutableProfiling || enableLibraryProfiling;

configFiles = makeConfigFiles {
component = componentForSetup;
inherit (package) identifier;
inherit component fullName flags needsProfiling enableDWARF;
inherit fullName flags needsProfiling enableDWARF;
};

enableFeature = enable: feature:
Expand All @@ -129,8 +143,13 @@ let

finalConfigureFlags = lib.concatStringsSep " " (
[ "--prefix=$out"
"${haskellLib.componentTarget componentId}"
"$(cat ${configFiles}/configure-flags)"
] ++ (
# If configureAllComponents is set we should not specify the component
# and Setup will attempt to configure them all.
if configureAllComponents
then ["--enable-tests" "--enable-benchmarks"]
else ["${haskellLib.componentTarget componentId}"]
) ++ [ "$(cat ${configFiles}/configure-flags)"
] ++ commonConfigureFlags);

# From nixpkgs 20.09, the pkg-config exe has a prefix matching the ghc one
Expand Down Expand Up @@ -328,7 +347,7 @@ let
++ (lib.optional enableSeparateDataOutput "data")
++ (lib.optional keepSource "source");

configurePhase =
prePatch =
# emcc is very slow if it cannot cache stuff in $HOME
(lib.optionalString (stdenv.hostPlatform.isGhcjs) ''
export HOME=$(mktemp -d)
Expand All @@ -340,7 +359,9 @@ let
cp -r . $source
cd $source
chmod -R +w .
'') + ''
'') + commonAttrs.prePatch;

configurePhase = ''
runHook preConfigure
echo Configure flags:
printf "%q " ${finalConfigureFlags}
Expand Down Expand Up @@ -368,7 +389,11 @@ let
target-pkg-and-db = "${ghc.targetPrefix}ghc-pkg -v0 --package-db $out/package.conf.d";
in ''
runHook preInstall
$SETUP_HS copy ${lib.concatStringsSep " " setupInstallFlags}
$SETUP_HS copy ${lib.concatStringsSep " " (
setupInstallFlags
++ lib.optional configureAllComponents
(haskellLib.componentTarget componentId)
)}
${lib.optionalString (haskellLib.isLibrary componentId) ''
$SETUP_HS register --gen-pkg-config=${name}.conf
${ghc.targetPrefix}ghc-pkg -v0 init $out/package.conf.d
Expand Down Expand Up @@ -455,9 +480,24 @@ let
'')
}
runHook postInstall
'' + (lib.optionalString keepSource ''
rm -rf dist
'') + (lib.optionalString (haskellLib.isTest componentId) ''
'' + (
# Keep just the autogen files and package.conf.inplace package
# DB (probably empty unless this is a library component).
# We also have to remove any refernces to $out to avoid
# circular references.
if configureAllComponents
then ''
mv dist dist-tmp-dir
mkdir -p dist/build
mv dist-tmp-dir/build/${componentId.cname}/autogen dist/build/
mv dist-tmp-dir/package.conf.inplace dist/
remove-references-to -t $out dist/build/autogen/*
rm -rf dist-tmp-dir
''
else lib.optionalString keepSource ''
rm -rf dist
''
) + (lib.optionalString (haskellLib.isTest componentId) ''
echo The test ${package.identifier.name}.components.tests.${componentId.cname} was built. To run the test build ${package.identifier.name}.checks.${componentId.cname}.
'');

Expand Down
6 changes: 3 additions & 3 deletions builder/hspkg-builder.nix
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,14 @@ let
inherit (pkg) preUnpack postUnpack;
};

buildComp = componentId: component: comp-builder {
inherit componentId component package name src flags setup cabalFile cabal-generator patches revision
buildComp = allComponent: componentId: component: comp-builder {
inherit allComponent componentId component package name src flags setup cabalFile cabal-generator patches revision
shellHook
;
};

in rec {
components = haskellLib.applyComponents buildComp pkg;
components = haskellLib.applyComponents (buildComp pkg.allComponent) pkg;
checks = pkgs.recurseIntoAttrs (builtins.mapAttrs
(_: d: haskellLib.check d)
(lib.filterAttrs (_: d: d.config.doCheck) components.tests));
Expand Down
2 changes: 1 addition & 1 deletion lib/check.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ let
in stdenv.mkDerivation ({
name = (drv.name + "-check");

# Useing `srcOnly` (rather than getting the `src` via a `drv.passthru`)
# Using `srcOnly` (rather than getting the `src` via a `drv.passthru`)
# should correctly apply the patches from `drv` (if any).
src = drv.source or (srcOnly drv);

Expand Down
199 changes: 119 additions & 80 deletions modules/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,86 @@ with types;

# Work around issue that can cause _lots_ of files to be copied into the store.
# See https://github.com/NixOS/nixpkgs/pull/64691
let path = types.path // { check = x: types.path.check (x.origSrc or x); };
let
path = types.path // { check = x: types.path.check (x.origSrc or x); };

componentType = submodule {
# add the shared componentOptions
options = (packageOptions config) // {
buildable = mkOption {
type = bool;
default = true;
};
depends = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
libs = mkOption {
type = listOfFilteringNulls (nullOr package);
default = [];
};
frameworks = mkOption {
type = listOfFilteringNulls package;
default = [];
};
pkgconfig = mkOption {
type = listOf (listOfFilteringNulls package);
default = [];
};
build-tools = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
modules = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
asmSources = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
cmmSources = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
cSources = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
cxxSources = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
jsSources = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
hsSourceDirs = mkOption {
type = listOfFilteringNulls unspecified;
default = ["."];
};
includeDirs = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
includes = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
mainPath = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
extraSrcFiles = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
platforms = mkOption {
type = nullOr (listOfFilteringNulls unspecified);
default = null;
};
};
};

in {
# This is how the Nix expressions generated by *-to-nix receive
Expand Down Expand Up @@ -138,85 +217,7 @@ in {
};
};

components = let
componentType = submodule {
# add the shared componentOptions
options = (packageOptions config) // {
buildable = mkOption {
type = bool;
default = true;
};
depends = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
libs = mkOption {
type = listOfFilteringNulls (nullOr package);
default = [];
};
frameworks = mkOption {
type = listOfFilteringNulls package;
default = [];
};
pkgconfig = mkOption {
type = listOf (listOfFilteringNulls package);
default = [];
};
build-tools = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
modules = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
asmSources = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
cmmSources = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
cSources = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
cxxSources = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
jsSources = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
hsSourceDirs = mkOption {
type = listOfFilteringNulls unspecified;
default = ["."];
};
includeDirs = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
includes = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
mainPath = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
extraSrcFiles = mkOption {
type = listOfFilteringNulls unspecified;
default = [];
};
platforms = mkOption {
type = nullOr (listOfFilteringNulls unspecified);
default = null;
};
};
};
in {
components = {
setup = mkOption {
type = nullOr componentType;
default = {
Expand Down Expand Up @@ -295,5 +296,43 @@ in {
type = listOf (either unspecified path);
default = [];
};
# This used to be `components.all` but it has been added back as `allComponent` to
# to avoid confusion. It is not mapped by `builder/hspkg-builder.nix` to anything
# you can build. Instead it is used internally when `configureAllComponents`
# is set or for tests whe on `cabal-doctest` is in the `setup-depends` of the package.
allComponent = mkOption {
type = componentType;
apply = all: all // {
# TODO: Should this check for the entire component
# definition to match, rather than just the identifier?
depends = builtins.filter (p: p.identifier != config.package.identifier) all.depends;
};
description = "The merged dependencies of all other components";
};
};

# This has one quirk. Manually setting options on the all component
# will be considered a conflict. This is almost always fine; most
# settings should be modified in either the package options, or an
# individual component's options. When this isn't sufficient,
# mkForce is a reasonable workaround.
#
# An alternative solution to mkForce for many of the options where
# this is relevant would be to switch from the bool type to
# something like an anyBool type, which would merge definitions by
# returning true if any is true.
config.allComponent =
let allComps = haskellLib.getAllComponents config;
in lib.mkMerge (
builtins.map (c:
# Exclude attributes that are likely to have conflicting definitions
# (a common use case for `all` is in `shellFor` and it only has an
# install phase).
builtins.removeAttrs c ["preCheck" "postCheck" "keepSource"]
) allComps
) // {
# If any one of the components needs us to keep the source
# then keep it for the `all` component
keepSource = lib.foldl' (x: comp: x || comp.keepSource) false allComps;
};
}
5 changes: 5 additions & 0 deletions modules/plan.nix
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ let
type = bool;
default = (def.enableShared or true);
};
configureAllComponents = mkOption {
description = "If set all the components in the package are configured (useful for cabal-doctest).";
type = bool;
default = false;
};
shellHook = mkOption {
description = "Hook to run when entering a shell";
type = unspecified; # Can be either a string or a function
Expand Down
6 changes: 6 additions & 0 deletions test/cabal-doctests/Setup.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Main where

import Distribution.Extra.Doctest (defaultMainWithDoctests)

main :: IO ()
main = defaultMainWithDoctests "doctests"

0 comments on commit 94cec97

Please sign in to comment.