make idea

July 10, 2011

Я периодически нарываюсь на проблемы параллельной сборки всяких проектов средствами make. Из недавних: баг #326347, баг #373947. Эти баги особенны тем, что они проявляются только на 8-головых (и выше) машинах. На моём корытце они не очень хотят проявляться.

Концептуально, Makefile - файл со списком целей и правил, по которым строятся промежуточные цели, чтобы достигнуть конечной.

A -(r1)-> B  \
C -(r2)-> D (r4)-> G
E -(r3)-> F  /

Обычно апстрим проекта тестирует сборку через команду make без всяких -jN параметров, а GNU make всегда выполняет правила для (хоть и независимых) целей в одном и том же порядке.

В итоге получаем порядок исполнения правил:

  1. r1
  2. r2
  3. r3
  4. r4

Но что, если r2 всё-таки требует результата r1 и Makefile - неправильный? Как бы извратиться и найти эту ошибку автоматически?

И вот что я надумал:

Простое решение. Произвольно переставлять порядок исполнения независимых целей при каждом запуске make в самом make. Так бы от запуска к запуску тестировались разные порядки сборки и возможные ошибки (правда, не все) выплывали чаще даже без использвания make -jN. Чтобы воспроизвести тот же порядок при ошибке make мог бы выводить на экран или в файл то, что заставило бы make пытаться собрать цели в том же порядке. К примеру, Makefile.faulty с явно заданной последовательностью правил.

Сложное решение. Встроить в make поддержку отслеживания всех порождаемых процессов (например, через ptrace или LD_PRELOAD) и записывать в какие цели они лезут на чтение/запись. После завершения сборки проверять: соответствует ли граф зависимотей целей тем целям, которые открывались дочерними программами. В теории, такой вариант (в отличии от предыдущего) способен находить сразу все недостаточные завосимости в Makefile.

ptrace используется sydbox из exherbo, LD_PRELOAD используется (надо проверить) sandbox из gentoo. На свете есть еще fsnotify.

Кто реализует раньше, чем я, тот - молодец! :]