Как сделать варианты сборки в встряхивании?

Как передать параметры в шейк и затем использовать их в наших правилах? Я хотел бы сделать некоторые эквиваленты:

make ARCH=x86_64
или
make DEBUG=YES и т. д...

На данный момент я использую переменные среды и функцию getEnv для их имитации.
Как я могу сделать зависимость от заданного параметра (переменной среды), чтобы его можно было прочитать один раз в сборке, сохранить где-нибудь и получить к нему доступ. из нескольких правил?

например На данный момент я делаю getEnv несколько раз в нескольких правилах, но во время компиляции переменная среды может измениться. Также, например, флаг отладки может изменить флаги как компилятора, так и компоновщика, что означает, что информация должна быть доступна как в правилах ссылки, так и в правилах вывода компиляции.


person Fr0stBit    schedule 05.10.2015    source источник
comment
но во время компиляции переменная среды может измениться - можете уточнить? Переменные среды захватываются в начале процесса, поэтому не будут изменяться во время выполнения, если только вы не вызовете что-то вроде setEnv.   -  person Neil Mitchell    schedule 06.10.2015
comment
Другой вопрос: хотите ли вы изменить DEBUG=YES на DEBUG=NO, чтобы изменить все правила, которые зависели от этого параметра (пересобрав большую часть вашего проекта), или просто проигнорировать изменение, или построить в другой каталог?   -  person Neil Mitchell    schedule 06.10.2015
comment
О первом комментарии: Ну, это то, о чем я забыл, так что соскребите это. По второму комментарию: Да, я хочу изменить все правила, которые зависят от изменения этого параметра. Например, изменятся флаги компиляции/связывания, а также выходные каталоги.   -  person Fr0stBit    schedule 06.10.2015


Ответы (1)


Существующий подход к использованию переменных среды должен работать, а поскольку переменные среды уже отслеживаются Shake, один из подходов состоит в том, чтобы проанализировать DEBUG=YES и превратить ее в переменную среды. Например:

main = shakeArgsWith shakeOptions [] $ \_ args -> do
    let (vars,files) = partition ('=' `elem`) args
    forM_ vars $ \v -> let (a,'=':b) = break (== '=') v in setEnv a b
    return $ Just $ if null files then rules else want files >> withoutActions rules

rules :: Rules ()
rules = ...

Поскольку переменные среды являются локальными для процесса (и его дочерних процессов), это, вероятно, будет работать нормально.

Конечно, хранить такую ​​информацию в переменных окружения немного некрасиво. Вместо этого вы можете создать свой собственный оракул для хранения информации:

main = shakeArgsWith shakeOptions [] $ \_ args -> do
    let (vars,files) = partition ('=' `elem`) args
    let vars2 = [(a,b) | v <- vars, let (a,'=':b) = break (== '=') v]
    return $ Just $ do
        global <- addOracle $ \(Global x) -> return $ lookup x vars2
        if null files then rules global else want files >> withoutActions (rules global)

newtype Global = Global String deriving (Show,Typeable,Eq,Hashable,Binary,NFData)

rules :: (Global -> Action (Maybe String)) -> Rules ()
rules global = undefined

Теперь вместо того, чтобы записывать информацию в переменную окружения с setEnv, мы сохраняем ее в оракуле с addOracle, который по-прежнему будет отслеживаться и не конфликтовать ни с какими другими частями переменных окружения.

person Neil Mitchell    schedule 06.10.2015
comment
Фантастические решения! Точка входа shakeArgsWith — это все, что я хотел. Функция оракула тоже кажется довольно удобной, но ее довольно сложно понять из документации. Хотя я попробую :P! Спасибо за ответы! - person Fr0stBit; 07.10.2015
comment
Лучшие документы находятся по адресу hackage.haskell.org/package. /шейк/документы/. Однако они являются одним из наиболее сложных аспектов Shake. - person Neil Mitchell; 08.10.2015