Как стать автором
Обновить

Комментарии 84

НЛО прилетело и опубликовало эту надпись здесь
Мне понравилось, что автор всегда точно понимает, «как оно должно быть на самом деле». Он знает, как обязан выглядеть «идеальный make» и описывает разницу.

Или, к примеру, почему удобный вариант использования надо дополнительно настраивать? Почему простые вещи делаются нетривиально?

Меня в своё время поведение команды git log поразило — надо же, учитывает, что её человек запустить может.
Зато если надо посмотреть так, чтобы в консоли что-то осталось, приходится подпрыгивать :)
Ну, если очень хочется добиться поведения «как у остальных», то можно git log | cat использовать.
Вот вы и подпрыгнули 8)
Перевожу проект с make на scons (сейчас он переходит в фазу активного тестирования и внедрения), в ближайшем будующем напишу несколько статей на эту тему. Могу сказать одно — я убедился что make это устаревший анархаизм. Хотя scons тоже не идеален, но мне на его базе удалось сделать достаточно удобную систему сборки, а точнее целый фреймворк который я в данный момент дорабатываю и смогу использовать с любым другими проектами в будущем (а может даже кто-то еще захочет).
Пользуюсь cmake + make. Вполне доволен.
Плюсы, минусы? Что раздражает, что радует? Большой ли проект?
Проекты у меня маленькие (вот этот, например, пока чуть больше восьми тысяч строк, в завершенном виде должен быть не больше ~30..40 тысяч строк; однако библиотек используется много — поэтому вручную писать Makefile неудобно).

Поначалу я писал Makefile'ы вручную, но когда стало появляться все больше и больше зависимостей, попробовал на automake перейти. Эта зараза мало того, что медленно работает, так еще и не находила кое-какие библиотеки.

А cmake'ом пользуюсь с удовольствием. По-моему, проще уже некуда. Разве только если какая-нибудь система сборки будет грепать мои исходники и самостоятельно каким-то чудным образом понимать, какие библиотеки надо подключить, всякие там msgfmt'ы и т.п. запустить, и куда чего при установке засунуть…
>Разве только если какая-нибудь система сборки будет грепать мои исходники и самостоятельно каким-то чудным образом понимать, какие библиотеки надо подключить, всякие там msgfmt'ы и т.п.
А такого нигде нету? Было бы неплохо вообще не думать о системе сборки и зависимостях (ну или минимум телодвижений).
Ну откуда система сборки знает, что, например, вы используете функции из библиотеки A, а не аналогично обозванные функции из библиотеки Б? Да и даже если во всех библиотеках функции называются по-разному, такой системе пришлось бы сначала просканировать все /usr/include и подобные директории для составления БД функций, соответствующих им заголовочных файлов и соответствующих библиотек. Затем, когда система наткнется на функцию f1, если присутствует #include <h1.h>, подключить библиотеку lib1, если же присутствует #include <h2.h> — библиотеку l2.
Далее: как система сборки узнает, что за способ локализации вы используете?
А как она узнает, куда вы предполагаете скомпилированные файлы разложить?
А что делать с условной сборкой, когда у клиента нет библиотеки l1, но она необязательна — можно собрать без нее (просто приложение станет либо тормознутее, либо лишится дополнительной функциональностью)?
В общем, таких вопросов много.
Я узнаю ТЗ на automake :-)
>Ну откуда система сборки знает, что, например, вы используете функции из библиотеки A,
>а не аналогично обозванные функции из библиотеки Б?

вы ей это скажете, конечно.
человек говорит компьютеру ЧТО делать, это его функция.

>Затем, когда система наткнется на функцию f1, если присутствует #include <h1.h>

сразу нет.
кто из нас делает проект — я или система сборки?
значит, я буду решать что, где и как подключать, а не какой-то магический автомат.

>А как она узнает, куда вы предполагаете скомпилированные файлы разложить?

Fine tuning of the installation directories:
--bindir=DIR user executables [EPREFIX/bin]
--sbindir=DIR system admin executables [EPREFIX/sbin]
--libexecdir=DIR program executables [EPREFIX/libexec]
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
--datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
--datadir=DIR read-only architecture-independent data [DATAROOTDIR]
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
--docdir=DIR documentation root [DATAROOTDIR/doc/]
--htmldir=DIR html documentation [DOCDIR]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
--psdir=DIR ps documentation [DOCDIR]

вот вам куча всяких ручек, крутите на здоровье.

>А что делать с условной сборкой, когда у клиента нет библиотеки l1, но она необязательна

проверить наличие, сообщить о присутвии/отсутствии и продолжить сборку.

на все эти вопросы уже давно есть ответы, надо просто уметь их искать, а не изобретать свои системы сборки.
Вот я и говорю, что «магической» системы сборки нет. А более-менее удобная — есть. Cmake.
Я не считаю удобным использование -D<SOME_OBSCURE_DEFINE> вместо ./configure --with-option=.

Есть еще одна претензия — вместо шелла cmake изобретает свой собственный язык, который я вынужден использовать для написания вариации на тему configure.in:

почему
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_DEPRECATE)
удобнее, чем
CFLAGS="$CFLAGS -D_CRT_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_DEPRECATE"
?

Я с первого взгляда не скажу что делает add_definition, а в случае с CFLAGS очевидней уже некуда.
Тут зависит от, конечно. В случае с Си — всë очень сложно. А вот в случае с Go, например, они уже написали тулзу для сборки свою, которая понимает зависимости (и умеет их даже с гитхаба/битбакета/гкода качать) и собирать в библиотеки или бинарники всë.
«Анархаизм» — интересное слово :) Может, «анахронизм»? Потому как «анархаизмов» никаких не существует, а «архаизмом» называют вышедшее из употребления слово :) Хотя, возможно, вы имели в виду, что make — это «анархизм»? :)
Это был «неологизм» :)
Воинствующий анархизм!
Судя по всему, анархаизм — унаследованные хаки. Из серии, нет ничего постояннее временного.
У меня есть железная отмазка — я писал это 6:33 утра и мой мозг после ночи бодрствования не смог оформить правильно поток моих мыслей. Я хотел сказать, что make существует уже очень давно и технологии постоянно развивается, а make как был так и остается на своем очень низком уровне. Но уровень технологий уже сильно вырос с его времен и соответственно требует новых подходов и решений к сборке и управлению ей.
анахренизм :)
Позанудствую. Статья оформлена не по правилам. Для переводов есть специальный тип топика — «перевод».
А как правильно их делать?
image
сменить тип уже опубликованного топика нельзя, только убирать текущий и делать новый.
достаточно вверху статьи написать
Перевод статьи ...
С точки зрения правил ресурса — недостаточно.
зато с точки зрения пользователя вполне хватит, т.к. я буди читать уже готовым к тому что автору я ответить не смогу…
Автор в итоге не сделал вообще ничего. Показательное презрение к сообществу и администрации.
Нет, изменено форматирование и оформление. Удалять статью и выкладывать заново как перевод считаю ошибкой, так как она уже у 100+ людей в «избранном» — они её потеряют.
Не сделано даже упоминание о то, что это перевод (не сделано сверху, чтобы пользователь сразу понимал это, начав читать и не готовил по ходу чтения список вопросов и возражений «автору»). Это хотя бы минимум уважения к читающим.
Кроме того, на момент, когда я сделал замечание, в избранное добавило всего пять человек и мой коммент был третьим по счету, была возможность спокойно сделать все по правилам. Ты же просто забил.
Список вопросов и возражений — это именно то, чего я добивался выкладывая этот перевод.

Утверждение об уважении к читателям оставлю на вашей совести.
Как раз таки уважение к читателям осталось на твоей совести )
Если не видишь проблемы — ок, дело твое.
А надуманная фраза — на вашей.
А надуманность надуманности — на твоей.
Я выиграл!
Ок, пусть будет так.
Зато перевод на редкость хорош. Я уже ближе к середине текста всерьез заметил признаки перевода, хотя на Хабре очень часто даже оригинальные тексты читать невозможно.
здесь должна быть шутка про обречённость любого языка, содержащего colon-equals assignment :)
Colon-equals assignment приводит к появлению ошибок при опечатках в операторах «==», «!=», «+=», «-=», «*=», «/=», «.=», «%=», «&=», «|=», «^=», «=>», «>=», «<=», и тем экономит нервы программиста, не принуждая его прибегать к долгой, мучительной, нравственно тягостной отладке.

Поэтому обречённость этого оператора свидетельствует о том, что мы обречены существовать в мире техносадомазохистов, действующих по правилу «я мучительно потрахался — теперь и ты, и ты поди мучительно потрахайся».
о каких конкретнее опечатках вы говорите?
int a = 3;
int b = 15;

if (a = b)
puts(«внезапно»);
имхо, конечно, но ошибка с пропущенным равно в '==' довольно натянута. после 1-2 таких опечаток, они обычно начинают сами бросаться в глаза. а если такая даже случайно допущена, то в большинстве случаев мысль проверить сравнение приходит в голову одной из первых.

если цепляться к опечаткам, то к примеру написать x := y вместо x >=y имеет такую же вероятность.
Нормальный компилятор не пропустит такую опечатку.
Поэтому приходится, если нужно в if для сокращения написать что-то вроде if(a=b), писать if((a=b)).
Это и спасает.
А вообще пора бросать экономить строчки.
Эти ошибки возникают только в условиях. Поэтому проблема не в том, что присваивание записывается как "=", без двоеточия, а в том, что результат присваивания может неявно приводиться к типу boolean. К примеру, в Java и C# этого нет, и никто не ошибается в написании условий.
Говоря еще точнее, эта ошибка прявляется там, где присваивание есть выражение (и возвращает значение). То, что оно кастуется к булеану — это даже хорошо :)
:= в мейке значит — вычислить то, что присваивается переменной, прямо сейчас. Есть и просто '=' — тогда присвоенное (например, функция) будет вычисляться позже.
Неожиданный вопрос: автор слышал про autoconf/automake?
Писать руками Makefiles — это Свежая и Оригинальная Идея (tm).
Я, возможно, слишком радикальных взглядов придерживаюсь, но autoconf/automake — это такой большой набор хрупких костылей, после которого make кажется образцом простоты и удобства. Спасибо, задействовать их, чтобы makefile'ы генерировать — это добавить к проекту ещё одну проблему.
я думаю вы просто не разобрались с автотулзами, да это костыли, но вопервых вполне рабочие что подтверждается практикой многих открытых продуктов, во-вторых создание рукотворных мейкфайлов как правило означает, что на платформе отличной от той под которую писал автор, будут будут проблемы со сборой. Неоднократно убеждался в этом эмпирическом правиле…
И да имхо порог вхождения в autotools + make достаточно высок.
Рабочие они только там, где их тестируют. А вот стоит скомпилировать gdb на mingw64 и оказывается, что какая-то из автотулзов считает, что для компиляции маленькой вспомогательной программы можно использовать просто gcc, ведь он же есть на любой платформе. А то, что надо использовать x86_64-w64-mingw32-gcc, как указано в configure верхнего уровня, авторов волнует мало. В результате из-за какой-то ненужной документации к bfd не собирается gdb.
а если бы мэйкфайл gcc написали бы руками то конечно был бы рай, да?
Нет, просто автотулзы тоже не помогают в самом интересном для меня случае — cygwin/mingw.
я бы сказал что «автотулзы тоже не всегда помогают»…
Вот из последнего, к примеру — wiki.buici.com/xwiki/bin/view/Programing+C+and+C%2B%2B/Autoconf+and+RPL_MALLOC
Берём проект, который использует autotools (который как бы декларирует, что будет компилироваться для любых платформ), компилируем для ARM'а — получаем ошибки. Особенно доставляет её описание.
Ну да, а C — это такой хрупкий костыль вокруг ассемблера, который вообще похож на вывод из /dev/random (кстати, хорошая тема для статьи).
Всё в этом мире — костыль!
А у костылей бывают костыли?
C — это такой хрупкий костыль вокруг ассемблера, который вообще похож на вывод из /dev/random
— спасибо, супер!
НЛО прилетело и опубликовало эту надпись здесь
autoconf/automake — ужасная штука. Ей только по историческим причинам и ради переносимости приходится пользоваться.

Каждый раз, когда я какого-нибудь апача собираю, и эта простыня ./configure тянется по полчаса, и для каждой из библиотек Апача (apr, apr-utils) перезапускается заново, и если ошибся в настройках компилятора, и make упал, то надо ее снова запускать и ждать полчаса — полдня на это может уйти.
К счастью, постепенно народ с глючных тормозных autotools переходит на cmake.
попробуйте кеширование в configure использовать, не будет так долго второй раз проверять библиотеки.
он использует кеширование, но как-то безсистемно (часть проверок кешируется, но большАя часть — нет), и даже с кешированием долго работает…
… бОльшая…
«Бессистемно»…
да я тоже сижу бывает с лицом страдальца когда что то бисекчу… пересобирать приходится помногу…
You have a problem and decide to use make.
Now you know how to make problems.

You have a problem and decide to use autotools.
Now you know how to make problems automatically.
Статья очень спорная на самом деле.
Начиная с фактических ошибок (mkdir -p <existing-dir-name> завершается успешно).
Заканчивая полным непониманием «миссии» make.

Make решает одну единственную задачу — по спецификации цели/зависимости/правила генерации найти отсутствующие или устаревшие цели и собрать их. Просто и примитивно, воплощенный UNIX way.

Это не проблема make, что для сборки среднего проекта, его возможностей недостаточно.

Зато Makefile — замечательный промежуточный формат для генераторов вроде autotools/cmake. И все довольны — билд-инжинер, потому что огромную кучу вспомогательного кода в мэйкфайле за него написал генератор; автор генератора — потому что сканирование зависимостей, сортировку задач и распараллеливание он переложил на make.

Кстати возможно решение с таймстемпами на файловой системе и не лишено недостатков, но по-сути — оно единственное. Тот же git например при поиске измененных файлов сначала смотрит на таймстемпы, и если таймстеп не изменился, то внутрь файла он даже не заглядывает.
Каждый, кто хоть раз писал makefile, скорее всего уже натолкнулся на “особенность” его синтаксиса: в нём используются табуляции. Каждая строка, описывающая запуск команды, должна начинаться с символа табуляции. Пробелы не подходят — только табуляция. К сожалению, это только один из странных аспектов языка make’а.


В книге Masterminds of programming кто-то (по-моему, Керниган) рассказывал историю: когда make только-только написали, он стал как-то использоваться и понемногу разошёлся по организации (Bell Labs).
И кто-то из «новых» пользователей обратил внимание на эту странную штуку с табами — why tabs? На что Feldman, автор этой новой утилиты, ответил, что пользователь конечно прав, и что с табами он плохо подумал, но менять это не будет, потому что это поломает обратную совместимость, а это делать нельзя, ведь у make уже 12 пользователей.

такой подход к обратной совместимости многое объясняет. фактически, он отвечает сразу по всем пунктам этой статьи.
facepalm.tar.gz

Целых 12… Порой программисты слишком заботливы в отношении пользователей: то добавляют ненужные фичи, то (как здесь) не добавляют нужные. Всё больше убеждаюсь в том, что в каждом программисте должна быть частичка менеджера. Но только частичка, а не ядро U-239.
Интересно, спросил он у этих 12-ти пользователей их мнения? А то ведь могло быть и так, что им табы тоже не нужны.
Пробелы бы вроде не поломали бы совместимость, альтернатива табам как а питоне
НЛО прилетело и опубликовало эту надпись здесь
Пользуюсь make, ругаюсь, но пользуюсь. Удивился, когда узнал что он не умеет делать математические операции (напр., если версия меньше чем что-то, то сделать что-то особое).

Очень надеялся, что наберет популярность такая система сборки как ninja (с ее помощью хромиум собирается). martine.github.com/ninja/ Замысел хороший, нацелена на простоту и скорость, легкий синтаксис, минимум возможностей. Т.е. ninja только собирает, а всей конфигурацией должна заниматься отдельный генератор типа configure.

Жаль, кажется не взлетела.
С ниндзей лень возиться просто. Сделал бы там чувак хотя бы базовые фичи какие-то (ну там хотя бы паттерны для имëн переменных, подобные штуки) — тогда да, а так — оно имеет смысл только для больших проектов, когда мейк тормозит.
Кстати, по поводу странностей ситнтаксиса, парсинга и интерпретации мейкфайлов — все то же самое справедливо и для Bash. Недавно статью прочитал — долго удивлялся: www.aosabook.org/en/bash.html
Кому не нравится, всегда может использовать аналоги, а также питон и прочие яп
Последний пункт не совсем верен, тк в make есть order-only prerequisites, которые не будут вызывать перекомпиляцию
debug/%.o: %.c | debug
$(CC) -c $< -o $@
debug:
mkdir $@
Спасибо, интересно.
Хотел сказать то же самое. Странно что автор не знал этого
Я в своём Leaflet сейчас использую jake — аналог rake под node.js. Очень просто, удобно, и к тому же приятно описывать билд-скрипты и зависимости для JS-проекта на JS же, без лишних сторонних языков.
Уже давно для своих проектов использую rake — весьма неплохая альтернатива make, лишенная перечисленных выше недостатков. К тому же, если возможностей Rake DSL не хватает, всегда можно локально перейти на обычный ruby — и все это бесшовно. Жаль только, что за пределами мира RoR rake малоизвестен. Фактически rake — это такой "'make' done right". Не больше, но и не меньше.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории