Почему никто не использует make для Java?

162

Почти каждый Java-проект, который я видел, использует Maven или Ant. Они прекрасные инструменты, и я думаю, что любой проект может использовать их. Но что же случилось с делать ? Он используется для различных не-Java проектов и может легко обрабатывать Java. Конечно, вам нужно скачать make.exe, если вы используете Windows, но Ant и Maven также не поставляются с JDK.

Есть ли какой-то фундаментальный недостаток в make при использовании с Java? Это только потому, что Ant и Maven написаны на Java?

User1
источник
37
Если вы перемещаете вещи и делаете больше, чем просто вызываете компилятор (и даже тогда), вещи для платформы становятся очень неудобными для обработки make. И иметь make-файл, который работает только в одной системе, не очень хорошо для кроссплатформенного языка.
Джои,
Кроме того, Gradle является новым игроком в пространстве Java, как и Гант (в меньшей степени). Maven или Муравей это ложная дихотомия.
Майкл Пасха
@ Майкл Пасхальный, ложная дихотомия будет Maven / Ant vs. Make. Истинная дихотомия, если я правильно вас понял, будет Gradle / Maven / Gant / Ant vs. Make. Но сложно сказать :)
Дэн Розенстарк

Ответы:

192

Основная проблема Make и Java заключается в том, что Make работает при условии, что у вас есть указанная зависимость, а затем правило для разрешения этой зависимости.

На базовом C, который обычно «для преобразования файла main.c в файл main.o, запустите« cc main.c ».

Вы можете сделать это в Java, но вы быстро чему-то научитесь.

Главным образом из-за того, что компилятор javac запускается медленно.

Разница между:

javac Main.java
javac This.java
javac That.java
javac Other.java

и

javac Main.java This.java That.java Other.java

ночь и день.

Усугубить это с сотнями классов, и это просто становится несостоятельным.

Затем вы объединяете это с тем фактом, что Java имеет тенденцию организовываться как группы файлов в каталогах, против C и других, которые имеют тенденцию к более плоской структуре. Make не имеет прямой поддержки для работы с иерархиями файлов.

Make также не очень хорошо определяет, какие файлы устарели на уровне коллекции.

С помощью Ant он будет проходить и суммировать все файлы, которые устарели, а затем скомпилирует их за один раз. Make будет просто вызывать компилятор Java для каждого отдельного файла. Для того, чтобы make НЕ делал этого, требуется достаточно внешних инструментов, чтобы действительно показать, что Make не совсем соответствует задаче.

Вот почему появились альтернативы, такие как Ant и Maven.

Уилл Хартунг
источник
6
Таким образом, чтобы использовать make в огромном Java-проекте, необходимо сохранить список всех измененных файлов .java и затем вызвать javac в конце? Это звучит не идеально для меня. Это лучший ответ, который я видел до сих пор.
User1
32
Мне это нравится. Важно, что вы говорите, что Ant был необходим, чтобы учесть тот факт, что javac работает слишком медленно.
cmcginty
25
Нет. Javac не медлителен, если вы используете его так, как он был разработан для использования. Это просто медленно, если вы используете его для компиляции одного файла за раз.
Стивен С.
7
@Casey Javac не слишком медленный. JVM слишком медленная для запуска.
Торбьерн Равн Андерсен
7
GNU Make, по крайней мере, имеет $?автоматическую переменную, которая расширяется до «всех предпосылок, которые новее, чем цель». Существует также функция шаблонных правил с несколькими целями, которая запускает рецепт только один раз, чтобы обновить все .classфайлы. Объедините это с каким - то умным использованием файла / текстовые функции , такие как $(wildcard), $(shell), $(eval)и вы можете научить Makefile , чтобы обнаружить сборки цели , разбросанную по вашей схеме директорий.
Tanz87
33

Почтенная makeпрограмма достаточно хорошо обрабатывает отдельно скомпилированные языки, такие как C и C ++. Вы компилируете модуль, он использует #includeдля извлечения текста других включаемых файлов и записывает один объектный файл в качестве вывода. Компилятор очень похож на систему за один раз, с отдельным шагом связывания, чтобы связать объектные файлы в исполняемый двоичный файл.

Однако в Java компилятор должен фактически скомпилировать другие классы, с которыми вы импортируете import. Хотя было бы возможно написать что-то, что сгенерировало бы все необходимые зависимости из исходного кода Java, так что это makeбудет создавать классы в правильном порядке по одному, это все равно не будет обрабатывать такие случаи, как циклические зависимости.

Компилятор Java также может быть более эффективным, кэшируя результаты, скомпилированные другими классами, при компиляции других классов, которые зависят от результатов уже скомпилированных. Такого рода автоматическая оценка зависимостей на самом деле невозможна в makeодиночку.

Грег Хьюгилл
источник
7
Похоже, что это скорее ответ против make и javac, чем ответ против make / maven. Исходя из вашего ответа, почему кто-то не может просто использовать make + javac (предоставляя javac весь пакет или «модуль» за раз, поэтому циклические зависимости скрыты от make)? Будет ли муравей или мавен принести какую-либо выгоду по сравнению с этим подходом?
Лоуренс Гонсалвес
1
@Laurence: Вы могли бы дать javac весь пакет сразу, но тогда он будет перекомпилировать все в этом пакете (так как вы это и сказали). Это правда, что java-компилятор довольно быстрый, но он еще быстрее, если вы позволите ему определить, какие классы являются минимальным для перекомпиляции после изменения чего-либо.
Грег Хьюгилл
Вы имеете в виду, что javac компилирует только ваш «основной» класс, а затем автоматически создает материал, от которого он зависит? В последний раз я проверял (правда, вероятно, в 1.4), что было ужасно ненадежным. -Xdepend был немного лучше (но медленнее, и все еще не работает), и они убрали этот флаг в 1.3.
Лоуренс Гонсалвес
4
Кроме того, это все еще не объясняет, почему я бы использовал Ant или Maven, а не просто javac ...
Laurence Gonsalves
28

Вопрос основан на неверном предположении: нетривиальное число разработчиков делает использование make. См. Инструменты сборки Java: Ant vs. Maven . Что касается того, почему разработчик не будет использовать make: многие разработчики либо никогда не использовали make, либо использовали его и ненавидели его с огнем, который горит сильнее, чем тысяча солнц. Как таковые, они используют альтернативные инструменты.

Хэнк Гей
источник
10
Мы используем его, и огонь горячее, чем тысяча и одно солнце.
2010 года
4
@reccles: Это просто ненависть к проектированию или созданию самого себя? Как бы Ant, Maven или что-то еще было бы лучше (то есть сделать плохой инструмент для своего класса)?
User1
5
@ User1 makeимеет много «функций», которые могли иметь смысл, когда он был написан, но теперь больше похожи на ошибки, например, вы должны использовать символ табуляции, а не пробелы, в определенных местах. Подобные вещи, вероятно, не беспокоят людей, которые действительно опытны в этом make, но сводят нас с ума.
Хэнк Гей
4
@HankGuy: пусть ваш редактор беспокоится об этой детали. Если ваш редактор не может корректно обрабатывать настройки табуляции <->, найдите новый редактор, и вы будете намного счастливее. Но вы правы, когда говорите, что многие функции устарели, например, как обрабатываются динамические зависимости ( make dependкто-нибудь?)
D.Shawley,
3
@ User1 Это масштаб проекта, который мы строим. У нас есть штатный сотрудник, который поддерживает файлы make и зависимости. Воспользовавшись maven, я обнаружил, что это более управляемо. Сказав, что Maven тоже не идеален. Ничто так не бесит, как попытка выяснить, какие настройки XML необходимы для создания сборки, которая немного отличается от заданной установки.
отжигает
28

Фактически, make может обрабатывать перекомпиляцию одной командой из всех устаревших java-файлов. Измените первую строку, если вы не хотите компилировать все файлы в каталоге или хотите определенный порядок ...

JAVA_FILES:=$(wildcard *.java)
#
# the rest is independent of the directory
#
JAVA_CLASSES:=$(patsubst %.java,%.class,$(JAVA_FILES))

.PHONY: classes
LIST:=

classes: $(JAVA_CLASSES)
        if [ ! -z "$(LIST)" ] ; then \
                javac $(LIST) ; \
        fi

$(JAVA_CLASSES) : %.class : %.java
        $(eval LIST+=$$<)
user1251840
источник
4
Ницца! Я искал что-то подобное. Нет необходимости использовать разные инструменты сборки для каждого языка, когда универсальная классика работает нормально. Спасибо!
RSP
17

Все остальные ответы о технических достоинствах каждого из них являются правдой. Antи Mavenможет быть лучше подходит для Java, чем make, или, как указывает Хэнк Гэй, они могут и не :)

Однако вы спросили, имеет ли значение, что Ant и Maven написаны на Java. Хотя в StackOverflow мы не учитываем такие мысли (закрытые! Не связанные с программированием! И т. Д.), Конечно же, ЧАСТЬ, ЧАСТЬ ВЕЩИ. На рельсах мы используем Rake, C dudes используют make, а в Java - Ant и Maven. Хотя разработчики Ant или Maven действительно будут заботиться о Java-разработчике, возможно, лучше, чем другие, есть еще один вопрос: для чего вы пишете задачи Ant? Ява. Если вы Java-разработчик, это легко.

Так что да, отчасти это использование инструментов, написанных на том языке, на котором вы работаете.

Дэн Розенстарк
источник
7
Ant также возник в то время, когда сообщество Java было увлечено XML. (Нельзя сказать, что XML не имеет места.)
Лоуренс Гонсалвес
3
@Laurence Гонсалвес, что это так верно. Но, пожалуйста, мы не говорим о причудах здесь, на SO :). Я учил Java-разработке в то время, и ВСЕ было XML. Теперь это все еще XML, но никому нет до этого дела.
Дэн Розенстарк
1
Инструментальный комментарий интересный. makeПроисходит из опыта работы в UNIX, поэтому инструменты создаются путем написания полезных компактных утилит и их конвейерной передачи. Вот почему большая часть сшивки выполняется с помощью команд оболочки.
Д.Шоули
2
@D. Shawley, все верно относительно makeмаленьких утилит Unix. GIT тоже дитя этого процесса. От себя лично, я бы не сказал, что это не лучше. Но это огромный сдвиг парадигмы для Java-программистов. Ant гораздо более созвучен образу мышления Java.
Дэн Розенстарк
12

Муравей и позже Maven были разработаны, чтобы решить некоторые головные боли, вызванные Make(при создании новых в процессе), это просто эволюция.

... Вскоре после этого несколько Java-проектов с открытым исходным кодом поняли, что Ant может решить проблемы, которые у них были с Makefiles ....

С http://ant.apache.org/faq.html#history

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

Основным преимуществом, которое он имеет, является возможность интеграции с Java.

Я думаю, что подобная история была бы с, rakeнапример.

OscarRyz
источник
4
Это не очень конкретно. Какие головные боли, вызванные make, решает Maven?
Лоуренс Гонсалвес
1
@Gonsalves: Это один из субъективных аспектов каждой новой технологии, создатель альтернативы говорит, что она решает много проблем, а создатели замененной технологии говорят, что это не дефекты, а достоинства и так далее. Я думаю, что в этой конкретной ситуации была интеграция Java и кросс-компиляция из коробки
OscarRyz
2
[Ссылаясь на ваше редактирование ответа, а не на ваш самый последний комментарий] Это по-прежнему не объясняет, какие проблемы были решены, только то, что создатели ant утверждают, что проблемы были решены ...: - / У меня сложилось впечатление, что Ant изначально был создан для быть более простой альтернативой Make. Со временем люди обнаружили, что есть вещи, которых ему не хватало, и поэтому добавили функции, пока Ant не стал таким же сложным, как make, но со встроенным binutils (make сильно зависит от внешних инструментов, таких как cp, rm и т. Д.), И конечно, есть синтаксис XML.
Лоуренс Гонсалвес
2
Да, но когда лучшее, что может сделать создатель новой альтернативы, это сказать «это решает проблемы, возникшие у старой», фактически не говоря, что это за проблемы, это не очень полезно для тех, кто рассматривает, какой вариант использовать. Решает ли Ant проблемы , с которыми я сталкиваюсь, с make, или он решает проблемы, которые я не считаю проблемными, при этом предлагая мне новые проблемы?
Лоуренс Гонсалвес
9

Одной из основных проблем, решаемых Maven (и настройками Ant с поддержкой Ivy) над make, является автоматическое разрешение зависимостей и загрузка ваших файлов зависимостей.

змееподобный
источник
6

Я думаю, что наиболее вероятное объяснение состоит в том, что несколько факторов препятствовали использованию make в сообществе Java в критический период времени (конец 1990-х годов):

  1. Поскольку Java охватывает несколько платформ, программисты на Java в целом не были настолько хороши в инструментах Unix, как программисты, как правило, ограниченные средой Unix (например, программисты на C и Perl). Обратите внимание, что это в общем. Без сомнения, есть и были одаренные программисты на Java с глубоким пониманием Unix.
  2. Следовательно, они были менее искусны в make и не знали, как эффективно использовать make.
  3. В то время как можно написать короткий и простой Makefile, который эффективно компилирует Java, требуется дополнительная осторожность, не зависящая от платформы.
  4. Следовательно, был аппетит к изначально независимому от платформы инструменту сборки.
  5. Именно в этой среде были созданы Ant и позже Maven.

Короче говоря, хотя make наверняка можно использовать для проектов Java, был момент, когда он стал инструментом де-факто для сборки Java. Этот момент прошел.

Дэвид А. Вентимилья
источник
5

Создание сценариев, как правило, зависит от платформы. Предполагается, что Java не зависит от платформы. Поэтому наличие системы сборки, которая работает только на одной платформе для многоплатформенной исходной базы, является своего рода проблемой.

Брайан Фокс
источник
5

Краткий ответ: потому что make это не хорошо. Даже на фронте C вы видите много альтернатив.

Длинный ответ: makeимеет несколько недостатков, которые делают его едва пригодным для компиляции C и совсем не подходящим для компиляции Java. Вы можете заставить его скомпилировать Java, если хотите, но ожидаете столкнуться с проблемами, некоторые из которых не имеют подходящего решения или обходного пути. Вот несколько из них:

Разрешение зависимостей

makeпо своей природе ожидает, что файлы будут иметь древовидную зависимость друг от друга, в которой один файл является результатом построения нескольких других. Это уже имеет неприятные последствия в C при работе с заголовочными файлами. makeтребует, makeчтобы был сгенерирован специфичный включаемый файл для представления зависимости файла C от его заголовочных файлов, поэтому изменение последнего приведет к перестроению предыдущего. Однако, поскольку сам файл C не воссоздается (просто перестраивается), make часто требует указывать цель как .PHONY. К счастью, GCC поддерживает автоматическое создание этих файлов.

В Java зависимость может быть круговой, и в ней нет инструмента для автоматического создания зависимостей классов. make формате. ant«S Dependзадача может, вместо того, чтобы прочитать файл класса непосредственно, определить , какие классы он импортирует, и удалить файл класса , если любой из них устарели. Без этого любая нетривиальная зависимость может привести к тому, что вы будете вынуждены использовать повторные чистые сборки, что исключает любые преимущества использования инструмента сборки.

Пробелы в именах файлов

Хотя ни Java, ни C не поощряют использование пробелов в именах файлов исходного кода, в makeэтом может возникнуть проблема, даже если пробелы находятся в пути к файлу. Рассмотрим, например, если ваш исходный код существует в C:\My Documents\My Code\program\src. Этого было бы достаточно, чтобы сломаться make. Это потому чтоmake обрабатывает имена файлов как строки. antтрактует пути как особые объекты.

Сканирование файлов для сборки

make требует явного указания, какие файлы должны быть созданы для каждой цели. antпозволяет указать папку, которая будет автоматически проверяться на наличие исходных файлов. Это может показаться незначительным удобством, но учтите, что в Java каждому новому классу требуется новый файл. Добавление файлов в проект может быстро стать большой проблемой.

И самая большая проблема с make :

make зависит от POSIX

Девиз Java - «Компилировать один раз, запустить везде». Но ограничивать эту компиляцию системами на основе POSIX, в которых поддержка Java на самом деле является худшей, не является намерением.

Правила сборки в makeосновном являются небольшими bashскриптами. Несмотря на наличие порта makeдля Windows, для правильной работы он должен быть связан с портом bash, который включает в себя уровень эмуляции POSIX для файловой системы.

Это приходит в двух вариантах:

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

  2. cygwinкоторая обеспечивает полную эмуляцию POSIX. Получающиеся программы, однако, имеют тенденцию полагаться на этот слой эмуляции.

По этой причине в Windows стандартный инструмент сборки даже не является make, а скорее MSBuildявляется инструментом, основанным на XML, в принципе ближе к нему ant.

Напротив, antон построен на Java, может работать везде и содержит внутренние инструменты, называемые «задачами», для манипулирования файлами и выполнения команд независимо от платформы. Он достаточно универсален, так что вы можете на самом деле легче создавать C-программу в Windows, antчем использовать make.

И последний минор:

Даже программы на C не используют make изначально

Вы можете не заметить этого изначально, но программы на C обычно не поставляются с Makefile. Они поставляются с CMakeLists.txtили bashсценарием конфигурации, который генерирует фактический Makefile. Напротив, исходный код Java-программы antпоставляется с antпредварительно созданным сценарием. A Makefile- это продукт других инструментов - вот почему сам makeпо себе инструмент сборки не подходит.antявляется автономным и имеет дело со всем, что вам нужно для процесса сборки Java, без каких-либо дополнительных требований или зависимостей.

Когда вы работаете antна любой платформе, она просто работает (тм). Вы не можете получить это с make. Это невероятно зависит от платформы и конфигурации.

SlugFiller
источник
4

Если я не являюсь никем, предположение, что никто не (неправильно) использует make для java, неверно.

«Управление проектами с помощью GNU Make» (доступно в GFDL) содержит полную главу, посвященную использованию makeс проектами Java.

Поскольку он содержит длинный (и, надеюсь, справедливый) список плюсов и минусов использования make вместо других инструментов, вы можете захотеть взглянуть туда. (см .: http://oreilly.com/catalog/make3/book/ )

mikyra
источник
Это точное резюме? make (в разных вариантах) полезен для Java, но с некоторыми трудностями. Ant и Mavenjmake ?) Делают особые вещи, которые нужны / нравятся Java, чтобы ускорить и упростить создание Java-проектов. Их также можно использовать для более независимого от платформы процесса сборки для проектов, не относящихся к Java, но они более приспособлены для Java.
Фил Перри
3

Ant - это улучшенное конфигурирование XML по сравнению с Makefiles, а Maven - это улучшенное средство построения зависимостей по сравнению с Ant. Некоторые проекты используют все три. Я думаю, что в проектах JDK использовалось сочетание make-файлов и ant.

Берлин Браун
источник
1

Одна из важных причин заключается в том, что Ant и Maven (и большинство инструментов SCM, CI и IDE, ориентированных на Java) написаны на Java для разработчиков Java. Это упрощает интеграцию в среду разработки и позволяет другим инструментам, таким как серверы IDE и CI, интегрировать части библиотек ant / maven в инфраструктуру сборки / развертывания.

Крис Нава
источник
1

Когда-то я работал над проектом Java, который использовал gmake. Мое воспоминание туманно, но IIRC нам было трудно разобраться со структурой каталогов пакетов, которую ожидает javac. Я также помню, что создавать файлы JAR было хлопотно, если у вас не было чего-то тривиального.


источник
1

ApacheAnt не похож на Make. Make рассказывает о зависимости между файлами и о том, как создавать файлы. Ant посвящен зависимостям между «задачами» и представляет собой скорее способ склеивания сценариев сборки.

это может помочь вам AntVsMake

Венки Вунгарала
источник
Мне бы очень хотелось узнать о причинах снижения голосов.
Гагелло
0

Ant и Maven подходят к графу зависимостей сборки и управлению им с более «современной» точки зрения ... Но, как говорит Оскар, они создали свои собственные проблемы, пытаясь решить старые проблемы с make.

Джон Уэлдон
источник
0

Я никогда не использовал GNU Make для проектов Java, но я использовал jmk . К сожалению, он не обновлялся с 2002 года.

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

В настоящее время я предполагаю, что у любого разработчика Java, с которым я делюсь кодом, установлен Ant.

finnw
источник