Hannes Siebenhandl pushed to branch wip/fendor/dep-json at Glasgow Haskell Compiler / GHC

Commits:

22 changed files:

Changes:

  • compiler/GHC/Driver/DynFlags.hs
    ... ... @@ -351,6 +351,7 @@ data DynFlags = DynFlags {
    351 351
     
    
    352 352
       --  For ghc -M
    
    353 353
       depMakefile           :: FilePath,
    
    354
    +  depJson               :: Maybe FilePath,
    
    354 355
       depIncludePkgDeps     :: Bool,
    
    355 356
       depIncludeCppDeps     :: Bool,
    
    356 357
       depExcludeMods        :: [ModuleName],
    
    ... ... @@ -694,6 +695,7 @@ defaultDynFlags mySettings =
    694 695
     
    
    695 696
             -- ghc -M values
    
    696 697
             depMakefile       = "Makefile",
    
    698
    +        depJson           = Nothing,
    
    697 699
             depIncludePkgDeps = False,
    
    698 700
             depIncludeCppDeps = False,
    
    699 701
             depExcludeMods    = [],
    

  • compiler/GHC/Driver/MakeFile.hs
    ... ... @@ -7,6 +7,8 @@
    7 7
     -- (c) The University of Glasgow 2005
    
    8 8
     --
    
    9 9
     -----------------------------------------------------------------------------
    
    10
    +{-# LANGUAGE DerivingVia #-}
    
    11
    +{-# LANGUAGE RecordWildCards #-}
    
    10 12
     
    
    11 13
     module GHC.Driver.MakeFile
    
    12 14
        ( doMkDependHS
    
    ... ... @@ -16,47 +18,64 @@ where
    16 18
     
    
    17 19
     import GHC.Prelude
    
    18 20
     
    
    19
    -import qualified GHC
    
    20
    -import GHC.Driver.Make
    
    21
    -import GHC.Driver.Monad
    
    21
    +import GHC qualified
    
    22
    +
    
    23
    +import GHC.Data.Bag (listToBag)
    
    24
    +import GHC.Data.FastString (lexicalCompareFS, unpackFS)
    
    25
    +import GHC.Data.Graph.Directed (SCC (..))
    
    26
    +import GHC.Data.OsPath (unsafeDecodeUtf, unsafeEncodeUtf)
    
    27
    +
    
    22 28
     import GHC.Driver.DynFlags
    
    23
    -import GHC.Utils.Misc
    
    24 29
     import GHC.Driver.Env
    
    25 30
     import GHC.Driver.Errors.Types
    
    26
    -import GHC.Types.UnresolvedImport
    
    27
    -import qualified GHC.SysTools as SysTools
    
    28
    -import GHC.Data.Graph.Directed ( SCC(..) )
    
    29
    -import GHC.Data.OsPath (unsafeDecodeUtf)
    
    30
    -import GHC.Utils.Outputable
    
    31
    -import GHC.Utils.Panic
    
    32
    -import GHC.Types.SourceError
    
    33
    -import GHC.Types.SrcLoc
    
    34
    -import GHC.Types.PkgQual
    
    35
    -import Data.List (partition)
    
    36
    -import GHC.Utils.TmpFs
    
    31
    +import GHC.Driver.Make
    
    32
    +import GHC.Driver.Monad
    
    33
    +import GHC.Driver.Phases
    
    34
    +import GHC.Driver.Pipeline
    
    35
    +import GHC.Driver.Pipeline.Monad
    
    36
    +import GHC.Driver.Session
    
    37 37
     
    
    38
    +import GHC.Iface.Errors.Types
    
    38 39
     import GHC.Iface.Load (cannotFindModule)
    
    39 40
     
    
    41
    +import GHC.SysTools qualified as SysTools
    
    42
    +import GHC.Types.PkgQual
    
    43
    +import GHC.Types.SourceError
    
    44
    +import GHC.Types.SrcLoc
    
    45
    +import GHC.Types.Unique.Set (UniqSet)
    
    46
    +import GHC.Types.Unique.Set qualified as UniqSet
    
    47
    +import GHC.Types.UnresolvedImport
    
    48
    +
    
    49
    +import GHC.Unit.Finder
    
    50
    +import GHC.Unit.Info
    
    40 51
     import GHC.Unit.Module
    
    41
    -import GHC.Unit.Module.ModSummary
    
    42 52
     import GHC.Unit.Module.Graph
    
    43
    -import GHC.Unit.Finder
    
    53
    +import GHC.Unit.Module.ModSummary
    
    54
    +import GHC.Unit.State (lookupUnitId)
    
    44 55
     
    
    45
    -import GHC.Utils.Exception
    
    46 56
     import GHC.Utils.Error
    
    57
    +import GHC.Utils.Exception
    
    58
    +import GHC.Utils.Json
    
    47 59
     import GHC.Utils.Logger
    
    60
    +import GHC.Utils.Misc
    
    61
    +import GHC.Utils.Outputable
    
    62
    +import GHC.Utils.Panic
    
    63
    +import GHC.Utils.TmpFs
    
    48 64
     
    
    65
    +import Control.Monad (when)
    
    66
    +import Data.Either
    
    67
    +import Data.Foldable (traverse_)
    
    68
    +import Data.IORef
    
    69
    +import Data.List (partition)
    
    70
    +import Data.Map.Strict qualified as Map
    
    71
    +import Data.Maybe (isJust, isNothing)
    
    72
    +import Data.Semigroup qualified as Semigroup
    
    73
    +import Data.Set qualified as Set
    
    74
    +import GHC.Generics (Generic, Generically (..))
    
    49 75
     import System.Directory
    
    50 76
     import System.FilePath
    
    51 77
     import System.IO
    
    52
    -import System.IO.Error  ( isEOFError )
    
    53
    -import Control.Monad    ( when, forM_ )
    
    54
    -import Data.Maybe       ( isJust )
    
    55
    -import Data.IORef
    
    56
    -import qualified Data.Set as Set
    
    57
    -import GHC.Iface.Errors.Types
    
    58
    -import Data.Either
    
    59
    -import GHC.Data.Bag (listToBag)
    
    78
    +import System.IO.Error (isEOFError)
    
    60 79
     
    
    61 80
     -----------------------------------------------------------------
    
    62 81
     --
    
    ... ... @@ -98,27 +117,52 @@ doMkDependHS srcs = do
    98 117
     
    
    99 118
     doMkDependModuleGraph :: GhcMonad m =>  DynFlags -> ModuleGraph -> m ()
    
    100 119
     doMkDependModuleGraph dflags module_graph = do
    
    120
    +    hsc_env <- getSession
    
    101 121
         logger <- getLogger
    
    102
    -    tmpfs <- hsc_tmpfs <$> getSession
    
    103
    -    let excl_mods = depExcludeMods dflags
    
    122
    +    let
    
    123
    +      tmpfs = hsc_tmpfs hsc_env
    
    124
    +      excl_mods = depExcludeMods dflags
    
    104 125
     
    
    105
    -    files <- liftIO $ beginMkDependHS logger tmpfs dflags
    
    106
    -    let sorted = GHC.topSortModuleGraph False module_graph Nothing
    
    126
    +    root <- liftIO getCurrentDirectory
    
    127
    +    let
    
    128
    +      dep_writer =
    
    129
    +        concat
    
    130
    +        [ [ SomeDependencyWriter $ initFileDepWriter logger root tmpfs dflags
    
    131
    +          ]
    
    132
    +        , [ SomeDependencyWriter $ initJsonDepWriter json_output dflags
    
    133
    +          | Just json_output <- [depJson dflags]
    
    134
    +          ]
    
    135
    +        ]
    
    107 136
     
    
    137
    +
    
    138
    +    let sorted = GHC.topSortModuleGraph False module_graph Nothing
    
    108 139
         -- Print out the dependencies if wanted
    
    109 140
         liftIO $ debugTraceMsg logger 2 (text "Module dependencies" $$ ppr sorted)
    
    110 141
     
    
    111
    -    -- Process them one by one, dumping results into makefile
    
    112
    -    -- and complaining about cycles
    
    113
    -    hsc_env <- getSession
    
    114
    -    root <- liftIO getCurrentDirectory
    
    115
    -    mapM_ (liftIO . processDeps dflags hsc_env excl_mods root (mkd_tmp_hdl files)) sorted
    
    116
    -
    
    117
    -    -- If -ddump-mod-cycles, show cycles in the module graph
    
    118
    -    liftIO $ dumpModCycles logger module_graph
    
    119
    -
    
    120
    -    -- Tidy up
    
    121
    -    liftIO $ endMkDependHS logger files
    
    142
    +    liftIO $ bracket
    
    143
    +      (do
    
    144
    +        traverse
    
    145
    +          (\ (SomeDependencyWriter writer) -> do
    
    146
    +            backend <- dw_beginWriter writer
    
    147
    +            pure $ SomeActiveDependencyWriter (writer, backend)
    
    148
    +          )
    
    149
    +          dep_writer
    
    150
    +      )
    
    151
    +      -- Tidy up
    
    152
    +      (\ writers -> do
    
    153
    +        traverse_
    
    154
    +          (\ (SomeActiveDependencyWriter (writer, backend)) -> do
    
    155
    +            dw_endWriter writer backend
    
    156
    +          )
    
    157
    +          writers
    
    158
    +      )
    
    159
    +      ( \ writers -> do
    
    160
    +        -- Process them one by one, dumping results and complaining about cycles
    
    161
    +        mapM_ (processDeps dflags hsc_env (UniqSet.mkUniqSet excl_mods) writers) sorted
    
    162
    +
    
    163
    +        -- If -ddump-mod-cycles, show cycles in the module graph
    
    164
    +        liftIO $ dumpModCycles logger module_graph
    
    165
    +      )
    
    122 166
     
    
    123 167
         -- Unconditional exiting is a bad idea.  If an error occurs we'll get an
    
    124 168
         --exception; if that is not caught it's fine, but at least we have a
    
    ... ... @@ -127,6 +171,196 @@ doMkDependModuleGraph dflags module_graph = do
    127 171
     
    
    128 172
         --`GHC.ghcCatch` \_ -> io $ exitWith (ExitFailure 1)
    
    129 173
     
    
    174
    +--------------------------------------------------------------------------------
    
    175
    +-- Types abstracting over the output
    
    176
    +--------------------------------------------------------------------------------
    
    177
    +
    
    178
    +data DepNode =
    
    179
    +  DepNode
    
    180
    +    { dn_mod :: Module
    
    181
    +    , dn_src :: FilePath
    
    182
    +    , dn_obj :: FilePath
    
    183
    +    , dn_hi :: FilePath
    
    184
    +    , dn_boot :: IsBootInterface
    
    185
    +    , dn_preprocessing :: PreprocessingNode
    
    186
    +    }
    
    187
    +
    
    188
    +data PreprocessingNode = PreprocessingNode
    
    189
    +  { pn_preprocessor :: Maybe String
    
    190
    +  , pn_options :: [String]
    
    191
    +  }
    
    192
    +
    
    193
    +data Dep
    
    194
    +  = DepHi
    
    195
    +    { dep_mod :: Module
    
    196
    +    , dep_path :: FilePath
    
    197
    +    , dep_unit :: Maybe UnitInfo
    
    198
    +    , dep_local :: Bool
    
    199
    +    , dep_boot :: IsBootInterface
    
    200
    +    }
    
    201
    +  | DepCpp
    
    202
    +    { dep_path :: FilePath
    
    203
    +    }
    
    204
    +
    
    205
    +data SomeDependencyWriter = forall backend . SomeDependencyWriter (DependencyWriter backend)
    
    206
    +
    
    207
    +data SomeActiveDependencyWriter = forall backend . SomeActiveDependencyWriter (DependencyWriter backend, backend)
    
    208
    +
    
    209
    +data DependencyWriter backend = DependencyWriter
    
    210
    +  { dw_beginWriter :: IO backend
    
    211
    +  , dw_writeDependency :: backend -> DepNode -> [Dep] -> IO ()
    
    212
    +  , dw_endWriter :: backend -> IO ()
    
    213
    +  }
    
    214
    +
    
    215
    +-----------------------------------------------------------------
    
    216
    +--
    
    217
    +--              processDeps
    
    218
    +--
    
    219
    +-----------------------------------------------------------------
    
    220
    +
    
    221
    +processDeps :: DynFlags
    
    222
    +            -> HscEnv
    
    223
    +            -> UniqSet ModuleName -- ^ Excludes
    
    224
    +            -> [SomeActiveDependencyWriter]
    
    225
    +            -> SCC ModuleGraphNode
    
    226
    +            -> IO ()
    
    227
    +-- Write suitable dependencies to handle
    
    228
    +-- Always:
    
    229
    +--                      this.o : this.hs
    
    230
    +--
    
    231
    +-- If the dependency is on something other than a .hi file:
    
    232
    +--                      this.o this.p_o ... : dep
    
    233
    +-- otherwise
    
    234
    +--                      this.o ...   : dep.hi
    
    235
    +--                      this.p_o ... : dep.p_hi
    
    236
    +--                      ...
    
    237
    +-- (where .o is $osuf, and the other suffixes come from
    
    238
    +-- the cmdline -s options).
    
    239
    +--
    
    240
    +-- For {-# SOURCE #-} imports the "hi" will be "hi-boot".
    
    241
    +
    
    242
    +processDeps _ hsc_env _ _ (CyclicSCC nodes)
    
    243
    +  =     -- There shouldn't be any cycles; report them
    
    244
    +    throwOneError (initSourceErrorContext (hsc_dflags hsc_env)) $ cyclicModuleErr nodes
    
    245
    +
    
    246
    +processDeps _ hsc_env _ _ (AcyclicSCC (InstantiationNode _uid node))
    
    247
    +  =     -- There shouldn't be any backpack instantiations; report them as well
    
    248
    +    throwOneError (initSourceErrorContext (hsc_dflags hsc_env)) $
    
    249
    +      mkPlainErrorMsgEnvelope noSrcSpan $
    
    250
    +      GhcDriverMessage $ DriverInstantiationNodeInDependencyGeneration node
    
    251
    +
    
    252
    +processDeps _dflags _ _ _ (AcyclicSCC (LinkNode {})) = return ()
    
    253
    +processDeps _dflags _ _ _ (AcyclicSCC (UnitNode {})) = return ()
    
    254
    +processDeps _ _ _ _ (AcyclicSCC (ModuleNode _ (ModuleNodeFixed {})))
    
    255
    +  -- No dependencies needed for fixed modules (already compiled)
    
    256
    +  = return ()
    
    257
    +
    
    258
    +processDeps dflags hsc_env excl_mods backends (AcyclicSCC (ModuleNode _ (ModuleNodeCompile node))) = do
    
    259
    +  pp <- preprocessor
    
    260
    +  let
    
    261
    +    dep_node = mkDepNode pp
    
    262
    +    find_deps imps = do
    
    263
    +      cpp_deps <- find_cpp_deps
    
    264
    +      import_deps <- find_import_deps imps
    
    265
    +      pure $ map Right cpp_deps ++ import_deps
    
    266
    +  (missing_dep_errs, deps) <- partitionEithers <$> find_deps (ms_imps node)
    
    267
    +
    
    268
    +  if null missing_dep_errs
    
    269
    +    then do
    
    270
    +      traverse_ (\ (SomeActiveDependencyWriter (writer, backend)) -> dw_writeDependency writer backend dep_node deps) backends
    
    271
    +    else do
    
    272
    +      let sec = initSourceErrorContext (hsc_dflags hsc_env)
    
    273
    +      throwErrors sec (mkMessages (listToBag missing_dep_errs))
    
    274
    +  where
    
    275
    +    src_file = msHsFilePath node
    
    276
    +    mkDepNode preproc =
    
    277
    +      DepNode {
    
    278
    +        dn_mod = ms_mod node,
    
    279
    +        dn_src = src_file,
    
    280
    +        dn_obj = msObjFilePath node,
    
    281
    +        dn_hi = msHiFilePath node,
    
    282
    +        dn_boot = isBootSummary node,
    
    283
    +        dn_preprocessing = preproc
    
    284
    +      }
    
    285
    +
    
    286
    +    preprocessor :: IO PreprocessingNode
    
    287
    +    preprocessor
    
    288
    +      | Just src <- ml_hs_file (ms_location node)
    
    289
    +      = runPipeline (hsc_hooks hsc_env) $ do
    
    290
    +        let (_, suffix) = splitExtension src
    
    291
    +            lit | Unlit _ <- startPhase suffix = True
    
    292
    +                | otherwise = False
    
    293
    +            pipe_env = mkPipeEnv StopPreprocess src Nothing NoOutputFile
    
    294
    +        unlit_fn <- if lit then use (T_Unlit pipe_env hsc_env src) else pure src
    
    295
    +        (dflags1, opts, _, _) <- use (T_FileArgs (hsc_logger hsc_env) (hsc_dflags hsc_env) unlit_fn)
    
    296
    +        let pp = pgm_F dflags1
    
    297
    +        pure PreprocessingNode
    
    298
    +          { pn_preprocessor = if null pp then global_preprocessor else Just pp
    
    299
    +          , pn_options = opts
    
    300
    +          }
    
    301
    +      | otherwise
    
    302
    +      = pure PreprocessingNode
    
    303
    +          { pn_preprocessor = global_preprocessor
    
    304
    +          , pn_options = []
    
    305
    +          }
    
    306
    +
    
    307
    +    global_preprocessor :: Maybe String
    
    308
    +    global_preprocessor
    
    309
    +      | let pp = pgm_F dflags
    
    310
    +      , not (null pp)
    
    311
    +      = Just pp
    
    312
    +      | otherwise
    
    313
    +      = Nothing
    
    314
    +
    
    315
    +    -- Emit a dependency for each CPP import
    
    316
    +    -- CPP deps are discovered in the module parsing phase by parsing
    
    317
    +    -- comment lines left by the preprocessor.
    
    318
    +    -- Note that GHC.parseModule may throw an exception if the module
    
    319
    +    -- fails to parse, which may not be desirable (see #16616).
    
    320
    +    find_cpp_deps :: IO [Dep]
    
    321
    +    find_cpp_deps = do
    
    322
    +      session <- Session <$> newIORef hsc_env
    
    323
    +      parsedMod <- reflectGhc (GHC.parseModule node) session
    
    324
    +      pure (DepCpp <$> GHC.pm_extra_src_files parsedMod)
    
    325
    +
    
    326
    +    -- Emit a dependency for each import
    
    327
    +    find_import_deps :: [UnresolvedImport PkgQual] -> IO [Either (MsgEnvelope GhcMessage) Dep]
    
    328
    +    find_import_deps idecls =
    
    329
    +      sequence
    
    330
    +        [ findDependency hsc_env decl
    
    331
    +        | decl <- idecls
    
    332
    +        , let L _loc mod = ui_mod_name decl
    
    333
    +        , not $ mod `UniqSet.elementOfUniqSet` excl_mods
    
    334
    +        ]
    
    335
    +
    
    336
    +findDependency  :: HscEnv
    
    337
    +                -> UnresolvedImport PkgQual   -- The import to find
    
    338
    +                -> IO (Either (MsgEnvelope GhcMessage) Dep)  -- Interface file
    
    339
    +findDependency hsc_env imp = do
    
    340
    +  -- Find the module; this will be fast because
    
    341
    +  -- we've done it once during downsweep.
    
    342
    +  r <- resolveImport hsc_env imp
    
    343
    +  case r of
    
    344
    +    Found loc dep_mod ->
    
    345
    +      pure $ Right
    
    346
    +        DepHi
    
    347
    +          { dep_mod = dep_mod
    
    348
    +          , dep_path = ml_hi_file loc
    
    349
    +          , dep_unit = lookupUnitId (hsc_units hsc_env) (moduleUnitId dep_mod)
    
    350
    +          , dep_local = isJust (ml_hs_file loc)
    
    351
    +          , dep_boot = is_boot
    
    352
    +          }
    
    353
    +
    
    354
    +    fail ->
    
    355
    +      return $
    
    356
    +        Left $
    
    357
    +          mkPlainErrorMsgEnvelope srcloc $
    
    358
    +          GhcDriverMessage $ DriverInterfaceError $
    
    359
    +             (Can'tFindInterface (cannotFindModule hsc_env mod_name fail) (LookingForModule mod_name is_boot))
    
    360
    +  where
    
    361
    +    L srcloc mod_name = ui_mod_name imp
    
    362
    +    is_boot           = ui_boot imp
    
    363
    +
    
    130 364
     -----------------------------------------------------------------
    
    131 365
     --
    
    132 366
     --              beginMkDependHs
    
    ... ... @@ -136,6 +370,14 @@ doMkDependModuleGraph dflags module_graph = do
    136 370
     --
    
    137 371
     -----------------------------------------------------------------
    
    138 372
     
    
    373
    +initFileDepWriter :: Logger -> FilePath -> TmpFs -> DynFlags -> DependencyWriter MkDepFiles
    
    374
    +initFileDepWriter logger root tmpfs dflags = DependencyWriter
    
    375
    +  { dw_beginWriter = beginMkDependHS logger tmpfs dflags
    
    376
    +  , dw_writeDependency = \ backend node deps -> do
    
    377
    +      writeDependencies (depIncludePkgDeps dflags) root (mkd_tmp_hdl backend) (depSuffixes dflags) node deps
    
    378
    +  , dw_endWriter = endMkDependHS logger
    
    379
    +  }
    
    380
    +
    
    139 381
     data MkDepFiles
    
    140 382
       = MkDep { mkd_make_file :: FilePath,          -- Name of the makefile
    
    141 383
                 mkd_make_hdl  :: Maybe Handle,      -- Handle for the open makefile
    
    ... ... @@ -188,138 +430,54 @@ beginMkDependHS logger tmpfs dflags = do
    188 430
       return (MkDep { mkd_make_file = makefile, mkd_make_hdl = mb_make_hdl,
    
    189 431
                       mkd_tmp_file  = tmp_file, mkd_tmp_hdl  = tmp_hdl})
    
    190 432
     
    
    433
    +writeDependencies ::
    
    434
    +  Bool ->
    
    435
    +  FilePath ->
    
    436
    +  Handle ->
    
    437
    +  [FilePath] ->
    
    438
    +  DepNode ->
    
    439
    +  [Dep] ->
    
    440
    +  IO ()
    
    441
    +writeDependencies include_pkgs root hdl suffixes node deps =
    
    442
    +  traverse_ write tasks
    
    443
    +  where
    
    444
    +    tasks = source_dep : boot_dep ++ concatMap import_dep deps
    
    445
    +
    
    446
    +    -- Emit std dependency of the object(s) on the source file
    
    447
    +    -- Something like       A.o : A.hs
    
    448
    +    source_dep = (obj_files, dn_src)
    
    449
    +
    
    450
    +    -- add dependency between objects and their corresponding .hi-boot
    
    451
    +    -- files if the module has a corresponding .hs-boot file (#14482)
    
    452
    +    boot_dep
    
    453
    +      | IsBoot <- dn_boot
    
    454
    +      = [([obj], hi) | (obj, hi) <- zip (suffixed (viaOsPath removeBootSuffix dn_obj)) (suffixed dn_hi)]
    
    455
    +      | otherwise
    
    456
    +      = []
    
    457
    +
    
    458
    +    -- Add one dependency for each suffix;
    
    459
    +    -- e.g.         A.o   : B.hi
    
    460
    +    --              A.x_o : B.x_hi
    
    461
    +    import_dep = \case
    
    462
    +      DepHi {dep_path, dep_boot, dep_unit}
    
    463
    +        | isNothing dep_unit || include_pkgs
    
    464
    +        , let path = if dep_boot == IsBoot then viaOsPath addBootSuffix dep_path else dep_path
    
    465
    +        -> [([obj], hi) | (obj, hi) <- zip obj_files (suffixed path)]
    
    191 466
     
    
    192
    ------------------------------------------------------------------
    
    193
    ---
    
    194
    ---              processDeps
    
    195
    ---
    
    196
    ------------------------------------------------------------------
    
    197
    -
    
    198
    -processDeps :: DynFlags
    
    199
    -            -> HscEnv
    
    200
    -            -> [ModuleName]
    
    201
    -            -> FilePath
    
    202
    -            -> Handle           -- Write dependencies to here
    
    203
    -            -> SCC ModuleGraphNode
    
    204
    -            -> IO ()
    
    205
    --- Write suitable dependencies to handle
    
    206
    --- Always:
    
    207
    ---                      this.o : this.hs
    
    208
    ---
    
    209
    --- If the dependency is on something other than a .hi file:
    
    210
    ---                      this.o this.p_o ... : dep
    
    211
    --- otherwise
    
    212
    ---                      this.o ...   : dep.hi
    
    213
    ---                      this.p_o ... : dep.p_hi
    
    214
    ---                      ...
    
    215
    --- (where .o is $osuf, and the other suffixes come from
    
    216
    --- the cmdline -s options).
    
    217
    ---
    
    218
    --- For {-# SOURCE #-} imports the "hi" will be "hi-boot".
    
    219
    -
    
    220
    -processDeps _ hsc_env _ _ _ (CyclicSCC nodes)
    
    221
    -  =     -- There shouldn't be any cycles; report them
    
    222
    -    throwOneError (initSourceErrorContext (hsc_dflags hsc_env)) $ cyclicModuleErr nodes
    
    223
    -
    
    224
    -processDeps _ hsc_env _ _ _ (AcyclicSCC (InstantiationNode _uid node))
    
    225
    -  =     -- There shouldn't be any backpack instantiations; report them as well
    
    226
    -    throwOneError (initSourceErrorContext (hsc_dflags hsc_env)) $
    
    227
    -      mkPlainErrorMsgEnvelope noSrcSpan $
    
    228
    -      GhcDriverMessage $ DriverInstantiationNodeInDependencyGeneration node
    
    229
    -
    
    230
    -processDeps _dflags _ _ _ _ (AcyclicSCC (LinkNode {})) = return ()
    
    231
    -processDeps _dflags _ _ _ _ (AcyclicSCC (UnitNode {})) = return ()
    
    232
    -processDeps _ _ _ _ _ (AcyclicSCC (ModuleNode _ (ModuleNodeFixed {})))
    
    233
    -  -- No dependencies needed for fixed modules (already compiled)
    
    234
    -  = return ()
    
    235
    -processDeps dflags hsc_env excl_mods root hdl (AcyclicSCC (ModuleNode _ (ModuleNodeCompile node)))
    
    236
    -  = do  { let extra_suffixes = depSuffixes dflags
    
    237
    -              include_pkg_deps = depIncludePkgDeps dflags
    
    238
    -              src_file  = msHsFilePath node
    
    239
    -              obj_file  = msObjFilePath node
    
    240
    -              obj_files = insertSuffixes obj_file extra_suffixes
    
    241
    -
    
    242
    -
    
    243
    -
    
    244
    -                -- Emit std dependency of the object(s) on the source file
    
    245
    -                -- Something like       A.o : A.hs
    
    246
    -        ; writeDependency root hdl obj_files src_file
    
    247
    -
    
    248
    -          -- add dependency between objects and their corresponding .hi-boot
    
    249
    -          -- files if the module has a corresponding .hs-boot file (#14482)
    
    250
    -        ; when (isBootSummary node == IsBoot) $ do
    
    251
    -            let hi_boot = msHiFilePath node
    
    252
    -            let obj     = unsafeDecodeUtf $ removeBootSuffix (msObjFileOsPath node)
    
    253
    -            forM_ extra_suffixes $ \suff -> do
    
    254
    -               let way_obj     = insertSuffixes obj     [suff]
    
    255
    -               let way_hi_boot = insertSuffixes hi_boot [suff]
    
    256
    -               mapM_ (writeDependency root hdl way_obj) way_hi_boot
    
    257
    -
    
    258
    -                -- Emit a dependency for each CPP import
    
    259
    -        ; when (depIncludeCppDeps dflags) $ do
    
    260
    -            -- CPP deps are discovered in the module parsing phase by parsing
    
    261
    -            -- comment lines left by the preprocessor.
    
    262
    -            -- Note that GHC.parseModule may throw an exception if the module
    
    263
    -            -- fails to parse, which may not be desirable (see #16616).
    
    264
    -          { session <- Session <$> newIORef hsc_env
    
    265
    -          ; parsedMod <- reflectGhc (GHC.parseModule node) session
    
    266
    -          ; mapM_ (writeDependency root hdl obj_files)
    
    267
    -                  (GHC.pm_extra_src_files parsedMod)
    
    268
    -          }
    
    269
    -
    
    270
    -                -- Emit a dependency for each import
    
    467
    +        | otherwise
    
    468
    +        -> []
    
    271 469
     
    
    272
    -        ; let find_deps imps = sequence
    
    273
    -                    [ findDependency hsc_env imp include_pkg_deps
    
    274
    -                    | imp <- imps
    
    275
    -                    , unLoc (ui_mod_name imp) `notElem` excl_mods
    
    276
    -                    ]
    
    470
    +      DepCpp {dep_path} -> [(obj_files, dep_path)]
    
    277 471
     
    
    278
    -              do_imp hi_file = do
    
    279
    -                let hi_files = insertSuffixes hi_file extra_suffixes
    
    280
    -                    write_dep (obj,hi) = writeDependency root hdl [obj] hi
    
    472
    +    write (from, to) = writeDependency root hdl from to
    
    281 473
     
    
    282
    -                 -- Add one dependency for each suffix;
    
    283
    -                 -- e.g.         A.o   : B.hi
    
    284
    -                 --              A.x_o : B.x_hi
    
    285
    -                mapM_ write_dep (obj_files `zip` hi_files)
    
    474
    +    obj_files = suffixed dn_obj
    
    286 475
     
    
    287
    -        ; (missing_dep_errs, deps) <- partitionEithers <$> find_deps (ms_imps node)
    
    476
    +    suffixed f = insertSuffixes f suffixes
    
    288 477
     
    
    289
    -        ; if null missing_dep_errs
    
    290
    -            then mapM_ (mapM_ do_imp) deps
    
    291
    -            else do
    
    292
    -              let sec = initSourceErrorContext (hsc_dflags hsc_env)
    
    293
    -              throwErrors sec (mkMessages (listToBag missing_dep_errs))
    
    294
    -        }
    
    478
    +    DepNode {dn_src, dn_obj, dn_hi, dn_boot} = node
    
    295 479
     
    
    296
    -findDependency  :: HscEnv
    
    297
    -                -> UnresolvedImport PkgQual   -- The import to find
    
    298
    -                -> Bool                 -- Record dependency on package modules
    
    299
    -                -> IO (Either (MsgEnvelope GhcMessage) (Maybe FilePath))  -- Interface file
    
    300
    -findDependency hsc_env imp include_pkg_deps = do
    
    301
    -  -- Find the module; this will be fast because
    
    302
    -  -- we've done it once during downsweep.
    
    303
    -  r <- resolveImport hsc_env imp
    
    304
    -  case r of
    
    305
    -    Found loc _
    
    306
    -        -- Home package: just depend on the .hi or hi-boot file
    
    307
    -        | isJust (ml_hs_file loc) || include_pkg_deps
    
    308
    -        -> return (Right (Just (ml_hi_file loc)))
    
    309
    -
    
    310
    -        -- Not in this package: we don't need a dependency
    
    311
    -        | otherwise
    
    312
    -        -> return (Right Nothing)
    
    313
    -
    
    314
    -    fail ->
    
    315
    -      return $
    
    316
    -        Left $
    
    317
    -          mkPlainErrorMsgEnvelope srcloc $
    
    318
    -          GhcDriverMessage $ DriverInterfaceError $
    
    319
    -             (Can'tFindInterface (cannotFindModule hsc_env mod_name fail) (LookingForModule mod_name is_boot))
    
    320
    -  where
    
    321
    -    L srcloc mod_name = ui_mod_name imp
    
    322
    -    is_boot           = ui_boot imp
    
    480
    +    viaOsPath f a = unsafeDecodeUtf (f (unsafeEncodeUtf a))
    
    323 481
     
    
    324 482
     -----------------------------
    
    325 483
     writeDependency :: FilePath -> Handle -> [FilePath] -> FilePath -> IO ()
    
    ... ... @@ -328,7 +486,7 @@ writeDependency :: FilePath -> Handle -> [FilePath] -> FilePath -> IO ()
    328 486
     writeDependency root hdl targets dep
    
    329 487
       = do let -- We need to avoid making deps on
    
    330 488
                --     c:/foo/...
    
    331
    -           -- on Windows as make gets confused by the :
    
    489
    +           -- on cygwin as make gets confused by the :
    
    332 490
                -- Making relative deps avoids some instances of this.
    
    333 491
                dep' = makeRelative root dep
    
    334 492
                forOutput = escapeSpaces . reslash Forwards . normalise
    
    ... ... @@ -352,11 +510,8 @@ insertSuffixes file_name extras
    352 510
     
    
    353 511
     
    
    354 512
     -----------------------------------------------------------------
    
    355
    ---
    
    356
    ---              endMkDependHs
    
    357
    ---      Complete the makefile, close the tmp file etc
    
    358
    ---
    
    359
    ------------------------------------------------------------------
    
    513
    +-- endMkDependHs
    
    514
    +-- Complete the makefile, close the tmp file etc
    
    360 515
     
    
    361 516
     endMkDependHS :: Logger -> MkDepFiles -> IO ()
    
    362 517
     
    
    ... ... @@ -385,6 +540,183 @@ endMkDependHS logger
    385 540
       showPass logger "Installing new makefile"
    
    386 541
       SysTools.copyFile tmp_file makefile
    
    387 542
     
    
    543
    +-----------------------------------------------------------------
    
    544
    +--
    
    545
    +--              JSON MkDepends output
    
    546
    +--
    
    547
    +-----------------------------------------------------------------
    
    548
    +
    
    549
    +initJsonDepWriter :: FilePath -> DynFlags -> DependencyWriter (JsonOutput DepJson)
    
    550
    +initJsonDepWriter output dflags = DependencyWriter
    
    551
    +  { dw_beginWriter = do
    
    552
    +      mkJsonOutput output initDepJson
    
    553
    +  , dw_writeDependency = \ backend node deps -> do
    
    554
    +      updateJson backend (updateDepJson (depIncludePkgDeps dflags) node deps)
    
    555
    +  , dw_endWriter =
    
    556
    +      writeJsonOutput
    
    557
    +  }
    
    558
    +
    
    559
    +--------------------------------------------------------------------------------
    
    560
    +-- Output interface for json dumps
    
    561
    +
    
    562
    +-- | Resources for a json dump option, used in "GHC.Driver.MakeFile".
    
    563
    +-- The flag @-dep-json@ add an additional output target for dependency
    
    564
    +-- diagnostics.
    
    565
    +data JsonOutput a =
    
    566
    +  JsonOutput {
    
    567
    +    -- | This ref is updated in @processDeps@ incrementally, using a
    
    568
    +    -- flag-specific type.
    
    569
    +    json_ref :: IORef a,
    
    570
    +
    
    571
    +    -- | The output file path specified as argument to the flag.
    
    572
    +    json_path :: FilePath
    
    573
    +  }
    
    574
    +
    
    575
    +-- | TODO: @fendor
    
    576
    +mkJsonOutput ::
    
    577
    +  FilePath ->
    
    578
    +  IO (IORef a) ->
    
    579
    +  IO (JsonOutput a)
    
    580
    +mkJsonOutput json_path mk_ref = do
    
    581
    +  json_ref <- mk_ref
    
    582
    +  pure JsonOutput {json_ref, json_path}
    
    583
    +
    
    584
    +-- | Update the dump data in 'json_ref' if the output target is present.
    
    585
    +updateJson :: JsonOutput a -> (a -> a) -> IO ()
    
    586
    +updateJson JsonOutput {json_ref} f = modifyIORef' json_ref f
    
    587
    +
    
    588
    +-- | Write a json object to the flag-dependent file if the output target is
    
    589
    +-- present.
    
    590
    +writeJsonOutput ::
    
    591
    +  ToJson a =>
    
    592
    +  JsonOutput a ->
    
    593
    +  IO ()
    
    594
    +writeJsonOutput JsonOutput {json_ref, json_path} = do
    
    595
    +  payload <- readIORef json_ref
    
    596
    +  writeJsonFile payload json_path
    
    597
    +
    
    598
    +--------------------------------------------------------------------------------
    
    599
    +-- Output helpers
    
    600
    +
    
    601
    +writeJsonFile :: ToJson a => a -> FilePath -> IO ()
    
    602
    +writeJsonFile doc p = do
    
    603
    +  withAtomicRename p
    
    604
    +    $ \tmp -> writeFile tmp $ showSDocUnsafe $ renderJSON $ json doc
    
    605
    +
    
    606
    +--------------------------------------------------------------------------------
    
    607
    +-- Payload for -dep-json
    
    608
    +
    
    609
    +newtype PackageDeps
    
    610
    +  = PackageDeps (Map.Map (String, UnitId, DPackageId) (Set.Set ModuleName))
    
    611
    +  deriving newtype (Monoid)
    
    612
    +
    
    613
    +newtype DPackageId = DPackageId PackageId
    
    614
    +  deriving newtype (Eq)
    
    615
    +
    
    616
    +instance Ord DPackageId where
    
    617
    +  DPackageId (PackageId d1) `compare` DPackageId (PackageId d2) = d1 `lexicalCompareFS` d2
    
    618
    +
    
    619
    +instance Semigroup PackageDeps where
    
    620
    +  PackageDeps l <> PackageDeps r = PackageDeps (Map.unionWith (Semigroup.<>) l r)
    
    621
    +
    
    622
    +data Deps
    
    623
    +  = Deps
    
    624
    +  { sources :: Set.Set FilePath
    
    625
    +  , modules :: (Set.Set ModuleName, Set.Set ModuleName)
    
    626
    +  , packages :: PackageDeps
    
    627
    +  , cpp :: Set.Set FilePath
    
    628
    +  , options :: [String]
    
    629
    +  , preprocessor :: Maybe FilePath
    
    630
    +  }
    
    631
    +  deriving stock (Generic)
    
    632
    +  deriving (Semigroup, Monoid) via (Generically Deps)
    
    633
    +
    
    634
    +newtype DepJson = DepJson (Map.Map ModuleName Deps)
    
    635
    +
    
    636
    +instance ToJson DepJson where
    
    637
    +  json (DepJson m) =
    
    638
    +    JSObject [
    
    639
    +      (moduleNameString target, JSObject [
    
    640
    +        ("sources", array sources normalise),
    
    641
    +        ("modules", array (fst modules) moduleNameString),
    
    642
    +        ("modules-boot", array (snd modules) moduleNameString),
    
    643
    +        ("packages",
    
    644
    +          JSArray
    
    645
    +            [ package name unit_id package_id mods
    
    646
    +            | ((name, unit_id, dpkd_id), mods) <- Map.toList packages
    
    647
    +            , let DPackageId package_id = dpkd_id
    
    648
    +            ]
    
    649
    +        ),
    
    650
    +        ("cpp", array cpp id),
    
    651
    +        ("options", JSArray $ map JSString options),
    
    652
    +        ("preprocessor", maybe JSNull JSString preprocessor)
    
    653
    +      ])
    
    654
    +      | (target, Deps {packages = PackageDeps packages, ..}) <- Map.toList m
    
    655
    +    ]
    
    656
    +    where
    
    657
    +      package name unit_id (PackageId package_id) mods =
    
    658
    +        JSObject [
    
    659
    +          ("id", JSString (unitIdString unit_id)),
    
    660
    +          ("name", JSString name),
    
    661
    +          ("package-id", JSString (unpackFS package_id)),
    
    662
    +          ("modules", array mods moduleNameString)
    
    663
    +        ]
    
    664
    +
    
    665
    +      array values render = JSArray (fmap (JSString . render) (Set.toList values))
    
    666
    +
    
    667
    +initDepJson :: IO (IORef DepJson)
    
    668
    +initDepJson = newIORef $ DepJson Map.empty
    
    669
    +
    
    670
    +insertDepJson :: [ModuleName] -> Deps -> DepJson -> DepJson
    
    671
    +insertDepJson targets dep (DepJson m0) =
    
    672
    +  DepJson
    
    673
    +    $ foldl'
    
    674
    +      ( \acc target ->
    
    675
    +          Map.insertWith
    
    676
    +            (Semigroup.<>)
    
    677
    +            target
    
    678
    +            dep
    
    679
    +            acc
    
    680
    +      )
    
    681
    +      m0
    
    682
    +      targets
    
    683
    +
    
    684
    +updateDepJson :: Bool -> DepNode -> [Dep] -> DepJson -> DepJson
    
    685
    +updateDepJson include_pkgs DepNode {..} deps =
    
    686
    +  insertDepJson [moduleName dn_mod] payload
    
    687
    +  where
    
    688
    +    payload = node_data Semigroup.<> foldMap dep deps
    
    689
    +
    
    690
    +    node_data =
    
    691
    +      mempty {
    
    692
    +        sources = Set.singleton dn_src,
    
    693
    +        preprocessor = pn_preprocessor dn_preprocessing,
    
    694
    +        options = pn_options dn_preprocessing
    
    695
    +      }
    
    696
    +
    
    697
    +    dep = \case
    
    698
    +      DepHi {dep_mod, dep_local, dep_unit, dep_boot}
    
    699
    +        | dep_local
    
    700
    +        , let set = Set.singleton $ moduleName dep_mod
    
    701
    +              value | IsBoot <- dep_boot = (Set.empty, set)
    
    702
    +                    | otherwise = (set, Set.empty)
    
    703
    +        -> mempty {modules = value}
    
    704
    +
    
    705
    +        | include_pkgs
    
    706
    +        , Just unit <- dep_unit
    
    707
    +        , let PackageName nameFS = unitPackageName unit
    
    708
    +              name = unpackFS nameFS
    
    709
    +              withLibName (PackageName c) = name ++ ":" ++ unpackFS c
    
    710
    +              lname = maybe name withLibName (unitComponentName unit)
    
    711
    +              key = (lname, unitId unit, DPackageId $ unitPackageId unit)
    
    712
    +        -> mempty {packages = PackageDeps (Map.singleton key (Set.singleton $ moduleName dep_mod))}
    
    713
    +
    
    714
    +        | otherwise
    
    715
    +        -> mempty
    
    716
    +
    
    717
    +      DepCpp {dep_path} ->
    
    718
    +        mempty {cpp = Set.singleton dep_path}
    
    719
    +
    
    388 720
     
    
    389 721
     -----------------------------------------------------------------
    
    390 722
     --              Module cycles
    

  • compiler/GHC/Driver/Pipeline.hs
    ... ... @@ -820,13 +820,13 @@ preprocessPipeline pipe_env hsc_env input_fn = do
    820 820
           use (T_Unlit pipe_env hsc_env input_fn)
    
    821 821
     
    
    822 822
     
    
    823
    -  (dflags1, p_warns1, warns1) <- use (T_FileArgs hsc_env unlit_fn)
    
    823
    +  (dflags1, _, p_warns1, warns1) <- use (fileArgsPhase hsc_env unlit_fn)
    
    824 824
       let hsc_env1 = hscSetFlags dflags1 hsc_env
    
    825 825
     
    
    826 826
       (cpp_fn, hsc_env2)
    
    827 827
         <- runAfterFlag hsc_env1 (Cpp HsSrcFile) (xopt LangExt.Cpp) (unlit_fn, hsc_env1) $ do
    
    828 828
               cpp_fn <- use (T_Cpp pipe_env hsc_env1 unlit_fn)
    
    829
    -          (dflags2, _, _) <- use (T_FileArgs hsc_env1 cpp_fn)
    
    829
    +          (dflags2, _, _, _) <- use (fileArgsPhase hsc_env1 cpp_fn)
    
    830 830
               let hsc_env2 = hscSetFlags dflags2 hsc_env1
    
    831 831
               return (cpp_fn, hsc_env2)
    
    832 832
     
    
    ... ... @@ -841,7 +841,8 @@ preprocessPipeline pipe_env hsc_env input_fn = do
    841 841
               then return (dflags1, p_warns1, warns1)
    
    842 842
               else do
    
    843 843
                 -- Reparse with original hsc_env so that we don't get duplicated options
    
    844
    -            use (T_FileArgs hsc_env pp_fn)
    
    844
    +            (dflagsPP, _, p_warns3, warns3) <- use (fileArgsPhase hsc_env pp_fn)
    
    845
    +            pure (dflagsPP, p_warns3, warns3)
    
    845 846
     
    
    846 847
       let print_config = initPrintConfig dflags3
    
    847 848
       liftIO (printOrThrowDiagnostics (hsc_logger hsc_env) print_config (initDiagOpts dflags3) (GhcPsMessage <$> p_warns3))
    
    ... ... @@ -865,6 +866,9 @@ preprocessPipeline pipe_env hsc_env input_fn = do
    865 866
               runAfter phase def
    
    866 867
                $ phaseIfFlag hsc_env flag def action
    
    867 868
     
    
    869
    +        fileArgsPhase env fn =
    
    870
    +          T_FileArgs (hsc_logger env) (hsc_dflags env) fn
    
    871
    +
    
    868 872
     -- | The complete compilation pipeline, from start to finish
    
    869 873
     fullPipeline :: P m => PipeEnv -> HscEnv -> FilePath -> HscSource -> m (ModIface, RecompLinkables)
    
    870 874
     fullPipeline pipe_env hsc_env pp_fn src_flavour = do
    

  • compiler/GHC/Driver/Pipeline/Execute.hs
    ... ... @@ -104,7 +104,7 @@ runPhase :: TPhase out -> IO out
    104 104
     runPhase (T_Unlit pipe_env hsc_env inp_path) = do
    
    105 105
       out_path <- phaseOutputFilenameNew (Cpp HsSrcFile) pipe_env hsc_env Nothing
    
    106 106
       runUnlitPhase hsc_env inp_path out_path
    
    107
    -runPhase (T_FileArgs hsc_env inp_path) = getFileArgs hsc_env inp_path
    
    107
    +runPhase (T_FileArgs logger dflags inp_path) = getFileArgsNoHsc logger dflags inp_path
    
    108 108
     runPhase (T_Cpp pipe_env hsc_env inp_path) = do
    
    109 109
       out_path <- phaseOutputFilenameNew (HsPp HsSrcFile) pipe_env hsc_env Nothing
    
    110 110
       runCppPhase hsc_env inp_path out_path
    
    ... ... @@ -620,17 +620,21 @@ runUnlitPhase hsc_env input_fn output_fn = do
    620 620
     
    
    621 621
         return output_fn
    
    622 622
     
    
    623
    -getFileArgs :: HscEnv -> FilePath -> IO ((DynFlags, Messages PsMessage, Messages DriverMessage))
    
    623
    +getFileArgs :: HscEnv -> FilePath -> IO ((DynFlags, [String], Messages PsMessage, Messages DriverMessage))
    
    624 624
     getFileArgs hsc_env input_fn = do
    
    625 625
       let dflags0 = hsc_dflags hsc_env
    
    626 626
           logger  = hsc_logger hsc_env
    
    627
    -      parser_opts = initParserOpts dflags0
    
    627
    +  getFileArgsNoHsc logger dflags0 input_fn
    
    628
    +
    
    629
    +getFileArgsNoHsc :: Logger -> DynFlags -> FilePath -> IO ((DynFlags, [String], Messages PsMessage, Messages DriverMessage))
    
    630
    +getFileArgsNoHsc logger dflags0 input_fn = do
    
    631
    +  let parser_opts = initParserOpts dflags0
    
    628 632
           sec = initSourceErrorContext dflags0
    
    629 633
       (warns0, src_opts) <- getOptionsFromFile parser_opts sec (supportedLanguagePragmas dflags0) input_fn
    
    630 634
       (dflags1, unhandled_flags, warns)
    
    631 635
         <- parseDynamicFilePragma logger dflags0 src_opts
    
    632 636
       checkProcessArgsResult dflags0 unhandled_flags
    
    633
    -  return (dflags1, warns0, warns)
    
    637
    +  return (dflags1, map unLoc src_opts, warns0, warns)
    
    634 638
     
    
    635 639
     runCppPhase :: HscEnv -> FilePath -> FilePath -> IO FilePath
    
    636 640
     runCppPhase hsc_env input_fn output_fn = do
    

  • compiler/GHC/Driver/Pipeline/Phases.hs
    ... ... @@ -13,6 +13,7 @@ import GHC.Driver.Errors.Types
    13 13
     import GHC.Fingerprint.Type
    
    14 14
     import GHC.Unit.Module.Location ( ModLocation )
    
    15 15
     import GHC.Unit.Module.ModIface
    
    16
    +import GHC.Utils.Logger
    
    16 17
     import GHC.Driver.Phases
    
    17 18
     
    
    18 19
     import Language.Haskell.Syntax.Module.Name ( ModuleName )
    
    ... ... @@ -25,7 +26,7 @@ import GHC.Unit.Home.ModInfo
    25 26
     -- phase if the inputs have been modified.
    
    26 27
     data TPhase res where
    
    27 28
       T_Unlit :: PipeEnv -> HscEnv -> FilePath -> TPhase FilePath
    
    28
    -  T_FileArgs :: HscEnv -> FilePath -> TPhase (DynFlags, Messages PsMessage, Messages DriverMessage)
    
    29
    +  T_FileArgs :: Logger -> DynFlags -> FilePath -> TPhase ((DynFlags, [String], Messages PsMessage, Messages DriverMessage))
    
    29 30
       T_Cpp   :: PipeEnv -> HscEnv -> FilePath -> TPhase FilePath
    
    30 31
       T_HsPp  :: PipeEnv -> HscEnv -> FilePath -> FilePath -> TPhase FilePath
    
    31 32
       T_HscRecomp :: PipeEnv -> HscEnv -> FilePath -> HscSource -> TPhase (HscEnv, ModSummary, HscRecompStatus)
    

  • compiler/GHC/Driver/Session.hs
    ... ... @@ -760,6 +760,9 @@ addOptCmmP f = alterToolSettings $ \s -> s
    760 760
     setDepMakefile :: FilePath -> DynFlags -> DynFlags
    
    761 761
     setDepMakefile f d = d { depMakefile = f }
    
    762 762
     
    
    763
    +setDepJson :: FilePath -> DynFlags -> DynFlags
    
    764
    +setDepJson f d = d { depJson = Just f }
    
    765
    +
    
    763 766
     setDepIncludeCppDeps :: Bool -> DynFlags -> DynFlags
    
    764 767
     setDepIncludeCppDeps b d = d { depIncludeCppDeps = b }
    
    765 768
     
    
    ... ... @@ -1245,6 +1248,7 @@ dynamic_flags_deps = [
    1245 1248
             -------- ghc -M -----------------------------------------------------
    
    1246 1249
       , make_ord_flag defGhcFlag "dep-suffix"              (hasArg addDepSuffix)
    
    1247 1250
       , make_ord_flag defGhcFlag "dep-makefile"            (hasArg setDepMakefile)
    
    1251
    +  , make_ord_flag defGhcFlag "dep-json"                (hasArg setDepJson)
    
    1248 1252
       , make_ord_flag defGhcFlag "include-cpp-deps"
    
    1249 1253
             (noArg (setDepIncludeCppDeps True))
    
    1250 1254
       , make_ord_flag defGhcFlag "include-pkg-deps"
    

  • testsuite/tests/driver/T24384/A.hs
    1
    +{-# language Strict #-}
    
    2
    +{-# options_ghc -fexpose-all-unfoldings #-}
    
    3
    +module A where
    
    4
    +
    
    5
    +import {-# source #-} C

  • testsuite/tests/driver/T24384/C.hs
    1
    +module C where
    
    2
    +
    
    3
    +import A
    
    4
    +import Data.Set
    
    5
    +
    
    6
    +data C = C

  • testsuite/tests/driver/T24384/C.hs-boot
    1
    +module C where
    
    2
    +
    
    3
    +import E
    
    4
    +
    
    5
    +data C

  • testsuite/tests/driver/T24384/D.hs
    1
    +module D where
    
    2
    +
    
    3
    +import B
    
    4
    +import C

  • testsuite/tests/driver/T24384/E.hs
    1
    +module E where
    
    2
    +
    
    3
    +import Language.Haskell.TH.Syntax
    
    4
    +import Dep
    
    5
    +import DepPublic
    
    6
    +
    
    7
    +e :: Q Exp
    
    8
    +e = lift (5 :: Integer)
    
    9
    +
    
    10
    +edep :: ()
    
    11
    +edep = dep
    
    12
    +
    
    13
    +edepPub :: ()
    
    14
    +edepPub = depPub

  • testsuite/tests/driver/T24384/Makefile
    1
    +TOP=../../..
    
    2
    +include $(TOP)/mk/boilerplate.mk
    
    3
    +include $(TOP)/mk/test.mk
    
    4
    +
    
    5
    +
    
    6
    +PKGCONF_LOCAL=./db.package.conf
    
    7
    +GHC_PKG_LOCAL='$(GHC_PKG)' --no-user-package-db -f $(PKGCONF_LOCAL)
    
    8
    +
    
    9
    +T24384:
    
    10
    +	$(GHC_PKG_LOCAL) init $(PKGCONF_LOCAL) 2>&1 >/dev/null
    
    11
    +
    
    12
    +	cd dep-internal && \
    
    13
    +		'$(TEST_HC)' $(TEST_HC_OPTS) $(WAY_FLAGS) -hisuf=$(ghciWayExt) $(ghciWayFlags) \
    
    14
    +			-v0 -fno-code -fwrite-interface -hidir outdir -this-unit-id dep-internal-1-XXX  \
    
    15
    +			-package base \
    
    16
    +			-i. DepInternal
    
    17
    +	$(GHC_PKG_LOCAL) register --force dep-internal/dep-internal.pkg 2>&1 >/dev/null
    
    18
    +
    
    19
    +	cd dep-public && \
    
    20
    +		'$(TEST_HC)' $(TEST_HC_OPTS) $(WAY_FLAGS) -hisuf=$(ghciWayExt) $(ghciWayFlags) \
    
    21
    +			-v0 -fno-code -fwrite-interface -hidir outdir -this-unit-id dep-public-1-XXX  \
    
    22
    +			-package base \
    
    23
    +			-i. DepPublic
    
    24
    +	$(GHC_PKG_LOCAL) register --force dep-public/dep-public.pkg 2>&1 >/dev/null
    
    25
    +
    
    26
    +	cd dep && \
    
    27
    +		'$(TEST_HC)' $(TEST_HC_OPTS) $(WAY_FLAGS) -hisuf=$(ghciWayExt) $(ghciWayFlags) \
    
    28
    +			-v0 -fno-code -fwrite-interface -hidir outdir -this-unit-id dep-1-XXX \
    
    29
    +			-package-db ../$(PKGCONF_LOCAL) -package-id dep-internal-1-XXX \
    
    30
    +			-i. Dep
    
    31
    +	$(GHC_PKG_LOCAL) register --force dep/dep.pkg 2>&1 >/dev/null
    
    32
    +
    
    33
    +	'$(TEST_HC)' -M -dep-json dep.json -include-pkg-deps -include-cpp-deps \
    
    34
    +		-hide-all-packages -package base -package containers -package template-haskell \
    
    35
    +		-package-db ./$(PKGCONF_LOCAL) -package-id dep-1-XXX -package-id dep-public-1-XXX \
    
    36
    +		A.hs lib/B.hs C.hs D.hs E.hs
    
    37
    +
    
    38
    +	cat dep.json | jq --sort-keys

  • testsuite/tests/driver/T24384/T24384.stdout
    1
    +{
    
    2
    +  "A": {
    
    3
    +    "cpp": [],
    
    4
    +    "modules": [],
    
    5
    +    "modules-boot": [
    
    6
    +      "C"
    
    7
    +    ],
    
    8
    +    "options": [
    
    9
    +      "-XStrict",
    
    10
    +      "-fexpose-all-unfoldings"
    
    11
    +    ],
    
    12
    +    "packages": [
    
    13
    +      {
    
    14
    +        "id": "base-4.23.0.0-inplace",
    
    15
    +        "modules": [
    
    16
    +          "GHC.Essentials",
    
    17
    +          "Prelude"
    
    18
    +        ],
    
    19
    +        "name": "base",
    
    20
    +        "package-id": "base-4.23.0.0"
    
    21
    +      }
    
    22
    +    ],
    
    23
    +    "preprocessor": null,
    
    24
    +    "sources": [
    
    25
    +      "A.hs"
    
    26
    +    ]
    
    27
    +  },
    
    28
    +  "B": {
    
    29
    +    "cpp": [],
    
    30
    +    "modules": [
    
    31
    +      "A"
    
    32
    +    ],
    
    33
    +    "modules-boot": [],
    
    34
    +    "options": [
    
    35
    +      "-F",
    
    36
    +      "-pgmF",
    
    37
    +      "./preproc.sh"
    
    38
    +    ],
    
    39
    +    "packages": [
    
    40
    +      {
    
    41
    +        "id": "base-4.23.0.0-inplace",
    
    42
    +        "modules": [
    
    43
    +          "GHC.Essentials",
    
    44
    +          "Prelude"
    
    45
    +        ],
    
    46
    +        "name": "base",
    
    47
    +        "package-id": "base-4.23.0.0"
    
    48
    +      }
    
    49
    +    ],
    
    50
    +    "preprocessor": "./preproc.sh",
    
    51
    +    "sources": [
    
    52
    +      "lib/B.hs"
    
    53
    +    ]
    
    54
    +  },
    
    55
    +  "C": {
    
    56
    +    "cpp": [],
    
    57
    +    "modules": [
    
    58
    +      "A",
    
    59
    +      "E"
    
    60
    +    ],
    
    61
    +    "modules-boot": [],
    
    62
    +    "options": [],
    
    63
    +    "packages": [
    
    64
    +      {
    
    65
    +        "id": "base-4.23.0.0-inplace",
    
    66
    +        "modules": [
    
    67
    +          "GHC.Essentials",
    
    68
    +          "Prelude"
    
    69
    +        ],
    
    70
    +        "name": "base",
    
    71
    +        "package-id": "base-4.23.0.0"
    
    72
    +      },
    
    73
    +      {
    
    74
    +        "id": "containers-0.8-inplace",
    
    75
    +        "modules": [
    
    76
    +          "Data.Set"
    
    77
    +        ],
    
    78
    +        "name": "containers",
    
    79
    +        "package-id": "containers-0.8"
    
    80
    +      }
    
    81
    +    ],
    
    82
    +    "preprocessor": null,
    
    83
    +    "sources": [
    
    84
    +      "C.hs",
    
    85
    +      "C.hs-boot"
    
    86
    +    ]
    
    87
    +  },
    
    88
    +  "D": {
    
    89
    +    "cpp": [],
    
    90
    +    "modules": [
    
    91
    +      "B",
    
    92
    +      "C"
    
    93
    +    ],
    
    94
    +    "modules-boot": [],
    
    95
    +    "options": [],
    
    96
    +    "packages": [
    
    97
    +      {
    
    98
    +        "id": "base-4.23.0.0-inplace",
    
    99
    +        "modules": [
    
    100
    +          "GHC.Essentials",
    
    101
    +          "Prelude"
    
    102
    +        ],
    
    103
    +        "name": "base",
    
    104
    +        "package-id": "base-4.23.0.0"
    
    105
    +      }
    
    106
    +    ],
    
    107
    +    "preprocessor": null,
    
    108
    +    "sources": [
    
    109
    +      "D.hs"
    
    110
    +    ]
    
    111
    +  },
    
    112
    +  "E": {
    
    113
    +    "cpp": [],
    
    114
    +    "modules": [],
    
    115
    +    "modules-boot": [],
    
    116
    +    "options": [],
    
    117
    +    "packages": [
    
    118
    +      {
    
    119
    +        "id": "base-4.23.0.0-inplace",
    
    120
    +        "modules": [
    
    121
    +          "GHC.Essentials",
    
    122
    +          "Prelude"
    
    123
    +        ],
    
    124
    +        "name": "base",
    
    125
    +        "package-id": "base-4.23.0.0"
    
    126
    +      },
    
    127
    +      {
    
    128
    +        "id": "dep-1-XXX",
    
    129
    +        "modules": [
    
    130
    +          "Dep"
    
    131
    +        ],
    
    132
    +        "name": "dep",
    
    133
    +        "package-id": "dep-1"
    
    134
    +      },
    
    135
    +      {
    
    136
    +        "id": "dep-public-1-XXX",
    
    137
    +        "modules": [
    
    138
    +          "DepPublic"
    
    139
    +        ],
    
    140
    +        "name": "dep-public",
    
    141
    +        "package-id": "dep-public-1"
    
    142
    +      },
    
    143
    +      {
    
    144
    +        "id": "template-haskell-2.25.0.0-inplace",
    
    145
    +        "modules": [
    
    146
    +          "Language.Haskell.TH.Syntax"
    
    147
    +        ],
    
    148
    +        "name": "template-haskell",
    
    149
    +        "package-id": "template-haskell-2.25.0.0"
    
    150
    +      }
    
    151
    +    ],
    
    152
    +    "preprocessor": null,
    
    153
    +    "sources": [
    
    154
    +      "E.hs"
    
    155
    +    ]
    
    156
    +  }
    
    157
    +}

  • testsuite/tests/driver/T24384/all.T
    1
    +test('T24384',
    
    2
    +    [ extra_files(['A.hs', 'lib/', 'C.hs', 'C.hs-boot', 'D.hs', 'E.hs',
    
    3
    +      'dep', 'dep-internal', 'dep-public',
    
    4
    +      'preproc.sh'
    
    5
    +      ])
    
    6
    +    ],
    
    7
    +    makefile_test, [])

  • testsuite/tests/driver/T24384/dep-internal/DepInternal.hs
    1
    +module DepInternal where
    
    2
    +depInt :: ()
    
    3
    +depInt = ()

  • testsuite/tests/driver/T24384/dep-internal/dep-internal.pkg
    1
    +name: dep-internal
    
    2
    +version: 1
    
    3
    +id: dep-internal-1-XXX
    
    4
    +key: dep-internal-1-XXX
    
    5
    +visibility:           public
    
    6
    +abi: inplace
    
    7
    +exposed-modules:      DepInternal
    
    8
    +depends:
    
    9
    +import-dirs: ${pkgroot}/dep-internal/outdir
    
    10
    +library-dirs: ${pkgroot}/dep-internal/outdir
    
    11
    +include-dirs:

  • testsuite/tests/driver/T24384/dep-public/DepPublic.hs
    1
    +module DepPublic where
    
    2
    +depPub :: ()
    
    3
    +depPub = ()

  • testsuite/tests/driver/T24384/dep-public/dep-public.pkg
    1
    +name: dep-public
    
    2
    +version: 1
    
    3
    +id: dep-public-1-XXX
    
    4
    +key: dep-public-1-XXX
    
    5
    +visibility:           public
    
    6
    +abi: inplace
    
    7
    +exposed-modules:      DepPublic
    
    8
    +depends:
    
    9
    +import-dirs: ${pkgroot}/dep-public/outdir
    
    10
    +library-dirs: ${pkgroot}/dep-public/outdir
    
    11
    +include-dirs:

  • testsuite/tests/driver/T24384/dep/Dep.hs
    1
    +module Dep where
    
    2
    +import DepInternal
    
    3
    +dep :: ()
    
    4
    +dep = depInt

  • testsuite/tests/driver/T24384/dep/dep.pkg
    1
    +name: dep
    
    2
    +version: 1
    
    3
    +id: dep-1-XXX
    
    4
    +key: dep-1-XXX
    
    5
    +visibility:           public
    
    6
    +abi: inplace
    
    7
    +exposed-modules:      Dep
    
    8
    +depends:              dep-internal-1-XXX
    
    9
    +import-dirs: ${pkgroot}/dep/outdir
    
    10
    +library-dirs: ${pkgroot}/dep/outdir
    
    11
    +include-dirs:

  • testsuite/tests/driver/T24384/lib/B.hs
    1
    +{-# options_ghc -F -pgmF ./preproc.sh #-}
    
    2
    +module B where

  • testsuite/tests/driver/T24384/preproc.sh
    1
    +#!/usr/bin/env bash
    
    2
    +
    
    3
    +sed '/preproc/d' $2 > $3
    
    4
    +echo 'import A' >> $3