@@ -48,6 +48,8 @@ import Distribution.Verbosity (Verbosity ())
48
48
import Distribution.Version (anyVersion )
49
49
import System.Directory (createDirectoryIfMissing , doesFileExist )
50
50
import System.FilePath
51
+ import Distribution.Types.LocalBuildInfo (componentNameCLBIs )
52
+ import Distribution.Types.ComponentLocalBuildInfo (componentIsIndefinite )
51
53
52
54
-- -------------------------------------------------------------------------
53
55
-- Haskell Program Coverage
@@ -73,44 +75,16 @@ mixDir
73
75
-- ^ \"dist/\" prefix
74
76
-> Way
75
77
-> FilePath
76
- -- ^ Component name
77
- -> FilePath
78
78
-- ^ Directory containing test suite's .mix files
79
- mixDir distPref way name = hpcDir distPrefBuild way </> " mix" </> name
80
- where
81
- -- This is a hack for HPC over test suites, needed to match the directory
82
- -- where HPC saves and reads .mix files when the main library of the same
83
- -- package is being processed, perhaps in a previous cabal run (#5213).
84
- -- E.g., @distPref@ may be
85
- -- @./dist-newstyle/build/x86_64-linux/ghc-9.0.1/cabal-gh5213-0.1/t/tests@
86
- -- but the path where library mix files reside has two less components
87
- -- at the end (@t/tests@) and this reduced path needs to be passed to
88
- -- both @hpc@ and @ghc@. For non-default optimization levels, the path
89
- -- suffix is one element longer and the extra path element needs
90
- -- to be preserved.
91
- distPrefElements = splitDirectories distPref
92
- distPrefBuild = case drop (length distPrefElements - 3 ) distPrefElements of
93
- [" t" , _, " noopt" ] ->
94
- joinPath $
95
- take (length distPrefElements - 3 ) distPrefElements
96
- ++ [" noopt" ]
97
- [" t" , _, " opt" ] ->
98
- joinPath $
99
- take (length distPrefElements - 3 ) distPrefElements
100
- ++ [" opt" ]
101
- [_, " t" , _] ->
102
- joinPath $ take (length distPrefElements - 2 ) distPrefElements
103
- _ -> distPref
79
+ mixDir distPref way = hpcDir distPref way </> " mix"
104
80
105
81
tixDir
106
82
:: FilePath
107
83
-- ^ \"dist/\" prefix
108
84
-> Way
109
85
-> FilePath
110
- -- ^ Component name
111
- -> FilePath
112
86
-- ^ Directory containing test suite's .tix files
113
- tixDir distPref way name = hpcDir distPref way </> " tix" </> name
87
+ tixDir distPref way = hpcDir distPref way </> " tix"
114
88
115
89
-- | Path to the .tix file containing a test suite's sum statistics.
116
90
tixFilePath
@@ -121,17 +95,15 @@ tixFilePath
121
95
-- ^ Component name
122
96
-> FilePath
123
97
-- ^ Path to test suite's .tix file
124
- tixFilePath distPref way name = tixDir distPref way name </> name <.> " tix"
98
+ tixFilePath distPref way name = tixDir distPref way </> name <.> " tix"
125
99
126
100
htmlDir
127
101
:: FilePath
128
102
-- ^ \"dist/\" prefix
129
103
-> Way
130
104
-> FilePath
131
- -- ^ Component name
132
- -> FilePath
133
105
-- ^ Path to test suite's HTML markup directory
134
- htmlDir distPref way name = hpcDir distPref way </> " html" </> name
106
+ htmlDir distPref way = hpcDir distPref way </> " html"
135
107
136
108
-- | Attempt to guess the way the test suites in this package were compiled
137
109
-- and linked with the library so the correct module interfaces are found.
@@ -146,14 +118,12 @@ markupTest
146
118
:: Verbosity
147
119
-> LocalBuildInfo
148
120
-> FilePath
149
- -- ^ \"dist/\" prefix
150
- -> String
151
- -- ^ Library name
121
+ -- ^ Testsuite \"dist/\" prefix
122
+ -> PD. PackageDescription
152
123
-> TestSuite
153
- -> Library
154
124
-> IO ()
155
- markupTest verbosity lbi distPref libraryName suite library = do
156
- tixFileExists <- doesFileExist $ tixFilePath distPref way $ testName'
125
+ markupTest verbosity lbi testDistPref pkg_descr suite = do
126
+ tixFileExists <- doesFileExist $ tixFilePath testDistPref way $ testName'
157
127
when tixFileExists $ do
158
128
-- behaviour of 'markup' depends on version, so we need *a* version
159
129
-- but no particular one
@@ -163,35 +133,36 @@ markupTest verbosity lbi distPref libraryName suite library = do
163
133
hpcProgram
164
134
anyVersion
165
135
(withPrograms lbi)
166
- let htmlDir_ = htmlDir distPref way testName'
136
+ let htmlDir_ = htmlDir testDistPref way
167
137
markup
168
138
hpc
169
139
hpcVer
170
140
verbosity
171
- (tixFilePath distPref way testName')
141
+ (tixFilePath testDistPref way testName')
172
142
mixDirs
173
143
htmlDir_
174
- (exposedModules library)
144
+ included
175
145
notice verbosity $
176
146
" Test coverage report written to "
177
147
++ htmlDir_
178
148
</> " hpc_index" <.> " html"
179
149
where
180
150
way = guessWay lbi
181
151
testName' = unUnqualComponentName $ testName suite
182
- mixDirs = map (mixDir distPref way) [testName', libraryName]
152
+ mixDirs = mixDir testDistPref way : map (libMixDir way testDistPref) (nonIndefiniteLibraries lbi pkg_descr)
153
+ included = concatMap exposedModules $ nonIndefiniteLibraries lbi pkg_descr
183
154
184
155
-- | Generate the HTML markup for all of a package's test suites.
185
156
markupPackage
186
157
:: Verbosity
187
158
-> LocalBuildInfo
188
159
-> FilePath
189
- -- ^ \"dist/\" prefix
160
+ -- ^ Testsuite \"dist/\" prefix
190
161
-> PD. PackageDescription
191
162
-> [TestSuite ]
192
163
-> IO ()
193
- markupPackage verbosity lbi distPref pkg_descr suites = do
194
- let tixFiles = map (tixFilePath distPref way) testNames
164
+ markupPackage verbosity lbi testDistPref pkg_descr suites = do
165
+ let tixFiles = map (tixFilePath testDistPref way) testNames
195
166
tixFilesExist <- traverse doesFileExist tixFiles
196
167
when (and tixFilesExist) $ do
197
168
-- behaviour of 'markup' depends on version, so we need *a* version
@@ -202,8 +173,8 @@ markupPackage verbosity lbi distPref pkg_descr suites = do
202
173
hpcProgram
203
174
anyVersion
204
175
(withPrograms lbi)
205
- let outFile = tixFilePath distPref way libraryName
206
- htmlDir' = htmlDir distPref way libraryName
176
+ let outFile = tixFilePath testDistPref way pkgName
177
+ htmlDir' = htmlDir testDistPref way
207
178
excluded = concatMap testModules suites ++ [main]
208
179
createDirectoryIfMissing True $ takeDirectory outFile
209
180
union hpc verbosity tixFiles outFile excluded
@@ -215,6 +186,75 @@ markupPackage verbosity lbi distPref pkg_descr suites = do
215
186
where
216
187
way = guessWay lbi
217
188
testNames = fmap (unUnqualComponentName . testName) suites
218
- mixDirs = map (mixDir distPref way) $ libraryName : testNames
219
- included = concatMap (exposedModules) $ PD. allLibraries pkg_descr
220
- libraryName = prettyShow $ PD. package pkg_descr
189
+ pkgName = prettyShow $ PD. package pkg_descr
190
+ mixDirs = mixDir testDistPref way : map (libMixDir way testDistPref) (nonIndefiniteLibraries lbi pkg_descr)
191
+ included = concatMap exposedModules $ nonIndefiniteLibraries lbi pkg_descr
192
+
193
+ -- | Get all the non-indefinite libraries in a package, ignoring indefinite
194
+ -- components and their instantiations.
195
+ -- HPC doesn't support backpack (eg. would does it mean to cover a module of a
196
+ -- library that is instantiated in two different ways?), so we invoke this
197
+ -- function to determine which library hpc dirs to add to the include path of
198
+ -- the hpc markup command.
199
+ nonIndefiniteLibraries :: LocalBuildInfo -> PD. PackageDescription -> [Library ]
200
+ nonIndefiniteLibraries lbi pkg_desc
201
+ = [ lib
202
+ | lib <- PD. allLibraries pkg_desc
203
+ -- We only care about libraries with exactly one CLBI.
204
+ -- If there were more than one CLBI, they would be the indefinite CLBI and
205
+ -- the multiple instantiations.
206
+ -- Because backpack is unsupported by hpc, we ignore all indefinite components
207
+ , [c] <- pure $ componentNameCLBIs lbi (PD. CLibName (libName lib))
208
+ , not $ componentIsIndefinite c
209
+ ]
210
+
211
+ -- | Determine the path to the library's `.mix` dir for the given way
212
+ libMixDir :: Way
213
+ -> FilePath
214
+ -- ^ Testsuite dist-dir prefix (needed in the pathToLibHpc hack)
215
+ -> Library
216
+ -> FilePath
217
+ libMixDir way testDistPref lib = pathToLibHpc testDistPref (PD. libName lib) `mixDir` way
218
+
219
+
220
+ -- | A (non-exported) hack to determine the path to the main and internal libs
221
+ -- directory given the testsuite's dist prefix.
222
+ --
223
+ -- We use this function when constructing calls to `hpc markup` since otherwise
224
+ -- having cabal-install communicate the path to the main and sub libraries
225
+ -- dist-dir when building the test component, via the Setup.hs interface, is
226
+ -- far more complicated.
227
+ pathToLibHpc :: FilePath -> PD. LibraryName -> FilePath
228
+ pathToLibHpc testDistPref libname = distPrefLib
229
+ where
230
+ -- This is a hack for HPC over test suites, needed to match the directory
231
+ -- where HPC saves and reads .mix files when the main library of the same
232
+ -- package is being processed, perhaps in a previous cabal run (#5213).
233
+ -- E.g., @distPref@ may be
234
+ -- @./dist-newstyle/build/x86_64-linux/ghc-9.0.1/cabal-gh5213-0.1/t/tests@
235
+ -- but the path where library mix files reside has two less components
236
+ -- at the end (@t/tests@) and this reduced path needs to be passed to
237
+ -- both @hpc@ and @ghc@. For non-default optimization levels, the path
238
+ -- suffix is one element longer and the extra path element needs
239
+ -- to be preserved.
240
+ distPrefElements = splitDirectories testDistPref
241
+ distPrefLib = case drop (length distPrefElements - 3 ) distPrefElements of
242
+ [" t" , _, " noopt" ] ->
243
+ joinPath $
244
+ take (length distPrefElements - 3 ) distPrefElements
245
+ ++ [distSuffixInternalLib]
246
+ ++ [" noopt" ]
247
+ [" t" , _, " opt" ] ->
248
+ joinPath $
249
+ take (length distPrefElements - 3 ) distPrefElements
250
+ ++ [distSuffixInternalLib]
251
+ ++ [" opt" ]
252
+ [_, " t" , _] ->
253
+ joinPath $
254
+ take (length distPrefElements - 2 ) distPrefElements
255
+ ++ [distSuffixInternalLib]
256
+ _ -> error " pathToLibHpc: Expecting `testDirPref` to be the dist prefix of a test-suite component"
257
+ distSuffixInternalLib = case libname of
258
+ PD. LMainLibName -> " "
259
+ PD. LSubLibName slname -> " l" </> unUnqualComponentName slname
260
+
0 commit comments