diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,192 @@
+# hpack: An alternative format for Haskell packages
+
+## Examples
+
+ * Given this [package.yaml](https://github.com/sol/hpack/blob/master/package.yaml) running `hpack` will generate [hpack.cabal](https://github.com/sol/hpack/blob/master/hpack.cabal)
+ * Given this [package.yaml](https://github.com/zalora/getopt-generics/blob/master/package.yaml) running `hpack` will generate [getopt-generics.cabal](https://github.com/zalora/getopt-generics/blob/master/getopt-generics.cabal)
+ * Given this [package.yaml](https://github.com/hspec/sensei/blob/master/package.yaml) running `hpack` will generate [sensei.cabal](https://github.com/hspec/sensei/blob/master/sensei.cabal)
+ * Given this [package.yaml](https://github.com/haskell-compat/base-orphans/blob/master/package.yaml) running `hpack` will generate [base-orphans.cabal](https://github.com/haskell-compat/base-orphans/blob/master/base-orphans.cabal)
+
+## Documentation
+
+### Getting started
+
+One easy way of getting started is to use
+[hpack-convert](http://hackage.haskell.org/package/hpack-convert) to convert an
+existing cabal file into a `package.yaml`.
+
+### Quick-reference
+
+#### Top-level fields
+
+| Hpack | Cabal | Default | Notes | Example |
+| --- | --- | --- | --- | --- |
+| `name` | `name` | | | |
+| `version` | `version` | `0.0.0` | | |
+| `synopsis` | `synopsis` | | | |
+| `description` | `description` | | | |
+| `category` | `category` | | | |
+| `stability` | `stability` | | | |
+| `homepage` | `homepage` | If `github` given, `<repo>#readme` | | |
+| `bug-reports` | `bug-reports` | If `github` given, `<repo>/issues` | | |
+| `author` | `author` | | May be a list | |
+| `maintainer` | `maintainer` | | May be a list | |
+| `copyright` | `copyright` | | May be a list |
+| `license` | `license` | | | |
+| `license-file` | `license-file` | `LICENSE` if file exists | | |
+| `tested-with` | `tested-with` | | | |
+| `build-type` | `build-type` | `Simple` | Must be `Simple`, `Configure`, `Make`, or `Custom` | |
+| | `cabal-version` | `>= 1.10` or `>= 1.21` | `>= 1.21` if library component has `reexported-modules` field | |
+| `extra-source-files` | `extra-source-files` | | Accepts [glob patterns](#file-globbing) | |
+| `data-files` | `data-files` | | Accepts [glob patterns](#file-globbing) | |
+| `github` | `source-repository head` | | Accepts `user/repo` or `user/repo/subdir` | `github: foo/bar`
+| `git`    | `source-repository head` | | No effect if `github` given | `git: https://my.repo.com/foo` |
+| `flags`  | `flag <name>` | | Map from flag name to flag (see [Flags](#flags)) | |
+| `library` | `library` | | See [Library fields](#library-fields) | |
+| `executables` | `executable <name>` | | Map from executable name to executable (see [Executable fields](#executable-fields)) | |
+| `tests` | `test-suite <name>` | | Map from test name to test (see [Test fields](#test-fields)) | |
+| `benchmarks` | `benchmark <name>` | | Map from benchmark name to benchmark (see [Benchmark fields](#benchmark-fields)) | |
+
+#### Global top-level fields
+
+These fields are merged with all library, executable, test, and benchmark components.
+
+| Hpack | Cabal | Default | Notes |
+| --- | --- | --- | --- |
+| `source-dirs` | `hs-source-dirs` | | |
+| `default-extensions` | `default-extensions` | | |
+| `other-extension` | `other-extensions` | | |
+| `ghc-options` | `ghc-options` | | |
+| `ghc-prof-options` | `ghc-prof-options` | | |
+| `cpp-options` | `cpp-options` | | |
+| `cc-options` | `cc-options` | | |
+| `c-sources` | `c-sources` | | |
+| `extra-lib-dirs` | `extra-lib-dirs` | | |
+| `extra-libraries` | `extra-libraries` | | |
+| `include-dirs` | `include-dirs` | | |
+| `install-includes` | `install-includes` | | |
+| `ld-options` | `ld-options` | | |
+| `buildable` | `buildable` | | May be overridden by later stanza |
+| `dependencies` | `build-depends` | | |
+| `build-tools` | `build-tools` | | |
+| `when` | | | Accepts a list of conditionals (see [Conditionals](#conditionals)) |
+
+#### <a name="library-fields"></a>Library fields
+
+| Hpack | Cabal | Default | Notes |
+| --- | --- | --- | --- |
+| `exposed` | `exposed` | | |
+| `exposed-modules` | `exposed-modules` | All modules in `source-dirs` less `other-modules` | |
+| `other-modules` | `other-modules` | All modules in `source-dirs` less `exposed-modules` | |
+| `reexported-modules` | `reexported-modules` | | |
+| | `default-language` | `Haskell2010` | |
+
+#### <a name="executable-fields"></a>Executable fields
+
+| Hpack | Cabal | Default | Notes |
+| --- | --- | --- | --- |
+| `main` | `main-is` | | |
+| `other-modules` | `other-modules` | | |
+| | `default-language` | `Haskell2010` | |
+
+#### <a name="test-fields"></a>Test fields
+
+| Hpack | Cabal | Default | Notes |
+| --- | --- | --- | --- |
+| | `type` | `exitcode-stdio-1.0` | |
+| `main` | `main-is` | | |
+| `other-modules` | `other-modules` | | |
+| | `default-language` | `Haskell2010` | |
+
+#### <a name="benchmark-fields"></a>Benchmark fields
+
+| Hpack | Cabal | Default | Notes |
+| --- | --- | --- | --- |
+| | `type` | `exitcode-stdio-1.0` | |
+| `main` | `main-is` | | |
+| `other-modules` | `other-modules` | | |
+| | `default-language` | `Haskell2010` | |
+
+#### <a name="flags"></a>Flags
+
+| Hpack | Cabal | Default | Notes |
+| --- | --- | --- | --- |
+| `description` | `description` | | Optional |
+| `manual` | `manual` | | Required (unlike Cabal) |
+| `default` | `default` | | Required (unlike Cabal) |
+
+#### <a name="conditionals"></a> Conditionals
+
+Conditionals with no else branch:
+
+- Must have a `condition` field
+- May have any number of other fields
+
+For example,
+
+    when:
+      - condition: os(darwin)
+        extra-lib-dirs: lib/darwin
+
+becomes
+
+    if os(darwin)
+      extra-lib-dirs:
+        lib/darwin
+
+Conditionals with an else branch:
+
+- Must have a `condition` field
+- Must have a `then` field, itself an object containing any number of other fields
+- Must have a `else` field, itself an object containing any number of other fields
+- All other top-level fields are ignored
+
+For example,
+
+    when:
+      - condition: flag(fast)
+        then:
+          ghc-options: -O2
+        else:
+          ghc-options: -O0
+
+becomes
+
+    if flag(fast)
+      ghc-options: -O2
+    else
+      ghc-options: -O0
+
+
+### <a name="file-globbing"></a>File globbing
+
+At place where you can specify a list of files you can also use glob patterns.
+Glob patters and ordinary file names can be freely mixed, e.g.:
+
+```yaml
+extra-source-files:
+  - static/*.js
+  - static/site.css
+```
+
+Glob patterns are expanded according to the following rules:
+
+ - `?` and `*` are expanded according to POSIX (they match arbitrary
+   characters, except for directory separators)
+ - `**` is expanded in a `zsh`-like fashion (matching across directory
+   separators)
+ - `?`, `*` and `**` do not match a `.` at the beginning of a file/directory
+
+### Slides
+
+ - Slides from my talk about `hpack` at the Singapore Haskell meetup:
+   http://typeful.net/talks/hpack
+
+## Vim integration
+
+To run `hpack` automatically on modifications to `package.yaml` add the
+following to your `~/.vimrc`:
+
+```vim
+autocmd BufWritePost package.yaml silent !hpack --silent
+```
diff --git a/hpack.cabal b/hpack.cabal
--- a/hpack.cabal
+++ b/hpack.cabal
@@ -1,9 +1,9 @@
--- This file has been generated from package.yaml by hpack version 0.14.1.
+-- This file has been generated from package.yaml by hpack version 0.15.0.
 --
 -- see: https://github.com/sol/hpack
 
 name:           hpack
-version:        0.15.0
+version:        0.16.0
 synopsis:       An alternative format for Haskell packages
 category:       Development
 homepage:       https://github.com/sol/hpack#readme
@@ -14,6 +14,9 @@
 build-type:     Simple
 cabal-version:  >= 1.10
 
+extra-source-files:
+    README.md
+
 source-repository head
   type: git
   location: https://github.com/sol/hpack
@@ -25,6 +28,7 @@
   build-depends:
       base >= 4.7 && < 5
     , base-compat >= 0.8
+    , bytestring
     , deepseq
     , directory
     , filepath
@@ -56,6 +60,7 @@
   build-depends:
       base >= 4.7 && < 5
     , base-compat >= 0.8
+    , bytestring
     , deepseq
     , directory
     , filepath
@@ -73,12 +78,13 @@
   main-is: Spec.hs
   hs-source-dirs:
       test
-    , src
+      src
   ghc-options: -Wall
   cpp-options: -DTEST
   build-depends:
       base >= 4.7 && < 5
     , base-compat >= 0.8
+    , bytestring
     , deepseq
     , directory
     , filepath
diff --git a/src/Hpack.hs b/src/Hpack.hs
--- a/src/Hpack.hs
+++ b/src/Hpack.hs
@@ -17,22 +17,23 @@
 import           Prelude ()
 import           Prelude.Compat
 
-import           Control.DeepSeq
-import           Control.Exception
 import           Control.Monad.Compat
+import qualified Data.ByteString as B
 import           Data.List.Compat
 import           Data.Maybe
+import qualified Data.Text as T
+import           Data.Text.Encoding (encodeUtf8)
 import           Data.Version (Version)
 import qualified Data.Version as Version
 import           System.Environment
 import           System.Exit
 import           System.IO
-import           System.IO.Error
 import           Text.ParserCombinators.ReadP
 
 import           Paths_hpack (version)
 import           Hpack.Config
 import           Hpack.Run
+import           Hpack.Util
 
 programVersion :: Version -> String
 programVersion v = "hpack version " ++ Version.showVersion v
@@ -113,14 +114,14 @@
 hpackWithVersionResult :: Version -> FilePath -> IO Result
 hpackWithVersionResult v dir = do
   (warnings, cabalFile, new) <- run dir
-  old <- either (const Nothing) (Just . splitHeader) <$> tryJust (guard . isDoesNotExistError) (readFile cabalFile >>= (return $!!))
+  old <- fmap splitHeader <$> tryReadFile cabalFile
   let oldVersion = fmap fst old >>= extractVersion
   status <-
     if (oldVersion <= Just v) then
       if (fmap snd old == Just (lines new)) then
         return OutputUnchanged
       else do
-        writeFile cabalFile $ header v ++ new
+        B.writeFile cabalFile $ encodeUtf8 $ T.pack $ header v ++ new
         return Generated
     else
       return AlreadyGeneratedByNewerHpack
diff --git a/src/Hpack/Config.hs b/src/Hpack/Config.hs
--- a/src/Hpack/Config.hs
+++ b/src/Hpack/Config.hs
@@ -462,13 +462,19 @@
 
 mkPackage :: FilePath -> (CaptureUnknownFields (Section PackageConfig)) -> IO ([String], Package)
 mkPackage dir (CaptureUnknownFields unknownFields globalOptions@Section{sectionData = PackageConfig{..}}) = do
-  let name = fromMaybe (takeBaseName dir) packageConfigName
+  let
+    (nameWarnings, name) = maybe (["Package name not specified, inferred " ++ show inferredName], inferredName) ((,) []) packageConfigName
+      where inferredName = takeBaseName dir
 
-  mLibrary <- mapM (toLibrary dir name globalOptions) mLibrarySection
-  executables <- toExecutables dir globalOptions (map (fmap captureUnknownFieldsValue) executableSections)
-  tests <- toExecutables dir globalOptions (map (fmap captureUnknownFieldsValue) testsSections)
-  benchmarks <- toExecutables dir globalOptions  (map (fmap captureUnknownFieldsValue) benchmarkSections)
+  libraryResult <- mapM (toLibrary dir name globalOptions) mLibrarySection
+  let
+    mLibrary = fmap snd libraryResult
+    libraryWarnings = maybe [] fst libraryResult
 
+  (executablesWarnings, executables) <- toExecutables dir globalOptions (map (fmap captureUnknownFieldsValue) executableSections)
+  (testsWarnings, tests) <- toExecutables dir globalOptions (map (fmap captureUnknownFieldsValue) testsSections)
+  (benchmarksWarnings, benchmarks) <- toExecutables dir globalOptions  (map (fmap captureUnknownFieldsValue) benchmarkSections)
+
   licenseFileExists <- doesFileExist (dir </> "LICENSE")
 
   missingSourceDirs <- nub . sort <$> filterM (fmap not <$> doesDirectoryExist . (dir </>)) (
@@ -479,10 +485,10 @@
     )
 
   (extraSourceFilesWarnings, extraSourceFiles) <-
-    expandGlobs dir (fromMaybeList packageConfigExtraSourceFiles)
+    expandGlobs "extra-source-files" dir (fromMaybeList packageConfigExtraSourceFiles)
 
   (dataFilesWarnings, dataFiles) <-
-    expandGlobs dir (fromMaybeList packageConfigDataFiles)
+    expandGlobs "data-files" dir (fromMaybeList packageConfigDataFiles)
 
   let pkg = Package {
         packageName = name
@@ -512,11 +518,16 @@
 
       warnings =
            formatUnknownFields "package description" unknownFields
+        ++ nameWarnings
         ++ flagWarnings
         ++ maybe [] (formatUnknownFields "library section") (captureUnknownFieldsFields <$> packageConfigLibrary)
         ++ formatUnknownSectionFields "executable" executableSections
         ++ formatUnknownSectionFields "test" testsSections
         ++ formatMissingSourceDirs missingSourceDirs
+        ++ libraryWarnings
+        ++ executablesWarnings
+        ++ testsWarnings
+        ++ benchmarksWarnings
         ++ extraSourceFilesWarnings
         ++ dataFilesWarnings
 
@@ -587,8 +598,13 @@
       where
         fromGithub = (++ "/issues") . sourceRepositoryUrl <$> github
 
-toLibrary :: FilePath -> String -> Section global -> Section LibrarySection -> IO (Section Library)
-toLibrary dir name globalOptions library = traverse fromLibrarySection sect
+expandCSources :: FilePath -> Section a -> IO ([String], Section a)
+expandCSources dir sect@Section{..} = do
+  (warnings, files) <- expandGlobs "c-sources" dir sectionCSources
+  return (warnings, sect {sectionCSources = files})
+
+toLibrary :: FilePath -> String -> Section global -> Section LibrarySection -> IO ([String], Section Library)
+toLibrary dir name globalOptions library = traverse fromLibrarySection sect >>= expandCSources dir
   where
     sect :: Section LibrarySection
     sect = mergeSections globalOptions library
@@ -603,8 +619,11 @@
           reexportedModules = fromMaybeList librarySectionReexportedModules
       return (Library librarySectionExposed exposedModules otherModules reexportedModules)
 
-toExecutables :: FilePath -> Section global -> [(String, Section ExecutableSection)] -> IO [Section Executable]
-toExecutables dir globalOptions executables = mapM toExecutable sections
+toExecutables :: FilePath -> Section global -> [(String, Section ExecutableSection)] -> IO ([String], [Section Executable])
+toExecutables dir globalOptions executables = do
+  result <- mapM toExecutable sections >>= mapM (expandCSources dir)
+  let (warnings, xs) = unzip result
+  return (concat warnings, xs)
   where
     sections :: [(String, Section ExecutableSection)]
     sections = map (fmap $ mergeSections globalOptions) executables
diff --git a/src/Hpack/Run.hs b/src/Hpack/Run.hs
--- a/src/Hpack/Run.hs
+++ b/src/Hpack/Run.hs
@@ -14,6 +14,7 @@
 , renderConditional
 , renderFlag
 , renderSourceRepository
+, renderDirectories
 , formatDescription
 #endif
 ) where
@@ -203,17 +204,17 @@
 
 renderSection :: Section a -> [Element]
 renderSection Section{..} = [
-    renderSourceDirs sectionSourceDirs
+    renderDirectories "hs-source-dirs" sectionSourceDirs
   , renderDefaultExtensions sectionDefaultExtensions
   , renderOtherExtensions sectionOtherExtensions
   , renderGhcOptions sectionGhcOptions
   , renderGhcProfOptions sectionGhcProfOptions
   , renderCppOptions sectionCppOptions
   , renderCcOptions sectionCcOptions
-  , Field "include-dirs" (LineSeparatedList sectionIncludeDirs)
+  , renderDirectories "include-dirs" sectionIncludeDirs
   , Field "install-includes" (LineSeparatedList sectionInstallIncludes)
   , Field "c-sources" (LineSeparatedList sectionCSources)
-  , Field "extra-lib-dirs" (LineSeparatedList sectionExtraLibDirs)
+  , renderDirectories "extra-lib-dirs" sectionExtraLibDirs
   , Field "extra-libraries" (LineSeparatedList sectionExtraLibraries)
   , renderLdOptions sectionLdOptions
   , renderDependencies sectionDependencies
@@ -232,8 +233,13 @@
 defaultLanguage :: Element
 defaultLanguage = Field "default-language" "Haskell2010"
 
-renderSourceDirs :: [String] -> Element
-renderSourceDirs = Field "hs-source-dirs" . CommaSeparatedList
+renderDirectories :: String -> [String] -> Element
+renderDirectories name = Field name . LineSeparatedList . replaceDots
+  where
+    replaceDots = map replaceDot
+    replaceDot xs = case xs of
+      "." -> "./."
+      _ -> xs
 
 renderExposedModules :: [String] -> Element
 renderExposedModules = Field "exposed-modules" . LineSeparatedList
diff --git a/src/Hpack/Util.hs b/src/Hpack/Util.hs
--- a/src/Hpack/Util.hs
+++ b/src/Hpack/Util.hs
@@ -19,14 +19,18 @@
 import           Prelude.Compat
 
 import           Control.Applicative
-import           Control.DeepSeq
 import           Control.Exception
 import           Control.Monad.Compat
 import           Data.Aeson.Types
+import qualified Data.ByteString as B
 import           Data.Char
 import           Data.Data
 import           Data.List.Compat hiding (sort)
 import           Data.Ord
+import qualified Data.Text as T
+import           Data.Text.Encoding (decodeUtf8With)
+import           Data.Text.Encoding.Error (lenientDecode)
+import           System.IO.Error
 import           System.Directory
 import           System.FilePath
 import qualified System.FilePath.Posix as Posix
@@ -95,20 +99,20 @@
 
 tryReadFile :: FilePath -> IO (Maybe String)
 tryReadFile file = do
-  r <- try (readFile file) :: IO (Either IOException String)
-  return $!! either (const Nothing) Just r
+  r <- tryJust (guard . isDoesNotExistError) (B.readFile file)
+  return $ either (const Nothing) (Just . T.unpack . decodeUtf8With lenientDecode) r
 
 toPosixFilePath :: FilePath -> FilePath
 toPosixFilePath = Posix.joinPath . splitDirectories
 
-expandGlobs :: FilePath -> [String] -> IO ([String], [FilePath])
-expandGlobs dir patterns = do
+expandGlobs :: String -> FilePath -> [String] -> IO ([String], [FilePath])
+expandGlobs name dir patterns = do
   files <- (fst <$> globDir compiledPatterns dir) >>= mapM removeDirectories
   let warnings = [warn pattern | ([], pattern) <- zip files patterns]
   return (warnings, combineResults files)
   where
     combineResults = nub . sort . map (toPosixFilePath . makeRelative dir) . concat
-    warn pattern = "Specified pattern " ++ show pattern ++ " for extra-source-files does not match any files"
+    warn pattern = "Specified pattern " ++ show pattern ++ " for " ++ name ++ " does not match any files"
     compiledPatterns = map (compileWith options) patterns
     removeDirectories = filterM doesFileExist
     options = CompOptions {
diff --git a/test/Hpack/ConfigSpec.hs b/test/Hpack/ConfigSpec.hs
--- a/test/Hpack/ConfigSpec.hs
+++ b/test/Hpack/ConfigSpec.hs
@@ -112,10 +112,10 @@
         let input = [i|
               c-sources:
                 - foo.c
-                - bar.c
+                - bar/*.c
               |]
         captureUnknownFieldsValue <$> decodeEither input
-          `shouldBe` Right (section Empty){sectionCSources = ["foo.c", "bar.c"]}
+          `shouldBe` Right (section Empty){sectionCSources = ["foo.c", "bar/*.c"]}
 
       it "accepts extra-lib-dirs" $ do
         let input = [i|
@@ -306,6 +306,7 @@
   describe "readPackageConfig" $ do
     it "warns on unknown fields" $ do
       withPackageWarnings_ [i|
+        name: foo
         bar: 23
         baz: 42
         |]
@@ -317,6 +318,7 @@
 
     it "warns on unknown fields in when block, list" $ do
       withPackageWarnings_ [i|
+        name: foo
         when:
           - condition: impl(ghc)
             bar: 23
@@ -330,6 +332,7 @@
 
     it "warns on unknown fields in when block, single" $ do
       withPackageWarnings_ [i|
+        name: foo
         when:
           condition: impl(ghc)
           github: foo/bar
@@ -342,6 +345,21 @@
         ]
         )
 
+    it "warns on missing name" $ do
+      withPackageWarnings_ [i|
+        {}
+        |]
+        (`shouldBe` [
+          "Package name not specified, inferred \"foo\""
+        ]
+        )
+
+    it "infers name" $ do
+      withPackageConfig_ [i|
+        {}
+        |]
+        (packageName >>> (`shouldBe` "foo"))
+
     it "accepts name" $ do
       withPackageConfig_ [i|
         name: bar
@@ -496,6 +514,7 @@
 
     it "warns on unknown fields in flag sections" $ do
       withPackageWarnings_ [i|
+        name: foo
         flags:
           integration-tests:
             description: Run the integration test suite
@@ -626,6 +645,7 @@
     context "when reading library section" $ do
       it "warns on unknown fields" $ do
         withPackageWarnings_ [i|
+          name: foo
           library:
             bar: 23
             baz: 42
@@ -690,6 +710,30 @@
           |]
           (packageLibrary >>> (`shouldBe` Just (section library) {sectionBuildTools = ["alex", "happy"]}))
 
+      it "accepts c-sources" $ do
+        withPackageConfig [i|
+          library:
+            c-sources:
+              - cbits/*.c
+          |]
+          (do
+          touch "cbits/foo.c"
+          touch "cbits/bar.c"
+          )
+          (packageLibrary >>> (`shouldBe` Just (section library) {sectionCSources = ["cbits/bar.c", "cbits/foo.c"]}))
+
+      it "accepts global c-sources" $ do
+        withPackageConfig [i|
+          c-sources:
+            - cbits/*.c
+          library: {}
+          |]
+          (do
+          touch "cbits/foo.c"
+          touch "cbits/bar.c"
+          )
+          (packageLibrary >>> (`shouldBe` Just (section library) {sectionCSources = ["cbits/bar.c", "cbits/foo.c"]}))
+
       it "allows to specify exposed" $ do
         withPackageConfig_ [i|
           library:
@@ -755,6 +799,7 @@
     context "when reading executable section" $ do
       it "warns on unknown fields" $ do
         withPackageWarnings_ [i|
+          name: foo
           executables:
             foo:
               main: Main.hs
@@ -915,10 +960,38 @@
           |]
           (`shouldBe` package {packageExecutables = [(section $ executable "foo" "driver/Main.hs") {sectionGhcProfOptions = ["-fprof-auto"]}]})
 
+      it "accepts c-sources" $ do
+        withPackageConfig [i|
+          executables:
+            foo:
+              main: driver/Main.hs
+              c-sources:
+                - cbits/*.c
+          |]
+          (do
+          touch "cbits/foo.c"
+          touch "cbits/bar.c"
+          )
+          (`shouldBe` package {packageExecutables = [(section $ executable "foo" "driver/Main.hs") {sectionCSources = ["cbits/bar.c", "cbits/foo.c"]}]})
 
+      it "accepts global c-sources" $ do
+        withPackageConfig [i|
+          c-sources:
+            - cbits/*.c
+          executables:
+            foo:
+              main: driver/Main.hs
+          |]
+          (do
+          touch "cbits/foo.c"
+          touch "cbits/bar.c"
+          )
+          (`shouldBe` package {packageExecutables = [(section $ executable "foo" "driver/Main.hs") {sectionCSources = ["cbits/bar.c", "cbits/foo.c"]}]})
+
     context "when reading test section" $ do
       it "warns on unknown fields" $ do
         withPackageWarnings_ [i|
+          name: foo
           tests:
             foo:
               main: Main.hs
@@ -975,6 +1048,7 @@
     context "when a specified source directory does not exist" $ do
       it "warns" $ do
         withPackageWarnings [i|
+          name: foo
           source-dirs:
             - some-dir
             - some-existing-dir
diff --git a/test/Hpack/RunSpec.hs b/test/Hpack/RunSpec.hs
--- a/test/Hpack/RunSpec.hs
+++ b/test/Hpack/RunSpec.hs
@@ -323,3 +323,11 @@
           , "  location: https://github.com/hspec/hspec"
           , "  subdir: hspec-core"
           ]
+
+  describe "renderDirectories" $ do
+    it "replaces . with ./. (for compatibility with cabal syntax)" $ do
+      (render defaultRenderSettings 0 $ renderDirectories "name" ["."])
+        `shouldBe` [
+            "name:"
+          , "    ./."
+          ]
diff --git a/test/Hpack/UtilSpec.hs b/test/Hpack/UtilSpec.hs
--- a/test/Hpack/UtilSpec.hs
+++ b/test/Hpack/UtilSpec.hs
@@ -97,22 +97,22 @@
   describe "expandGlobs" $ around withTempDirectory $ do
     it "accepts simple files" $ \dir -> do
         touch (dir </> "foo.js")
-        expandGlobs dir ["foo.js"] `shouldReturn` ([], ["foo.js"])
+        expandGlobs "field-name" dir ["foo.js"] `shouldReturn` ([], ["foo.js"])
 
     it "removes duplicates" $ \dir -> do
       touch (dir </> "foo.js")
-      expandGlobs dir ["foo.js", "*.js"] `shouldReturn` ([], ["foo.js"])
+      expandGlobs "field-name" dir ["foo.js", "*.js"] `shouldReturn` ([], ["foo.js"])
 
     it "rejects directories" $ \dir -> do
       touch (dir </> "foo")
       createDirectory (dir </> "bar")
-      expandGlobs dir ["*"] `shouldReturn` ([], ["foo"])
+      expandGlobs "field-name" dir ["*"] `shouldReturn` ([], ["foo"])
 
     it "rejects character ranges" $ \dir -> do
       touch (dir </> "foo1")
       touch (dir </> "foo2")
       touch (dir </> "foo[1,2]")
-      expandGlobs dir ["foo[1,2]"] `shouldReturn` ([], ["foo[1,2]"])
+      expandGlobs "field-name" dir ["foo[1,2]"] `shouldReturn` ([], ["foo[1,2]"])
 
     context "when expanding *" $ do
       it "expands by extension" $ \dir -> do
@@ -122,36 +122,36 @@
               , "files/baz.js"]
         mapM_ (touch . (dir </>)) files
         touch (dir </> "files/foo.hs")
-        expandGlobs dir ["files/*.js"] `shouldReturn` ([], sort files)
+        expandGlobs "field-name" dir ["files/*.js"] `shouldReturn` ([], sort files)
 
       it "rejects dot-files" $ \dir -> do
         touch (dir </> "foo/bar")
         touch (dir </> "foo/.baz")
-        expandGlobs dir ["foo/*"] `shouldReturn` ([], ["foo/bar"])
+        expandGlobs "field-name" dir ["foo/*"] `shouldReturn` ([], ["foo/bar"])
 
       it "accepts dot-files when explicitly asked to" $ \dir -> do
         touch (dir </> "foo/bar")
         touch (dir </> "foo/.baz")
-        expandGlobs dir ["foo/.*"] `shouldReturn` ([], ["foo/.baz"])
+        expandGlobs "field-name" dir ["foo/.*"] `shouldReturn` ([], ["foo/.baz"])
 
       it "matches at most one directory component" $ \dir -> do
         touch (dir </> "foo/bar/baz.js")
         touch (dir </> "foo/bar.js")
-        expandGlobs dir ["*/*.js"] `shouldReturn` ([], ["foo/bar.js"])
+        expandGlobs "field-name" dir ["*/*.js"] `shouldReturn` ([], ["foo/bar.js"])
 
     context "when expanding **" $ do
       it "matches arbitrary many directory components" $ \dir -> do
         let file = "foo/bar/baz.js"
         touch (dir </> file)
-        expandGlobs dir ["**/*.js"] `shouldReturn` ([], [file])
+        expandGlobs "field-name" dir ["**/*.js"] `shouldReturn` ([], [file])
 
     context "when a pattern does not match anything" $ do
       it "warns" $ \dir -> do
-        expandGlobs dir ["foo"] `shouldReturn`
-          (["Specified pattern \"foo\" for extra-source-files does not match any files"], [])
+        expandGlobs "field-name" dir ["foo"] `shouldReturn`
+          (["Specified pattern \"foo\" for field-name does not match any files"], [])
 
     context "when a pattern only matches a directory" $ do
       it "warns" $ \dir -> do
         createDirectory (dir </> "foo")
-        expandGlobs dir ["foo"] `shouldReturn`
-          (["Specified pattern \"foo\" for extra-source-files does not match any files"], [])
+        expandGlobs "field-name" dir ["foo"] `shouldReturn`
+          (["Specified pattern \"foo\" for field-name does not match any files"], [])
