44{-# LANGUAGE RankNTypes #-}
55{-# LANGUAGE RecordWildCards #-}
66{-# LANGUAGE ScopedTypeVariables #-}
7+ {-# LANGUAGE CPP #-}
78
89-----------------------------------------------------------------------------
910-- |
@@ -112,17 +113,19 @@ import qualified Distribution.Simple.HaskellSuite as HaskellSuite
112113
113114import Control.Exception
114115 ( ErrorCall , Exception , evaluate , throw , throwIO , try )
116+ import Control.Monad ( forM , forM_ )
115117import Distribution.Compat.Binary ( decodeOrFailIO , encode )
116118import Data.ByteString.Lazy (ByteString )
117119import qualified Data.ByteString as BS
118120import qualified Data.ByteString.Lazy.Char8 as BLC8
119121import Data.List
120- ( (\\) , partition , inits , stripPrefix )
122+ ( (\\) , partition , inits , stripPrefix , intersect )
121123import Data.Either
122124 ( partitionEithers )
123125import qualified Data.Map as Map
124126import System.Directory
125- ( doesFileExist , createDirectoryIfMissing , getTemporaryDirectory )
127+ ( doesFileExist , createDirectoryIfMissing , getTemporaryDirectory
128+ , removeFile )
126129import System.FilePath
127130 ( (</>) , isAbsolute , takeDirectory )
128131import qualified System.Info
@@ -137,6 +140,18 @@ import Text.PrettyPrint
137140import Distribution.Compat.Environment ( lookupEnv )
138141import Distribution.Compat.Exception ( catchExit , catchIO )
139142
143+
144+ #if !MIN_VERSION_directory(1,2,5)
145+ import System.Directory (getDirectoryContents )
146+ listDirectory :: FilePath -> IO [FilePath ]
147+ listDirectory path =
148+ (filter f) <$> (getDirectoryContents path)
149+ where f filename = filename /= " ." && filename /= " .."
150+ #else
151+ import System.Directory (listDirectory )
152+ #endif
153+
154+
140155type UseExternalInternalDeps = Bool
141156
142157-- | The errors that can be thrown when reading the @setup-config@ file.
@@ -1647,9 +1662,42 @@ checkForeignDeps pkg lbi verbosity =
16471662 allLibs = collectField PD. extraLibs
16481663
16491664 ifBuildsWith headers args success failure = do
1665+ checkDuplicateHeaders
16501666 ok <- builds (makeProgram headers) args
16511667 if ok then success else failure
16521668
1669+ -- ensure that there is only one header with a given name
1670+ -- in either the generated (most likely by `configure`)
1671+ -- dist/build directory or in the source directory.
1672+ --
1673+ -- if it exists in both, we'll remove the one in the source
1674+ -- directory, as the generated should take precedence.
1675+ --
1676+ -- C compilers like to prefer source local relative
1677+ -- includes, as such providing the compiler with -I search
1678+ -- paths is ignored if the included file can be found
1679+ -- relative to the including file. As such we need to take
1680+ -- drastic measures and delete the offending file in the
1681+ -- source directory.
1682+ checkDuplicateHeaders = do
1683+ let relIncDirs = filter (not . isAbsolute) (collectField PD. includeDirs)
1684+ isHeader = isSuffixOf " .h"
1685+ genHeaders <- forM relIncDirs $ \ dir ->
1686+ fmap (dir </> ) . filter isHeader <$> listDirectory (buildDir lbi </> dir)
1687+ `catchIO` (\ _ -> return [] )
1688+ srcHeaders <- forM relIncDirs $ \ dir ->
1689+ fmap (dir </> ) . filter isHeader <$> listDirectory (baseDir lbi </> dir)
1690+ `catchIO` (\ _ -> return [] )
1691+ let commonHeaders = concat genHeaders `intersect` concat srcHeaders
1692+ forM_ commonHeaders $ \ hdr -> do
1693+ warn verbosity $ " Duplicate header found in "
1694+ ++ (buildDir lbi </> hdr)
1695+ ++ " and "
1696+ ++ (baseDir lbi </> hdr)
1697+ ++ " ; removing "
1698+ ++ (baseDir lbi </> hdr)
1699+ removeFile (baseDir lbi </> hdr)
1700+
16531701 findOffendingHdr =
16541702 ifBuildsWith allHeaders ccArgs
16551703 (return Nothing )
0 commit comments