Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions nix-tools/cabal.project
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
index-state: 2025-04-12T00:00:00Z
with-compiler: ghc-9.6

-- Needed for building aarch64-linux musl version with GHC 9.6
constraints: containers installed, Cabal >=3.14.1.0
Expand Down
196 changes: 151 additions & 45 deletions nix-tools/nix-tools/make-install-plan/ProjectPlanOutput.hs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
{-# HLINT ignore "Eta reduce" #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}

Expand All @@ -11,50 +8,52 @@ module ProjectPlanOutput (
writePlanExternalRepresentation,
) where

import Distribution.Client.DistDirLayout
import Distribution.Client.HashValue (hashValue, showHashValue)
import Distribution.Client.ProjectPlanning.Types
import Distribution.Client.Types.ConfiguredId (confInstId)
import Distribution.Client.Types.PackageLocation (PackageLocation (..))
import Distribution.Client.Types.Repo (RemoteRepo (..), Repo (..))
import Distribution.Client.Types.SourceRepo (SourceRepoMaybe, SourceRepositoryPackage (..))
import Distribution.Client.Version (cabalInstallVersion)

import qualified Distribution.Client.InstallPlan as InstallPlan
import qualified Distribution.Client.Utils.Json as J
import qualified Distribution.Simple.InstallDirs as InstallDirs
import qualified Data.ByteString.Builder as BB
import qualified Data.Map as Map

import qualified Distribution.Solver.Types.ComponentDeps as ComponentDeps
import System.FilePath

import Distribution.System
import Distribution.InstalledPackageInfo (InstalledPackageInfo)
import Distribution.Package
import qualified Distribution.PackageDescription as PD
import Distribution.Types.ComponentName
import Distribution.Types.Version (mkVersion)
import Distribution.Utils.Path (makeSymbolicPath, getSymbolicPath)
import qualified Distribution.Types.ParStrat as ParStrat
import qualified Distribution.Verbosity as Verbosity

import qualified Distribution.Simple.InstallDirs as InstallDirs
import Distribution.Simple.BuildPaths (
buildInfoPref,
dllExtension,
exeExtension,
)
import Distribution.Simple.Compiler (
showCompilerId,
)
import Distribution.Simple.Compiler (showCompilerId)
import Distribution.Simple.Utils
import Distribution.System
import Distribution.Types.ComponentName
import Distribution.Types.Version (
mkVersion,
)
import Distribution.Simple.Command (CommandUI(..), commandShowOptions)
import qualified Distribution.Simple.Setup as Cabal
import Distribution.Simple.Program.Db (defaultProgramDb)

import Distribution.Client.BuildReports.Types (ReportLevel(..))
import Distribution.Client.DistDirLayout
import Distribution.Client.HashValue (hashValue, showHashValue)
import Distribution.Client.ProjectOrchestration (BuildTimeSettings(..))
import Distribution.Client.ProjectPlanning
import Distribution.Client.ProjectPlanning.Types
import Distribution.Client.Types.ConfiguredId (confInstId)
import Distribution.Client.Types.PackageLocation (PackageLocation (..))
import Distribution.Client.Types.ReadyPackage (GenericReadyPackage(..))
import Distribution.Client.Types.Repo (RemoteRepo (..), Repo (..))
import Distribution.Client.Types.SourceRepo (SourceRepoMaybe, SourceRepositoryPackage (..))
import Distribution.Client.Version (cabalInstallVersion)
import qualified Distribution.Client.InstallPlan as InstallPlan
import qualified Distribution.Client.Utils.Json as J
import qualified Distribution.Solver.Types.ComponentDeps as ComponentDeps

import Distribution.Client.Compat.Prelude
import Prelude ()

import qualified Data.ByteString.Builder as BB
import qualified Data.Map as Map

import System.FilePath

import Distribution.Client.ProjectPlanning
import Distribution.Utils.Path (makeSymbolicPath, getSymbolicPath)

-----------------------------------------------------------------------------
-- Writing plan.json files
--
Expand Down Expand Up @@ -118,11 +117,11 @@ encodePlanAsJson distDirLayout elaboratedInstallPlan elaboratedSharedConfig targ
[ "pkg-name" J..= jdisplay (pkgName pkgId)
, "pkg-version" J..= jdisplay (pkgVersion pkgId)
, "component-name" J..= jdisplay componentName
, "available" J..= map avaialbeTargetToJ ts
, "available" J..= map availableTargetToJ ts
]

avaialbeTargetToJ :: AvailableTarget (UnitId, ComponentName) -> J.Value
avaialbeTargetToJ target =
availableTargetToJ :: AvailableTarget (UnitId, ComponentName) -> J.Value
availableTargetToJ target =
case availableTargetStatus target of
TargetDisabledByUser -> J.String "TargetDisabledByUser"
TargetDisabledBySolver -> J.String "TargetDisabledBySolver"
Expand Down Expand Up @@ -189,7 +188,7 @@ encodePlanAsJson distDirLayout elaboratedInstallPlan elaboratedSharedConfig targ
]
++ ( case elabBuildStyle elab of
BuildInplaceOnly _ ->
["dist-dir" J..= J.String dist_dir] ++ [buildInfoFileLocation]
["dist-dir" J..= J.String dist_dir, buildInfoFileLocation]
BuildAndInstall ->
-- TODO: install dirs?
[]
Expand All @@ -199,12 +198,10 @@ encodePlanAsJson distDirLayout elaboratedInstallPlan elaboratedSharedConfig targ
let components =
J.object
$ [ comp2str c
J..= ( J.object
$ [ "depends" J..= map (jdisplay . confInstId) (map fst ldeps)
J..= J.object (
[ "depends" J..= map ((jdisplay . confInstId) . fst) ldeps
, "exe-depends" J..= map (jdisplay . confInstId) edeps
]
++ bin_file c
)
] ++ bin_file c)
| (c, (ldeps, edeps)) <-
ComponentDeps.toList
$ ComponentDeps.zip
Expand All @@ -213,12 +210,117 @@ encodePlanAsJson distDirLayout elaboratedInstallPlan elaboratedSharedConfig targ
]
in ["components" J..= components]
ElabComponent comp ->
[ "depends" J..= map (jdisplay . confInstId) (map fst $ elabLibDependencies elab)
[ "depends" J..= map ((jdisplay . confInstId) . fst) (elabLibDependencies elab)
, "exe-depends" J..= map jdisplay (elabExeDependencies elab)
, "component-name" J..= J.String (comp2str (compSolverName comp))
]
++ bin_file (compSolverName comp)
++ [
"configure-args" J..= j_string_list (renderFlags (Cabal.configureCommand defaultProgramDb) configFlags configArgs),
"build-args" J..= j_string_list (renderFlags (Cabal.buildCommand defaultProgramDb) buildFlags buildArgs),
"copy-args" J..= j_string_list (renderFlags Cabal.copyCommand copyFlags copyArgs),
"haddock-args" J..= j_string_list (renderFlags Cabal.haddockCommand haddockFlags haddockArgs),
"test-args" J..= j_string_list (renderFlags Cabal.testCommand testFlags testArgs),
"benchmark-args" J..= j_string_list (renderFlags Cabal.benchmarkCommand benchFlags benchArgs),
"repl-args" J..= j_string_list (renderFlags (Cabal.replCommand defaultProgramDb) replFlags replArgs)
]
where
j_string_list = J.Array . map J.String

-- The setupHs* functions are defined in Distribution.Client.ProjectPlanning
-- and are intended to be opaque to the plan execution layer. We make a concession
-- in copyFlags since it's trivial and we need to adapt it to be agnostic to the
-- build directory

-- NOTE: We should filter these flags since the Setup.hs we are going
-- to invoke might not support all features that this version of cabal-install
-- supports.

commonFlags :: Cabal.CommonSetupFlags
commonFlags = mempty

configArgs = setupHsConfigureArgs elab
configFlags =
runIdentity $
setupHsConfigureFlags
(fmap makeSymbolicPath . Identity)
elaboratedInstallPlan
(ReadyPackage elab)
elaboratedSharedConfig
commonFlags

buildArgs = setupHsBuildArgs elab
buildFlags =
setupHsBuildFlags
Cabal.NoFlag
elab
elaboratedSharedConfig
commonFlags

-- Simplified version
copyArgs = setupHsBuildArgs elab
copyFlags =
Cabal.CopyFlags
{ copyCommonFlags = commonFlags
, copyDest = Cabal.NoFlag
}

testArgs = setupHsTestArgs elab
testFlags =
setupHsTestFlags
elab
commonFlags

benchArgs = setupHsBenchArgs elab
benchFlags =
setupHsBenchFlags
elab
elaboratedSharedConfig
commonFlags

replArgs = setupHsReplArgs elab
replFlags =
setupHsReplFlags
elab
elaboratedSharedConfig
commonFlags

haddockArgs = setupHsHaddockArgs elab
haddockFlags =
setupHsHaddockFlags
elab
elaboratedSharedConfig
buildTimeSettings
commonFlags

-- NOTE: this is only used in setupHsHaddockFlags (for
-- buildSettingHaddockOpen),and it is not used during planning. I filled it
-- with reasonable defaults but it's mostly going to be ignored.
buildTimeSettings = BuildTimeSettings {
buildSettingDryRun = False,
buildSettingOnlyDeps = False,
buildSettingOnlyDownload = False,
buildSettingSummaryFile = mempty,
buildSettingLogFile = Nothing,
buildSettingLogVerbosity = Verbosity.normal,
buildSettingBuildReports = NoReports,
buildSettingSymlinkBinDir = [],
buildSettingNumJobs = ParStrat.Serial,
buildSettingKeepGoing = False,
buildSettingOfflineMode = False,
buildSettingKeepTempFiles = False,
buildSettingRemoteRepos = [],
buildSettingLocalNoIndexRepos = [],
-- non-empty string for troubleshooting
buildSettingCacheDir = "<cache-dir>",
buildSettingHttpTransport = Nothing,
buildSettingIgnoreExpiry = False,
buildSettingReportPlanningFailure = False,
buildSettingProgPathExtra = [],
buildSettingHaddockOpen = False
}


-- \| Only add build-info file location if the Setup.hs CLI
-- is recent enough to be able to generate build info files.
-- Otherwise, write 'null'.
Expand Down Expand Up @@ -285,7 +387,7 @@ encodePlanAsJson distDirLayout elaboratedInstallPlan elaboratedSharedConfig targ
sourceRepoToJ SourceRepositoryPackage{..} =
J.object
$ filter ((/= J.Null) . snd)
$ [ "type" J..= jdisplay srpType
[ "type" J..= jdisplay srpType
, "location" J..= J.String srpLocation
, "branch" J..= fmap J.String srpBranch
, "tag" J..= fmap J.String srpTag
Expand Down Expand Up @@ -333,3 +435,7 @@ style2str False BuildAndInstall = "global"

jdisplay :: (Pretty a) => a -> J.Value
jdisplay = J.String . prettyShow

renderFlags :: CommandUI flags -> flags -> [String] -> [String]
renderFlags cmd flags extraArgs =
commandName cmd : commandShowOptions cmd flags ++ extraArgs
3 changes: 2 additions & 1 deletion nix-tools/overlay.nix
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ let
configureArgs = final.lib.mkDefault "--disable-tests";

# Tools to include in the development shell
shell.tools.cabal = "latest";
shell.tools.cabal = {};
shell.tools.haskell-language-server = {};
}
args
];
Expand Down
Loading