没有直接的方法,但有可能。
假设您使用的是 Distribution.Simple,您基本上需要在构建阶段添加一个用户挂钩。
以下所有更改都需要出现在 Setup.hs 中:
更改 main 以使用构建挂钩,例如:
main :: IO ()
main = defaultMainWithHooks simpleUserHooks { buildHook = myBuildHook }
接下来你需要一个构建钩子。它可能如下所示:
myBuildHook pkg_descr local_bld_info user_hooks bld_flags =
do
let lib = fromJust (library pkg_descr)
lib_bi = libBuildInfo lib
custom_bi = customFieldsBI lib_bi
cpp_name = fromJust (lookup "x-cc-name" custom_bi)
c_srcs = cSources lib_bi
cc_opts = ccOptions lib_bi
inc_dirs = includeDirs lib_bi
lib_dirs = extraLibDirs lib_bi
bld_dir = buildDir local_bld_info
-- Compile C/C++ sources
putStrLn "invoking my compile phase"
objs <- mapM (compileCxx cpp_name cc_opts inc_dirs bld_dir) c_srcs
-- Remove C/C++ source code from the hooked build (don't change libs)
let lib_bi' = lib_bi { cSources = [] }
lib' = lib { libBuildInfo = lib_bi' }
pkg_descr' = pkg_descr { library = Just lib' }
-- The following line invokes the standard build behaviour
putStrLn "Invoke default build hook"
bh <- buildHook simpleUserHooks pkg_descr' local_bld_info user_hooks bld_flags
return bh
上面的代码可能需要解压一下。let 子句基本上是关于从传递给构建钩子的结构中解包所需的数据字段。请注意,您可以在 foo.cabal 中创建自定义节。我提供了代码来支持一个节,例如:
x-cc-name: icc
作为指定编译器的一种方式。提取所有源文件后,您使用函数映射它们以编译单个文件(注意:这在某些情况下是次优的,例如那些可以有效编译多个源文件以产生单个对象输出并受益的编译器来自大规模优化,但我们暂时将其放在一边)。
最后,由于我们现在已经编译了 C/C++ 代码,在将所有内容传递给默认构建挂钩之前,将其从构建结构中删除。
抱歉,这更像是一个“HOWTO”而不是一个固定的答案,但它应该可以帮助你开始。
我应该提到代码未经测试。我已经根据我在 wxHaskell 构建系统上所做的一些工作对其进行了改编,所以我知道这个想法很好用。Cabal API 实际上有很好的文档记录——它的主要缺点是在其中一些区域有些不稳定。