Weird GCC arguments being generated on Windows for includeDirs (cabal 2.4.1.0).
- Dominant language
- Haskell
- Stars
- 1.7k
- Forks
- 750
- Avg merge
- 4d 3h
- Merged PRs (30d)
- 28
Description
So, I'm trying to get `mysql` package to build on windows and I'm nearly done, but I'm getting some weird behavior from Cabal.
It generates some unexpected GCC parameters:
```
Resolving dependencies...
Build profile: -w ghc-8.6.5 -O1
In order, the following will be built (use -v for more details):
- mysql-0.1.7 (lib:mysql) (first run)
[1 of 1] Compiling Main ( C:\Users\lh\Desktop\mysql\dist-newstyle\build\x86_64-windows\ghc-8.6.5\mysql-0.1.7\setup\setup.hs, C:\Users\lh\Desktop\mysql\dist-newstyle\build\x86_64-windows\ghc-8.6.5\mysql-0.1.7\setup\Main.o )
Linking C:\Users\lh\Desktop\mysql\dist-newstyle\build\x86_64-windows\ghc-8.6.5\mysql-0.1.7\setup\setup.exe ...
Configuring mysql-0.1.7...
Preprocessing library for mysql-0.1.7..
In file included from C.hsc:73:0:
include/mysql_signals.h:9:10: fatal error: mysql.h: No such file or directory
#include "mysql.h"
^~~~~~~~~
compilation terminated.
C:\Users\lh\Desktop\mysql\dist-newstyle\build\x86_64-windows\ghc-8.6.5\mysql-0.1.7\build\Database\MySQL\Base\C_hsc_make.c failed (exit code 1)
command was:
C:\Users\lh\Haskell\GHC\Versions\ghc-8.6.5\lib\../mingw/bin\gcc.exe
-c C:\Users\lh\Desktop\mysql\dist-newstyle\build\x86_64-windows\ghc-8.6.5\mysql-0.1.7\build\Database\MySQL\Base\C_hsc_make.c
-o C:\Users\lh\Desktop\mysql\dist-newstyle\build\x86_64-windows\ghc-8.6.5\mysql-0.1.7\build\Database\MySQL\Base\C_hsc_make.o
-fno-stack-protector -D__GLASGOW_HASKELL__=806 -Dmingw32_BUILD_OS=1 -Dx86_64_BUILD_ARCH=1 -Dmingw32_HOST_OS=1 -Dx86_64_HOST_ARCH=1
-I"C:\Program Files\MySQL\MySQL Server 8.0\include"
-Iinclude
-IC:\Users\lh\Desktop\mysql\dist-newstyle\build\x86_64-windows\ghc-8.6.5\mysql-0.1.7\build\"C:\Program Files\MySQL\MySQL Server 8.0\include"
-IC:\Users\lh\Desktop\mysql\dist-newstyle\build\x86_64-windows\ghc-8.6.5\mysql-0.1.7\build\include
-IC:\Users\lh\Desktop\mysql\dist-newstyle\build\x86_64-windows\ghc-8.6.5\mysql-0.1.7\build\autogen
-IC:\Users\lh\Desktop\mysql\dist-newstyle\build\x86_64-windows\ghc-8.6.5\mysql-0.1.7\build\global-autogen
-include C:\Users\lh\Desktop\mysql\dist-newstyle\build\x86_64-windows\ghc-8.6.5\mysql-0.1.7\build\autogen\cabal_macros.h
-IC:\Users\lh\Haskell\GHC\Versions\ghc-8.6.5\lib\bytestring-0.10.8.2\include
-IC:\Users\lh\Haskell\GHC\Versions\ghc-8.6.5\lib\base-4.12.0.0\include
-IC:\Users\lh\Haskell\GHC\Versions\ghc-8.6.5\lib\integer-gmp-1.0.2.0\include
-IC:\Users\lh\Haskell\GHC\Versions\ghc-8.6.5\lib/include
-IC:\Users\lh\Haskell\GHC\Link/lib/include/
```
Basically, in the `includeDirs` field for my `BuildInfo` I've added this (hardcoded for testing purposes):
```haskell
["\"C:\\Program Files\\MySQL\\MySQL Server 8.0\\include\""]
```
In the generated `gcc` command I get the following expected flag:
```
-I"C:\Program Files\MySQL\MySQL Server 8.0\include"
```
But I also get this flag which has `C:\Program Files\MySQL\MySQL Server 8.0\include` tacked on to the end for some reason:
```
-IC:\Users\lh\Desktop\mysql\dist-newstyle\build\x86_64-windows\ghc-8.6.5\mysql-0.1.7\build\"C:\Program Files\MySQL\MySQL Server 8.0\include"
```
If I remove this flag and manually execute `gcc` command the program is built, but I can't figure out why this flag is generated and how to remove it.
---
Here is the full code of my current `Setup.hs`, mysql paths are set in `mysqlBuildInfo` function:
```haskell
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{- OPTIONS_GHC -Wall #-}
#ifndef MIN_VERSION_Cabal
#define MIN_VERSION_Cabal(x,y,z) 0
#endif
import Control.Monad (liftM, msum, sequence)
import Data.Text ( Text, pack, unpack, splitOn, replace)
import qualified Data.Text as Text
import Data.List (isPrefixOf, nub)
import Distribution.PackageDescription
import Distribution.Simple
import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.Program
import Distribution.Verbosity
-- A Cabal 1.16 vs 1.18 compatibility hack, as in 1.18
-- findProgramLocation has a new (unused in this case) parameter.
-- ConstOrId adds this parameter when types say it is mandatory.
class ConstOrId a b where
constOrId :: a -> b
instance ConstOrId a a where
constOrId = id
instance ConstOrId a (b -> a) where
constOrId = const
main :: IO ()
main = defaultMainWithHooks simpleUserHooks
{ hookedPrograms = [mysqlConfigProgram]
, confHook = \pkg flags -> do
lbi <- confHook simpleUserHooks pkg flags
bi <- mysqlBuildInfo lbi
return lbi
{ localPkgDescr = updatePackageDescription (Just bi, []) (localPkgDescr lbi)
}
}
#if defined (mingw32_HOST_OS)
mysqlConfigProgram = simpleProgram "perl"
#else
mysqlConfigProgram = (simpleProgram "mysql_config") {
programFindLocation = \verbosity -> constOrId $ liftM msum $ sequence
#if MIN_VERSION_Cabal(1,24,0)
[ (findProgramOnSearchPath verbosity [ProgramSearchPathDefault] "mysql_config")
, (findProgramOnSearchPath verbosity [ProgramSearchPathDefault] "mysql_config5")
, (findProgramOnSearchPath verbosity [ProgramSearchPathDefault] "mariadb_config")
]
#else
[ (findProgramLocation verbosity "mysql_config")
, (findProgramLocation verbosity "mysql_config5")
, (findProgramLocation verbosity "mariadb_config")
]
#endif
}
#endif
mysqlBuildInfo :: LocalBuildInfo -> IO BuildInfo
mysqlBuildInfo lbi = do
#if MIN_VERSION_Cabal(2,0,0)
let mysqlConfig = wordfix . getDbProgramOutput normal
mysqlConfigProgram (withPrograms lbi)
#else
let mysqlConfig = wordfix . rawSystemProgramStdoutConf normal
mysqlConfigProgram (withPrograms lbi)
#endif
#if defined (mingw32_HOST_OS)
let cfg = mysqlConfig . (\args -> ["-S", "mysql_config.pl"] <> args )
#else
let cfg = mysqlConfig
#endif
include <- cfg ["--include"]
libs <- cfg ["--libs"]
libsR <- cfg ["--libs_r"]
#if defined ( mingw32_HOST_OS)
-- let include = ["-I\"C:\\Program Files\\MySQL\\MySQL Server 8.0\\include\""]
-- let libs = ["-L\"C:\\Program Files\\MySQL\\MySQL Server 8.0\\lib\\\"","ws2_32","crypt32","Secur32"]
-- let libsR = ["-L\"C:\\Program Files\\MySQL\\MySQL Server 8.0\\lib\\\"","ws2_32","crypt32","Secur32"]
#endif
return emptyBuildInfo
{ extraLibDirs
= map (drop 2)
. filter ("-L" `isPrefixOf`)
$ libs
, extraLibs
= map (drop 2) . filter ("-l" `isPrefixOf`)
. filter (/= "-lmygcc")
$ filter (/= "-lmysqlclient_r")
$ nub (libs ++ libsR)
, includeDirs
= map (drop 2) include
}
#if defined (mingw32_HOST_OS)
where wordfix = fmap $ fmap fixword . filter (/="-lLIBMYSQL_OS_OUTPUT_NAME-NOTFOUND") . fmap unpack . splitOn "\" \"" . pack . reverse . dropWhile (=='"') . reverse . dropWhile (=='"') . takeWhile (/='\n')
#else
where wordfix = fmap words
#endif
fixword :: String -> String
fixword path = unpack $ if lori txt then fixupPath txt else txt
where txt = pack path
lori :: Text -> Bool
lori txt = ( "-L/c/" `Text.isPrefixOf` txt ) || ( "-I/c/" `Text.isPrefixOf` txt )
fixupPath :: Text -> Text
fixupPath pth = pfx <> pth'
where pfx = Text.take 2 pth
pth' = "\"C:\\" <> (replace "/" "\\" $ Text.drop 5 pth) <> "\""
```
Contributor guide
Assessment
This issue has not been assessed yet.