diff --git a/CHANGES.txt b/CHANGES.txt
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,7 @@
 Changelog for Weeder
 
+1.0.9, released 2020-06-11
+    #55, fix handling of internal libraries
 1.0.8, released 2018-08-26
     #42, make paths case-insensitive on MacOS
 1.0.7, released 2018-08-23
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright Neil Mitchell 2017-2018.
+Copyright Neil Mitchell 2017-2020.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,9 +1,16 @@
-# Weeder [![Hackage version](https://img.shields.io/hackage/v/weeder.svg?label=Hackage)](https://hackage.haskell.org/package/weeder) [![Stackage version](https://www.stackage.org/package/weeder/badge/nightly?label=Stackage)](https://www.stackage.org/package/weeder) [![Linux Build Status](https://img.shields.io/travis/ndmitchell/weeder/master.svg?label=Linux%20build)](https://travis-ci.org/ndmitchell/weeder) [![Windows Build Status](https://img.shields.io/appveyor/ci/ndmitchell/weeder/master.svg?label=Windows%20build)](https://ci.appveyor.com/project/ndmitchell/weeder)
+# Weeder [![Hackage version](https://img.shields.io/hackage/v/weeder.svg?label=Hackage)](https://hackage.haskell.org/package/weeder) [![Stackage version](https://www.stackage.org/package/weeder/badge/nightly?label=Stackage)](https://www.stackage.org/package/weeder) [![Linux build status](https://img.shields.io/travis/ndmitchell/weeder/master.svg?label=Linux%20build)](https://travis-ci.org/ndmitchell/weeder) [![Windows build status](https://img.shields.io/appveyor/ci/ndmitchell/weeder/master.svg?label=Windows%20build)](https://ci.appveyor.com/project/ndmitchell/weeder)
 
+# Weeder has moved!
+
+Weeder 2.0 is being developed at https://github.com/ocharles/weeder on different foundations. This repo is for historical reference only.
+
+-------------------
+
 Most projects accumulate code over time. Weeder detects unused Haskell exports, allowing dead code to be removed (pulling up the weeds). Weeder piggy-backs off files generated by [`stack`](https://www.haskellstack.org), so first obtain stack, then:
 
 * Install `weeder` by running `stack install weeder --resolver=nightly`.
 * Ensure your project has a `stack.yaml` file. If you don't normally build with `stack` then run `stack init` to generate one.
+* Make sure you have `ghc-options: {"$locals": -ddump-to-file -ddump-hi}` in your `stack.yaml`.
 * Run `weeder . --build`, which builds your project with `stack` and reports any weeds.
 
 ## What does Weeder detect?
@@ -47,19 +54,15 @@
 
 Before running Weeder on your continuous integration (CI) server, you should first ensure there are no existing weeds. One way to achieve that is to ignore existing hints by running `weeder . --yaml > .weeder.yaml` and checking in the resulting `.weeder.yaml`.
 
-On the CI you should then run `weeder .` (or `weeder . --build` to compile as well). To avoid the cost of compilation you may wish to fetch the [latest Weeder binary release](https://github.com/ndmitchell/weeder/releases/latest). For certain CI environments there are helper scripts to do that.
-
-**Travis:** Execute the following command:
-
-    curl -sSL https://raw.github.com/ndmitchell/weeder/master/misc/travis.sh | sh -s .
-
-The arguments after `-s` are passed to `weeder`, so modify the final `.` if you want other arguments.
+On the CI you should then run `weeder .` (or `weeder . --build` to compile as well). To avoid the cost of compilation you may wish to fetch the [latest Weeder binary release](https://github.com/ndmitchell/weeder/releases/latest).
 
-**Appveyor:** Add the following statement to `.appveyor.yml`:
+For the CI systems [Travis](https://travis-ci.org/), [Appveyor](https://www.appveyor.com/) and [Azure Pipelines](https://azure.microsoft.com/en-gb/services/devops/pipelines/) add the line:
 
-    - ps: Invoke-Command ([Scriptblock]::Create((Invoke-WebRequest 'https://raw.githubusercontent.com/ndmitchell/weeder/master/misc/appveyor.ps1').Content)) -ArgumentList @('.')
+```sh
+curl -sSL https://raw.github.com/ndmitchell/weeder/master/misc/run.sh | sh -s .
+```
 
-The arguments inside `@()` are passed to `weeder`, so add new arguments surrounded by `'`, space separated - e.g. `@('.' '--build')`.
+The arguments after `-s` are passed to `weeder`, so modify the final `.` if you want other arguments. This command works on Windows, Mac and Linux.
 
 ## What about Cabal users?
 
diff --git a/src/Cabal.hs b/src/Cabal.hs
--- a/src/Cabal.hs
+++ b/src/Cabal.hs
@@ -54,6 +54,7 @@
     [ joinPath (root : x : components) <.> "dump-hi"
     | extra <- [".",distDir]
     , root <- concat [["build" </> extra </> x </> (x ++ "-tmp")
+                      ,"build" </> extra </> x </> x
                       ,"build" </> extra </> x </> (x ++ "-tmp") </> distDir </> "build" </> x </> (x ++ "-tmp")]
                      | Just x <- [cabalSectionTypeName sectionType]] ++
               ["build", "build" </> distDir </> "build"]
@@ -72,27 +73,29 @@
     mempty = Cabal "" []
     mappend = (<>)
 
-data CabalSectionType = Library | Executable String | TestSuite String | Benchmark String
+data CabalSectionType = Library (Maybe String) | Executable String | TestSuite String | Benchmark String
     deriving (Eq,Ord)
 
 cabalSectionTypeName :: CabalSectionType -> Maybe String
-cabalSectionTypeName Library = Nothing
+cabalSectionTypeName (Library x) = x
 cabalSectionTypeName (Executable x) = Just x
 cabalSectionTypeName (TestSuite x) = Just x
 cabalSectionTypeName (Benchmark x) = Just x
 
 instance Show CabalSectionType where
-    show Library = "library"
+    show (Library Nothing) = "library"
+    show (Library (Just x)) = "library:" ++ x
     show (Executable x) = "exe:" ++ x
     show (TestSuite x) = "test:" ++ x
     show (Benchmark x) = "bench:" ++ x
 
 instance Read CabalSectionType where
-    readsPrec _ "library" = [(Library,"")]
+    readsPrec _ "library" = [(Library Nothing,"")]
     readsPrec _ x
         | Just x <- stripPrefix "exe:" x = [(Executable x, "")]
         | Just x <- stripPrefix "test:" x = [(TestSuite x, "")]
         | Just x <- stripPrefix "bench:" x = [(Benchmark x, "")]
+        | Just x <- stripPrefix "library:" x = [(Library (Just x), "")]
     readsPrec _ _ = []
 
 data CabalSection = CabalSection
@@ -109,20 +112,22 @@
         CabalSection x1 (x2?:y2) (x3<>y3) (x4<>y4) (x5<>y5) (x6<>y6)
 
 instance Monoid CabalSection where
-    mempty = CabalSection Library "" [] [] [] []
+    mempty = CabalSection (Library Nothing) "" [] [] [] []
     mappend = (<>)
 
 parseCabal :: FilePath -> IO Cabal
 parseCabal = fmap parseTop . readFile'
 
-parseTop = mconcat . map f . parseHanging . filter (not . isComment) . lines
+parseTop = mconcatMap f . parseHanging . filter (not . isComment) . lines
     where
         isComment = isPrefixOf "--" . trimStart
         keyName = (lower *** fst . word1) . word1
 
         f (keyName -> (key, name), xs) = case key of
             "name:" -> mempty{cabalName=name}
-            "library" -> mempty{cabalSections=[parseSection Library xs]}
+            "library" -> case name of
+                "" -> mempty{cabalSections=[parseSection (Library Nothing) xs]}
+                x -> mempty{cabalSections=[parseSection (Library (Just x)) xs]}
             "executable" -> mempty{cabalSections=[parseSection (Executable name) xs]}
             "test-suite" -> mempty{cabalSections=[parseSection (TestSuite name) xs]}
             "benchmark" -> mempty{cabalSections=[parseSection (Benchmark name) xs]}
@@ -130,7 +135,7 @@
 
 parseSection typ xs = mempty{cabalSectionType=typ} <> parse xs
     where
-        parse = mconcat . map f . parseHanging
+        parse = mconcatMap f . parseHanging
         keyValues (x,xs) = let (x1,x2) = word1 x in (lower x1, trimEqual $ filter (not . null) $ x2:xs)
         trimEqual xs = map (drop n) xs
             where n = minimum $ 0 : map (length . takeWhile isSpace) xs
@@ -145,5 +150,5 @@
             "hs-source-dirs:" -> mempty{cabalSourceDirs=listSplit vs}
             "exposed-modules:" -> mempty{cabalExposedModules=listSplit vs}
             "other-modules:" -> mempty{cabalOtherModules=listSplit vs}
-            "main-is:" -> mempty{cabalMainIs=head $ vs ++ [""]}
+            "main-is:" -> mempty{cabalMainIs=headDef "" vs}
             _ -> mempty
diff --git a/src/Check.hs b/src/Check.hs
--- a/src/Check.hs
+++ b/src/Check.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE RecordWildCards, NamedFieldPuns, ScopedTypeVariables #-}
+{-# LANGUAGE RecordWildCards, ScopedTypeVariables #-}
 
 module Check(check) where
 
@@ -51,6 +51,7 @@
     [ Warning pkg [cabalSectionType] "Redundant build-depends entry" (Just p) Nothing Nothing
     | (CabalSection{..}, (x1,x2,_)) <- sections
     , let usedPackages = Set.unions $ map (Set.map fst . hiImportPackageModule . hi) $ x1 ++ x2
+    , not $ "" `Set.member` usedPackages -- Sometimes we don't get the package name at all, e.g. https://gitlab.haskell.org/ghc/ghc/issues/16886
     , p <- Set.toList $ Set.fromList cabalPackages `Set.difference` usedPackages
     , p /= if isWindows then "unix" else "Win32" -- ignore packages that must be conditional on the other platform
     , p /= "semigroups" -- ignore packages that are often conditional
diff --git a/src/CmdLine.hs b/src/CmdLine.hs
--- a/src/CmdLine.hs
+++ b/src/CmdLine.hs
@@ -44,6 +44,6 @@
     ,cmdShowAll = nam "show-all" &= help "Show even ignored warnings"
     ,cmdDistDir = nam "dist-dir" &= typDir &= help "Stack dist-dir, defaults to 'stack path --dist-dir'"
     } &= explicit &= verbosity
-    &= name "weeder" &= program "weeder" &= summary ("Weeder v" ++ showVersion version ++ ", (C) Neil Mitchell 2017-2018")
+    &= name "weeder" &= program "weeder" &= summary ("Weeder v" ++ showVersion version ++ ", (C) Neil Mitchell 2017-2020")
     where
         nam xs = def &= explicit &= name xs &= name [head xs]
diff --git a/src/Hi.hs b/src/Hi.hs
--- a/src/Hi.hs
+++ b/src/Hi.hs
@@ -13,6 +13,7 @@
 import System.Time.Extra
 import GHC.Generics
 import Data.Tuple.Extra
+import Data.Maybe
 import Control.Monad
 import Control.Exception
 import Control.DeepSeq
@@ -106,16 +107,17 @@
     where names = Set.fromList [s | Ident m s <- Set.toList hiExportIdent, m == hiModuleName]
 
 hiParseContents :: Str -> Hi
-hiParseContents = mconcat . map f . parseHanging2 . S.linesCR
+hiParseContents = mconcatMap f . parseHanging2 . S.linesCR
     where
         f (x,xs)
             | Just x <- S.stripPrefix "interface " x = mempty{hiModuleName = parseInterface $ S.toList x}
-            | Just x <- S.stripPrefix "exports:" x = mconcat $ map (parseExports . S.toList) $ unindent2 xs
+            | Just x <- S.stripPrefix "exports:" x = mconcatMap (parseExports . S.toList) $ unindent2 xs
             | Just x <- S.stripPrefix "orphans:" x = mempty{hiImportOrphan = Set.fromList $ map parseInterface $ concatMap (words . S.toList) $ x:xs}
             | Just x <- S.stripPrefix "package dependencies:" x = mempty{hiImportPackage = Set.fromList $ map parsePackDep $ concatMap (words . S.toList) $ x:xs}
             | Just x <- S.stripPrefix "import " x = case unindent2 xs of
-                [] | (pkg, mod) <- breakOn ":" $ words (S.toList x) !! 1 -> mempty
-                    {hiImportPackageModule = Set.singleton (parsePackDep pkg, drop 1 mod)}
+                [] | let s = words (S.toList x) !! 1
+                   , (pkg, mod) <- fromMaybe ("", s) $ stripInfix ":" s -> mempty
+                    {hiImportPackageModule = Set.singleton (parsePackDep pkg, mod)}
                 xs -> let m = words (S.toList x) !! 1 in mempty
                     {hiImportModule = Set.singleton m
                     ,hiImportIdent = Set.fromList $ map (Ident m . fst . word1 . S.toList) $ dropWhile ("exports:" `S.isPrefixOf`) xs}
diff --git a/src/Warning.hs b/src/Warning.hs
--- a/src/Warning.hs
+++ b/src/Warning.hs
@@ -124,7 +124,7 @@
 
 readWarningsFile :: FilePath -> IO [Warning]
 readWarningsFile file = do
-    x <- either throwIO return =<< Yaml.decodeFileEither file
+    x <- eitherM throwIO return $ Yaml.decodeFileEither file
     let res = map warningUnpath $ concatMap (f warningLabels) $ valueToVal x
     mapM_ evaluate res -- ensure exceptions happen immediately
     return res
diff --git a/weeder.cabal b/weeder.cabal
--- a/weeder.cabal
+++ b/weeder.cabal
@@ -1,13 +1,13 @@
 cabal-version:      >= 1.18
 build-type:         Simple
 name:               weeder
-version:            1.0.8
+version:            1.0.9
 license:            BSD3
 license-file:       LICENSE
 category:           Development
 author:             Neil Mitchell <ndmitchell@gmail.com>
 maintainer:         Neil Mitchell <ndmitchell@gmail.com>
-copyright:          Neil Mitchell 2017-2018
+copyright:          Neil Mitchell 2017-2020
 synopsis:           Detect dead code
 description:
     Find redundant package dependencies or redundant module exports.
@@ -16,7 +16,7 @@
 extra-doc-files:
     README.md
     CHANGES.txt
-tested-with:        GHC==8.4.3, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3
+tested-with:        GHC==8.10.1, GHC==8.8.3, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2
 
 source-repository head
     type:     git
