Skip to content

Commit 720333c

Browse files
authored
Merge pull request #7408 from dminuoso/add_default_component_for_packages
Set exe as default component for `cabal run` and `cabal list-bin`
2 parents 5ef4d23 + 3d3986f commit 720333c

File tree

6 files changed

+174
-29
lines changed

6 files changed

+174
-29
lines changed

cabal-install/src/Distribution/Client/CmdListBin.hs

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@
66
module Distribution.Client.CmdListBin (
77
listbinCommand,
88
listbinAction,
9+
10+
-- * Internals exposed for testing
11+
selectPackageTargets,
12+
selectComponentTarget,
13+
noComponentsProblem,
14+
matchesMultipleProblem,
15+
multipleTargetsProblem,
16+
componentNotRightKindProblem
917
) where
1018

1119
import Distribution.Client.Compat.Prelude
@@ -210,17 +218,21 @@ selectPackageTargets :: TargetSelector
210218
-> [AvailableTarget k] -> Either ListBinTargetProblem [k]
211219
selectPackageTargets targetSelector targets
212220

213-
-- If there is exactly one buildable executable then we select that
221+
-- If there is a single executable component, select that. See #7403
214222
| [target] <- targetsExesBuildable
223+
= Right [target]
224+
225+
-- Otherwise, if there is a single executable-like component left, select that.
226+
| [target] <- targetsExeLikesBuildable
215227
= Right [target]
216228

217229
-- but fail if there are multiple buildable executables.
218-
| not (null targetsExesBuildable)
219-
= Left (matchesMultipleProblem targetSelector targetsExesBuildable')
230+
| not (null targetsExeLikesBuildable)
231+
= Left (matchesMultipleProblem targetSelector targetsExeLikesBuildable')
220232

221233
-- If there are executables but none are buildable then we report those
222-
| not (null targetsExes)
223-
= Left (TargetProblemNoneEnabled targetSelector targetsExes)
234+
| not (null targetsExeLikes')
235+
= Left (TargetProblemNoneEnabled targetSelector targetsExeLikes')
224236

225237
-- If there are no executables but some other targets then we report that
226238
| not (null targets)
@@ -230,14 +242,19 @@ selectPackageTargets targetSelector targets
230242
| otherwise
231243
= Left (TargetProblemNoTargets targetSelector)
232244
where
233-
-- Targets that can be executed
234-
targetsExecutableLike =
235-
concatMap (\kind -> filterTargetsKind kind targets)
236-
[ExeKind, TestKind, BenchKind]
237-
(targetsExesBuildable,
238-
targetsExesBuildable') = selectBuildableTargets' targetsExecutableLike
239-
240-
targetsExes = forgetTargetsDetail targetsExecutableLike
245+
-- Targets that are precisely executables
246+
targetsExes = filterTargetsKind ExeKind targets
247+
targetsExesBuildable = selectBuildableTargets targetsExes
248+
249+
-- Any target that could be executed
250+
targetsExeLikes = targetsExes
251+
++ filterTargetsKind TestKind targets
252+
++ filterTargetsKind BenchKind targets
253+
254+
(targetsExeLikesBuildable,
255+
targetsExeLikesBuildable') = selectBuildableTargets' targetsExeLikes
256+
257+
targetsExeLikes' = forgetTargetsDetail targetsExeLikes
241258

242259

243260
-- | For a 'TargetComponent' 'TargetSelector', check if the component can be

cabal-install/src/Distribution/Client/CmdRun.hs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,9 @@ runCommand = CommandUI
121121

122122
++ "Any executable-like component in any package in the project can be "
123123
++ "specified. A package can be specified if contains just one "
124-
++ "executable-like. The default is to use the package in the current "
125-
++ "directory if it contains just one executable-like.\n\n"
124+
++ "executable-like, preferring a single executable. The default is to "
125+
++ "use the package in the current directory if it contains just one "
126+
++ "executable-like.\n\n"
126127

127128
++ "Extra arguments can be passed to the program, but use '--' to "
128129
++ "separate arguments for the program from arguments for " ++ pname
@@ -480,17 +481,21 @@ selectPackageTargets :: TargetSelector
480481
-> [AvailableTarget k] -> Either RunTargetProblem [k]
481482
selectPackageTargets targetSelector targets
482483

483-
-- If there is exactly one buildable executable then we select that
484+
-- If there is a single executable component, select that. See #7403
484485
| [target] <- targetsExesBuildable
485486
= Right [target]
486487

487-
-- but fail if there are multiple buildable executables.
488-
| not (null targetsExesBuildable)
489-
= Left (matchesMultipleProblem targetSelector targetsExesBuildable')
488+
-- Otherwise, if there is a single executable-like component left, select that.
489+
| [target] <- targetsExeLikesBuildable
490+
= Right [target]
491+
492+
-- but fail if there are multiple buildable executables.
493+
| not (null targetsExeLikesBuildable)
494+
= Left (matchesMultipleProblem targetSelector targetsExeLikesBuildable')
490495

491496
-- If there are executables but none are buildable then we report those
492-
| not (null targetsExes)
493-
= Left (TargetProblemNoneEnabled targetSelector targetsExes)
497+
| not (null targetsExeLikes')
498+
= Left (TargetProblemNoneEnabled targetSelector targetsExeLikes')
494499

495500
-- If there are no executables but some other targets then we report that
496501
| not (null targets)
@@ -500,14 +505,19 @@ selectPackageTargets targetSelector targets
500505
| otherwise
501506
= Left (TargetProblemNoTargets targetSelector)
502507
where
503-
-- Targets that can be executed
504-
targetsExecutableLike =
505-
concatMap (\kind -> filterTargetsKind kind targets)
506-
[ExeKind, TestKind, BenchKind]
507-
(targetsExesBuildable,
508-
targetsExesBuildable') = selectBuildableTargets' targetsExecutableLike
509-
510-
targetsExes = forgetTargetsDetail targetsExecutableLike
508+
-- Targets that are precisely executables
509+
targetsExes = filterTargetsKind ExeKind targets
510+
targetsExesBuildable = selectBuildableTargets targetsExes
511+
512+
-- Any target that could be executed
513+
targetsExeLikes = targetsExes
514+
++ filterTargetsKind TestKind targets
515+
++ filterTargetsKind BenchKind targets
516+
517+
(targetsExeLikesBuildable,
518+
targetsExeLikesBuildable') = selectBuildableTargets' targetsExeLikes
519+
520+
targetsExeLikes' = forgetTargetsDetail targetsExeLikes
511521

512522

513523
-- | For a 'TargetComponent' 'TargetSelector', check if the component can be

cabal-install/tests/IntegrationTests2.hs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import qualified Distribution.Client.CmdRun as CmdRun
4343
import qualified Distribution.Client.CmdTest as CmdTest
4444
import qualified Distribution.Client.CmdBench as CmdBench
4545
import qualified Distribution.Client.CmdHaddock as CmdHaddock
46+
import qualified Distribution.Client.CmdListBin as CmdListBin
4647

4748
import Distribution.Package
4849
import Distribution.PackageDescription
@@ -109,6 +110,7 @@ tests config =
109110
, testCaseSteps "problems (build)" (testTargetProblemsBuild config)
110111
, testCaseSteps "problems (repl)" (testTargetProblemsRepl config)
111112
, testCaseSteps "problems (run)" (testTargetProblemsRun config)
113+
, testCaseSteps "problems (list-bin)" (testTargetProblemsListBin config)
112114
, testCaseSteps "problems (test)" (testTargetProblemsTest config)
113115
, testCaseSteps "problems (bench)" (testTargetProblemsBench config)
114116
, testCaseSteps "problems (haddock)" (testTargetProblemsHaddock config)
@@ -861,9 +863,85 @@ testTargetProblemsRepl config reportSubCase = do
861863
[ TargetPackage TargetExplicitNamed ["p-0.1"] (Just BenchKind) ]
862864
[ ("p-0.1-inplace-a-benchmark", CBenchName "a-benchmark") ]
863865

866+
testTargetProblemsListBin :: ProjectConfig -> (String -> IO ()) -> Assertion
867+
testTargetProblemsListBin config reportSubCase = do
868+
reportSubCase "one-of-each"
869+
do (_,elaboratedPlan,_) <- planProject "targets/one-of-each" config
870+
assertProjectDistinctTargets
871+
elaboratedPlan
872+
CmdListBin.selectPackageTargets
873+
CmdListBin.selectComponentTarget
874+
[ TargetPackage TargetExplicitNamed ["p-0.1"] Nothing
875+
]
876+
[ ("p-0.1-inplace-p1", CExeName "p1")
877+
]
878+
879+
reportSubCase "multiple-exes"
880+
assertProjectTargetProblems
881+
"targets/multiple-exes" config
882+
CmdListBin.selectPackageTargets
883+
CmdListBin.selectComponentTarget
884+
[ ( flip CmdListBin.matchesMultipleProblem
885+
[ AvailableTarget "p-0.1" (CExeName "p2")
886+
(TargetBuildable () TargetRequestedByDefault) True
887+
, AvailableTarget "p-0.1" (CExeName "p1")
888+
(TargetBuildable () TargetRequestedByDefault) True
889+
]
890+
, mkTargetPackage "p-0.1" )
891+
]
892+
893+
reportSubCase "multiple targets"
894+
do (_,elaboratedPlan,_) <- planProject "targets/multiple-exes" config
895+
assertProjectDistinctTargets
896+
elaboratedPlan
897+
CmdListBin.selectPackageTargets
898+
CmdListBin.selectComponentTarget
899+
[ mkTargetComponent "p-0.1" (CExeName "p1")
900+
, mkTargetComponent "p-0.1" (CExeName "p2")
901+
]
902+
[ ("p-0.1-inplace-p1", CExeName "p1")
903+
, ("p-0.1-inplace-p2", CExeName "p2")
904+
]
905+
906+
reportSubCase "exes-disabled"
907+
assertProjectTargetProblems
908+
"targets/exes-disabled" config
909+
CmdListBin.selectPackageTargets
910+
CmdListBin.selectComponentTarget
911+
[ ( flip TargetProblemNoneEnabled
912+
[ AvailableTarget "p-0.1" (CExeName "p") TargetNotBuildable True
913+
]
914+
, mkTargetPackage "p-0.1" )
915+
]
916+
917+
reportSubCase "empty-pkg"
918+
assertProjectTargetProblems
919+
"targets/empty-pkg" config
920+
CmdListBin.selectPackageTargets
921+
CmdListBin.selectComponentTarget
922+
[ ( TargetProblemNoTargets, mkTargetPackage "p-0.1" )
923+
]
924+
925+
reportSubCase "lib-only"
926+
assertProjectTargetProblems
927+
"targets/lib-only" config
928+
CmdListBin.selectPackageTargets
929+
CmdListBin.selectComponentTarget
930+
[ (CmdListBin.noComponentsProblem, mkTargetPackage "p-0.1" )
931+
]
864932

865933
testTargetProblemsRun :: ProjectConfig -> (String -> IO ()) -> Assertion
866934
testTargetProblemsRun config reportSubCase = do
935+
reportSubCase "one-of-each"
936+
do (_,elaboratedPlan,_) <- planProject "targets/one-of-each" config
937+
assertProjectDistinctTargets
938+
elaboratedPlan
939+
CmdRun.selectPackageTargets
940+
CmdRun.selectComponentTarget
941+
[ TargetPackage TargetExplicitNamed ["p-0.1"] Nothing
942+
]
943+
[ ("p-0.1-inplace-p1", CExeName "p1")
944+
]
867945

868946
reportSubCase "multiple-exes"
869947
assertProjectTargetProblems
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
packages: ./
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: p
2+
version: 0.1
3+
build-type: Simple
4+
cabal-version: >= 1.10
5+
6+
executable p1
7+
main-is: P1.hs
8+
build-depends: base
9+
10+
benchmark p2
11+
type: exitcode-stdio-1.0
12+
main-is: P2.hs
13+
build-depends: base
14+
15+
test-suite p3
16+
type: exitcode-stdio-1.0
17+
main-is: P3.hs
18+
build-depends: base
19+
20+
library p4
21+
exposed-modules: P4
22+
build-depends: base
23+
24+
foreign-library libp
25+
type: native-shared
26+
other-modules: FLib

doc/cabal-commands.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,19 @@ Tests and benchmarks are also treated as executables.
194194

195195
See `the v2-build section <#cabal-v2-build>`__ for the target syntax.
196196

197+
When ``TARGET`` is one of the following:
198+
199+
- A component target: execute the specified executable, benchmark or test suite
200+
201+
- A package target:
202+
1. If the package has exactly one executable component, it will be selected.
203+
2. If the package has multiple executable components, an error is raised.
204+
3. If the package has exactly one test or benchmark component, it will be selected.
205+
4. Otherwise an issue is raised
206+
207+
- Empty target: Same as package target, implicitly using the package from the current
208+
working directory.
209+
197210
Except in the case of the empty target, the strings after it will be
198211
passed to the executable as arguments.
199212

0 commit comments

Comments
 (0)