2011-02-26 13 views
6

Trabajo en un grupo donde producimos muchas aplicaciones pequeñas y utilizamos ANT para nuestros procesos de compilación.¿Cuáles son algunas buenas formas de distribuir un archivo común de hormigas para incluir en compilaciones?

Nos gustaría que algunas de nuestras directivas de uso común se alojen de manera común. Actualmente, se requiere una unidad asignada a una ubicación común, y usamos

<import file="${env.MAPPED_DRIVE}/common_directive.xml"> 

Tiene que haber una mejor manera de distribuir un archivo hormiga común incluir en muchos proyectos sin tener que asignar una unidad. ¿Tiene alguna otra sugerencia?

La importación es una directiva de "nivel superior", lo que significa que no funcionará dentro de un objetivo. Por lo tanto, no puedo simplemente crear un objetivo que descargue el archivo y luego importarlo.

Respuesta

4

Si está usando ANT 1.8+, you could specify a URL y aloja el fragmento de compilación común en un sitio web.

Desde 1.8.0 Ant la tarea también puede recursos de importación de direcciones URL o recursos de ruta de clases (que son las direcciones URL, realmente). Si necesita saber si el origen del archivo de compilación actual tiene ha sido un archivo o una URL, puede consultar la propiedad ant.file.type.projectname (utilizando el mismo ejemplo que el anterior ant.file.type.builddocs) que tienen el valor "archivo" o "url".

+0

¡Muchas gracias! Estaba buscando en la tarea incorrecta. No es de extrañar que no pudiera encontrarlo. Algunos enlaces a ejemplos también serían de gran ayuda: siéntete libre si tienes algunos buenos. – nrobey

+4

Esta es una mala idea si quieres compilaciones repetibles. –

+0

@Dominic Mitchell - Buen punto. Si common_directive.xml no es estático, sería mejor administrar esa dependencia un poco mejor. –

1

Dominic Mitchell 's comentario sobre la referencia URL ser una mala idea si quieres repetible construye me hizo pensar ...

Otra solución para considerar, si está utilizando SVN para el control de versiones, es crea un SVN Externals Definition que apunta al common_directive.xml.

Luego, solo use una ruta relativa para su referencia de archivo de importación ANT.

A veces es útil construir una copia de trabajo que está hecho de un número de diferentes cajas. Para ejemplo, puede desear que diferentes subdirectorios provengan de diferentes ubicaciones en un repositorio o quizás de diferentes repositorios en total. Sin duda, puede configurar tal escenario usando manualmente svn checkout para crear el tipo de estructura de copia de trabajo anidada que está intentando lograr. Pero si este diseño es importante para todos los que usan su repositorio , todos los demás usuarios necesitarán para realizar las mismas operaciones de verificación que usted realizó.

Afortunadamente, Subversion proporciona compatibilidad con para las definiciones externas. Un definición externa es una asignación de un directorio local a la URL-e, idealmente, una revisión particular de un directorio versionado . En Subversion, declara definiciones externas en grupos usando la propiedad svn:externals. Puede crear o modificar esta propiedad usando svn propset o svn propedit (consulte la sección llamada "Manipulating Properties"). Se puede establecer en cualquier directorio versionado , y su valor describe tanto la ubicación del repositorio externo como el directorio del lado del cliente al que debe estar desprotegida esa ubicación .

La conveniencia de la propiedad svn:externals es que una vez que se encuentra en una directorio versionado, todos los que obtiene una copia de trabajo con ese directorio también obtiene el beneficio de la definición lo externo. En otras palabras, una vez que una persona ha hecho el esfuerzo de definen la estructura copia de trabajo anidada, nadie más tiene que molestar-Subversion, después de comprobar a cabo la copia de trabajo original, automáticamente también echa un vistazo a la copias externas de trabajo.

+0

Me encanta su sugerencia, y yo mismo lo he sugerido. Desafortunadamente, debido a pasado svn: abuso externo, el departamento está "quemado" con este método y tiene una aversión irracional hacia él. Lo intentaré de nuevo, sin embargo, porque lo sugirió. ¡Gracias! – nrobey

+1

@nrobey: si su equipo se preocupa por la repetibilidad y la confiabilidad de las compilaciones, parece como si SVN externos fuera mejor que usar un disco mapeado. La propiedad Externals está bajo control de versión, y si está apuntando a una ubicación SVN para la ruta de compilación común, ese contenido también está bajo control de versión. Puede señalar una etiqueta particular para el repositorio de compilación común. –

+1

Si le importan las compilaciones repetibles, entonces usar svn: external suele ser malo. Más a menudo que no svn: external se usa sin una revisión (AKA sin fijar), lo que significa que no sabrá qué revisión se utilizó para una compilación en particular. Puede tener una política que requiera que se especifique la revisión, pero es difícil de aplicar y, por lo demás, es difícil de mantener. –

2

he trabajado a cabo una solución que crea un archivo JAR que contiene los scripts de construcción reutilizables en un directorio, por ejemplo com/example/ant/sharedbuild, que puede ser importado en Ant 1.8:

<project> 
    <import> 
     <javaresource name="com/example/ant/sharedbuild/java.xml"> 
      <classpath location="../../../../target/ant-shared-build.jar" /> 
     </javaresource> 
    </import> 
</project> 

En mi caso, esto define todos los objetivos "públicos" para que el proyecto realice una compilación basada en Java.

La sintaxis es un poco prolija, especialmente a medida que agrego más y más archivos de inclusión (por ejemplo, para agregar la capacidad de crear un archivo OSGi). Al agregar un antlib.xml que contiene una combinación de un macrodef y scriptdef al archivo jar (en el mismo directorio que los scripts compilados), el archivo de compilación ahora puede verse así (y ahora también crea un paquete OSGi jar):

<project xmlns:build="antlib:com.example.ant.sharedbuild"> 
    <taskdef uri="antlib:com.example.ant.sharedbuild" 
      classpath="../../../../target/ant-shared-build.jar" /> 
    <build:build using="java, jar, bundle" /> 
</project> 

por desgracia, no puedo compartir el código en el macrodef o scriptdef, pero en realidad no es difícil: un poco de javascript para analizar el uso de atributos y lazo sobre cada uno, derivar un nombre de archivo de la misma, e importar

Hago referencia al archivo jar en una ubicación fija (relativa a mi proyecto) en mi disco duro. Pienso que podemos hacerlo mejor. Idealmente, me gustaría obtener un archivo jar (¡versionado!) Desde una ubicación central. Puesto que ya estamos usando Ivy (con un repositorio de HTTP) podemos publicar el archivo jar allí (de nuevo, con una versión) y recogerla directamente desde allí:

<project xmlns:build="antlib:com.example.ant.sharedbuild"> 
    <property name="ant.shared.build.jar.file" 
       location="${user.home}/ant/ant-shared-build-1.5.3.jar" /> 
    <get src="http://repo.example.com/.../ant-shared-build-1.5.3.jar" 
     dest="${ant.shared.build.jar.file}" 
     skipexisting="true" /> 
    <taskdef uri="antlib:com.example.ant.sharedbuild" 
      classpath="${ant.shared.build.jar.file}" /> 
    <build:build using="java, jar, bundle" /> 
</project> 

Hay algunos problemas con esto:

  1. Se vuelve detallado de nuevo.
  2. La verbosidad se repite para cada build.xml.
  3. Hay una gran repetición repetitiva, especialmente el número de versión.

Para mitigar estos problemas, en cada directorio que contiene un build.xml también tengo un bootstrap.xml (el nombre en realidad no importa). Cada construcción.xml continuación incluye este archivo:

<project xmlns:build="antlib:com.example.ant.sharedbuild"> 
    <include file="bootstrap.xml" /> 
    <build:build using="java, jar, bundle" /> 
</project> 

Cada bootstrap.xml, como mínimo, incluye que es bootstrap.xml de los padres:

<project> 
    <include file="../bootstrap.xml" /> 
</project> 

El bootstrap.xml de nivel superior (la raíz), luego hace el trabajo de conseguir el archivo jar y la creación de las tareas personalizadas, como el anterior:

<project> 
    <property name="ant.shared.build.version" 
       value="1.5.3" /> 
    <property name="ant.shared.build.jar.filename" 
       value="ant-shared-build-${ant.shared.build.version}.jar" /> 
    <property name="ant.shared.build.jar.file" 
       location="${user.home}/ant/${ant.shared.build.jar.filename}" /> 
    <get src="http://repo.example.com/.../${ant.shared.build.jar.filename}" 
     dest="${ant.shared.build.jar.file}" 
     skipexisting="true" /> 
    <taskdef uri="antlib:com.example.ant.sharedbuild" 
      classpath="${ant.shared.build.jar.file}" /> 
</project> 

Aunque no directamente relacionado con la cuestión, en realidad estoy reelaboración del macrodef y scriptdef en una tarea personalizada hormiga, porque quiero ser capaz de soportar una sintaxis que tiene este aspecto:

<project xmlns:build="antlib:com.example.ant.sharedbuild"> 
    <include file="bootstrap.xml" /> 
    <build:build> 
     <using> 
      <java /> 
      <bundle> 
       <manifest> 
        Import-Package: *,org.joda.time;version="[1.6.0,1.6.0]" 
        Bundle-Activator: com.example.time.impl.Activator 
       </manifest> 
      </bundle> 
     </using> 
    </build:build> 
</project> 

Debo señalar que sólo la creación de una acumulación redistribuible no significa que va a ser útil. Todavía necesita dedicar el tiempo y el esfuerzo para crear una implementación cohesiva, modular y consistente en línea con un diseño de características similares. Esto es más importante ya que necesita compartir scripts en proyectos, equipos, fronteras organizacionales, etc.

En conclusión, al crear un archivo jar con un número de versión que se puede distribuir independientemente de la ubicación de un archivo específico o una herramienta SCM podemos obtener compilaciones reales pero reproducibles.

+0

+1 por tiempo, verbosidad, amabilidad. ¡Ojalá más gente respondiera así! ¡Gracias! – nrobey

+0

¿Hay alguna razón en particular para usar 'get' en lugar de' ivy: retrieve'? –

+0

@Tom: la compilación compartida es lo que bootstraps Ivy, por lo que tratar de usar Ivy para obtener lo que obtiene Ivy deformará totalmente tu cerebro en lógica circular. –

Cuestiones relacionadas