1 дек. 2015 г.

SCons: проблемы с генерацией исходников, VariantDir и SConsign

Проблема


После добавления в проект, использующий VariantDir, генерации исходников и их сборки, происходит следующее:
  • после каждого запуска, scons пересобирает все или некоторые файлы заново, даже если они не изменялись;
  • если удалить файл .sconsign.dblite, scons не может перегенерировать его, как обычно, и падает в конце сборки со следующим трейсом:
OSError: [Errno 2] No such file or directory: '.sconsign.dblite':
  File "/usr/lib64/python2.7/site-packages/SCons/Script/Main.py", line 1372:
    _exec_main(parser, values)
  File "/usr/lib64/python2.7/site-packages/SCons/Script/Main.py", line 1335:
    _main(parser)
  File "/usr/lib64/python2.7/site-packages/SCons/Script/Main.py", line 1099:
    nodes = _build_targets(fs, options, targets, target_top)
  File "/usr/lib64/python2.7/site-packages/SCons/Script/Main.py", line 1297:
    jobs.run(postfunc = jobs_postfunc)
  File "/usr/lib64/python2.7/site-packages/SCons/Job.py", line 113:
    postfunc()
  File "/usr/lib64/python2.7/site-packages/SCons/Script/Main.py", line 1294:
    SCons.SConsign.write()
  File "/usr/lib64/python2.7/site-packages/SCons/SConsign.py", line 109:
    syncmethod()
  File "/usr/lib64/python2.7/site-packages/SCons/dblite.py", line 127:
    self._os_unlink(self._file_name)
Exception OSError: OSError(2, 'No such file or directory') in
  <bound method dblite.__del__ of <SCons.dblite.dblite object at 0x7fa287435c10>> ignored

У меня проблема проявляется на scons 2.3.5 и 2.4.1, но только в составе большого проекта. Воспроизвести вне этого проекта баг не удалось.

Баг


Баг заключается в том, что:
  • по-умолчанию SCons создает отдельные файлы .sconsign для каталога с исходниками (например, ту где лежит SConstruct, но я не знаю от чего это зависит) и для каталога сборки (куда указывает VariantDir);
  • при каком-то стечении обстоятельств, scons записывает информацию о сборке в .sconsign внутри VariantDir, а ищет ее в другом каталоге, и не может найти.
Т.к. SCons не смог найти информацию о предыдущей сборке файла, он считает что файл не был собран. При запуске с --debug=explain можно увидеть следующее:

scons: Cannot explain why `<FILENAME>' is being rebuilt: No previous build information found       

Решение


Чтобы все починить, можно заствить SCons использовать один глобальный файл .sconsign на весь проект. Для этого надо передать абсолютный путь в функцию SConsignFile, например:

import os.path
env.SConsignFile(os.path.join(env.Dir('#').abspath, '.sconsign.dblite'))

Комментариев нет:

Отправить комментарий