Skip to content
Merged
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
39 changes: 34 additions & 5 deletions Cabal/src/Distribution/Simple/GHC/Build.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ module Distribution.Simple.GHC.Build where
import Distribution.Compat.Prelude
import Prelude ()

import Control.Monad.IO.Class
import qualified Distribution.Compat.Graph as Graph

import Distribution.PackageDescription as PD hiding (buildInfo)
import Distribution.Simple.Build.Inputs
import Distribution.Simple.Flag (Flag)
Expand All @@ -25,6 +26,8 @@ import Distribution.Utils.NubList (fromNubListR)
import Distribution.Utils.Path

import Distribution.Verbosity (VerbosityHandles, mkVerbosity, verbosityHandles)

import Control.Monad.IO.Class
import System.FilePath (splitDirectories)

{- Note [Build Target Dir vs Target Dir]
Expand Down Expand Up @@ -75,7 +78,7 @@ build numJobs verbHandles pkg_descr pbci = do
verbosity = mkVerbosity verbHandles $ buildVerbosity pbci
isLib = buildIsLib pbci
lbi = localBuildInfo pbci
bi = buildBI pbci
comp = buildComponent pbci
clbi = buildCLBI pbci
isIndef = componentIsIndefinite clbi
mbWorkDir = mbWorkDirLBI lbi
Expand Down Expand Up @@ -118,9 +121,35 @@ build numJobs verbHandles pkg_descr pbci = do
let wantedWays@(wantedLibWays, wantedFLibWay, wantedExeWay) = buildWays lbi

-- Ways which are needed due to the compiler configuration
let doingTH = usesTemplateHaskellOrQQ bi
let doingTH =
-- Does this component, or another component that (transitively) depends
-- on this component, use TemplateHaskell or QuasiQuotes?
--
-- Ticket #7684 showed that we need to take into account intra-package
-- dependencies.
any usesTemplateHaskellOrQQ thisCompAndReverseDepsBuildInfos

-- The BuildInfos for this component and all of the components that
-- transitively depend on it (its reverse dependencies).
thisCompAndReverseDepsBuildInfos =
[ componentBuildInfo revDepComp
| let compUnitId = componentUnitId clbi
, -- 'revClosure' retrieves components that depend on this component.
revDepCLBI <- fromMaybe [clbi] $ Graph.revClosure (componentGraph lbi) [compUnitId]
, -- Use 'lookupComponent' here; don't use any function that goes via
-- 'getComponent' (e.g. mkTargetInfo or unitIdTarget'), as that will
-- tiresomely cause an error for 'detailed-0.9' test-suites because
-- 'testSuiteLibV09AsLibAndExe' creates a stub PackageDescription with
-- most components zeroed out.
--
-- The implementation below means we will get 'Nothing' when the
-- current component is a 'detailed-0.9' test-suite, which is fine
-- as nothing can depend on a test-suite.
Just revDepComp <- [lookupComponent pkg_descr $ componentLocalName revDepCLBI]
]

defaultGhcWay = compilerBuildWay (buildCompiler pbci)
wantedModBuildWays = case buildComponent pbci of
wantedModBuildWays = case comp of
CLib _ -> wantedLibWays isIndef
CFLib fl -> [wantedFLibWay (withDynFLib fl)]
CExe _ -> [wantedExeWay]
Expand All @@ -129,7 +158,7 @@ build numJobs verbHandles pkg_descr pbci = do
finalModBuildWays =
wantedModBuildWays
++ [defaultGhcWay | doingTH && defaultGhcWay `notElem` wantedModBuildWays]
compNameStr = showComponentName $ componentName $ buildComponent pbci
compNameStr = showComponentName $ componentName comp

liftIO $ info verbosity ("Wanted module build ways(" ++ compNameStr ++ "): " ++ show wantedModBuildWays)
liftIO $ info verbosity ("Final module build ways(" ++ compNameStr ++ "): " ++ show finalModBuildWays)
Expand Down
24 changes: 24 additions & 0 deletions cabal-testsuite/PackageTests/T7684/T7684.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
cabal-version: 2.2
name: T7684
version: 0.1.0.0
license: BSD-3-Clause
author: Matthew Pickering
maintainer: The Cabal team
build-type: Simple
synopsis: Test for Cabal bug #7684
description:
Check that we compile sublibraries in the dynamic way when that is needed
due to TemplateHaskell or QuasiQuotes in another component that depends on it.

library library-a
hs-source-dirs: lib-a
exposed-modules: A
build-depends: base, template-haskell

default-language: Haskell2010

library
hs-source-dirs: lib
exposed-modules: B
build-depends: base, library-a
default-language: Haskell2010
4 changes: 4 additions & 0 deletions cabal-testsuite/PackageTests/T7684/cabal.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
packages: .

shared: False
executable-dynamic: False
5 changes: 5 additions & 0 deletions cabal-testsuite/PackageTests/T7684/cabal.test.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Test.Cabal.Prelude

main = setupAndCabalTest $ recordMode DoNotRecord $ do
setup "configure" []
setup "build" []
8 changes: 8 additions & 0 deletions cabal-testsuite/PackageTests/T7684/lib-a/A.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{-# LANGUAGE TemplateHaskellQuotes #-}

module A where

import Language.Haskell.TH.Syntax ( Q, Exp )

a :: Q Exp
a = [| putStrLn "a" |]
7 changes: 7 additions & 0 deletions cabal-testsuite/PackageTests/T7684/lib/B.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{-# LANGUAGE TemplateHaskell #-}

module B where

import A

main = $(a)
11 changes: 11 additions & 0 deletions changelog.d/IntraPackageDyn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
synopsis: Build dynamic libraries when needed for intra-package dependencies
packages: [Cabal]
prs: 11791
issues: 7684
---

When building a package with a sublibrary, Cabal now properly takes into account
intra-package dependencies when deciding whether each sublibrary should be built
in the dynamic way (e.g. because another library that depends on it uses
TemplateHaskell or QuasiQuotes).
Loading