1

直到现在我有以下代码:

shakeArgsWith opts additionalFlags $ \flags targets -> return $ Just $ do
    ...
    -- Get target arch from command line flags
    let givenArch = listToMaybe [v | AFlag v <- flags]
    let arch = fromMaybe defArch givenArch
    ...
    -- Set the main target
    let outName = masterOutName projType toolchain projName

    let mainTgt = (case projType of
                    Binary _ -> "bin"
                    Archive  -> "lib")
                  </> prettyShowArch arch
                  </> show variant
                  </> outName

    -- Set the build directory for the current run
    let buildDir = bldDir </> show toolchain </> prettyShowArch arch </> show variant
    ...
    mainTgt %> \out -> do ...
    ...
    buildDir <//> "*.o" %> \out -> do ...
    ...

这意味着规则的名称是根据我正在解析的命令行标志构造的(它们包含 arch 变量)。

因此,如果我给shake --arch=x64我在bin/x64/Release目录中构建主要目标,并在tmp/x64/Release文件夹中相应地构建我的中间文件。

但是现在我不使用命令行标志,而是希望用于构造规则名称的共享 arch 变量根据某些命令的输出来填充,例如,如果我可以定义一些顶级操作,它将是这样的:

Stdout sout <- quietly $ cmd (EchoStdout False) (EchoStderr False) "gcc -dumpmachine" :: Action (Stdout String)
let foundArch = show (gccTripletToArch sout)

mainTgt并在构造andbuildDir名称时使用变量 foundArch 而不是 arch 。显然这是无法做到的,因为即使是可以使用action函数返回的唯一顶级规则Rule ()。我能做什么呢?

4

1 回答 1

1

我认为你应该能够做到:

shakeArgsWith opts additionalFlags $ \flags targets -> do
     Stdout sout <- cmd (EchoStdout False) (EchoStderr False) "gcc -dumpmachine"
     let arch = show (gccTripletToArch sout)
     return $ Just $ do
         let buildDir = bldDir </> show toolchain </> prettyShowArch arch </> show variant
         ...
         buildDir <//> "*.o" %> \out -> do ...

Shake 中的目标模式必须是静态已知的,因为这确保了一些与快速重建有关的重要属性(您可以保证一个地方的更改具有可预测的效果)。但是,您可以在创建构建脚本之前运行命令来确定诸如架构、编译器版本等内容,并将它们烘焙进去。

另一种观点是,您是基于拱门动态生成的构建系统。使用 Shake,作为 Haskell EDSL,这没有什么特别的问题,而且你可以说以前是用命令行来做的。

于 2015-11-13T13:23:46.737 回答