Какой у вас опыт работы с нерекурсивным make?

Несколько лет назад я прочитал статью Рекурсивное объявление считается вредным и реализовал эту идею в собственном процесс сборки. Недавно я прочитал другую статью с идеями о том, как реализовать нерекурсивный make . Итак, у меня есть несколько точек данных, которые нерекурсивно make работают по крайней мере для нескольких проектов.

Но мне интересно узнать об опыте других. Вы пробовали нерекурсивный make? Сделало это лучше или хуже? Стоило ли потратить время?


person Jon Ericson    schedule 17.02.2009    source источник
comment
В случае, если это будет полезно для кого-либо: ссылка на «Реализация нерекурсивной бумаги make» в вопросе теперь 404s, но документ можно найти по адресу новый веб-сайт автора.   -  person Gareth McCaughan    schedule 22.05.2019
comment
Да, и кажется, что это может быть лучшим местом, чтобы найти рекурсивное объявление как вредное.   -  person Gareth McCaughan    schedule 22.05.2019
comment
@GarethMcCaughan: Спасибо, что нашли эти ссылки! Я отредактировал их в посте. (Из любопытства, помогло бы, если бы функция редактирования была более заметной или вы неохотно редактируете посты других людей? Я пытаюсь понять, как мы могли бы улучшить сайт. Опасность работа ;-)   -  person Jon Ericson    schedule 22.05.2019
comment
Хех. На самом деле я забыл, что у меня достаточно репутации на SO, чтобы сделать это здесь. У меня нет проблем с редактированием постов других людей, и я являюсь модом на другом сайте Stack Exchange. Приношу свои извинения за глупые поступки, а не за разумные поступки.   -  person Gareth McCaughan    schedule 22.05.2019
comment
@GarethMcCaughan: Нет проблем! Я только что подумал, почему иногда не используется редактирование. (И я не заметил, что ты мод! Теперь мне неловко. ;-)   -  person Jon Ericson    schedule 23.05.2019
comment
Я пытаюсь сделать это еще раз, но эта страница не была приходя в хиты. В частности, мультиархитектурные сборки очень полезны для многих проектов. и должен подключиться к нерекурсивной структуре.   -  person artless noise    schedule 28.09.2019


Ответы (8)


Мы используем нерекурсивную систему GNU Make в компании, в которой я работаю. Он основан на статье Миллера и особенно на приведенной вами ссылке «Реализация нерекурсивного make». Нам удалось усовершенствовать код Бергена до системы, в которой в make-файлах подкаталогов вообще нет шаблонов. По большому счету, она работает нормально и намного лучше, чем наша предыдущая система (рекурсивная вещь, сделанная с помощью GNU Automake).

Мы поддерживаем все основные операционные системы (коммерчески): AIX, HP-UX, Linux, OS X, Solaris, Windows, даже мэйнфрейм AS / 400. Мы компилируем один и тот же код для всех этих систем, при этом зависимые от платформы части изолированы в библиотеки.

В нашем дереве более двух миллионов строк кода C примерно в 2000 подкаталогах и 20000 файлах. Мы серьезно рассматривали возможность использования SCons, но никак не могли заставить его работать достаточно быстро. В более медленных системах Python использовал бы пару десятков секунд только для синтаксического анализа файлов SCons, тогда как GNU Make сделал то же самое примерно за одну секунду. Это было около трех лет назад, так что с тех пор все могло измениться. Обратите внимание, что мы обычно храним исходный код в общей папке NFS / CIFS и строим тот же код на нескольких платформах. Это означает, что инструмент сборки еще медленнее сканирует дерево исходных текстов на предмет изменений.

Наша нерекурсивная система GNU Make не лишена проблем. Вот некоторые из самых серьезных препятствий, с которыми вы можете столкнуться:

  • Сделать его переносимым, особенно в Windows, - это большая работа.
  • Хотя GNU Make - почти удобный язык функционального программирования, он не подходит для программирования в целом. В частности, здесь нет пространств имен, модулей или чего-либо подобного, чтобы помочь вам изолировать части друг от друга. Это может вызвать проблемы, хотя и не такие большие, как вы думаете.

Основные преимущества нашей старой рекурсивной системы make-файлов:

  • Это быстро. Требуется около двух секунд, чтобы проверить все дерево (2k каталогов, 20k файлов) и либо решить, что оно актуально, либо начать компиляцию. Старая рекурсивная вещь потребовала бы больше минуты, чтобы ничего не сделать.
  • Он правильно обрабатывает зависимости. Наша старая система основывалась на порядке создания подкаталогов и т. Д. Как и следовало ожидать, читая статью Миллера, рассмотрение всего дерева как единого объекта - действительно правильный способ решения этой проблемы.
  • После всей тяжелой работы, которую мы вложили в него, он переносится на все наши поддерживаемые системы. Это довольно круто.
  • Система абстракции позволяет нам писать очень лаконичные make-файлы. Типичный подкаталог, определяющий только библиотеку, занимает всего две строки. В одной строке указано имя библиотеки, а в другой перечислены библиотеки, от которых она зависит.

Что касается последнего пункта в приведенном выше списке. В итоге мы реализовали своего рода средство расширения макросов в системе сборки. Подкаталоги makefiles перечисляют программы, подкаталоги, библиотеки и другие общие вещи в переменных, таких как PROGRAMS, SUBDIRS, LIBS. Затем каждое из них расширяется до «настоящих» правил GNU Make. Это позволяет нам избежать многих проблем с пространством имен. Например, в нашей системе нормально иметь несколько исходных файлов с одним и тем же именем, это не проблема.

В любом случае, это потребовало огромной работы. Если вы можете заставить SCons или что-то подобное работать для вашего кода, я бы посоветовал вам сначала взглянуть на это.

person Ville Laurikari    schedule 18.02.2009
comment
Я не думаю, что какая-либо система сборки действительно может соответствовать правильно написанной нерекурсивной системе сборки GNU. - person JesperE; 19.02.2009
comment
@JesperE, попробуйте tup и удивитесь gittup.org/tup/make_vs_tup.html и Конечно, Premake и cmake генерируют make-файлы автоматически, поэтому я предполагаю, что они могут соответствовать ему по определению. - person Elazar Leibovich; 27.04.2011
comment
@Ville, я убежден, что создание нерекурсивного make возможно. Но я не уверен, что это ремонтопригодно. Вам приходилось использовать sed для make-файлов? Сколько шаблонов вам нужно было использовать, чтобы включить определенный подпроект? Насколько легко скомпилировать единственный подпроект в одиночку? Вы поместили выходные файлы (.c, .d) в отдельный каталог, чем исходные файлы? - person Elazar Leibovich; 27.04.2011
comment
@Elazar: Я пробовал tup, и это действительно впечатляло. Особенно интересен подход к наблюдению за тем, как инструменты взаимодействуют с файловой системой. - person JesperE; 27.04.2011
comment
@Elazar, шаблон для включения подпроекта (каталога) был не чем иным, как упоминанием имени каталога в переменной SUBDIRS. Компиляция отдельного подпроекта заключалась в переходе с диска в каталог и запуске make там, но при необходимости он все равно перестраивал зависимости в других каталогах. Было поддержано и рекомендовано отдельное дерево объектов для вывода. Для создания файлов make-файлов подкаталога не требовалось никакого выполнения команды sed или другой предварительной обработки. Файлы makefile были достаточно удобными для сопровождения, но код GNU Make, который реализовал все ... не так уж и много. - person Ville Laurikari; 27.04.2011
comment
@Ville, не хочешь поделиться кодом? Я бы с удовольствием это прочитал. Но на самом деле я имел в виду код GNU Make и задавал неправильные вопросы. Настоящий вопрос в том, что если мне теперь нужно предварительно обработать файлы C в определенном каталоге перед его компиляцией, насколько легко это сделать. - person Elazar Leibovich; 27.04.2011
comment
@Elazar, извините, у меня нет прав на код, и я даже больше не работаю в той же компании. Предварительная обработка файлов C может выполняться с помощью обычного правила GNU Make, только пути будут отличаться от традиционных правил, поскольку файлы не находятся в текущем рабочем каталоге. - person Ville Laurikari; 27.04.2011
comment
@Ville, да, но я имел в виду, насколько сложно интегрировать его с вашей системой (т.е. записать обработанные файлы C во временный каталог объектов и т. Д.). - person Elazar Leibovich; 27.04.2011
comment
@VilleLaurikari Судя по их отсутствию, вы не использовали для этого автоинструменты, верно? Почему? Я потратил некоторое время на работу над этим, и кажется, что нерекурсивные автоинструменты должны быть нерекурсивными, а рекурсивные автоинструменты - рекурсивными. Т.е. более автоматический. - person lmat - Reinstate Monica; 17.04.2016
comment
Вот пример нерекурсивной системы сборки на основе GNU-make github. com / igagis / prorab / blob / master / wiki / HomePage.md - person igagis; 21.08.2016
comment
@JesperE (или другие): Есть ли обновления по этому поводу в 2019 году? - person user541686; 25.01.2019

После прочтения статьи RMCH я поставил перед собой цель написать правильный нерекурсивный Makefile для небольшого проекта, над которым я работал в то время. После того, как я закончил, я понял, что должно быть возможно создать общую «структуру» Makefile, которую можно использовать для очень простого и лаконичного указания make, какие конечные цели вы хотите построить, какие они цели (например, библиотеки или исполняемые файлы). ) и какие исходные файлы нужно скомпилировать для их создания.

После нескольких итераций я в конечном итоге создал именно это: единый шаблонный Makefile из примерно 150 строк синтаксиса GNU Make, который никогда не нуждается в модификации - он просто работает для любого проекта, в котором я хочу его использовать, и достаточно гибок для сборки несколько целей различных типов с достаточной степенью детализации, чтобы указать точные флаги компиляции для каждого исходного файла (если я хочу) и точные флаги компоновщика для каждого исполняемого файла. Для каждого проекта все, что мне нужно сделать, это предоставить ему небольшие отдельные Makefile, которые содержат биты, подобные этому:

TARGET := foo

TGT_LDLIBS := -lbar

SOURCES := foo.c baz.cpp

SRC_CFLAGS   := -std=c99
SRC_CXXFLAGS := -fstrict-aliasing
SRC_INCDIRS  := inc /usr/local/include/bar

Makefile проекта, подобный приведенному выше, будет делать именно то, что вы ожидаете: создать исполняемый файл с именем "foo", скомпилировать foo.c (с CFLAGS = -std = c99) и baz.cpp (с CXXFLAGS = -fstrict-aliasing) и добавление "./inc" и "/ usr / local / include / bar" в #include путь поиска с окончательной компоновкой, включая библиотеку "libbar". Также можно было бы заметить, что существует исходный файл C ++ и известно использование компоновщика C ++ вместо компоновщика C. Фреймворк позволяет мне указать гораздо больше, чем показано здесь в этом простом примере.

Шаблонный файл Makefile выполняет все построение правил и автоматическое создание зависимостей, необходимых для построения указанных целей. Все файлы, созданные при сборке, помещаются в отдельную иерархию выходных каталогов, поэтому они не смешиваются с исходными файлами (и это делается без использования VPATH, поэтому нет проблем с наличием нескольких исходных файлов с одинаковыми именами).

Я сейчас (повторно) использовал тот же Makefile как минимум в двух десятках разных проектов, над которыми я работал. Что мне больше всего нравится в этой системе (помимо того, насколько легко создать правильный Makefile для любого нового проекта):

  • Это быстро. Он может практически мгновенно определить, устарели ли какие-либо данные.
  • 100% надежные зависимости. Вероятность того, что параллельная сборка непонятным образом сломается, равна нулю, и она всегда создает ровно минимум, необходимый для обновления всего.
  • Мне никогда не нужно снова переписывать полный make-файл: D

Наконец, я бы просто упомянул, что с проблемами, присущими рекурсивному make, я не думаю, что мне удалось бы это осуществить. Я, вероятно, был бы обречен переписывать некорректные make-файлы снова и снова, тщетно пытаясь создать тот, который действительно работал бы должным образом.

person Dan Moulding    schedule 29.08.2009
comment
И вы покажете нам свой базовый make-файл на 150 строк? - person zxcat; 02.11.2009
comment
@zxcat: см. github.com/dmoulding/boilermake. Чтобы использовать его, вы должны предоставить main.mk (и любые другие вспомогательные файлы, которые вы хотите предоставить). См. Файлы README и MANUAL для получения дополнительной информации. В каталоге test-app есть образец main.mk и другие файлы submakefiles, которые создают простую и глупую небольшую тестовую программу. Развлекайся. - person Dan Moulding; 06.11.2009
comment
Ваш make-файл выглядит впечатляюще! Поправьте меня, если я ошибаюсь, но он не создает общих объектов, верно? Или, лучше сказать, как общие объекты, так и статическая библиотека одновременно - person Shahbaz; 06.03.2013
comment
@Shahbaz Он может создавать общие объекты. Ваши собственные файлы submakefiles должны сообщать ему, какие CFLAGS / CXXFLAGS и LDFLAGS следует использовать при построении общего объекта. Это связано с тем, что создание общих объектов, в отличие от создания статических архивов, нестандартно и полностью зависит от платформы. Вы можете делать как статические, так и общие, создав два файла submake; назовем их static.mk и shared.mk. В static.mk укажите TARGET=libfoo.a и CFLAGS / LDFLAGS, соответствующие статической библиотеке. В shared.mk укажите TARGET=libfoo.so.x.y и CFLAGS / LDFLAGS, соответствующие общему объекту (например, -fPIC, -shared). - person Dan Moulding; 07.03.2013
comment
@DanMoulding, проблема в том, куда помещаются файлы .o. Дело в том, что если вы собираете a.o из a.c с использованием статических CFLAGS, то при создании общего объекта Makefile будет думать, что a.o уже обновлен, тогда как на самом деле его нужно скомпилировать снова (с -fPIC). Таким образом, вам понадобятся отдельные каталоги для объектов статической и общей библиотеки. - person Shahbaz; 07.03.2013
comment
@Shahbaz Вы абсолютно правы, но Makefile справляется с этим правильно. Файлы .o для libfoo.a будут находиться в build/libfoo.a/, а файлы .o для libfoo.so.x.y - в build/libfoo.so.x.y/, поэтому каждый исходный файл будет компилироваться дважды (один раз с -fPIC и один раз без него). - person Dan Moulding; 07.03.2013
comment
@DanMoulding, это здорово! Хорошо сделано - person Shahbaz; 07.03.2013
comment
Как он обрабатывает структуру каталогов, в которой есть каталоги без целей? - person Plazgoth; 19.10.2013
comment
Вот еще один пример нерекурсивной системы сборки github.com/igagis/ prorab / blob / master / wiki / - person igagis; 27.08.2016

Позвольте мне подчеркнуть один аргумент из статьи Миллера: когда вы начинаете вручную разрешать отношения зависимости между различными модулями и испытываете трудности с обеспечением порядка сборки, вы эффективно повторно реализуете логику, для решения которой изначально была создана система сборки. Создание надежных рекурсивных систем сборки make очень сложно. Реальные проекты состоят из множества взаимозависимых частей, порядок сборки которых нетривиально определить, и поэтому эту задачу следует оставить на усмотрение системы сборки. Однако он может решить эту проблему только в том случае, если он имеет глобальные знания о системе.

Более того, рекурсивные сборочные системы make часто разваливаются при одновременной сборке на нескольких процессорах / ядрах. Хотя может показаться, что эти системы сборки надежно работают на одном процессоре, многие недостающие зависимости остаются незамеченными, пока вы не начнете строить свой проект параллельно. Я работал с рекурсивной системой сборки make, которая работала на четырех процессорах, но внезапно вылетела на машине с двумя четырехъядерными процессорами. Затем я столкнулся с другой проблемой: эти проблемы параллелизма практически невозможно отладить, и в итоге я нарисовал блок-схему всей системы, чтобы выяснить, что пошло не так.

Возвращаясь к вашему вопросу, мне трудно придумать веские причины, по которым кто-то хочет использовать рекурсивный make. Производительность нерекурсивных систем сборки GNU Make во время выполнения трудно превзойти, и, наоборот, многие рекурсивные системы сборки имеют серьезные проблемы с производительностью (слабая поддержка параллельной сборки снова является частью проблемы). Существует статья, в которой я оценил конкретный ( рекурсивный) Сделайте сборку системы и сравните ее с портом SCons. Результаты производительности не являются репрезентативными, потому что система сборки была очень нестандартной, но в этом конкретном случае порт SCons был на самом деле быстрее.

Итог: если вы действительно хотите использовать Make для управления сборками программного обеспечения, выберите нерекурсивный Make, потому что это значительно облегчит вашу жизнь в долгосрочной перспективе. Лично я предпочел бы использовать SCons из соображений удобства использования (или Rake - в основном любую систему сборки, использующую современный язык сценариев и имеющую неявную поддержку зависимостей).

person Pankrat    schedule 18.02.2009
comment
Проблема параллелизма кусает меня в проекте, над которым я работаю прямо сейчас. Мне удалось активировать параллелизм внутри модулей GNU make, но мне пришлось бы иметь дело с межмодульными отношениями вручную, если бы я хотел параллелизм между модулями. В результате я наблюдаю, как на 16-ядерной машине в среднем меньше двух активных ядер, пока я строил этого зверя более сорока минут. Ага! - person dmckee --- ex-moderator kitten; 24.01.2013

На своей предыдущей работе я сделал нерешительную попытку сделать систему сборки (основанную на GNU make) полностью нерекурсивной, но столкнулся с рядом проблем:

  • Источники артефактов (т. Е. Построенных библиотек и исполняемых файлов) были распределены по нескольким каталогам, и их поиски использовались с помощью vpath.
  • Несколько исходных файлов с одинаковым именем существовали в разных каталогах
  • Несколько исходных файлов были общими для артефактов, часто скомпилированных с разными флагами компилятора.
  • У разных артефактов часто разные флаги компилятора, настройки оптимизации и т. Д.

Одна из возможностей GNU make, которая упрощает нерекурсивное использование, - это значения переменных для конкретных целей:

foo: FOO=banana
bar: FOO=orange

Это означает, что при построении цели «foo» $ (FOO) будет расширяться до «банана», но при создании целевой «bar» $ (FOO) будет расширяться до «оранжевого».

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

Основная недостающая функция GNU make, необходимая для поддержки нерекурсивности, заключается в отсутствии пространств имен. Переменные, зависящие от цели, могут ограниченным образом использоваться для «имитации» пространств имен, но на самом деле вам нужно иметь возможность включить Makefile в подкаталог, используя локальную область видимости.

РЕДАКТИРОВАТЬ: Еще одна очень полезная (и часто недостаточно используемая) функция GNU make в этом контексте - это средства расширения макросов (см. eval, например). Это очень полезно, когда у вас есть несколько целей, которые имеют похожие правила / цели, но различаются способами, которые не могут быть выражены с помощью обычного синтаксиса GNU make.

person JesperE    schedule 18.02.2009
comment
Полезно: да. Ремонтопригодный: нет. - person reinierpost; 24.01.2011
comment
Этому уже много лет, но вы упоминаете переменные, зависящие от цели ... опасность, Уилл Робинсон! Они не делают того, чего вы ожидаете! При сборке foo, FOO будет установлен как для foo , так и для всех предварительных требований, созданных foo. Итак, если foo и bar беспокоят, зависят от baz, то будет ли baz собран с FOO=orange или FOO=banana, зависит от того, увидит ли make сначала foo или bar. Это приводит к незаметному нарушению параллельных сборок, которые, как правило, не являются детерминированными. - person David Given; 08.05.2016
comment
Я бы не рекомендовал GNU make в качестве инструмента сборки сегодня ни при каких обстоятельствах. - person JesperE; 09.05.2016

Я согласен с утверждениями в упомянутой статье, но мне потребовалось много времени, чтобы найти хороший шаблон, который все это делает и по-прежнему прост в использовании.

В настоящее время я работаю над небольшим исследовательским проектом, в котором экспериментирую с непрерывной интеграцией; автоматический модульный тест на ПК, а затем запуск системного теста на (встроенной) цели. Это нетривиально для make, и я искал хорошее решение. Обнаружив, что make по-прежнему является хорошим выбором для переносимых мультиплатформенных сборок, я наконец нашел хорошую отправную точку в http://code.google.com/p/nonrec-make

Это было настоящим облегчением. Теперь мои make-файлы

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

Я обязательно воспользуюсь им и в следующем (большом) проекте (при условии C / C ++).

person Adriaan    schedule 30.07.2009


Я разработал нерекурсивную систему make для одного проекта C ++ среднего размера, который предназначен для использования в unix-подобных системах (включая Mac). Код в этом проекте находится в дереве каталогов с корнем в каталоге src /. Я хотел написать нерекурсивную систему, в которой можно было бы набрать "make all" из любого подкаталога верхнего уровня каталога src /, чтобы скомпилировать все исходные файлы в дереве каталогов с корнем в рабочем каталоге, как в рекурсивной системе make. Поскольку мое решение, кажется, немного отличается от других, которые я видел, я хотел бы описать его здесь и посмотреть, получу ли я какую-нибудь реакцию.

Основными элементами моего решения были следующие:

1) Каждый каталог в дереве src / имеет файл с именем sources.mk. Каждый такой файл определяет переменную makefile, в которой перечислены все исходные файлы в дереве с корнем в каталоге. Имя этой переменной имеет вид [каталог] _SRCS, в котором [каталог] представляет собой каноническую форму пути от каталога src / верхнего уровня к этому каталогу, с обратными косыми чертами, замененными знаками подчеркивания. Например, файл src / util / param / sources.mk определяет переменную с именем util_param_SRCS, которая содержит список всех исходных файлов в src / util / param и его подкаталоги, если таковые имеются. Каждый файл sources.mk также определяет переменную с именем [каталог] _OBJS, которая содержит список соответствующих целей объектного файла * .o. В каждом каталоге, содержащем подкаталоги, файл sources.mk включает файл sources.mk из каждого подкаталога и объединяет переменные [подкаталог] _SRCS для создания своей собственной переменной [каталог] _SRCS.

2) Все пути выражаются в файлах sources.mk как абсолютные пути, в которых каталог src / представлен переменной $ (SRC_DIR). Например, в файле src / util / param / sources.mk файл src / util / param / Componenent.cpp будет указан как $ (SRC_DIR) /util/param/Component.cpp. Значение $ (SRC_DIR) не установлено ни в одном файле sources.mk.

3) Каждый каталог также содержит Makefile. Каждый Makefile включает глобальный файл конфигурации, который устанавливает значение переменной $ (SRC_DIR) равным абсолютному пути к корневому каталогу src /. Я решил использовать символическую форму абсолютных путей, потому что это оказался самый простой способ создать несколько make-файлов в нескольких каталогах, которые будут одинаково интерпретировать пути для зависимостей и целей, при этом позволяя при желании перемещать все исходное дерево. , изменив значение $ (SRC_DIR) в одном файле. Это значение устанавливается автоматически простым скриптом, который пользователь получает указание запустить, когда пакет загружается или клонируется из репозитория git, или когда перемещается все исходное дерево.

4) Makefile в каждом каталоге включает файл sources.mk для этого каталога. Целевой объект "all" для каждого такого Makefile перечисляет файл [directory] _OBJS для этого каталога как зависимость, что требует компиляции всех исходных файлов в этом каталоге и его подкаталогах.

5) Правило для компиляции файлов * .cpp создает файл зависимостей для каждого исходного файла с суффиксом * .d в качестве побочного эффекта компиляции, как описано здесь: http://mad-science.net/make/autodep.html. Я решил использовать компилятор gcc для генерации зависимостей, используя параметр -M. Я использую gcc для генерации зависимостей даже при использовании другого компилятора для компиляции исходных файлов, потому что gcc почти всегда доступен в unix-подобных системах, и потому что это помогает стандартизировать эту часть системы сборки. Фактически для компиляции исходных файлов можно использовать другой компилятор.

6) Использование абсолютных путей для всех файлов в переменных _OBJS и _SRCS потребовало, чтобы я написал сценарий для редактирования файлов зависимостей, сгенерированных gcc, который создает файлы с относительными путями. Я написал для этой цели скрипт на Python, но другой человек мог использовать sed. Пути для зависимостей в результирующих файлах зависимостей являются буквальными абсолютными путями. В данном контексте это нормально, потому что файлы зависимостей (в отличие от файлов sources.mk) создаются локально, а не распространяются как часть пакета.

7) Makefile в каждом директоре включает файл sources.mk из того же каталога и содержит строку «-include $ ([directory] _OBJS: .o = .d)», которая пытается включить файлы зависимостей для каждого исходного файла. в каталоге и его подкаталогах, как описано в приведенном выше URL-адресе.

Основное различие между этой схемой и другими схемами, которые я видел, которые позволяют вызывать "make all" из любого каталога, заключается в использовании абсолютных путей, позволяющих согласованно интерпретировать одни и те же пути, когда Make вызывается из разных каталогов. Пока эти пути выражаются с использованием переменной, представляющей исходный каталог верхнего уровня, это не мешает перемещать исходное дерево и является более простым, чем некоторые альтернативные методы достижения той же цели.

В настоящее время моя система для этого проекта всегда выполняет сборку «на месте»: объектный файл, созданный путем компиляции каждого исходного файла, помещается в тот же каталог, что и исходный файл. Было бы просто включить неуместные сборки, изменив сценарий, который редактирует файлы зависимостей gcc, чтобы заменить абсолютный путь к каталогу src / на переменную $ (BUILD_DIR), которая представляет каталог сборки в выражении для цель объектного файла в правиле для каждого объектного файла.

На данный момент я считаю эту систему простой в использовании и обслуживании. Необходимые фрагменты make-файла короткие и сравнительно простые для понимания соавторами.

Проект, для которого я разработал эту систему, написан на полностью автономном ANSI C ++ без внешних зависимостей. Я думаю, что такая самодельная нерекурсивная система make-файлов - разумный вариант для автономного, очень переносимого кода. Однако я бы рассмотрел более мощную систему сборки, такую ​​как CMake или gnu autotools, для любого проекта, который имеет нетривиальные зависимости от внешних программ или библиотек или от нестандартных функций операционной системы.

person D Morse    schedule 10.12.2012

Я написал не очень хорошую нерекурсивную систему сборки make, а с тех пор очень чистую модульную рекурсивную систему сборки make для проекта под названием Pd-расширенный. По сути, это похоже на язык сценариев с кучей включенных библиотек. Сейчас я также работаю с нерекурсивной системой Android, так что это контекст моих мыслей по этой теме.

Я не могу много сказать о различиях в производительности между ними, я особо не обращал внимания, поскольку полные сборки на самом деле всегда выполняются только на сервере сборки. Обычно я работаю либо над основным языком, либо над конкретной библиотекой, поэтому меня интересует только создание этого подмножества всего пакета. Рекурсивный метод make имеет огромное преимущество, поскольку делает систему сборки как автономной, так и интегрированной в единое целое. Это важно для нас, поскольку мы хотим использовать одну систему сборки для всех библиотек, независимо от того, интегрированы ли они или написаны внешним автором.

Сейчас я работаю над созданием собственной версии внутреннего устройства Android, например, версии классов Android SQLite, основанных на зашифрованном sqlite SQLCipher. Поэтому мне приходится писать нерекурсивные файлы Android.mk, которые содержат всевозможные странные системы сборки, такие как sqlite. Я не могу понять, как заставить Android.mk выполнять произвольный скрипт, хотя, по моему опыту, это было бы несложно в традиционной рекурсивной системе make.

person Hans-Christoph Steiner    schedule 23.02.2011