module DDC.Build.Builder
( BuilderConfig (..)
, Builder (..)
, BuilderResult (..)
, builders
, determineDefaultBuilder)
where
import DDC.Build.Platform
import DDC.Base.Pretty hiding ((</>))
import System.FilePath
import System.Exit
import System.Process
import qualified DDC.Core.Salt.Platform as Llvm
data BuilderConfig
= BuilderConfig
{
builderConfigBaseSrcDir :: FilePath
, builderConfigBaseLibDir :: FilePath }
data Builder
= Builder
{
builderName :: String
, buildHost :: Platform
, buildTarget :: Platform
, buildSpec :: Llvm.Platform
, buildBaseSrcDir :: FilePath
, buildBaseLibDir :: FilePath
, buildCC :: FilePath -> FilePath -> IO ()
, buildLlc :: FilePath -> FilePath -> IO ()
, buildAs :: FilePath -> FilePath -> IO ()
, buildLdExe :: FilePath -> FilePath -> IO ()
, buildLdLibStatic :: [FilePath] -> FilePath -> IO ()
, buildLdLibShared :: [FilePath] -> FilePath -> IO () }
data BuilderResult
= BuilderSuccess
| BuilderCanceled
| BuilderFailed
deriving (Show, Eq)
instance Show Builder where
show builder
= "Builder " ++ show (builderName builder)
instance Pretty Builder where
ppr builder
= vcat
[ text "Builder Name : " <> text (builderName builder)
, empty
, text "Host Platform"
, indent 1 $ ppr $ buildHost builder
, empty
, text "Target Platform"
, indent 1 $ ppr $ buildTarget builder
, empty
, text "LLVM Target Spec"
, indent 1 $ ppr $ buildSpec builder ]
builders :: BuilderConfig -> [Builder]
builders config
= [ builder_X8632_Darwin config
, builder_X8664_Darwin config
, builder_X8632_Linux config
, builder_X8664_Linux config
, builder_PPC32_Linux config ]
determineDefaultBuilder :: BuilderConfig -> IO (Maybe Builder)
determineDefaultBuilder config
= do mPlatform <- determineHostPlatform
case mPlatform of
Just (Platform ArchX86_32 OsDarwin)
-> return $ Just (builder_X8632_Darwin config)
Just (Platform ArchX86_64 OsDarwin)
-> return $ Just (builder_X8664_Darwin config)
Just (Platform ArchX86_32 OsLinux)
-> return $ Just (builder_X8632_Linux config)
Just (Platform ArchX86_64 OsLinux)
-> return $ Just (builder_X8664_Linux config)
Just (Platform ArchPPC_32 OsLinux)
-> return $ Just (builder_PPC32_Linux config)
Just (Platform ArchX86_32 OsCygwin)
-> return $ Just (builder_X8632_Cygwin config)
Just (Platform ArchX86_32 OsMingw)
-> return $ Just (builder_X8632_Mingw config)
_ -> return Nothing
builder_X8632_Darwin config
= Builder
{ builderName = "x86_32-darwin"
, buildHost = Platform ArchX86_32 OsDarwin
, buildTarget = Platform ArchX86_32 OsDarwin
, buildSpec = Llvm.platform32
, buildBaseSrcDir = builderConfigBaseSrcDir config
, buildBaseLibDir = builderConfigBaseLibDir config
, buildLlc
= \llFile sFile
-> doCmd "LLVM compiler" [(2, BuilderCanceled)]
[ "llc -O3 -march=x86 -relocation-model=pic -disable-cfi"
, llFile
, "-o", sFile ]
, buildCC
= \cFile oFile
-> doCmd "C compiler" [(2, BuilderCanceled)]
[ "gcc -Werror -std=c99 -O3 -m32"
, "-c", cFile
, "-o", oFile
, "-I" ++ builderConfigBaseSrcDir config </> "sea/runtime"
, "-I" ++ builderConfigBaseSrcDir config </> "sea/primitive" ]
, buildAs
= \sFile oFile
-> doCmd "assembler" [(2, BuilderCanceled)]
[ "as -arch i386"
, "-o", oFile
, sFile ]
, buildLdExe
= \oFile binFile
-> doCmd "linker" [(2, BuilderCanceled)]
[ "gcc -m32"
, "-o", binFile
, oFile
, builderConfigBaseLibDir config </> "libddc-runtime.dylib" ]
, buildLdLibStatic
= \oFiles libFile
-> doCmd "linker" [(2, BuilderCanceled)]
$ ["ar r", libFile] ++ oFiles
, buildLdLibShared
= \oFiles libFile
-> doCmd "linker" [(2, BuilderCanceled)]
$ [ "gcc -m32 -dynamiclib -undefined dynamic_lookup"
, "-o", libFile ] ++ oFiles
}
builder_X8664_Darwin config
= Builder
{ builderName = "x86_64-darwin"
, buildHost = Platform ArchX86_64 OsDarwin
, buildTarget = Platform ArchX86_64 OsDarwin
, buildSpec = Llvm.platform64
, buildBaseSrcDir = builderConfigBaseSrcDir config
, buildBaseLibDir = builderConfigBaseLibDir config
, buildLlc
= \llFile sFile
-> doCmd "LLVM compiler" [(2, BuilderCanceled)]
[ "llc -O3 -march=x86-64 -relocation-model=pic -disable-cfi"
, llFile
, "-o", sFile ]
, buildCC
= \cFile oFile
-> doCmd "C compiler" [(2, BuilderCanceled)]
[ "gcc -Werror -std=c99 -O3 -m64"
, "-c", cFile
, "-o", oFile
, "-I" ++ builderConfigBaseSrcDir config </> "sea/runtime"
, "-I" ++ builderConfigBaseSrcDir config </> "sea/primitive" ]
, buildAs
= \sFile oFile
-> doCmd "assembler" [(2, BuilderCanceled)]
[ "as -arch x86_64"
, "-o", oFile
, sFile ]
, buildLdExe
= \oFile binFile
-> doCmd "linker" [(2, BuilderCanceled)]
[ "gcc -m64"
, "-o", binFile
, oFile
, builderConfigBaseLibDir config </> "libddc-runtime.dylib" ]
, buildLdLibStatic
= \oFiles libFile
-> doCmd "linker" [(2, BuilderCanceled)]
$ ["ar r", libFile] ++ oFiles
, buildLdLibShared
= \oFiles libFile
-> doCmd "linker" [(2, BuilderCanceled)]
$ [ "gcc -m64 -dynamiclib -undefined dynamic_lookup"
, "-o", libFile ] ++ oFiles
}
builder_X8632_Linux config
= Builder
{ builderName = "x86_32-linux"
, buildHost = Platform ArchX86_32 OsLinux
, buildTarget = Platform ArchX86_32 OsLinux
, buildSpec = Llvm.platform32
, buildBaseSrcDir = builderConfigBaseSrcDir config
, buildBaseLibDir = builderConfigBaseLibDir config
, buildLlc
= \llFile sFile
-> doCmd "LLVM compiler" [(2, BuilderCanceled)]
[ "llc -O3 -march=x86 -relocation-model=pic"
, llFile
, "-o", sFile ]
, buildCC
= \cFile oFile
-> doCmd "C compiler" [(2, BuilderCanceled)]
[ "gcc -Werror -std=c99 -O3 -m32 -fPIC"
, "-c", cFile
, "-o", oFile
, "-I" ++ builderConfigBaseSrcDir config </> "sea/runtime"
, "-I" ++ builderConfigBaseSrcDir config </> "sea/primitive" ]
, buildAs
= \sFile oFile
-> doCmd "assembler" [(2, BuilderCanceled)]
[ "as --32"
, "-o", oFile
, sFile ]
, buildLdExe
= \oFile binFile
-> doCmd "linker" [(2, BuilderCanceled)]
[ "gcc -m32"
, "-o", binFile
, oFile
, builderConfigBaseLibDir config </> "libddc-runtime.so" ]
, buildLdLibStatic
= \oFiles libFile
-> doCmd "linker" [(2, BuilderCanceled)]
$ ["ar r", libFile] ++ oFiles
, buildLdLibShared
= \oFiles libFile
-> doCmd "linker" [(2, BuilderCanceled)]
$ [ "gcc -shared", "-o", libFile ] ++ oFiles
}
builder_X8664_Linux config
= Builder
{ builderName = "x86_64-linux"
, buildHost = Platform ArchX86_64 OsLinux
, buildTarget = Platform ArchX86_64 OsLinux
, buildSpec = Llvm.platform64
, buildBaseSrcDir = builderConfigBaseSrcDir config
, buildBaseLibDir = builderConfigBaseLibDir config
, buildLlc
= \llFile sFile
-> doCmd "LLVM compiler" [(2, BuilderCanceled)]
[ "llc -O3 -march=x86-64 -relocation-model=pic"
, llFile
, "-o", sFile ]
, buildCC
= \cFile oFile
-> doCmd "C compiler" [(2, BuilderCanceled)]
[ "gcc -Werror -std=c99 -O3 -m64 -fPIC"
, "-c", cFile
, "-o", oFile
, "-I" ++ builderConfigBaseSrcDir config </> "sea/runtime"
, "-I" ++ builderConfigBaseSrcDir config </> "sea/primitive" ]
, buildAs
= \sFile oFile
-> doCmd "assembler" [(2, BuilderCanceled)]
[ "as --64"
, "-o", oFile
, sFile ]
, buildLdExe
= \oFile binFile
-> doCmd "linker" [(2, BuilderCanceled)]
[ "gcc -m64"
, "-o", binFile
, oFile
, builderConfigBaseLibDir config </> "libddc-runtime.so" ]
, buildLdLibStatic
= \oFiles libFile
-> doCmd "linker" [(2, BuilderCanceled)]
$ ["ar r", libFile] ++ oFiles
, buildLdLibShared
= \oFiles libFile
-> doCmd "linker" [(2, BuilderCanceled)]
$ [ "gcc -shared", "-o", libFile ] ++ oFiles
}
builder_PPC32_Linux config
= Builder
{ builderName = "ppc32-linux"
, buildHost = Platform ArchPPC_32 OsLinux
, buildTarget = Platform ArchPPC_32 OsLinux
, buildSpec = Llvm.platform32
, buildBaseSrcDir = builderConfigBaseSrcDir config
, buildBaseLibDir = builderConfigBaseLibDir config
, buildLlc
= \llFile sFile
-> doCmd "LLVM compiler" [(2, BuilderCanceled)]
[ "llc -O3 -march=ppc32 -relocation-model=pic"
, llFile
, "-o", sFile ]
, buildCC
= \cFile oFile
-> doCmd "C compiler" [(2, BuilderCanceled)]
[ "gcc -Werror -std=c99 -O3 -m32"
, "-c", cFile
, "-o", oFile
, "-I" ++ builderConfigBaseSrcDir config </> "sea/runtime"
, "-I" ++ builderConfigBaseSrcDir config </> "sea/primitive" ]
, buildAs
= \sFile oFile
-> doCmd "assembler" [(2, BuilderCanceled)]
[ "as"
, "-o", oFile
, sFile ]
, buildLdExe
= \oFile binFile
-> doCmd "linker" [(2, BuilderCanceled)]
[ "gcc -m32"
, "-o", binFile
, oFile
, builderConfigBaseLibDir config </> "libddc-runtime.so" ]
, buildLdLibStatic
= \oFiles libFile
-> doCmd "linker" [(2, BuilderCanceled)]
$ ["ar r", libFile] ++ oFiles
, buildLdLibShared
= \oFiles libFile
-> doCmd "linker" [(2, BuilderCanceled)]
$ [ "gcc -shared", "-o", libFile ] ++ oFiles
}
builder_X8632_Cygwin config
= Builder
{ builderName = "x86_32-cygwin"
, buildHost = Platform ArchX86_32 OsCygwin
, buildTarget = Platform ArchX86_32 OsCygwin
, buildSpec = Llvm.platform32
, buildBaseSrcDir = builderConfigBaseSrcDir config
, buildBaseLibDir = builderConfigBaseLibDir config
, buildLlc
= \llFile sFile
-> doCmd "LLVM compiler" [(2, BuilderCanceled)]
[ "llc -O3 -march=x86 "
, normalise llFile
, "-o", normalise sFile ]
, buildCC
= \cFile oFile
-> doCmd "C compiler" [(2, BuilderCanceled)]
[ "gcc-4 -Werror -std=c99 -O3 -m32"
, "-c", cFile
, "-o", oFile
, "-I" ++ builderConfigBaseSrcDir config </> "sea/runtime"
, "-I" ++ builderConfigBaseSrcDir config </> "sea/primitive" ]
, buildAs
= \sFile oFile
-> doCmd "assembler" [(2, BuilderCanceled)]
[ "as --32"
, "-o", normalise oFile
, normalise sFile ]
, buildLdExe
= \oFile binFile
-> doCmd "linker" [(2, BuilderCanceled)]
[ "gcc-4 -m32"
, "-o", normalise binFile
, normalise oFile
, normalise $ builderConfigBaseLibDir config </> "libddc-runtime.a" ]
, buildLdLibStatic
= \oFiles libFile
-> doCmd "linker" [(2, BuilderCanceled)]
$ ["ar r", libFile] ++ oFiles
, buildLdLibShared
= \oFiles libFile
-> doCmd "linker" [(2, BuilderCanceled)]
$ [ "gcc -shared", "-o", libFile ] ++ oFiles
}
builder_X8632_Mingw config
= Builder
{ builderName = "x86_32-mingw"
, buildHost = Platform ArchX86_32 OsMingw
, buildTarget = Platform ArchX86_32 OsMingw
, buildSpec = Llvm.platform32
, buildBaseSrcDir = builderConfigBaseSrcDir config
, buildBaseLibDir = builderConfigBaseLibDir config
, buildLlc
= \llFile sFile
-> doCmd "LLVM compiler" [(2, BuilderCanceled)]
[ "llc -O3 -march=x86 "
, normalise llFile
, "-o", normalise sFile ]
, buildCC
= \cFile oFile
-> doCmd "C compiler" [(2, BuilderCanceled)]
[ "gcc -Werror -std=c99 -O3 -m32"
, "-c", cFile
, "-o", oFile
, "-I" ++ builderConfigBaseSrcDir config </> "sea/runtime"
, "-I" ++ builderConfigBaseSrcDir config </> "sea/primitive" ]
, buildAs
= \sFile oFile
-> doCmd "assembler" [(2, BuilderCanceled)]
[ "as --32"
, "-o", normalise oFile
, normalise sFile ]
, buildLdExe
= \oFile binFile
-> doCmd "linker" [(2, BuilderCanceled)]
[ "gcc -m32"
, "-o", normalise binFile
, normalise oFile
, normalise $ builderConfigBaseLibDir config </> "libddc-runtime.a" ]
, buildLdLibStatic
= \oFiles libFile
-> doCmd "linker" [(2, BuilderCanceled)]
$ ["ar r", libFile] ++ oFiles
, buildLdLibShared
= \oFiles libFile
-> doCmd "linker" [(2, BuilderCanceled)]
$ [ "gcc -shared", "-o", libFile ] ++ oFiles
}
doCmd :: String
-> [(Int, BuilderResult)]
-> [String]
-> IO ()
doCmd thing exitCodeMeanings cmdParts
= do
code <- system cmd
case code of
ExitSuccess
-> return ()
ExitFailure c
| Just meaning <- lookup c exitCodeMeanings
-> case meaning of
BuilderSuccess -> return ()
BuilderCanceled -> exitWith $ ExitFailure 2
BuilderFailed -> die c
| otherwise -> die c
where cmd = unwords cmdParts
die c = error
$ unlines
[ "System command failed when invoking external " ++ thing ++ "."
, " Command was: " ++ cmd
, " Exit code: " ++ show c ]