cabal-buck2-0.1.0.0: src/Distribution/Client/CmdBuck2.hs
-- | cabal-install CLI command: buck2
--
-- Sets up (or refreshes) a buck2 build for the current project, using the
-- prelude and support scripts checked out at @buck2\/@ (a checkout of
-- <https://github.com/simonmar/haskell-buck2>, see @buck2\/README.md@).
--
-- There are 6 main pieces to this, each with a small API:
--
-- 1. "Distribution.Client.Buck2.BuildDependencies": Build every
-- dependency (never the local packages themselves), the same as
-- @cabal build all --only-dependencies@ would.
--
-- 2. "Distribution.Client.Buck2.Setup": Create
-- @.buckconfig@\/@PACKAGE@ if they don't exist yet. These are
-- boilerplate copied from @buck2\/example@.
--
-- 3. "Distribution.Client.Buck2.Prebuilt": Tell @buck2@ about all
-- the library and tool dependencies. These are all recorded
-- under @third-party\/haskell@.
--
-- 4. "Distribution.Client.Buck2.Configure": Configure every
-- component of the local packages, to get the 'LocalBuildInfo'.
--
-- 5. "Distribution.Client.Buck2.Generate": Generate buck2 targets
-- for each local component to be built. A pure function of
-- 'PackageDescription', 'LocalBuildInfo' and a few other things.
--
-- 6. "Distribution.Client.Buck2.Write": Write the generated buck2
-- targets for each package to @BUCK.cabal.bzl@, and the autogen
-- files into @cabal-buck2/autogen@ in each package's directory.
module Distribution.Client.CmdBuck2
( buck2Command
, buck2Action
) where
import Distribution.Client.Compat.Prelude
import Prelude ()
import Distribution.Client.DistDirLayout (DistDirLayout (distProjectRootDirectory))
import Distribution.Client.NixStyleOptions
( NixStyleFlags (..)
, cfgVerbosity
, defaultNixStyleFlags
, nixStyleOptions
)
import Distribution.Client.ProjectOrchestration
import Distribution.Client.ScriptUtils
( AcceptNoTargets (..)
, TargetContext (..)
, updateContextAndWriteProjectFile
, withContextAndSelectors
)
import Distribution.Client.Setup
( GlobalFlags
, InstallFlags (installOnlyDeps)
)
import Distribution.Simple.Command (CommandUI (..), usageAlternatives)
import Distribution.Simple.Flag (toFlag)
import qualified Distribution.Simple.PackageIndex as PackageIndex
import Distribution.Simple.Utils (die', notice)
import Distribution.Verbosity (normal)
import Distribution.Client.Buck2.BuildDependencies (buildDependencies)
import Distribution.Client.Buck2.Configure (configureComponents)
import Distribution.Client.Buck2.LocalPackages
( builtLocalPackages
, projectTestOptions
, wantedBuildTools
)
import Distribution.Client.Buck2.Prebuilt (generatePrebuilt)
import Distribution.Client.Buck2.Setup
( checkBuck2Prelude
, ensureBuckconfigAndPackage
)
import Distribution.Client.Buck2.Write (writeAllPackages)
-- | The @cabal buck2@ CLI command
buck2Command :: CommandUI (NixStyleFlags ())
buck2Command =
CommandUI
{ commandName = "buck2"
, commandSynopsis = "Set up (or refresh) a buck2 build for this project."
, commandUsage = usageAlternatives "buck2" ["[FLAGS]"]
, commandDescription = Just $ \_ ->
"Builds every dependency of the project (as `cabal build all "
++ "--only-dependencies` would), then generates the buck2 build "
++ "files (.buckconfig, PACKAGE, third-party/haskell, and a "
++ "BUCK.cabal.bzl for each local package) needed to build the "
++ "project with buck2 instead of cabal. Requires a checkout of "
++ "https://github.com/simonmar/haskell-buck2 at ./buck2. See "
++ "buck2/README.md for details.\n\n"
++ "Flags that would normally be passed to `cabal build`/`cabal "
++ "configure` (-f, --enable-profiling, --enable-tests, etc.) are "
++ "honoured here too, and apply to the dependency build."
, commandNotes = Nothing
, commandDefaultFlags = defaultNixStyleFlags ()
, commandOptions = nixStyleOptions (const [])
}
-- | Implement @cabal buck2@
buck2Action :: NixStyleFlags () -> [String] -> GlobalFlags -> IO ()
buck2Action flags extraArgs globalFlags = do
unless (null extraArgs) $
die' verbosity ("'cabal buck2' doesn't take any extra arguments: " ++ unwords extraArgs)
withContextAndSelectors verbosity RejectNoTargets Nothing depsFlags ["all"] globalFlags BuildCommand $
\targetCtx ctx targetSelectors -> do
baseCtx <- case targetCtx of
ProjectContext -> return ctx
GlobalContext -> return ctx
ScriptContext path exemeta -> updateContextAndWriteProjectFile ctx path exemeta
let projectRoot = distProjectRootDirectory (distDirLayout baseCtx)
checkBuck2Prelude verbosity projectRoot
buildCtx <- buildDependencies verbosity baseCtx targetSelectors
ensureBuckconfigAndPackage verbosity projectRoot
localPkgs <- builtLocalPackages verbosity (distDirLayout baseCtx) (elaboratedPlanOriginal buildCtx)
(externalBuildTools, resolvedDeps) <-
generatePrebuilt
verbosity
projectRoot
(cabalDirLayout baseCtx)
(elaboratedShared buildCtx)
(elaboratedPlanToExecute buildCtx)
(wantedBuildTools localPkgs)
-- 'generatePrebuilt' already found and parsed every real @.conf@
-- file of the resolved dependency closure.
componentLBIs <- configureComponents verbosity baseCtx buildCtx (PackageIndex.fromList resolvedDeps)
writeAllPackages
verbosity
projectRoot
componentLBIs
externalBuildTools
(projectTestOptions (elaboratedPlanOriginal buildCtx))
localPkgs
notice verbosity $
unlines
[ "cabal buck2: done. You can now:"
, " buck2 build //... # build everything"
, " buck2 test //... # test everything"
, " buck2 build //... -m opt # build everything in opt mode"
]
where
verbosity = cfgVerbosity normal flags
depsFlags = flags{installFlags = (installFlags flags){installOnlyDeps = toFlag True}}