next_inactive up previous

Environnements de développement libres pour java

Bruno Böttcher
Copyright (C) 1999 Bruno Böttcher
bboett@adlp.org
http://inforezo.u-strasbg.fr/ bboett


Table des matières

Introduction

Pour le dévelopement de programmes java existent toute une pléthore d'outils de développement qui sont sensés faciliter la conception de programmes java. Cette présentation montrera une des nombreuses possibilités qui à l'avantage d'utiliser en majeure partie (le jdk de sun ne pouvant pas encore ètre qualifié de libre) des outils standards, puissants, d'un lancement rapide et libres.

Les outils libres utilisés ici sont exuberant ctags, vim, make et lynx.

Attentes envers un environnement de développement

La raison pour laquelle on se tourne vers des soi-disants kits de développement est que l'on voudrait se simplifier la vie et idéalement avoir le moins de contact possible avec les mécanismes du langage eventuellement, de la compilation sûrement.

Quand on essaye de comparer les différents environnements de développement, l'on se rend compte que l'écrasante majorité sont des outils graphiques, qui promettent la conception rapide d'applications graphiques. Or les applications graphiques ne représentent pas tous les types de développements.

De plus la liste des proprietés de tous ce environnements est souvent très impressionnante, mais la question reste souvent en suspens sur ce dont on aura vraiment besoin.

Caractéristiques nécessaires à un environnement de développement

Le but d'un environnement de développement est avant tout de faciliter le cycle de développement qui se compose de l'édition du code source, la compilation des sources et le test du programme.

Intéressant surtout sont les deux premièrs points, l'editeur pour la simple raison que c'est la que seront saisis ou générés les lignes de code qui composeront le programme, ce qui correspond donc à la partie la plus visible de l'environnement et la compilation, car souvent pour compiler il faut connaître les fichiers à compiler et eventuellement des options à donner au compilateur.

Caractéristiques nécessaires à l'étape de l'édition

Nécessaires sont d'un côté un éditeur de textes puissant, adapté à l'édition de fichiers de code source et comfortable ainsi qu'un mécanisme pour afficher de manière concise, claire et rapide la structure du programme (la hierarchie de classes).

Le cahier des charges de l'éditeur contient:

Caractéristiques nécessaires à l'étape de la compilation

Comparé à d'autres langages la compilation de code sources java est largement simplifée. Malgré cela il peut se révéler nécessaire de livrer au compilateur des arguments en plus des fichiers à compiler. Il faut donc prévoir un mécanisme pour simplifier à l'utilisateur l'appel du compilateur. Idéalement uniquement les fichiers modifiés devraient ètre recompilés, ainsi que les fichiers qui en dépendent et la aussi uniquement les fichiers pertinents au projet. Car souvent un projet de programme java est composé d'une grande multitude de fichiers de code source (il est rappelé que chaque définition de classe est stoquée dans un fichier propre) et recompiler l'ensemble des fichiers peut prendre un temps considérable, ce qui ralentirait le cycle de développement.

Présentation de la solution

Les prémisses demandées dans le chapitre précédent peuvent ètre tenues par des logiciels libres, livrés en standard avec les distributions majeures et dits simples. Pourquoi dits simples? Parce qu'il s'agit d'utilitaires qui existent pour la pluspart depuis le début des systèmes UN*X (qui ont cependant beaucoup évolué depuis ces débuts) et sont des outils dits en-ligne, donc ne nécessitant pas d'environnemnt graphique et utilisables même à partir d'un simple terminal.

Dans les sections qui suivent seront présentés les outils qui participeront de façon ouverte (comme make ou vim) ou couverte (ctags, polardoc) aux fonctionalités de l'environnement de développement.


La shell ou ligne de commandes

La ligne de commande UN*X est un des outils discrets mais primordiaux dans toute manipulation, la aussi il s'agit de la configurer pour faciliter le travail.

En utilisant une shell standard dans les distributions linux, bash un dérivatif de sh la pluspart connaissent déjà la complétion de nom automatique (lancée par la touche $<$TAB$>$), par défaut em bash essayera de proposer tous les fichiers avec la racine proposée par l'utilisateur.

Souvent c'est le comportement désiré, sauf que dans le cas du développement de programmes en général, l'on se trouve dans des répertoires remplis de fichiers intermédiaires variés, utiles en tant que librairies et résultats de compilation, mais qu'en de très rares cas l'on veuille consulter dans un éditeur (p. ex. les fichers .class). Un mécanisme existe pour ignorer pendant la complétion automatique certains suffixes en exportant (p. ex. dans le fichier d'intilialisation  /.bashrc, ou dans le scripte qui lance l'environnement de développement java) la variable FIGNORE (p. ex. FIGNORE='.o:.class:.dvi:.toc:.d:.u:.aux:.lof:.lot: '.


Exuberant ctags

Ce programme compile à partir de fichiers source (ctags est capable d'analyser des fichiers source en langages C, C++, Fortran, Pascal, LaTeX, Scheme, Emacs Lisp/Common Lisp, Erlang, Prolog et java) une liste indexée des definitions de classes et de leurs méthodes, classés par fichier. Cette liste est transcrie dans un fichier appelé tags, qui sera automatiquement pris en compte par les éditeurs de style vi.


Lynx

Lynx est ce qu'on appelle un ''browser web'', un programme qui prend comme entrée des fichiers au format HTML et qui compile un resultat formaté. Ce logiciel fait aussi partie des logiciels en ligne, le résultat est du texte seul, cet outil est donc particulièrement adapté dans les cas ou l'on travaille sur des consoles sans capabilités graphiques (Ce qui est de plus en plus rarement les cas).

Ce qui nous intéresse particulièrement ici c'est que nous n'avons que des informations non graphiques à afficher (la hierarchie des classes et methodes d'un projet) et que lynx se lance et charge des pages HTML extrèment rapidement, avec une empreinte mémoire minime et des fonctionalités de recherche par mot clé style vi, donc d'un accès eficace (Tout ceci accroit considérablement le temps des cycles de développement, en réduisant les temps de consultation).


Javadoc/polardoc/doc++

Trois logiciels qui en gros font la même chose à peu de choses près. Noyé dans le source sont placés des commentaires formatés spécialement (p.ex. /**) qui seront extraits par ces programmes. Les deux premiers sont spécialement conçus pour le langage java, le dernier vient du monde C/C++ mais est aussi capable de traiter du java.

En règle générale ces commentaires spéciaux sont placés juste avant des déclarations de classes et de méthodes, et seront donc automatiquement attribués aux-dites classes ou méthodes.

Ces logiciels parseront les fichiers sources qu'on leur livre pour en extraire la structure (classes, relations d'héritage entre classes et méthodes contenues dans les classes) et les commentaires associés pour compiler un ou des fichiers HTML représentant de manière concise et inter-référencée la structure d'un projet.


Make

C'est un outil spécialement conçu pour le développement. Consigné dans un fichier (généralement appelé ''Makefile'') sont spécifiés des buts à atteindre en fonction de préconditions. Les préconditions sont en général la date d'écriture de fichiers source par rapport à la date de création du compilé, ou des buts plus complexes. P.ex.

all: toto

toto.class: toto.java
	jikes toto.java

toto: toto.class

Dans l'exemple qui précède (très primitif, et sans grand intérêt) le but par défaut (''all'') dépend de toto, toto dépend de toto.class, toto.class dépend de toto.java. Si make détermine que toto.java est de date plus récente que toto.class, la règle toto.class sera exécutée, et la commande jikes toto.java exécutée.

Un exemple plus pratique de Makefile est dans l'annexe A (en fait il s'agit de mon Makefile personnel qui est sensé ètre le plus générique possible).

Sans vraiment entrer dans les détails de ce fichier de configuration pour make, le compilateur est déterminé, à ce niveau il y aura des problèmes, car si jikes ne pourra pas ètre trouvé, les opérations faites par la suite ne manqueront pas de rater, il faudrait donc terminer l'exécution de make avec un message d'erreur dans ce cas. Quelques variables sont initialisées, en partie en utilisant des scriptes shell (p.ex. EXTCLASSPATH) ou des fonctions implicites de make (p.ex. MAINS).

Des règles implicites sont déclarées (p. ex. comment arriver en général d'un fichier .java à un fichier .class), puis le but/la règle ''all'' est mise sous condition (date de la dernière modification) par rapport à tous les fichiers à terminaison ''.class'' dont le fichier source contient ls séquence ''public static void main'' (s'ils n'existent pas, ils sont générés grâce à la règle implicite). Une fois que tous les fichiers nécessaires sont à jour la classe ''Main'' peut ètre executée dans la machine java virtuelle.

Dans la foulée le fichier ''tags'' (voir 3.2) est compilé, ainsi que les fichiers de dépendances des fichiers classes nécessaires à l'execution de la classe contenant la méthode main statique.

Pour des raisons pratiques ( = incapacité de l'auteur) la documentation n'est pas automatiquement générée, mais la règle doit ètre invoquée à la main.


Vim

Sur vi en général et vim spécifiquement on pourrait écrire des livres entiers. Cela dépasserait le cadre de ce document que de faire une introduction à cet excellent outil (se reférer à http://www.linux-france.com/article/appli/vi/vim). Les informations livrées ici se cantonneront donc aux fonctionalités nécessitées par une utilisation efficace mais pas forcément très répandues.

Cela commence par quelques préparations, insérées directement dans le fichier ''.vimrc'' ou bien essayées dans le vif et puis sauvegardées grâce à la commande vim '':mkv'' ( [*]).

Préparatifs

syntax on
valide le mode de coloration syntaxique, le module pour le parsage du java à du ètre au préalable rajouté à la distribution de vim.

set autowrite
cette option valide le fait que le fichier actuellement édité peut ètre automatiquement sauvegardé avant de changer de fichier ou avant un appel make.

quelques abbreviations
définition de quelques abbreviations utiles.

Autocommandes
définition de quelques fonctions utiles lors de la saisie.

fonctions mappées
définition de quelques macros utiles lors de la saisie. Pour cela récupérer du site http://www.tpp24.net/stephen.riehm/vim/ l'excellent paquetage de macros de développement de Stephen.Riehm@bigfoot.com et suivre les informations d'installation.

Utilisation

Les préparatifs décrits plus haut auront des effets variés, discrets pour la pluspart, mais qui accroitront la productivité, dans un permier temps il est utile de transcrire les abbreviations et fonctions mappées sur du papier pour les avoir tout le temps sous les yeux, le temps de les mémoriser.

Maintenant nous pouvons commencer à assembler/utiliser tout ce que nous avons préparé tout au long de ce cours.

Écriture de code

Lancez VIM comme d'habitude, en fonction du nom de fichier choisi, il lancera automatiquement la colorisation syntaxique qui se doit (donc le mode java, si le fichier se termine en '.java'). Maintenant vous pouvez commencer `a vide`, soit utiliser un fichier 'template' préparé à l'avance (en l'incluant avec :e  /mestemplates/std.java) qui proposera un fichier classe java standard, avec des marques la ou des insertions sont appropriées.

Utilisation des macros

Lisez la doc des macros pour les connaitre toutes, leur utilisation est très simple: elles sont activées en utilisant la touche Alt/Meta avec un type d'environnement. L'environnement est dans la pluspart un des symboles délimiteur ((,,< etc.), normalement le délimitateur ouvrant, ouvre un environnement monoligne simple, le fermant commence un bloc. Ces commandes s'appliquent aussi en mode 'v'.

En appliquant ces macros, l'on voit apparaitre de drôles de signes dans le texte, ces signes sont les marqueurs que l'on pourra atteindre en tapant la touche DEL en mode insertion toujours. Du coup vu que l'on n'a pas besoin de sortir de mode d'insertion, créer des arborescences imbriquées (if, else, while etc) devient un vrai plaisir.

Utilisation de la completion automatique

En compilant le fichier de 'tags' (voir 3.2) l'on obtient aussi une aide à l'écriture des noms de variables ou méthodes. L'on commence par taper le nom de la variable/methode et puis ctrl-Xctrl-, en continuant à taper ctrl- l'on peut cycler à travers les autres choix (ctrl-P le fait dans le sens inverse). Si le choix est bon continuer de taper son texte normalement.

Compilation

Commencez par créer quelques classes java dans des fichiers séparés. Maintenant, essayez de compiler ce nouveau projet en tapant '':make''. Dans le Makefile nous avions spécifé l'option ''+E'' pour jikes, qui l'incite à formater les erreurs trouvées au format emacs et non en liste humainement lisible, ce format est aussi utilisé par VI(M).

S'il devait y avoir des erreurs de compilation, VI(M) se positionera automatiquement sur la première erreur, et l'on pourra passer en avant et en arrière dans la liste d'erreurs avec '':cn'' et '':cN'' respectivement.

Lecture de code/deboguage

Un gros problème quand on programme, est la lecture du code source, et le deboguage, la recherche dans le code source d'erreurs. Au plus tard avec l'avènement des langages orienté object la lecture de sources code c'est considérablement compliquée, car traversant nombre de fichiers différents.

Ceci dit, pensé déjà pour des langages comme le C, le programme ctags (voir 3.2) permet de faciliter sensiblement la lecture. Dépendammnet des options fournies au programme ctags, sont pris en compte (en nous recentrant à nouveau autour de java) les noms de classes, les noms de méthodes et au choix les noms de variables.

En positionnant le curseur sur un mot clé, p.ex. un appel de méthode et en tapant $<$ctrl$>$-] (ou :tag nomDuTag) l'on sera transporté à l'endroit de la déclaration de cette méthode. En fait chaque appel à cette fonctionalité va empiler la localisation avant de la changer vers l'endroit cible. Donc l'on pourra suivre librement le cours du programme à travers les suites d'appels de méthodes pour pouvoir en revenir facilement en tapant $<$ctrl$>$-t (ou :pop).

Sauf que VI(M) n'est pas un compilateur, donc ne sera pas capable de reconnaitre le type de l'object dont une méthode est appelée et donc il y aura souvent plusieurs choix possibles (dus p.ex. aux mécanismes d'héritage).

Par défaut $<$ctrl$>$-] prendra le premier choix possible (normalement dans le même fichier, ou le premier fichier par ordre alphabetique ou cette méthode apparaît), ceci n'étant pas forcément approprié l'on peut demander la liste des possibilités avec g$<$ctrl$>$-] (ou :ts), si choix il y a, une liste numérotée apparaîtra, d'ou l'on selectionnera par chiffre la bonne cible.


Makefile génériques pour compilation java


Makefile générique pour compilation java

# .AUTODEPEND
# Petit exemple comment on peut se faciliter la vie en utilisant les
# utilitaires gnu :)


#               *Translator Definitions*
#top level Makefile definitions
ifeq (0,${MAKELEVEL})
# some Variables
IDL=/usr/local/JacORB/bin/idl
DOCDIR = ~/www/jSim
DOCOPTIONS = -d $(DOCDIR) -J-mx64M -author 

# test automagically for jdk1.2 
EXTCLASSPATH = $(shell if [ -f /usr/local/java/jre/lib/rt.jar ]; then echo "/usr/local/java/jre/lib/rt.jar:$(CLASSPATH)"; else echo $(CLASSPATH);  fi; )
JAVAC=$(shell if [ -n `which jikes` ]; then \
              { if [ -x `which jikes` ]; then \
	           echo jikes; \
                else echo javac; \
                fi; \
	      }; \
	      else echo javac;\
	      fi\
       )
 cur-dir   := $(shell pwd)
 #jikes need the classpath, while sun-javac doesn't, further use the
 #emacs-error-style to let emacs or vi(m) use the error tags
 ifeq ($(JAVAC),jikes)
  JOPTIONS := -g +E -classpath $(EXTCLASSPATH)
 else
  JOPTIONS := -g -bootclasspath $(EXTCLASSPATH)
 endif # ifeq ($(JAVAC),jikes)

endif #ifeq (0,${MAKELEVEL})

# some Variables
# test automagically for jdk1.2 
export JAVAC EXTCLASSPATH JOPTIONS DOCDIR DOCCOMPILER DOCOPTIONS IDL 
#               *Macros        *


#GENERIC_DEP := $(patsubst %.java,%.class,$(wildcard *.java))
MAINS := $(shell grep main *.java |grep static|grep public|grep -v "//"\
                |grep -v "/\*" |cut -d':' -f1)
MAIN_STARTS := $(patsubst %.java,%.class,$(MAINS))
SUBSIDIARIES = $(patsubst %.java,%.class,$(shell grep "extends Electrical" *.java|cut -d':' -f1))
SUBSID2 = $(patsubst %.java,%.class,$(shell grep "extends ModellElectrical" *.java|cut -d':' -f1))
CIRCUITS = $(patsubst %.java,%.class,$(shell grep "extends Circuit" *.java|cut -d':' -f1))
FUNCTIONS = $(patsubst %.java,%.class,$(shell grep "extends Function" *.java|cut -d':' -f1))
#if there was only one file with suffix .java, the grep will not add the
# filename...
ifeq ($(MAIN_STARTS),"")
	echo "hum first rule failed...";
	MAINS = $(wildcard *.java)
	MAIN_STARTS = $(patsubst %.java,%.class,$(MAINS))
endif


#               *Implicit Rules*

%.class:%.java  
	@$(JAVAC) $(JOPTIONS) $< |joinLines 

%.d:%.java
	@$(JAVAC) +M $(JOPTIONS) $<|joinLines; \
	cat $*.u| sed 's/\($*\)\.class[: ]*/\1.class $@ : /g' > $@; [ -s $@ ] || rm -f $@

#               *Explicit Rules*

all: $(MAINS:.java=.d) $(MAIN_STARTS) $(SUBSIDIARIES) $(SUBSID2) $(CIRCUITS) $(FUNCTIONS) tags 
	@#(cd ..;jar cf jSim.jar jSim;scp jSim.jar inforezo.u-strasbg.fr:java;scp jSim.jar erm1.u-strasbg.fr:java;scp jSim.jar yoda.u-strasbg.fr:java;)
	@#(cd ..;jar cf jSim.jar jSim;)

.PHONY : doc clean

doc:
	-mkdir $(DOCDIR)
	rm -rf $(DOCDIR)/*
	#polardoc $(DOCOPTIONS) *.java
	javadoc $(DOCOPTIONS) *.java */*.java
	-ln -s /usr/local/java/docs/api/images /home/bboett/www/jSim/images

clean : 
	@-rm -f *.class  *.swp core plot log* *~ *.u *.d
	@(cd doc; $(MAKE) clean)
	@(cd CORBA; $(MAKE) clean)

tags: *.java */*.java
	@ctags -R  *.java */*.java

include $(MAINS:.java=.d)


Makefile générique pour compilation d'arborescences de documentations latex

[Makefile pour arborescences latex]

# .AUTODEPEND
# Petit exemple comment on peut se faciliter la vie en utilisant les
# utilitaires gnu :)
# Make génerique  pour arborescence de documentations latex
# Autheur Bruno Boettcher <bboett@adlp.org>
# ce fichier est mis sous la licence GPL, ce qui en gros veut dire : vous
# pouvez tout faire avec ces sources tant que mon nom est spécifé comme auteur
# et qu'en cas d'amelioration vous publiez celles-ci sous cette même licence


#               *Translator Definitions*
TEXC = latex 

#subdirs =  Utilitaires introBash javaDev vim
subdirs =  $(shell ls -p |grep "/"|tr / ' ') 
#subMakes = $(foreach mak,$(subdirs),$(wildcard $(mak)/Makefile))
subMakes = $(foreach mak,$(subdirs),$(mak)/Makefile)

TOPTIONS = 

#               *Explicit Rules*

.PHONY : all html ${subdirs} clean

export TEXC TOPTIONS

all: ${subMakes} ${subdirs} 
	echo list $(subdirs)

${subMakes}: Makefile.subdir
	echo creating Makefile in $@
	cp Makefile.subdir $@
	if [ -e htaccess ]; then cp htaccess $(dir $@).htaccess; fi

${subdirs}:
	echo doing $@
	${MAKE} cur-dir=${cur-dir}/$@ -C $@ all

html: 
	@TOTO="$(foreach src,$(subdirs),$(shell \
	(cd $(src); $(MAKE) html);\
	))"

clean : 
	@TOTO="$(foreach src,$(subdirs),$(shell \
	(cd $(src); $(MAKE) clean);\
	))"


Makefile générique pour compilation de documentations latex

# .AUTODEPEND
# Petit exemple comment on peut se faciliter la vie en utilisant les
# utilitaires gnu :)
# Make génerique  pour documentation latex
# Autheur Bruno Boettcher <bboett@adlp.org>
# ce fichier est mis sous la licence GPL, ce qui en gros veut dire : vous
# pouvez tout faire avec ces sources tant que mon nom est spécifé comme auteur
# et qu'en cas d'amelioration vous publiez celles-ci sous cette même licence


#               *Translator Definitions*
TEX = latex 
BIBTEX = bibtex 
DVI = xdvi 
LP = dvips 
RMCOMMAND=@rm -f *.bak *.dvi *.swp *.aux *.lof *.log *.lot *.toc out title.tex *~

#               *Macros        *
TOPTIONS = 

GENERIC_TEX := $(shell grep begin *.tex |grep document|cut -d':' -f1)
GENERIC_TEX := $(strip $(GENERIC_TEX))
GREPCORRECT = $(findstring \begin{document},$(GENERIC_TEX))	       
GREPCORRECT := $(strip $(GREPCORRECT))
#if there was only one file with suffix .tex,the grep will not add the
# filename...
ifeq ($(GREPCORRECT),\begin{document}) 
	GENERIC_TEX := $(wildcard *.tex)
endif
GENERIC_DVI := $(patsubst %.tex,%.dvi,$(GENERIC_TEX))
GENERIC_PS = $(patsubst %.tex,%.ps,$(GENERIC_TEX))
.SUFFIXES: .dvi .tex .ps
	
#               *Implicit Rules*

.dvi.tex:  
#	$(TEX) $(TOPTIONS) $< |tee theLog
#	if [ "$(findstring Rerun,$(shell cat theLog|grep Rerun))"\
#	      == "Rerun" ]; then  \
#	touch $<;\
#	$(MAKE);\
#	fi
	echo Rerun > theLog
	count=0 ; \
	while [ $count -le 5 ] && grep Rerun theLog >/dev/null ; \
	then \
	$(TEX) $(TOPTIONS) $< 2>&1| tee theLog ; \
	count=`expr $count + 1` ; \
	fi ; \
	if [ $count -gt 5 ] ; \
	then echo '***' too much texing around! ; \
	exit 1 ; \
	fi
	rm -f theLog


.ps.dvi:
	$(LP) -o $@.ps  $< 


#               *Explicit Rules*
.PHONY : all clean html 

all: $(GENERIC_DVI)

ps: $(GENERIC_PS)

html:  $(GENERIC_DVI)
	if [ ! -e ~/www ]; then \
	echo "creating root- www directory..."\
	mkdir ~/www; fi
	$(foreach src,$(GENERIC_TEX),$(shell\
	toto=$(basename $(src)); \
	latex2html -dir ~/www/$$toto $$toto; >/dev/null 2>&1 \
	cp htaccess ~/www/$$toto/.htaccess; \
	))
clean : 
	$(RMCOMMAND)	

veryclean : clean uninstall

uninstall:
	$(foreach src,$(GENERIC_TEX),$(shell\
	toto=$(basename $(src)); \
	rm -rf ~/www/$$toto; \
	))

Liens HTML intéressants


Introduction a VI(M) http://www.linux-france.com/article/appli/vi/vim


Liste des tableaux


Liste des figures

À propos de ce document...

Environnements de développement libres pour java

This document was generated using the LaTeX2HTML translator Version 99.2beta6 (1.42)

Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The command line arguments were:
latex2html -dir /home/bboett/www/javaDev javaDev

The translation was initiated by Bruno Boettcher on 2000-02-29


next_inactive up previous
Bruno Boettcher
2000-02-29