Ant, Rekursion

Status
Nicht offen für weitere Antworten.
Z

Zergling

Gast
Hallo,

wer nicht alles lesen möchte, ich habe die Frage einmal zusammengefasst:

Also Kurzzusammenfassung:
Ich habe das Propertyfile config.properties:
Code:
list = KlasseA
KlasseA = KlasseB,KlasseC,KlasseD
KlasseC = KlasseE
KlasseD = KlasseE,KlasseF
KlasseG = KlasseH

Wie kann ich daraus ein:
Code:
all = KlasseA,KlasseB,KlasseC,KlasseE,KlasseD,KlasseE,KlasseF

basteln?


Die Frage im Kontext:
Ich arbeite seit einiger Zeit mit Ant. Dabei sollen C++ Klassen kompiliert werden, welche wiederrum von anderen abhängig sein können, welche auch wiederum von anderen abhängig sein können usw. Sprich ich habe eine unbekannte Tiefe von Abhängigkeiten.

Definiert ist das in einem Ant-Propertyfile (config.properties) z.B. so:

list = KlasseA
KlasseA = KlasseB,KlasseC,KlasseD
KlasseC = KlasseE
KlasseD = KlasseE,KlasseF
KlasseG = KlasseH

Mein Ziel ist es, eine Property zu haben, die dann so aussieht:
return = KlasseA,KlasseB,KlasseC,KlasseE,KlasseD,KlasseE,KlasseF.

Ein Ant-Target, dass mir doppelte Einträge herauslöscht habe ich bereits geschrieben.
Soviel zum Zweck und Ziel meiner Aufgabe.

Mein Lösungsansatz war, in einer foreach-Schleife alle Elemente durchzulaufen, zu prüfen ob ein Element als Property existiert und das Value davon erneut als Liste zu interpretieren und in der obigen foreach-Schleife auch zu durchlaufen. Wenn ein ListenElement keine Property ist (z.B. KlasseB) wird diese in einer return-Property hinzugefügt.

Soweit so gut, mein Lösungsansatz bis jetzt:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<project name="Build RecursiveList" default="recursiveList_all">
	<target name="recursiveList_init">
		<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
		
		<if>
			<not><isset property="config.properties"/></not>
			<then>
				<fail>Property &config.properties& is not set.</fail>
			</then>
		</if>

		<if>
			<not><isset property="tmp.properties"/></not>
			<then>
				<fail>Property &tmp.properties& is not set.</fail>
			</then>
		</if>
		
		<property file="${config.properties}"/>
		
		<if>
			<not><isset property="list"/></not>
			<then>
				<fail>Config file &${config.properties}& does not set property &list&.</fail>
			</then>
		</if>
		
		<if>
			<not><isset property="delimiter"/></not>
			<then>
				<property name="delimiter" value="+"/>
			</then>
		</if>
		
		<if>
			<not><isset property="self"/></not>
			<then>
				<property name="self" value="build-recursiveList.xml"/>
			</then>
		</if>
		
		<propertyfile file="${tmp.properties}">
			<entry key="counter" value="0"/>
		</propertyfile>
	</target>
	
	
	
	<target name="recursiveList">
		<property file="${tmp.properties}"/>
		
		<foreach list="${list}" delimiter="${delimiter}" target="recursiveList_single" param="current" inheritall="true"/>
	</target>
	
	
	
	<target name="recursiveList_single">
		<propertyfile file="${tmp.properties}">
			<entry key="counter" operation="+" type="int" value="1" default="0"/>
		</propertyfile>
		<property file="${tmp.properties}"/>

		<if>
			<isset property="${current}"/>
			<then>
				<propertycopy name="content" from="${current}"/>
				<property name="tmp.config.properties" value="tmp.${counter}.config.properties"/>
				<property name="tmp.tmp.properties" value="tmp.${counter}.tmp.properties"/>

				<copy file="${config.properties}" tofile="${tmp.config.properties}"/>
				<replaceregexp file="${tmp.config.properties}"
					match="list\s*=\s*(.*)"
					replace="list=${content}"/>
				<!--<ant antfile="build-recursiveList.xml" inheritall="false">
					<property name="config.properties" value="${tmp.config.properties}"/>
					<property name="tmp.properties"   value="${tmp.properties}"/>
					<property name="delimiter"        value="${delimiter}"/>
				</ant>-->
				<copy file="${self}" tofile="tmp.${self}"/>
				<exec executable="ant">
					<arg line="-buildfile tmp.${self} -Dconfig.properties=${tmp.config.properties} -Dtmp.properties=${tmp.tmp.properties} -Dself=copy.${self}"/>
				</exec>
				<delete file="tmp.${self}"/>
			</then>
			<else>
				<echo>Property &${current}& is not set, no recursion needed here.</echo>
			</else>
		</if>
		
		<propertyfile file="${tmp.properties}">
			<entry key="recursiveList.return" operation="+" type="string" value="${current}${delimiter}" default=""/>
		</propertyfile>
	</target>
	
	
	
	<target name="recursiveList_summary">
		<property file="${tmp.properties}"/>
		<echo>
--- RecursiveList --- summary ----------------------------------
List      : ${list}
Delimiter : ${delimiter}
Return    : ${recursiveList.return}
		</echo>
	</target>
	
	
	
	<target name="recursiveList_all" depends="recursiveList_init,recursiveList,recursiveList_summary"/>
</project>

Wobei dem XML-Build die Property
config.properties (Dateiname, Datei enthält list-Property und die Zuordnung der Abhängigkeiten)
tmp.properties (Dateiname, temporäre Properties)
delimiter ist Trennzeichen der Liste

Ein Selbstaufruf per <antcall> schlägt fehl, da Propertys nicht überschrieben werden können (in einer Datei schon, nicht aber zur Laufzeit wieder abgefragt werden können). Ein kompletter Selbstaufruf per <exec> schlägt wegen einer IOException auch fehl (darum habe ich probiert, dass von der build.xml eine Kopie angelegt wird, welche dann aufgerufen wird, klappt auch nicht).

Ich habe die Info gefunden, es soll per JavaScript in Ant möglich sein, rekursiv vorzugehen, allerdings habe ich dazu nur ein Beispiel für einen Ordnerdurchlauf gefunden, was mir nicht weitergeholfen. Ich habe zwar solide bis gute JavaScript Vorkenntnisse, aber bekannt kam mir bei diesem Beispiel auch überhaupt nichts vor. Außer eben der Syntax, aber die kann ja ja jeder mit Programmier-Vorkenntnissen.
 

Bleiglanz

Gesperrter Benutzer
1. man soll ant möglichst nicht programmieren

2. verwende doch einfach die ant-targets für diesen zweck

<target name="A" depends"B,C,D">...</target>

usw., der Mechanismus von ant würde dann genau das machen was du willst?

3. warum nimmst du nicht make?
 
Z

Zergling

Gast
Ich will ja die Abhängigkeiten nicht per Ant-Target-Namen definieren, sondern in einem Properties-File. Die Idee ist interessant, aber <target name="recursion_all" depends="${list}"/>
funktioniert nicht, da die Target-Attribut-Werte nicht variabel sein können (Target `${list}' does not exist in this project. It is used from target `recursion_all'. ; bei Aufruf: ant -buildfile build-recursion.xml -Dlist=xy).

Was ist denn make?
 
Z

Zergling

Gast
Hmm du hast irgendwie schon recht, eigentlich ist depends genau was ich suche...Ich mach mir darüber mal meine Gedanken und schreib dann hier zu welchem Schluss ich gekommen bin. Danke also vorerst fürs Mitüberlegen :)
 
Z

Zergling

Gast
Also vielen Dank, der Tipp war echt naheliegend, aber deshalb trotzdem nicht weniger genial. Ist zwar kein guter Stil Ant zu mißbrauchen ein anderes Ant-File zu schreiben, aber der Zweck heiligt die Mittel. Also nochmal vielen Dank, Problem ist damit gelöst! :)
 
Z

Zergling

Gast
Edit: Vielleicht kann jemand das Problem abhaken, ich finde hier keine solche Option, bin aber auch kein registrierter User.
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Oben