Dlaczego nikt nie używa make for Java?

162

Prawie każdy projekt Java, który widziałem, używa Mavena lub Anta. To dobre narzędzia i myślę, że każdy projekt może ich użyć. Ale to, co zdarzyło się zrobić ? Jest używany w różnych projektach innych niż Java i może z łatwością obsługiwać Javę. Oczywiście, jeśli używasz systemu Windows, musisz pobrać make.exe, ale Ant i Maven również nie są dostarczane z JDK.

Czy jest jakaś fundamentalna luka w make, gdy jest używana z Javą? Czy to tylko dlatego, że Ant i Maven są napisane w Javie?

Użytkownik1
źródło
37
Jeśli przenosisz rzeczy i robisz więcej niż tylko wywoływanie kompilatora (a nawet wtedy), rzeczy specyficzne dla platformy stają się bardzo niewygodne w obsłudze make. Posiadanie pliku makefile, który działa tylko w jednym systemie, nie jest zbyt przyjemne dla języka wieloplatformowego.
Joey,
Na marginesie, Gradle jest nowym graczem w przestrzeni Javy, podobnie jak Gant (w mniejszym stopniu). Maven lub Ant to fałszywa dychotomia.
Wielkanoc Michaela
@Michael Easter, fałszywa dychotomia brzmiałaby: Maven / Ant vs. Make. Prawdziwą dychotomią, jeśli dobrze cię czytam, byłaby Gradle / Maven / Gant / Ant vs. Make. Ale trochę trudno powiedzieć :)
Dan Rosenstark,

Odpowiedzi:

192

Podstawowy problem z programami Make i Java polega na tym, że program Make działa w oparciu o założenie, że określono zależność, a następnie regułę rozwiązującą tę zależność.

W przypadku podstawowego C, to zazwyczaj „aby przekonwertować plik main.c do pliku main.o, należy uruchomić„ cc main.c ”.

Możesz to zrobić w Javie, ale szybko się czegoś nauczysz.

Przede wszystkim kompilator javac wolno się uruchamia.

Różnica pomiędzy:

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

i

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

jest noc i dzień.

Zaostrz to setkami zajęć, a stanie się to po prostu nie do utrzymania.

Następnie łączysz to z faktem, że java ma tendencję do organizowania się jako grupy plików w katalogach, w porównaniu z C i innymi, które mają bardziej płaską strukturę. Make nie ma bezpośredniego wsparcia w pracy z hierarchiami plików.

Make również nie jest zbyt dobry w określaniu, które pliki są nieaktualne na poziomie kolekcji.

Dzięki Ant przejrzy i podsumuje wszystkie nieaktualne pliki, a następnie skompiluje je za jednym razem. Make po prostu wywoła kompilator java dla każdego pojedynczego pliku. Jeśli Make NIE robi tego wymaga wystarczających narzędzi zewnętrznych, aby naprawdę pokazać, że Make nie jest w stanie sprostać temu zadaniu.

Dlatego pojawiły się alternatywy, takie jak Ant i Maven.

Will Hartung
źródło
6
Aby więc używać make w ogromnym projekcie Java, konieczne byłoby utrzymanie listy wszystkich zmienionych plików .java, a na końcu wywołanie javac? Wydaje mi się to mniej niż idealne. To najlepsza odpowiedź, jaką do tej pory widziałem.
Użytkownik 1
32
Uwielbiam to. Zasadniczo mówisz, że Ant był potrzebny, aby zająć się faktem, że javac jest zbyt wolny.
cmcginty
25
Nie. Javac nie jest powolny, jeśli używasz go tak, jak został zaprojektowany do użytku. Jest po prostu powolny, jeśli używasz go do kompilowania jednego pliku na raz.
Stephen C
7
@Casey javac nie jest zbyt wolny. JVM działa zbyt wolno, aby się uruchomić.
Thorbjørn Ravn Andersen
7
GNU Make ma przynajmniej $?zmienną automatyczną, która rozwija się do „wszystkich wymagań wstępnych, które są nowsze niż cel”. Istnieje również funkcja reguł wzorcowych z wieloma celami, które uruchamiają recepturę tylko raz, aby zaktualizować wszystkie .classpliki. Łącząc to z jakiegoś sprytnego wykorzystania pliku / funkcje tekstowe podoba $(wildcard), $(shell), $(eval)a można nauczyć makefile odkryć cele budowania rozproszonych w całej swojej strukturze katalogów.
Tanz87
33

Czcigodny makeprogram dość dobrze radzi sobie z oddzielnie kompilowanymi językami, takimi jak C i C ++. Kompilujesz moduł, używa on #includedo ściągania tekstu z innych plików dołączanych i zapisuje pojedynczy plik obiektowy jako wynik. Kompilator jest systemem działającym pojedynczo, z oddzielnym krokiem łączenia w celu powiązania plików obiektowych w wykonywalny plik binarny.

Jednak w Javie kompilator musi faktycznie skompilować inne klasy, z którymi importujesz import. Chociaż byłoby możliwe napisanie czegoś, co generowałoby wszystkie niezbędne zależności z kodu źródłowego Javy, tak aby makebudować klasy w odpowiedniej kolejności pojedynczo, to nadal nie obsługiwałoby przypadków takich jak zależności cykliczne.

Kompilator Java może być również bardziej wydajny, buforując skompilowane wyniki innych klas podczas kompilowania kolejnych klas, które zależą od wyników już skompilowanych. Ten rodzaj automatycznej oceny zależności nie jest naprawdę możliwy w przypadku makesamego.

Greg Hewgill
źródło
7
Wydaje się, że jest to bardziej odpowiedź typu make versus javac niż odpowiedź make versus ant / maven. Opierając się na twojej odpowiedzi, dlaczego ktoś nie mógłby po prostu użyć make + javac (dając javacowi cały pakiet lub „moduł” naraz, więc zależności cykliczne są ukryte przed make)? Czy mrówka lub maven przyniosą jakiekolwiek korzyści w porównaniu z takim podejściem?
Laurence Gonsalves,
1
@Laurence: Możesz dać javacowi cały pakiet naraz, ale wtedy przekompiluje on wszystko w tym pakiecie (ponieważ tak mu kazałeś ). To prawda, że ​​kompilator java jest dość szybki, ale jest jeszcze szybszy, jeśli pozwolisz mu określić, które klasy są minimum potrzebne do ponownej kompilacji po zmianie czegoś.
Greg Hewgill,
Czy masz na myśli mówienie javacowi, aby kompilował tylko twoją "główną" klasę, a następnie automatycznie budował rzeczy, od których zależy? Ostatnio sprawdzałem (trzeba przyznać, że prawdopodobnie w 1.4) było to strasznie zawodne. -Xdepend był nieco lepszy (ale wolniejszy i nadal zepsuty) i usunęli tę flagę w 1.3.
Laurence Gonsalves,
4
Co więcej, to nadal nie wyjaśnia, dlaczego używałbym Ant lub Maven, a nie tylko prostego javaca ...
Laurence Gonsalves,
28

Pytanie opiera się na błędnym założeniu: numer nietrywialne programistów zrobić korzystania make. Zobacz Java Build Tools: Ant vs. Maven . Jak, dlaczego deweloper nie będzie korzystać z make: wielu programistów bądź nigdy nie używany make, lub używał go i nienawidzili go z ognia, który płonie lepszy niż tysiąc słońc. W związku z tym używają alternatywnych narzędzi.

Hank Gay
źródło
10
Używamy go, a ogień jest gorętszy niż tysiąc i jeden słońc.
reccles
4
@reccles: Czy to tylko nienawiść do tworzenia inżynierii, czy do samego siebie? W jaki sposób Ant, Maven lub coś innego byłoby lepsze (tj. Jest złym narzędziem dla swojej klasy)?
Użytkownik 1,
5
@ User1 makema wiele "funkcji", które mogły mieć sens, kiedy został napisany, ale teraz są bardziej podobne do błędów, np. W niektórych miejscach musisz użyć znaku TAB, a nie spacji. Takie rzeczy prawdopodobnie nie przeszkadzają ludziom, którzy są naprawdę doświadczeni make, ale doprowadza resztę do szału.
Hank Gay
4
@HankGuy: pozwól swojemu redaktorowi martwić się o ten szczegół. Jeśli twój edytor nie obsługuje poprawnie ustawień spacji tab <->, zdobądź nowego edytora, a będziesz o wiele szczęśliwszy. Ale masz rację, mówiąc, że wiele funkcji jest przestarzałych, na przykład sposób, w jaki obsługiwane są dynamiczne zależności (czy make dependktoś?)
D.Shawley,
3
@ User1 To skala projektu, który budujemy. Mamy pełnoetatowego pracownika zajmującego się plikami make i zależnościami kompilacji. Używając mavena, okazało się, że jest łatwiejszy do opanowania. Powiedziawszy, że maven też nie był doskonały. Nie ma nic bardziej irytującego niż próba ustalenia, jakie ustawienia XML są potrzebne do wykonania kompilacji, która różni się nieco od zalecanej konfiguracji.
reccles
28

W rzeczywistości make może obsłużyć rekompilację wszystkich nieaktualnych plików Java za pomocą jednego polecenia. Zmień pierwszą linię, jeśli nie chcesz kompilować wszystkich plików w katalogu lub chcesz mieć określoną kolejność ...

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
źródło
4
Miły! Szukałem czegoś takiego. Nie ma potrzeby używania innego narzędzia do kompilacji dla każdego języka, gdy uniwersalny klasyk działa dobrze. Dzięki!
rsp
17

Wszystkie inne odpowiedzi dotyczące technicznych zalet każdego z nich są prawdziwe. Anti Mavenmoże lepiej pasować do Javy niż make, lub jak wskazuje Hank Gay, może nie :)

Jednak zapytałeś, czy ma znaczenie, że Ant i Maven są napisane w Javie. Chociaż na StackOverflow nie bierzemy pod uwagę takich myśli (zamknięte! Niezwiązane z programowaniem! Itp.), OCZYWIŚCIE JEST TO CZĘŚĆ RZECZY. Na szynach używamy Rake'a, kolesie C używają make, aw Javie używamy Ant i Maven. Chociaż prawdą jest, że programiści Ant lub Maven będą opiekować się programistą Java być może lepiej niż inni, jest też inne pytanie: w czym piszesz zadania Ant? Jawa. Jeśli jesteś programistą Java, to łatwe dopasowanie.

Więc tak, częścią tego jest użycie narzędzi napisanych w języku, którego używasz.

Dan Rosenstark
źródło
7
Ant pojawił się również w czasie, gdy społeczność Java była zauroczona XML. (Co nie znaczy, że XML nie ma miejsca.)
Laurence Gonsalves,
3
@Laurence Gonsalves, to jest tak prawdziwe. Ale proszę, nie rozmawiamy tutaj o modach w SO :) Uczyłem wtedy programistów Javy i WSZYSTKO było XML. Teraz to wciąż XML, ale nikogo to nie obchodzi.
Dan Rosenstark,
1
Komentarz dotyczący narzędzi jest interesujący. makepochodzi z systemu UNIX, więc narzędzia są wykonywane przez pisanie przydatnych kompaktowych narzędzi i łączenie ich razem. Dlatego większość zszywania jest wykonywana za pomocą poleceń powłoki.
D.Shawley
2
@RE. Shawley, wszystkie prawdziwe makei małe narzędzia Unix. GIT jest również dzieckiem tego procesu. Osobiście nie powiedziałbym, że nie jest lepiej. Ale to ogromna zmiana paradygmatu dla programistów Java. Mrówka jest znacznie bardziej zgodna ze sposobem myślenia Javy.
Dan Rosenstark
12

Ant, a później Maven zostały zaprojektowane, aby rozwiązać niektóre bóle głowy spowodowane Make(podczas tworzenia nowych w procesie) To tylko ewolucja.

... Wkrótce potem kilka projektów Java Open Source zdało sobie sprawę, że Ant może rozwiązać problemy, które mieli z Makefiles ....

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

To, czy coś rozwiązują, czy po prostu tworzą dodatkowy format do nauki, jest tematem subiektywnym. Prawda jest taka, że ​​jest to prawie historia każdego nowego wynalazku: twórca twierdzi, że rozwiązuje wiele problemów, a pierwotni użytkownicy twierdzą, że są to zalety.

Jego główną zaletą jest możliwość integracji z java.

Myślę, że podobna historia byłaby rakena przykład.

OscarRyz
źródło
4
To nie jest zbyt konkretne. Jakie bóle głowy spowodowane marką rozwiązuje Maven?
Laurence Gonsalves,
1
@Gonsalves: Cóż, to jeden z subiektywnych aspektów każdej nowej technologii, twórca alternatywy mówi, że rozwiązuje ona wiele problemów, a twórcy zastępowanej technologii mówią, że to nie są wady, ale zalety i tak dalej. Myślę, że w tej konkretnej sytuacji była integracja java i kompilacja krzyżowa po wyjęciu z pudełka
OscarRyz
2
[Odnosząc się do twojej edycji odpowiedzi, a nie ostatniego komentarza] To wciąż nie wyjaśnia, jakie problemy zostały rozwiązane, tylko że twórcy twierdzą, że problemy zostały rozwiązane ...: - / Moje wrażenie było takie, że Ant pierwotnie stworzył, aby być prostszą alternatywą dla Make. Z biegiem czasu ludzie odkryli, że brakuje pewnych rzeczy, więc dodawali funkcje, aż Ant stał się tak samo złożony jak make, ale z wbudowanym binutilsem (make opiera się w dużej mierze na narzędziach zewnętrznych, takich jak cp, rm itp.), Oraz oczywiście jest składnia XML.
Laurence Gonsalves,
2
Tak, ale kiedy twórca nowej alternatywy może najlepiej powiedzieć, że „to rozwiązuje problemy, które miał stary”, bez faktycznego mówienia, jakie to problemy, nie jest to zbyt przydatne dla tych, którzy zastanawiają się, której opcji użyć. Czy Ant rozwiązuje problemy, które mam z make, czy też rozwiązuje rzeczy, których nie uważam za problemy, wprowadzając dla mnie nowe problemy?
Laurence Gonsalves,
9

Jednym z głównych problemów rozwiązywanych przez Mavena (i konfiguracje Ant z obsługą Ivy) w związku z make jest automatyczne rozwiązywanie zależności i pobieranie plików JAR z zależnościami.

Ofidian
źródło
6

Myślę, że najbardziej prawdopodobnym wyjaśnieniem jest to, że kilka czynników zniechęcało do używania marki w społeczności Java w krytycznym okresie (późne lata 90-te):

  1. Ponieważ Java obejmuje wiele platform, programiści Java na ogół nie byli tak biegli w narzędziach uniksowych, jak programiści generalnie ograniczeni do środowiska Unix (np. Programiści C i Perl). Zauważ, że jest to OGÓLNE. Bez wątpienia istnieją i byli utalentowani programiści Java z głębokim zrozumieniem Uniksa.
  2. W rezultacie byli mniej biegli w tworzeniu i nie wiedzieli, jak efektywnie używać go.
  3. Chociaż możliwe jest napisanie krótkiego i prostego pliku Makefile, który wydajnie kompiluje Javę, wymagana jest dodatkowa ostrożność, aby zrobić to w sposób niezależny od platformy.
  4. W związku z tym pojawił się apetyt na narzędzie do budowania niezależne od platformy.
  5. W tym środowisku powstał Ant, a później Maven.

Krótko mówiąc, chociaż make z całą pewnością może być używany w projektach Java, był moment, aby uczynić go de facto narzędziem do budowania Javy. Ta chwila minęła.

David A. Ventimiglia
źródło
5

Tworzenie skryptów jest z natury zależne od platformy. Java ma być niezależna od platformy. Dlatego posiadanie systemu kompilacji, który działa tylko na jednej platformie dla wieloplatformowej bazy źródłowej, jest pewnym problemem.

Brian Fox
źródło
5

Krótka odpowiedź: ponieważ makenie jest dobre. Nawet na froncie C widać wiele alternatyw.

Długa odpowiedź: makema kilka wad, które sprawiają, że ledwie nadaje się do kompilacji C, aw ogóle nie nadaje się do kompilowania Javy. Jeśli chcesz, możesz zmusić go do skompilowania Javy, ale spodziewaj się problemów, z których niektóre nie mają odpowiedniego rozwiązania lub obejścia. Tu jest kilka:

Rozwiązanie zależności

makez natury oczekuje, że pliki będą miały od siebie zależność podobną do drzewa, w której jeden plik jest wynikiem budowania kilku innych. To już działa odwrotnie w C, gdy mamy do czynienia z plikami nagłówkowymi. makewymaga makewygenerowania specyficznego pliku dołączanego, który będzie reprezentował zależność pliku C od jego plików nagłówkowych, więc zmiana tego ostatniego spowodowałaby odbudowanie poprzedniego. Jednak ponieważ sam plik C nie jest odtwarzany (tylko przebudowywany), make często wymaga określenia celu jako .PHONY. Na szczęście GCC obsługuje automatyczne generowanie tych plików.

W Javie zależność może być cykliczna i nie ma narzędzia do automatycznego generowania zależności klas w makeformacie. ant„s Dependzadanie może, zamiast czytać plik klasy bezpośrednio określić, które klasy importuje i usunąć plik klasy, czy któryś z nich są nieaktualne. Bez tego każda nietrywialna zależność może spowodować, że będziesz zmuszony do korzystania z powtarzających się czystych kompilacji, usuwając wszelkie korzyści z używania narzędzia do kompilacji.

Spacje w nazwach plików

Chociaż ani Java, ani C nie zachęcają do używania spacji w nazwach plików kodu źródłowego, makemoże to stanowić problem, nawet jeśli spacje znajdują się w ścieżce pliku. Rozważmy na przykład, czy Twój kod źródłowy istnieje w C:\My Documents\My Code\program\src. To wystarczy, żeby się złamać make. Dzieje się tak, ponieważ maketraktuje nazwy plików jako ciągi. anttraktuje ścieżki jako obiekty specjalne.

Skanowanie plików pod kątem kompilacji

makewymaga jawnego ustawienia, które pliki mają być zbudowane dla każdego celu. antumożliwia określenie folderu, który ma być automatycznie skanowany w poszukiwaniu plików źródłowych. Może się to wydawać niewielkim ułatwieniem, ale weź pod uwagę, że w Javie każda nowa klasa wymaga nowego pliku. Dodawanie plików do projektu może szybko stać się dużym kłopotem.

I największy problem z make:

make jest zależne od POSIX

Mottem Javy jest „kompiluj raz, gdy uruchomisz się wszędzie”. Ale ograniczenie tej kompilacji do systemów opartych na POSIX, w których obsługa języka Java jest w rzeczywistości najgorsza, nie jest intencją.

Reguły budowania w maketo zasadniczo małe bashskrypty. Mimo że istnieje port makesystemu Windows, aby działał poprawnie, musi być dołączony do portu bash, który zawiera warstwę emulacji POSIX dla systemu plików.

Występuje w dwóch odmianach:

  1. MSYS który próbuje ograniczyć translację POSIX do ścieżek plików i dlatego może mieć nieprzyjemne problemy podczas uruchamiania zewnętrznych narzędzi, które nie są specjalnie do tego przeznaczone.

  2. cygwinco zapewnia pełną emulację POSIX. Powstałe programy nadal jednak polegają na tej warstwie emulacji.

Z tego powodu w systemie Windows standardowe narzędzie do kompilacji wcale nie jest wcale make, ale raczej MSBuild, które jest również narzędziem opartym na języku XML, w zasadzie bliższym ant.

W przeciwieństwie do tego, antjest zbudowany w Javie, może działać wszędzie i zawiera wewnętrzne narzędzia, zwane „zadaniami”, do manipulowania plikami i wykonywania poleceń w sposób niezależny od platformy. Jest na tyle wszechstronny, że w rzeczywistości łatwiej jest zbudować program w języku C w systemie Windows przy użyciu antniż przy użyciu make.

I ostatnia drobna:

Nawet programy w C nie używają make natywnie

Możesz tego początkowo nie zauważyć, ale programy C zazwyczaj nie są dostarczane z rozszerzeniem Makefile. Są dostarczane ze skryptem konfiguracyjnym CMakeLists.txtlub bashskryptem konfiguracyjnym, który generuje rzeczywisty plik Makefile. Z kolei źródło programu Java zbudowanego przy użyciu antjest dostarczane z gotowym antskryptem. A Makefilejest produktem innych narzędzi - tyle makenie nadaje się do samodzielnego budowania. antjest samodzielny i obsługuje wszystko, czego potrzebujesz do procesu tworzenia Java, bez żadnych dodatkowych wymagań ani zależności.

Po uruchomieniu antna dowolnej platformie to po prostu działa (tm). Nie możesz tego dostać make. Jest niesamowicie zależny od platformy i konfiguracji.

SlugFiller
źródło
4

O ile nie jestem nikim, założenie, że nikt (niewłaściwie) używa make for java jest błędne.

„Zarządzanie projektami za pomocą GNU Make” (dostępne pod GFDL) zawiera kompletny rozdział poświęcony używaniu makez projektami java.

Ponieważ zawiera długą (i miejmy nadzieję, uczciwą) listę zalet i wad używania make zamiast innych narzędzi, warto tam zajrzeć. (patrz: http://oreilly.com/catalog/make3/book/ )

mikyra
źródło
Czy to jest dokładne podsumowanie? make (w różnych wersjach) jest użyteczne w Javie, ale z pewnym bólem. Ant i Maven (i jmake ?) Robią specjalne rzeczy, których Java potrzebuje / lubi, aby projekty Java były szybsze i łatwiejsze do zbudowania. Można ich również używać w procesie budowania bardziej niezależnym od platformy dla projektów innych niż Java, ale są one bardziej dostosowane do języka Java.
Phil Perry
3

Ant to ulepszenie zorientowane na konfigurację XML w stosunku do Makefiles, a Maven to ulepszenie narzędzia do budowania zależności w porównaniu z Ant. Niektóre projekty wykorzystują wszystkie trzy. Myślę, że projekty JDK używały mieszanki makefile i ant.

Berlin Brown
źródło
1

Jednym z głównych powodów jest to, że zarówno Ant, jak i Maven (oraz większość narzędzi SCM, CI i IDE ukierunkowanych na java) są napisane w języku Java przez / dla programistów Java. Ułatwia to integrację ze środowiskiem programistycznym i umożliwia innym narzędziom, takim jak serwery IDE i CI, integrację części bibliotek ant / maven w ramach infrastruktury budowania / wdrażania.

Chris Nava
źródło
1

Kiedyś pracowałem nad projektem Java, który korzystał z gmake. Moje wspomnienia są mgliste, ale IIRC mieliśmy trudności z radzeniem sobie ze strukturą katalogów pakietów, której oczekuje javac. Pamiętam też, że tworzenie plików JAR było kłopotliwe, chyba że było coś trywialnego.


źródło
1

ApacheAnt w niczym nie przypomina Make. Make polega na opisywaniu zależności między plikami i tworzeniu plików. Ant dotyczy zależności między „zadaniami” i jest raczej sposobem łączenia ze sobą skryptów budowania.

może ci pomóc AntVsMake

Venky Vungarala
źródło
Naprawdę chciałbym wiedzieć o powodach głosów przeciw.
hagello
0

Ant i Maven podchodzą do grafu zależności kompilacji i zarządzania nim z bardziej „nowoczesnego” punktu widzenia ... Ale jak mówi Oscar, stworzyli własne problemy, próbując rozwiązać stare problemy za pomocą make.

John Weldon
źródło
0

Nigdy nie używałem GNU Make w projektach Java, ale używałem jmk . Niestety nie był aktualizowany od 2002 roku.

Miał pewne funkcje specyficzne dla Javy, ale był na tyle mały, że można go było dołączyć do puli źródłowej bez znaczącego zwiększania jego rozmiaru.

Obecnie zakładam, że każdy programista Java, któremu udostępniam kod, ma zainstalowaną aplikację Ant.

finnw
źródło