diff --git a/cabal2nix.cabal b/cabal2nix.cabal
--- a/cabal2nix.cabal
+++ b/cabal2nix.cabal
@@ -1,5 +1,5 @@
 name:               cabal2nix
-version:            2.10.2
+version:            2.11
 synopsis:           Convert Cabal files into Nix build instructions.
 description:
   Convert Cabal files into Nix build instructions. Users of Nix can install the latest
diff --git a/hackage2nix/Main.hs b/hackage2nix/Main.hs
--- a/hackage2nix/Main.hs
+++ b/hackage2nix/Main.hs
@@ -151,7 +151,7 @@
 
           drv :: Derivation
           drv = fromGenericPackageDescription haskellResolver nixpkgsResolver targetPlatform (compilerInfo config) flagAssignment [] descr
-                  & src .~ DerivationSource "url" ("mirror://hackage/" ++ display pkgId ++ ".tar.gz") "" tarballSHA256
+                  & src .~ urlDerivationSource ("mirror://hackage/" ++ display pkgId ++ ".tar.gz") tarballSHA256
                   & editedCabalFile .~ cabalSHA256
                   & metaSection.hydraPlatforms %~ (`Set.difference` Map.findWithDefault Set.empty name (dontDistributePackages config))
                   & metaSection.maintainers .~ Map.findWithDefault Set.empty name globalPackageMaintainers
@@ -193,7 +193,10 @@
 
 resolveConstraint :: Constraint -> Hackage -> Version
 resolveConstraint c = fromMaybe (error msg) . resolveConstraint' c
-  where msg = "constraint " ++ display c ++ " cannot be resolved in Hackage"
+  where msg = unlines [ "constraint " ++ display c ++ " cannot be resolved in Hackage"
+                      , "This could be due the package being missing in the hackage directory"
+                      , "or the file system not being case sensitive."
+                      ]
 
 resolveConstraint' :: Constraint -> Hackage -> Maybe Version
 resolveConstraint' (Dependency name vrange) hackage
diff --git a/src/Cabal2nix.hs b/src/Cabal2nix.hs
--- a/src/Cabal2nix.hs
+++ b/src/Cabal2nix.hs
@@ -64,6 +64,7 @@
   , optHackageSnapshot :: Maybe UTCTime
   , optNixpkgsIdentifier :: NixpkgsResolver
   , optUrl :: String
+  , optFetchSubmodules :: Bool
   }
 
 options :: Parser Options
@@ -90,6 +91,7 @@
           <*> optional (option utcTimeReader (long "hackage-snapshot" <> help "hackage snapshot time, ISO format"))
           <*> pure (\i -> Just (binding # (i, path # [ident # "pkgs", i])))
           <*> strArgument (metavar "URI")
+          <*> flag True False (long "dont-fetch-submodules" <> help "do not fetch git submodules from git sources")
 
 -- | A parser for the date. Hackage updates happen maybe once or twice a month.
 -- Example: parseTime defaultTimeLocale "%FT%T%QZ" "2017-11-20T12:18:35Z" :: Maybe UTCTime
@@ -187,14 +189,16 @@
 
 cabal2nix' :: Options -> IO (Either Doc Derivation)
 cabal2nix' opts@Options{..} = do
-  pkg <- getPackage optHpack optHackageDb optHackageSnapshot $ Source optUrl (fromMaybe "" optRevision) (maybe UnknownHash Guess optSha256) (fromMaybe "" optSubpath)
+  pkg <- getPackage optHpack optFetchSubmodules optHackageDb optHackageSnapshot $
+         Source optUrl (fromMaybe "" optRevision) (maybe UnknownHash Guess optSha256) (fromMaybe "" optSubpath)
   processPackage opts pkg
 
 cabal2nixWithDB :: DB.HackageDB -> Options -> IO (Either Doc Derivation)
 cabal2nixWithDB db opts@Options{..} = do
   when (isJust optHackageDb) $ hPutStrLn stderr "WARN: HackageDB provided directly; ignoring --hackage-db"
   when (isJust optHackageSnapshot) $ hPutStrLn stderr "WARN: HackageDB provided directly; ignoring --hackage-snapshot"
-  pkg <- getPackage' optHpack (return db) $ Source optUrl (fromMaybe "" optRevision) (maybe UnknownHash Guess optSha256) (fromMaybe "" optSubpath)
+  pkg <- getPackage' optHpack optFetchSubmodules (return db) $
+         Source optUrl (fromMaybe "" optRevision) (maybe UnknownHash Guess optSha256) (fromMaybe "" optSubpath)
   processPackage opts pkg
 
 processPackage :: Options -> Package -> IO (Either Doc Derivation)
diff --git a/src/Distribution/Nixpkgs/Fetch.hs b/src/Distribution/Nixpkgs/Fetch.hs
--- a/src/Distribution/Nixpkgs/Fetch.hs
+++ b/src/Distribution/Nixpkgs/Fetch.hs
@@ -6,7 +6,7 @@
 module Distribution.Nixpkgs.Fetch
   ( Source(..)
   , Hash(..)
-  , DerivationSource(..), fromDerivationSource
+  , DerivationSource(..), fromDerivationSource, urlDerivationSource
   , fetch
   , fetchWith
   ) where
@@ -18,7 +18,10 @@
 import Control.Monad.Trans.Maybe
 import Data.Aeson
 import qualified Data.ByteString.Lazy.Char8 as BS
+import qualified Data.List as L
+import Data.Maybe
 import GHC.Generics ( Generic )
+import Language.Nix.PrettyPrinting as PP
 import System.Directory
 import System.Environment
 import System.Exit
@@ -56,6 +59,7 @@
   , derivUrl      :: String -- ^ URL to fetch from.
   , derivRevision :: String -- ^ Revision to use. Leave empty if the fetcher doesn't support revisions.
   , derivHash     :: String -- ^ The hash of the source.
+  , derivSubmodule :: Maybe Bool -- ^ The fetchSubmodule setting (if any)
   }
   deriving (Show, Eq, Ord, Generic)
 
@@ -66,22 +70,46 @@
         <$> o .: "url"
         <*> o .: "rev"
         <*> o .: "sha256"
+        <*> o .: "fetchSubmodules"
   parseJSON _ = error "invalid DerivationSource"
 
+instance PP.Pretty DerivationSource where
+  pPrint DerivationSource {..} =
+    let isHackagePackage = "mirror://hackage/" `L.isPrefixOf` derivUrl
+        fetched = derivKind /= ""
+    in if isHackagePackage then attr "sha256" $ string derivHash
+       else if not fetched then attr "src" $ text derivUrl
+            else vcat
+                 [ text "src" <+> equals <+> text ("fetch" ++ derivKind) <+> lbrace
+                 , nest 2 $ vcat
+                   [ attr "url" $ string derivUrl
+                   , attr "sha256" $ string derivHash
+                   , if derivRevision /= "" then attr "rev" (string derivRevision) else PP.empty
+                   , boolattr "fetchSubmodules" (isJust derivSubmodule) (fromJust derivSubmodule)
+                   ]
+                 , rbrace PP.<> semi
+                 ]
+
+
+urlDerivationSource :: String -> String -> DerivationSource
+urlDerivationSource url hash = DerivationSource "url" url "" hash Nothing
+
 fromDerivationSource :: DerivationSource -> Source
 fromDerivationSource DerivationSource{..} = Source derivUrl derivRevision (Certain derivHash) "."
 
 -- | Fetch a source, trying any of the various nix-prefetch-* scripts.
-fetch :: forall a. (String -> MaybeT IO a)      -- ^ This function is passed the output path name as an argument.
+fetch :: forall a.
+         Bool                                   -- ^ If True, fetch submodules when the source is a git repository
+      -> (String -> MaybeT IO a)                -- ^ This function is passed the output path name as an argument.
                                                 -- It should return 'Nothing' if the file doesn't match the expected format.
                                                 -- This is required, because we cannot always check if a download succeeded otherwise.
       -> Source                                 -- ^ The source to fetch from.
       -> IO (Maybe (DerivationSource, a))       -- ^ The derivation source and the result of the processing function. Returns Nothing if the download failed.
-fetch f = runMaybeT . fetchers where
+fetch optSubModules f = runMaybeT . fetchers where
   fetchers :: Source -> MaybeT IO (DerivationSource, a)
   fetchers source = msum . (fetchLocal source :) $ map (\fetcher -> fetchWith fetcher source >>= process)
     [ (False, "url", [])
-    , (True, "git", ["--fetch-submodules"])
+    , (True, "git", ["--fetch-submodules" | optSubModules ])
     , (True, "hg", [])
     , (True, "svn", [])
     , (True, "bzr", [])
@@ -100,17 +128,19 @@
     guard $ existsDir || existsFile
     let path' | '/' `elem` path = path
               | otherwise       = "./" ++ path
-    process (DerivationSource "" path' "" "", path') <|> localArchive path'
+    process (localDerivationSource path', path') <|> localArchive path'
 
   localArchive :: FilePath -> MaybeT IO (DerivationSource, a)
   localArchive path = do
     absolutePath <- liftIO $ canonicalizePath path
     unpacked <- snd <$> fetchWith (False, "url", ["--unpack"]) (Source ("file://" ++ absolutePath) "" UnknownHash ".")
-    process (DerivationSource "" absolutePath "" "", unpacked)
+    process (localDerivationSource absolutePath, unpacked)
 
   process :: (DerivationSource, FilePath) -> MaybeT IO (DerivationSource, a)
   process (derivSource, file) = (,) derivSource <$> f file
 
+  localDerivationSource p = DerivationSource "" p "" "" Nothing
+
 -- | Like 'fetch', but allows to specify which script to use.
 fetchWith :: (Bool, String, [String]) -> Source -> MaybeT IO (DerivationSource, FilePath)
 fetchWith (supportsRev, kind, addArgs) source = do
@@ -135,7 +165,13 @@
             buf'   = BS.unlines (reverse ls)
         case length ls of
           0 -> return Nothing
-          1 -> return (Just (DerivationSource kind (sourceUrl source) "" (BS.unpack (head ls))  , sourceUrl source))
+          1 -> return (Just (DerivationSource { derivKind = kind
+                                              , derivUrl = sourceUrl source
+                                              , derivRevision = ""
+                                              , derivHash = BS.unpack (head ls)
+                                              , derivSubmodule = Nothing
+                                              }
+                            , sourceUrl source))
           _ -> case eitherDecode buf' of
                  Left err -> error ("invalid JSON: " ++ err ++ " in " ++ show buf')
                  Right ds -> return (Just (ds { derivKind = kind }, BS.unpack l))
diff --git a/src/Distribution/Nixpkgs/Haskell/Derivation.hs b/src/Distribution/Nixpkgs/Haskell/Derivation.hs
--- a/src/Distribution/Nixpkgs/Haskell/Derivation.hs
+++ b/src/Distribution/Nixpkgs/Haskell/Derivation.hs
@@ -112,7 +112,7 @@
     , nest 2 $ vcat
       [ attr "pname"   $ doubleQuotes $ disp (packageName _pkgid)
       , attr "version" $ doubleQuotes $ disp (packageVersion _pkgid)
-      , sourceAttr _src
+      , pPrint _src
       , onlyIf (_subpath /= ".") $ attr "postUnpack" postUnpack
       , onlyIf (_revision > 0) $ attr "revision" $ doubleQuotes $ int _revision
       , onlyIf (not (null _editedCabalFile) && _revision > 0) $ attr "editedCabalFile" $ string _editedCabalFile
@@ -148,17 +148,5 @@
       renderedFlags = [ text "-f" <> (if enable then empty else char '-') <> text (unFlagName f) | (f, enable) <- unFlagAssignment _cabalFlags ]
                       ++ map text (toAscList _configureFlags)
       isHackagePackage = "mirror://hackage/" `isPrefixOf` derivUrl _src
-      sourceAttr DerivationSource {..}
-        | isHackagePackage = attr "sha256" $ string derivHash
-        | derivKind /= "" = vcat
-           [ text "src" <+> equals <+> text ("fetch" ++ derivKind) <+> lbrace
-           , nest 2 $ vcat
-             [ attr "url" $ string derivUrl
-             , attr "sha256" $ string derivHash
-             , if derivRevision /= "" then attr "rev" (string derivRevision) else empty
-             ]
-           , rbrace <> semi
-           ]
-        | otherwise = attr "src" $ text derivUrl
 
       postUnpack = string $ "sourceRoot+=/" ++ _subpath ++ "; echo source root reset to $sourceRoot"
diff --git a/src/Distribution/Nixpkgs/Haskell/FromCabal/License.hs b/src/Distribution/Nixpkgs/Haskell/FromCabal/License.hs
--- a/src/Distribution/Nixpkgs/Haskell/FromCabal/License.hs
+++ b/src/Distribution/Nixpkgs/Haskell/FromCabal/License.hs
@@ -36,5 +36,6 @@
 fromCabalLicense ISC                                       = Known "stdenv.lib.licenses.isc"
 fromCabalLicense OtherLicense                              = Unknown Nothing
 fromCabalLicense (UnknownLicense "CC0-1.0")                = Known "stdenv.lib.licenses.cc0"
+fromCabalLicense (UnknownLicense "BSD3ClauseORApache20")   = Known "stdenv.lib.licenses.bsd3"
 fromCabalLicense l                                         = error $ "Distribution.Nixpkgs.Haskell.FromCabal.License.fromCabalLicense: unknown license"
                                                                   ++ show l ++"\nChoose one of: " ++ intercalate ", " (map display knownLicenses)
diff --git a/src/Distribution/Nixpkgs/Haskell/FromCabal/Name.hs b/src/Distribution/Nixpkgs/Haskell/FromCabal/Name.hs
--- a/src/Distribution/Nixpkgs/Haskell/FromCabal/Name.hs
+++ b/src/Distribution/Nixpkgs/Haskell/FromCabal/Name.hs
@@ -55,7 +55,7 @@
 libNixName "GLU"                                = ["libGLU","libGL"]
 libNixName "glut"                               = ["freeglut","libGLU","libGL"]
 libNixName "gnome-keyring"                      = return "gnome-keyring"
-libNixName "gnome-keyring-1"                    = return "gnome-keyring"
+libNixName "gnome-keyring-1"                    = return "libgnome_keyring"
 libNixName "gnome-vfs-2.0"                      = return "gnome-vfs"
 libNixName "gnome-vfs-module-2.0"               = return "gnome-vfs_module"
 libNixName "gobject-2.0"                        = return "glib"
diff --git a/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs b/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs
--- a/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs
+++ b/src/Distribution/Nixpkgs/Haskell/PackageSourceSpec.hs
@@ -41,35 +41,41 @@
 
 getPackage :: Bool
            -- ^ Whether hpack should regenerate the cabal file.
+           -> Bool
+           -- ^ Whether to fetch submodules if fetching from git
            -> Maybe FilePath
            -- ^ The path to the Hackage database.
            -> Maybe UTCTime
            -- ^ If we have hackage-snapshot time.
            -> Source
            -> IO Package
-getPackage optHpack optHackageDB optHackageSnapshot =
-  getPackage' optHpack (loadHackageDB optHackageDB optHackageSnapshot)
+getPackage optHpack optSubmodules optHackageDB optHackageSnapshot =
+  getPackage' optHpack optSubmodules (loadHackageDB optHackageDB optHackageSnapshot)
 
 getPackage' :: Bool
             -- ^ Whether hpack should regenerate the cabal file.
+            -> Bool
+            -- ^ Whether to fetch submodules if fetching from git
             -> IO DB.HackageDB
             -> Source
             -> IO Package
-getPackage' optHpack hackageDB source = do
-  (derivSource, ranHpack, pkgDesc) <- fetchOrFromDB optHpack hackageDB source
+getPackage' optHpack optSubmodules hackageDB source = do
+  (derivSource, ranHpack, pkgDesc) <- fetchOrFromDB optHpack optSubmodules hackageDB source
   (\s -> Package s ranHpack pkgDesc) <$> maybe (sourceFromHackage (sourceHash source) (showPackageIdentifier pkgDesc) $ sourceCabalDir source) return derivSource
 
 fetchOrFromDB :: Bool
               -- ^ Whether hpack should regenerate the cabal file
+              -> Bool
+              -- ^ Whether to fetch submodules if fetching from git
               -> IO DB.HackageDB
               -> Source
               -> IO (Maybe DerivationSource, Bool, Cabal.GenericPackageDescription)
-fetchOrFromDB optHpack hackageDB src
+fetchOrFromDB optHpack optSubmodules hackageDB src
   | "cabal://" `isPrefixOf` sourceUrl src = do
       (msrc, pkgDesc) <- fromDB hackageDB . drop (length "cabal://") $ sourceUrl src
       return (msrc, False, pkgDesc)
   | otherwise                             = do
-    r <- fetch (\dir -> cabalFromPath optHpack (dir </> sourceCabalDir src)) src
+    r <- fetch optSubmodules (\dir -> cabalFromPath optHpack (dir </> sourceCabalDir src)) src
     case r of
       Nothing -> fail $ "Failed to fetch source. Does this source exist? " ++ show src
       Just (derivSource, (externalSource, ranHpack, pkgDesc)) ->
@@ -92,7 +98,7 @@
   vd <- maybe unknownPackageError return (DB.lookup name hackageDB >>= lookupVersion)
   let ds = case DB.tarballSha256 vd of
              Nothing -> Nothing
-             Just hash -> Just (DerivationSource "url" url "" hash)
+             Just hash -> Just (urlDerivationSource url hash)
   return (ds, setCabalFileHash (DB.cabalFileSha256 vd) (DB.cabalFile vd))
  where
   pkgId :: Cabal.PackageIdentifier
@@ -138,20 +144,20 @@
   -- Use the cached hash (either from cache file or given on cmdline via sha256 opt)
   -- if available, otherwise download from hackage to compute hash.
   case cachedHash of
-    Guess hash -> return $ DerivationSource "url" url "" hash
+    Guess hash -> return $ urlDerivationSource url hash
     Certain hash ->
       -- We need to force the hash here. If we didn't do this, then when reading the
       -- hash from the cache file, the cache file will still be open for reading
       -- (because lazy io) when writeFile opens the file again for writing. By forcing
       -- the hash here, we ensure that the file is closed before opening it again.
       seq (length hash) $
-      DerivationSource "url" url "" hash <$ writeFile cacheFile hash
+      urlDerivationSource url hash <$ writeFile cacheFile hash
     UnknownHash -> do
       maybeHash <- runMaybeT (derivHash . fst <$> fetchWith (False, "url", []) (Source url "" UnknownHash cabalDir))
       case maybeHash of
         Just hash ->
           seq (length hash) $
-          DerivationSource "url" url "" hash <$ writeFile cacheFile hash
+          urlDerivationSource url hash <$ writeFile cacheFile hash
         Nothing -> do
           hPutStr stderr $ unlines
             [ "*** cannot compute hash. (Not a hackage project?)"
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -57,6 +57,7 @@
                                   , derivUrl      = "mirror://hackage/foo.tar.gz"
                                   , derivRevision = ""
                                   , derivHash     = "deadbeef"
+                                  , derivSubmodule = Nothing
                                   }
                        & extraFunctionArgs %~ Set.union (Set.singleton "inherit stdenv")
   goldenVsFileDiff
