![]() |
Quanti di voi programmatori Java hanno avuto problemi per la compilazione di programmi? librerie fuori da $CLASSPATH, parametri chilometrici da passare al compilatore Java. Anche usando ambienti di sviluppo per Java la situazione non migliora di molto. Spendiamo molto tempo a settare paramteri e ogni volta che lanciamo la compilazione manca sempre qualcosa! |
Potete evitare tutti questi problemi semplicemente organizzando i sorgenti Java e usando un Makefile scritto ad hoc.
Cos’è un Makefile
Un makefile è un file che descrive i passi da efftuare per arrivare ai file che vorremmo ottenere e tutto l’albero delle sue dipendenze. È molto usato nelle piattaforme basate su Unix e può essere utilizzato per compilare ogni tipo di programma. L’utility make interpreta i makefile e compila il codice sorgente per ottenere programmi eseguibili e librerie.
Vantaggi nell’uso di make
Molti di voi saranno scettici nell’utilizzo di un makefile per ogni progetto Java per la semplice ragione che il makefile richiede di specificare tutte le dipendenze tra i files, che sicuramente cambia da progetto a progetto. Quindi dovremmo scrivere un makefile diverso per ogni nostro progetto. Questo limite può essere superato scrivendo un makefile generico e in grado di calcolarsi tutte le dipendenze per il progetto da compilare in modo da utilizzare lo stesso script per tutti i progetti senza bisogno di moficare niente all’interno del makefile.
Un vantaggio sicuramente non trascurabile è la capacità di make di compilare solo il necessario. Evita quindi di compiare ciò che è già compilato e non è stato modificato con un risparmio notevole di tempo.
Con un solo makefile si riesce a compilare tutti i sorgenti del progetto.
Come usarlo
Il makefile che ho scritto per compilare progetti Java può può essere utilizzato senza alcuna modifica per progetti che hanno una certa struttura di directory. I sorgenti Java devono avere una directory per i .java, una per i file .class, e una per le librerie jar.
Come ad esempio:
|-- src | `-- main | |-- java | | `-- com | | `-- example | | |-- ExampleA.java | | |-- ExampleB.java | | `-- ExampleC.java | `-- resources | `-- Res.java |-- classes |-- libs | |-- general | | |-- DataBase | | | |-- DB1.jar | | | `-- DB2.jar | `-- Logging | `-- log.jar |-- jars
Per usarlo quindi basta scrivere il codice quì sotto nel file Makefile nella directory root del progetto, verificare che il nome delle directory sia quello specificato nel file (classes per i .class; src per i .java e libs per i jar) e lanciare il comando
make
questo è tutto. Se vogliamo anche un jar contenente tutto il progetto basta lanciare
make && make jar
Makefile
# # Makefile # author: Danilo Abbasciano # # set here the directories for classes and sources CLASS_DIR = classes SOURCE_DIR = src JARS_DIR = jars SUBDIRS := $(shell find $(SOURCE_DIR) -name "*.java" -printf %h\\n | sort | uniq | sed 's/$(SOURCE_DIR)\/\?//') JAVA_HOME=/usr/local/java/bin # compiler field #JDEBUGFLAGS = -g -deprecation #JDEBUGFLAGS = -O -depend -nowarn JCC = $(JAVA_HOME)/javac .PHONY: clean classes compile jar all: @@for p in $(SUBDIRS); do \ echo 'compile ' $p; \ export SUBDIR=$p; \ make --no-print-directory compile; \ done clean: -rm -f *~ *.class *.bak $(foreach dir,$(SUBDIRS),$(CLASS_DIR)/$(dir)/*.class) LOCAL_CLASS_DIR=$(CLASS_DIR)/$(SUBDIR) LOCAL_SOURCE_DIR=$(SOURCE_DIR)/$(SUBDIR) jar: cd $(CLASS_DIR); jar -cf ../$(JARS_DIR)/project.jar * compile: classes # create target class dir if not present. $(LOCAL_CLASS_DIR): mkdir -p $(LOCAL_CLASS_DIR) # new rule for java .SUFFIXES: .SUFFIXES: .java .class # magical command that tells make to find class files in another dir vpath %.class $(LOCAL_CLASS_DIR) vpath %.java $(LOCAL_SOURCE_DIR) # classpath; all in ./jars and ./libs LIBCLASSPATH:=$(CLASS_DIR):$(SOURCE_DIR):$(subst .jar ,.jar:,$(wildcard libs/*.jar libs/*/*.jar libs/*/*/*.jar jars/*.jar)) # compil command .java.class: CLASSPATH=$(LIBCLASSPATH) $(JCC) -nowarn -d $(CLASS_DIR) $(JDEBUGFLAGS)
lt;
# find out target files
PATHFILES = $(wildcard $(LOCAL_SOURCE_DIR)/*.java)
FILES = $(subst $(LOCAL_SOURCE_DIR)/,,$(PATHFILES))
classes: $(FILES:.java=.class)
Buona compilazione.