Írok egy programot, ami sok osztályt definiál, és minden osztály egy-egy külön fájlban van, ráadásul mappákba szervezve.
Szeretnék írni egy Makefile-t mindehhez, hogy a fordító lefordíthassa.
A Makefile-ban a címke után fel kellene sorolnom az összes forrásfájlt, vagy van erre valami egyszerűbb megoldás is? Az lenne a legkényelmesebb, ha megadhatnék mappát/mappákat, és a mappán belül minden fájlt figyelne, hogy történt-e változás.
Vagy mi a kulturált módja a sokfájlos Makefile elkészítésének?
Egy megoldás:
FILES=$(shell find ./classes -type f -name '*.class')
main: $(FILES)
- 885 megtekintés
Hozzászólások
%.o: %.cpp targetnek?
- A hozzászóláshoz be kell jelentkezni
Nem cpp a fordító, és nincsenek object fájlok a fordítás után.
A % jelnek mi a jelentése a Makefile-on belül?
- A hozzászóláshoz be kell jelentkezni
Pattern matchingnel wildcard.
- A hozzászóláshoz be kell jelentkezni
Szerintem Makefile-ból is lehet hierarchiát létrehozni (mappánként).
Húzz le valami komolyabb forrást (Postgres mondjuk) és nézz bele hogy csinálja.
zászló, zászló, szív
- A hozzászóláshoz be kell jelentkezni
Úgy tűnik, egy járható út a következő:
FILES=$(shell find ./classes -type f -name '*.class')
main: $(FILES)
Nem tudom, ez a legszebb megoldás-e, de ezzel már működik, és elég egyszer elkészíteni a Makefile-t.
- A hozzászóláshoz be kell jelentkezni
all:
javac $$(find . -name '*.java')
- A hozzászóláshoz be kell jelentkezni
Köszönöm, ez szebb.
- A hozzászóláshoz be kell jelentkezni
Lehet, hogy szebb, de nem jó.
- A hozzászóláshoz be kell jelentkezni
Ez mindig lefut, mivel várhatólag egy "all" nevű fájl nem fog keletkezni. Ha meg véletlen mégis lesz egy "all", akkor meg nem fut le...
Ha ez nem gond (mármint az, hogy mindig lefut a parancs), akkor felesleges a make, hiszen sokkal egyszerűbb lenne egy szimpla kb. egysoros szkriptet írni, amiben ez a parancs fut le.
- A hozzászóláshoz be kell jelentkezni
Viszont a Makefile-ba később bele tudsz tenni egy ilyen részt:
clean: find . -name '*.class' -o -name '*.jar' -delete
- A hozzászóláshoz be kell jelentkezni
Mint ahogy egy szkriptbe is bele tudod ezt tenni :)
De a Makefile-od szerintem továbbra sem jó.
- A hozzászóláshoz be kell jelentkezni
Vagyis már két szkripted van (`all` és `clean`). Jöhet a harmadik:
build: clean all product.jar
product.jar:
${JAR} cf $@ $$(find . -name '*.class')
- A hozzászóláshoz be kell jelentkezni
Lehet egy szkriptbe, és paraméterként megkapja, mit csináljon :D
De nem azért írtam, hanem azért, hogy ha már make-et használunk, akkor használjuk ki a nyújtott lehetőségeit, ha más nem, a függőségkezelését.
- A hozzászóláshoz be kell jelentkezni
Joggal kérdezhetnénk, hogy miért nem követjük a függőségeket (jdeps?) és fordítjuk csak azt, amit tényleg kell. Azt érdemes tudni, hogy a javac (vagy bármilyen java alkalmazás) indulása lassú. Tényleg lassú. Végezhetünk mérést is, kis projekt, 121 /.java file-ban összesen 21240 sor:
time find . -name '*.java' javac {} \;
real 1m22.756s
user 2m59.546s
sys 0m10.769s
$ time javac $(find . -name '*.java')
real 0m2.307s
user 0m7.211s
sys 0m0.211s
- A hozzászóláshoz be kell jelentkezni
Viszont GNU Make (és bmake) esetében ott a $?, ami visszatér azokkal a függőségekkel, amik újabbak, mint a cél, azaz pl.
target: java-fajl-list
javac $?
clean:
rm -rf target
.PHONY: clean target
És már ki is használtad a make előnyét a szkripthez képest.
- A hozzászóláshoz be kell jelentkezni
Ezek a .java fájlok (illetve a generált .class fájlok) egymástól is függhetnek, akár körkörösen is.
A `javac` lefordítja a függőségeket, ha pl. látja, hogy `whatnot.java` fordításához `foo.class` kellene, de csak `foo.java` van, de ha van `foo.class` csak régebbi, mint a `foo.java`, azzal nem törődik, szóval a biztos módszer mégis az, ha mindent egyszerre fordítunk. (Mármint egy terméken belül, ahol nincsenek jól definiált határok (interface-ek) az egyes komponensek között.)
- A hozzászóláshoz be kell jelentkezni
Hát márpedig az a normális megoldás, hogy az ember a Makefile-ban precízen leírja a függőségeket. Mármint szerintem.
.java.class.
\t javac $?
whatnot.class: foo.class
foo.class: whatnot.class
main.class: foo.class whatnot.class
(Vagy valami hasonló)
- A hozzászóláshoz be kell jelentkezni
mindent egyszerre fordítunk
Ehhez meg nem kell a make tudása.
- A hozzászóláshoz be kell jelentkezni
Tudom nem ez volt a kérdés..... de ha már java akkor miért nem gradle vagy maven (legrosszabb esetben ant)? mert habár mindent IS meg lehet csinálni make-kel, de a fentiek "valóak" a java-hoz....
- A hozzászóláshoz be kell jelentkezni
##
# source directory
##
SRC_DIR := src
##
# output directory
##
OUT_DIR := out
##
# sources
##
SRCS := $(wildcard $(SRC_DIR)/*.java)
##
# classes
##
CLS := $(SRCS:$(SRC_DIR)/%.java=$(OUT_DIR)/%.class)
##
# compiler and compiler flags
##
JC := javac
JCFLAGS := -d $(OUT_DIR)/ -cp $(SRC_DIR)/
##
# suffixes
##
.SUFFIXES: .java
##
# targets that do not produce output files
##
.PHONY: all clean
##
# default target(s)
##
all: $(CLS)
$(CLS): $(OUT_DIR)/%.class: $(SRC_DIR)/%.java
$(JC) $(JCFLAGS) $<
##
# clean up any output files
##
clean:
rm $(OUT_DIR)/*.class
de amúgy ne használj Jávát, hanem inkább valami értelmes program nyelvet tanulj meg!
- A hozzászóláshoz be kell jelentkezni
Ej, ez a sok fölösleges komment :)
- A hozzászóláshoz be kell jelentkezni