Ответ 1
Во-первых, обратите внимание, что многократное вызов Latex не всегда приводит к фиксированной точке, поэтому убедитесь, что у вас есть привязка к итерациям. Кроме того, некоторые дистрибутивы (MikTex) предоставляют версии Latex, которые автоматически запускаются столько раз, сколько им нужно, поэтому, если вы используете их, проблема исчезнет.
Напишите свою собственную команду foo_transitive
Самый простой способ решить проблему, предполагая, что каждый запуск foo
имеет одинаковые зависимости, заключается в том, чтобы решить проблему за пределами системы сборки. Просто напишите команду foo_transitive
, либо как оболочку script, либо как функцию Haskell, которая при подаче входного файла создает выходной файл, повторно запуская его и проверяя, достиг ли он фиксированной точки. Теперь система сборки может использовать foo_transitive
, и нет проблем с зависимостями.
Кодировать его в системе сборки
Вам нужно написать два правила, один из которых делает один шаг, и тот, который определяет, какой шаг является правильным:
let step i = "tempfile" <.> show i
"tempfile.*" *> \out -> do
let i = read $ takeExtension out :: Int
if i == 0 then
copyFile "input" out
else
let prev = step (i-1)
need [prev]
-- perhaps require addition dependencies, depending on prev
system' "foo" [prev,out]
"output" *> \out -> do
let f i = do
old <- readFile' $ step (i-1)
new <- readFile' $ step i
if old == new || i > 100 then copyFile (step i) out else f (i+1)
f 1
Первое правило генерирует tempfile.2
из tempfile.1
и т.д., поэтому мы можем need ["tempfile.100"]
получить 100-ю итерацию. Если зависимости изменяются на каждом шаге, мы можем посмотреть на предыдущий результат, чтобы вычислить новые зависимости.
Второе правило циклически проверяет каждую пару значений в последовательности и останавливается, когда они равны. Если вы реализуете это в производственной системе сборки, вы можете не называть readFile'
для каждого элемента дважды (один раз как i-1
и один раз как i
).