PiumaLab

Idee, esperimenti, tentativi e molto altro

Makefile per Java

gnu make 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
# Site: http://www.piumalab.org/java-makefile/
#
 
# 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 ' </span>p<span style=; \
		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) $<
 
# find out target files
PATHFILES = $(wildcard $(LOCAL_SOURCE_DIR)/*.java)
FILES = $(subst $(LOCAL_SOURCE_DIR)/,,$(PATHFILES))
classes: $(FILES:.java=.class)

Buona compilazione.

3 Responses to Makefile per Java

  1. thegamer says:

    Preferisco di gran lunga ant!
    Dovresti provarlo...

  2. Gianni says:

    Ciao sono rimasto incredibilmente colpito dal tuo makefile di esempio.mi potrestri fornire una guida con tutti i comandi che hai usato oppure un sito che spiega bene come fare un makefile con i fiocchi?Ci sono delle cose che non ho del tutto capito o meglio non riesco ad adattarle al caso mio.ti ringrazio anticipatamente.Gianni

Leave a Reply

Your email address will not be published. Required fields are marked *