InglésFrancésEspañol

Ad


icono de página de OnWorks

contras - Online en la nube

Ejecute contras en el proveedor de alojamiento gratuito de OnWorks sobre Ubuntu Online, Fedora Online, emulador en línea de Windows o emulador en línea de MAC OS

Estas son las desventajas de los comandos que se pueden ejecutar en el proveedor de alojamiento gratuito de OnWorks utilizando una de nuestras múltiples estaciones de trabajo en línea gratuitas, como Ubuntu Online, Fedora Online, emulador en línea de Windows o emulador en línea de MAC OS.

PROGRAMA:

NOMBRE


Contras: un sistema de construcción de software

DESCRIPCIÓN


Una guía y referencia para la versión 2.2.0

Copyright (c) 1996-2000 Fundación de Software Libre, Inc.

Este programa es software gratuito; puedes redistribuirlo y / o modificarlo bajo los términos de
la Licencia Pública General GNU publicada por la Free Software Foundation; cualquiera
versión 2 de la Licencia, o (a su elección) cualquier versión posterior.

Este programa se distribuye con la esperanza de que sea útil, pero SIN NINGUNA GARANTÍA;
incluso sin la garantía implícita de COMERCIABILIDAD o APTITUD PARA UN PROPÓSITO PARTICULAR.
Consulte la Licencia pública general GNU para obtener más detalles.

Debería haber recibido una copia de la Licencia Pública General GNU junto con este programa;
ver el archivo COPIA. Si no es así, escriba a Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, EE. UU.

Introducción


Desventajas es un sistema para construir, principalmente, software, pero es bastante diferente de
sistemas de construcción de software anteriores. Contras fue diseñado desde cero para tratar
fácilmente con la construcción de software distribuido en múltiples directorios de origen. Contras
facilita la creación de scripts de compilación que sean simples, comprensibles y fáciles de mantener.
Contras garantiza que el software complejo se pueda reproducir de forma fácil y precisa.

Cons usa una serie de técnicas para lograr todo esto. Los guiones de construcción son solo
Scripts en Perl, haciéndolos fáciles de comprender y muy flexibles. Alcance global de
Las variables se reemplazan con un mecanismo de importación / exportación para compartir información entre
scripts, mejorando significativamente la legibilidad y mantenibilidad de cada script.
Construcción ambientes se introducen: estos son objetos Perl que capturan la
información necesaria para controlar el proceso de construcción. Se utilizan varios entornos
cuando se requiere una semántica diferente para generar productos en el árbol de construcción. Contras
implementa el análisis de dependencia automático y lo utiliza para secuenciar globalmente todo el
construir. Las compilaciones variantes se producen fácilmente a partir de un único árbol de origen. Construcción inteligente
el subconjunto es posible, cuando se trabaja en cambios localizados. Las anulaciones se pueden configurar para
anula fácilmente las instrucciones de compilación sin modificar ningún script. Criptográfico MD5
firmas están asociados con archivos derivados y se utilizan para determinar con precisión si
un archivo determinado necesita ser reconstruido.

Si bien ofrece todo lo anterior y más, Cons sigue siendo simple y fácil de usar. Esta voluntad,
con suerte, se aclarará al leer el resto de este documento.

¿Por qué ¿Contras? ¿Por qué no ¿Hacer?


Contras es un para lograr reemplazo. En los siguientes párrafos, analizamos algunos de los
características indeseables de la marca, y entornos de construcción típicos basados ​​en la marca, que
motivó el desarrollo de Cons.

Construcción complejidad

Los sistemas tradicionales basados ​​en marcas de cualquier tamaño tienden a volverse bastante complejos. La marca original
la utilidad y sus derivados han contribuido a esta tendencia de varias formas. Hacer es
no es bueno para tratar con sistemas que se distribuyen en varios directorios. Varios trabajos
se utilizan rodeos para superar esta dificultad; la elección habitual es hacer invocar
a sí mismo de forma recursiva para cada subdirectorio de una compilación. Esto conduce a un código complicado, en
que a menudo no está claro cómo se establece una variable, o qué efecto tiene la configuración de una variable
tendrá en la construcción como un todo. El lenguaje de creación de secuencias de comandos se ha ampliado gradualmente.
para proporcionar más posibilidades, pero estas han servido en gran medida para abarrotar un ya
Lenguaje sobre extendido. A menudo, las compilaciones se realizan en varias pasadas para proporcionar
productos apropiados de un directorio a otro directorio. Esto representa una
aumento de la complejidad de la construcción.

Construcción reproducibilidad

La pesadilla de todas las marcas siempre ha sido el correcto manejo de las dependencias. Muy a menudo, un
se intenta hacer un trabajo razonable de dependencias dentro de un solo directorio, pero no
Se hace un intento serio de hacer el trabajo entre directorios. Incluso cuando las dependencias son
funcionando correctamente, la marca se basa en una simple comparación de marcas de tiempo para determinar si
un expediente que está desactualizado con respecto a sus dependientes no es, en general, adecuado para
determinar cuándo se debe volver a derivar un archivo. Si una biblioteca externa, por ejemplo, es
reconstruido y luego `` encajado '' en su lugar, las marcas de tiempo en sus archivos recién creados pueden
Será anterior a la última construcción local, ya que se construyó antes de que se hiciera visible.

Variante construye

Make proporciona solo instalaciones limitadas para manejar versiones variantes. Con la proliferación
de las plataformas de hardware y la necesidad de un código depurable frente a un código optimizado, la capacidad de
Crear fácilmente estas variantes es fundamental. Más importante aún, si se crean variantes,
es importante para poder separar las variantes o para poder reproducir el
original o variante a voluntad. Con make es muy difícil separar las construcciones en
múltiples directorios de compilación, separados de la fuente. Y si no se usa esta técnica,
También es prácticamente imposible garantizar en un momento dado qué variante está presente en
el árbol, sin recurrir a una reconstrucción completa.

Repositorios

Make proporciona solo soporte limitado para la creación de software a partir del código que existe en un
estructura de directorio del repositorio central. La característica VPATH de GNU make (y algunas otras
hacer implementaciones) está destinado a proporcionar esto, pero no funciona como se esperaba:
cambia la ruta del archivo de destino al nombre VPATH demasiado pronto en su análisis y, por lo tanto,
busca todas las dependencias en el directorio VPATH. Para asegurar un correcto desarrollo
compilaciones, es importante poder crear un archivo en un directorio de compilación local y tener
cualquier archivo en un repositorio de código (un directorio VPATH, en términos de make) que dependa del local
el archivo se reconstruye correctamente. Esto no es posible con VPATH, sin codificar mucho
conocimiento complejo del repositorio directamente en los archivos MAKE.

Acuerdo it simples


Algunas de las dificultades con make se han citado anteriormente. En este y posteriores
secciones, presentaremos Contras y mostraremos cómo se abordan estos problemas.

Perl guiones

Cons está basado en Perl. Es decir, guiones de Cons ...Reclutar y Construcción archivos, el equivalente
a Makefile or makefile--están todos escritos en Perl. Esto proporciona un beneficio inmediato: la
El lenguaje para escribir guiones es familiar. Incluso si no eres un Perl
programador, es útil saber que Perl es básicamente un simple lenguaje declarativo,
con un flujo de control bien definido y una semántica familiar. Tiene variables que se comportan
básicamente de la forma en que esperaría que lo hicieran, subrutinas, flujo de control, etc. Allí
no se ha introducido una sintaxis especial para Cons. El uso de Perl como lenguaje de programación
simplifica la tarea de expresar la solución adecuada a los a menudo complejos
requisitos de una construcción.

Hola, ¡Mundo!

Para fundamentar la siguiente discusión, así es como podría construir el Hola, ¡Mundo! C
aplicación con Contras:

$ env = new cons ();
Programa $ env 'hola', 'hola.c';

Si instala este script en un directorio, nombrar el script Construccióny crea el
Hola C archivo de origen en el mismo directorio, luego puede escribir `cons hello 'para construir el
solicitud:

% contras hola
cc -c hola.c -o hola.o
cc -o hola hola. o

Construcción ambientes

Una simplificación clave de Contras es la idea de un construcción entorno. Una construccion
el medio ambiente es un objeto caracterizado por un conjunto de pares clave / valor y un conjunto de métodos.
Para decirle a Cons cómo construir algo, invoca el método apropiado a través de un
Entorno de construcción apropiado. Considere el siguiente ejemplo:

$ env = nuevos contras (
CC => 'gcc',
LIBS => 'libworld.a'
);

Programa $ env 'hola', 'hola.c';

En este caso, en lugar de utilizar el entorno de construcción predeterminado, como está, tenemos
anulado el valor de `CC 'para que se use el equivalente del compilador GNU C, en su lugar. Ya que
esta versión de Hola, ¡Mundo! requiere una biblioteca, libworld.a, hemos especificado que cualquier
El programa vinculado en este entorno debe estar vinculado con esa biblioteca. Si la biblioteca
ya existe, muy bien, pero si no, también tendremos que incluir la declaración:

Biblioteca $ env 'libworld', 'world.c';

Ahora, si escribe 'cons hello', la biblioteca se creará antes de que el programa esté vinculado y,
por supuesto, se usará `gcc 'para compilar ambos módulos:

% contras hola
gcc -c hola.c -o hola.o
gcc -c mundo.c -o mundo.o
ar r libworld.un mundo.o
ar: creando libworld.a
ranlib libworld.a
gcc -o hola hola.o libworld.a

Automático y completar dependencia análisis

Con Cons, las dependencias se manejan automáticamente. Continuando con el ejemplo anterior, tenga en cuenta
que cuando modificamos mundo.c, mundo.o se vuelve a compilar, libworld.a recreado, y ¡Hola
vuelto a vincular:

% vi mundo.c
[EDITAR]
% contras hola
gcc -c mundo.c -o mundo.o
ar r libworld.un mundo.o
ar: creando libworld.a
ranlib libworld.a
gcc -o hola hola.o libworld.a

Este es un ejemplo relativamente simple: Cons `` sabe '' mundo.o depende de mundo.c, porque
la dependencia se establece explícitamente mediante el método "Biblioteca". También sabe que libworld.a
depende de mundo.o y que ¡Hola depende de libworld.a, todo por razones similares.

Ahora resulta que Hola C también incluye el archivo de definición de interfaz, mundo.h:

% emacs mundo.h
[EDITAR]
% contras hola
gcc -c hola.c -o hola.o
gcc -o hola hola.o libworld.a

¿Cómo sabe Cons eso Hola C incluye mundo.h, Y que hola o por lo tanto debe ser
recompilado? Por ahora, basta con decir que al considerar si hola o depende-
Hasta la fecha, Cons invoca un escáner para su dependencia, Hola C. Este escáner enumera los
archivos incluidos por Hola C para elaborar una lista de dependencias adicionales, más allá de las
hecho explícito por el script Cons. Este proceso es recursivo: cualquier archivo incluido por
también se analizarán los archivos incluidos.

¿No es esto caro? La respuesta es, depende. Si crea una compilación completa de un sistema grande,
el tiempo de escaneo es insignificante. Si realiza una reconstrucción de un sistema grande, Cons
Dedique bastante tiempo a pensar en ello antes de decidir que nada tiene que ser
hecho (¡aunque no necesariamente más tiempo del que hace!). La buena noticia es que Cons lo hace
Es muy fácil crear subconjuntos de forma inteligente en su compilación, cuando está trabajando en cambios localizados.

Automático global build secuenciación

Porque Cons realiza un análisis de dependencia completo y preciso, y lo hace a nivel mundial, para el
compilación completa, Cons puede utilizar esta información para tomar el control total de la secuenciación
de la construcción. Esta secuenciación es evidente en los ejemplos anteriores, y es equivalente a lo que
que esperaría hacer, dado un conjunto completo de dependencias. Con Contras, esto se extiende
trivialmente a compilaciones más grandes de varios directorios. Como resultado, toda la complejidad involucrada
para asegurarse de que una compilación esté organizada correctamente, incluida la jerarquización de múltiples pasadas
construye - se elimina. Discutiremos esto más a fondo en las próximas secciones.

Construir la large árboles - todavía solo as simples


A jerarquía of build guiones

Una construcción más grande, en Contras, se organiza creando una jerarquía de build guiones. En la cima
del árbol hay un guión llamado Construcción. El resto de los guiones, por convención, son cada uno
, que son Reclutar. Estos scripts están conectados entre sí, de manera muy simple, por el 'Build',
Comandos 'Exportar' e 'Importar'.

El Construcción comando

El comando 'Construir' toma una lista de Reclutar nombres de archivo, y los arregla para que sean
incluido en la construcción. Por ejemplo:

Construir qw (
conductores / pantalla / recluta
drivers / mouse / Conscript
analizador / recluta
servicios públicos / recluta
);

Esta es una jerarquía simple de dos niveles de scripts de compilación: todas las Reclutar archivos
se mencionan en el nivel superior Construcción expediente. Tenga en cuenta que no todos los directorios del árbol
necesariamente tienen scripts de construcción asociados con ellos.

Esto también podría escribirse como un script de varios niveles. Por ejemplo, el Construcción archivo podría
contener este comando:

Construir qw (
analizador / recluta
conductores / recluta
servicios públicos / recluta
);

y del Reclutar presentar en el conductores El directorio puede contener esto:

Construir qw (
exhibición / recluta
ratón / recluta
);

La experiencia ha demostrado que el modelo anterior es un poco más fácil de entender, ya que
Todo el árbol de construcción se coloca frente a usted, en el nivel superior. Los esquemas híbridos son
también es posible. Un componente mantenido por separado que necesita ser incorporado en un
el árbol de construcción, por ejemplo, podría engancharse al árbol de construcción en un lugar, pero definir su propio
jerarquía de construcción.

Por defecto, Cons no cambia su directorio de trabajo al directorio que contiene un
filial Reclutar archivo que incluye. Este comportamiento se puede habilitar para una compilación mediante
especificando, en el nivel superior Construcción archivo:

Conscript_chdir 1;

Cuando está habilitado, Cons cambiará a la subsidiaria Reclutar directorio que contiene el archivo
mientras lee ese archivo, y luego vuelva al directorio de nivel superior una vez que el archivo
ha sido procesado.

Se espera que este comportamiento se convierta en el predeterminado en alguna versión futura de Cons.
Para prepararse para esta transición, compilaciones que esperan que los Contras permanezcan en la parte superior de la compilación
mientras lee en una subsidiaria Reclutar archivo debe deshabilitar explícitamente esta función como
manera:

Conscript_chdir 0;

Relativo, pariente superior, y fotometría absoluta) presentar nombres

Es posible que haya notado que los nombres de archivo especificados en el comando Compilar son relativos a
la ubicación del script desde el que se invoca. Esto es generalmente cierto para otro nombre de archivo.
argumentos a otros comandos, aunque también podríamos mencionar aquí que si comienza
un nombre de archivo con una marca de almohadilla, `` # '', entonces ese archivo se interpreta en relación con la parte superior
directorio de nivel (donde el Construcción archivo reside). Y, como es lógico, si lo empiezas
con `` / '', entonces se considera un nombre de ruta absoluto. Esto es cierto incluso en sistemas
que utilizan una barra invertida en lugar de una barra inclinada para nombrar rutas absolutas.

Usar módulos in build guiones

Puede colocar módulos en cada Reclutar archivo usando el Perl normal `use 'o` require'
declaraciones:

usa el inglés;
require My :: Module;

Cada "uso" o "requerimiento" solo afecta al Reclutar archivo en el que aparece. Para usar un
módulo en múltiples Reclutar archivos, debe poner una declaración 'use' o 'require' en cada
uno que necesita el módulo.

Lo que hacemos of las variables

El nivel superior Construcción archivo y todo Reclutar los archivos comienzan su vida en un Perl común e independiente
paquete. Desventajas controla la tabla de símbolos para el paquete de modo que, la tabla de símbolos para
cada script está vacío, excepto por el Construcción archivo, que obtiene parte de la línea de comando
argumentos. Todas las variables que se establecen o se utilizan, por lo tanto, las establece el script
en sí mismo, no por algún script externo.

Las variables pueden ser explícitamente importado por un script de su script padre. Para importar un
variable, debe haber sido exportado por el padre e inicializado (de lo contrario, un error
ocurrira).

El Exportar comando

El comando 'Exportar' se utiliza como en el siguiente ejemplo:

$ env = new cons ();
$ INCLUDE = "# exportar / incluir";
$ LIB = "# export / lib";
Exportar qw (env INCLUDE LIB);
Construir qw (util / Conscript);

Los valores de las variables simples mencionadas en la lista "Exportar" se eliminarán
por cualquier comando posterior de 'Construir'. El comando 'Exportar' solo exportará Perl escalar
variables, es decir, variables cuyo nombre comienza con '$'. Otras variables, objetos, etc.
se puede exportar por referencia, pero todos los scripts se referirán al mismo objeto, y esto
El objeto debe ser considerado de solo lectura por los scripts subsidiarios y por el original.
exportar script. Sin embargo, es aceptable asignar un nuevo valor al escalar exportado.
variable: eso no cambiará la variable subyacente a la que se hace referencia. Esta secuencia, por
ejemplo, está bien:

$ env = new cons ();
Exportar qw (env INCLUDE LIB);
Construir qw (util / Conscript);
$ env = nuevos contras (CFLAGS => '-O');
Construir qw (otro / Conscript);

No importa si la variable se establece antes o después del comando "Exportar". los
Lo importante es el valor de la variable en el momento en que se ejecuta el comando "Build".
Esto es lo que se esconde. Cualquier comando de 'Exportar' subsiguiente, por cierto,
invalidar el primero: debe mencionar todas las variables que desea exportar en cada
Comando 'Exportar'.

El Importa comando

Las variables exportadas por el comando `Exportar 'pueden ser importadas en scripts subsidiarios por el
Comando 'Importar'. El script subsidiario siempre importa variables directamente desde el
guión superior. Considere este ejemplo:

Importar qw (env INCLUDE);

Esto solo es legal si el script padre exportó tanto '$ env' como '$ INCLUDE'. También debe
han dado valores a cada una de estas variables. Está bien que el script subsidiario solo
importar un subconjunto de las variables exportadas (en este ejemplo, '$ LIB', que fue exportado por
el ejemplo anterior, no se importa).

Todas las variables importadas se reexportan automáticamente, por lo que la secuencia:

Importar qw (env INCLUDE);
Construir qw (debajo de mí / Recluta);

proporcionará tanto '$ env' como '$ INCLUDE' al archivo subsidiario. Si solo '$ env' va a ser
exportado, entonces lo siguiente será suficiente:

Importar qw (env INCLUDE);
Exportar qw (env);
Construir qw (debajo de mí / Recluta);

No hace falta decir que las variables pueden modificarse localmente antes de invocar 'Build' en el
guión subsidiario.

Construcción guión evaluación solicite

La única restricción en el orden de los scripts de compilación es que los scripts superiores son
evaluados antes que sus guiones inferiores. El nivel superior Construcción archivo, por ejemplo, es
evaluado primero, seguido de cualquier guión inferior. Esto es todo lo que realmente necesitas saber
sobre el orden de evaluación, ya que el orden es generalmente irrelevante. Considera lo siguiente
Comando 'Construir':

Construir qw (
conductores / pantalla / recluta
drivers / mouse / Conscript
analizador / recluta
servicios públicos / recluta
);

Hemos optado por poner los nombres de los guiones en orden alfabético, simplemente porque es lo más
conveniente para fines de mantenimiento. Cambiar el orden no supondrá ninguna diferencia para el
construir.

A Modelo para compartir archivos


Cosas simples convenciones

En cualquier sistema de software complejo, se debe establecer un método para compartir productos de compilación.
establecido. Proponemos un conjunto simple de convenciones que son triviales de implementar con
Contras, pero muy eficaz.

La regla básica es exigir que todos los productos de construcción que necesitan ser compartidos entre
los directorios se comparten a través de un directorio intermedio. Normalmente hemos llamado a esto
exportar, y, en un entorno C, proporcionó subdirectorios convencionales de este directorio,
como incluir, lib, papelera, etc.

Estos directorios están definidos por el nivel superior Construcción expediente. Un simple Construcción se declara en
a Hola, ¡Mundo! La aplicación, organizada en varios directorios, podría tener este aspecto:

# Construir archivo para Hello, World!

# Dónde poner todos nuestros productos compartidos.
$ EXPORTAR = '#exportar';

Exportar qw (CONS INCLUYE LIB BIN);

# Directorios estándar para compartir productos.
$ INCLUDE = "$ EXPORTAR / incluir";
$ LIB = "$ EXPORTAR / lib";
$ BIN = "$ EXPORTAR / contenedor";

# Un entorno de construcción estándar.
$ CONTRAS = nuevas contras (
CPPPATH => $ INCLUDE, # Incluir ruta para compilaciones C
LIBPATH => $ LIB, # Ruta de la biblioteca para vincular programas
LIBS => '-lworld', # Lista de bibliotecas estándar
);

Construir qw (
hola / recluta
mundo / Recluta
);

El mundo directorio Reclutar archivo tiene este aspecto:

# Archivo de reclutamiento para el mundo de directorios
Importar qw (CONS INCLUYE LIB);

# Instalar los productos de este directorio
Instale $ CONS $ LIB, 'libworld.a';
Instale $ CONS $ INCLUDE, 'world.h';

# Productos internos
Biblioteca $ CONS 'libworld.a', 'world.c';

y del ¡Hola directorio Reclutar archivo tiene este aspecto:

# Archivo de reclutamiento para el directorio hola
Importar qw (CONS BIN);

# Productos exportados
Instale $ CONS $ BIN, 'hola';

# Productos internos
Programa $ CONS 'hola', 'hola.c';

Para construir un Hola, ¡Mundo! programa con esta estructura de directorio, vaya al nivel superior
directorio e invocar `cons 'con los argumentos apropiados. En el siguiente ejemplo,
dile a Cons que construya el directorio exportar. Para construir un directorio, Cons construye de forma recursiva todos
productos conocidos dentro de ese directorio (solo si necesitan reconstruirse, por supuesto). Si alguno de
esos productos dependen de otros productos en otros directorios, luego se crearán,


% contras de exportación
Instale world / world.h como export / include / world.h
cc -Iexportar / incluir -c hola / hola.c -o hola / hola.o
cc -Iexportar / incluir -c mundo / mundo.c -o mundo / mundo.o
ar r world / libworld.a world / world.o
ar: creando mundo / libworld.a
ranlib world / libworld.a
Instale world / libworld.a como export / lib / libworld.a
cc -o hola / hola hola / hola.o -Lexport / lib -lworld
Instale hello / hello como export / bin / hello

Limpio, comprensible, independiente de la ubicación guiones

Notarás que los dos Reclutar los archivos son muy limpios y van al grano. Ellos simplemente
especificar productos del directorio y cómo construir esos productos. Las instrucciones de construcción
son mínimos: especifican qué entorno de construcción utilizar, el nombre del producto,
y el nombre de las entradas. Tenga en cuenta también que los scripts son independientes de la ubicación: si
desea reorganizar su árbol de fuentes, puede hacerlo: solo tiene que cambiar el
Construcción archivo (en este ejemplo), para especificar las nuevas ubicaciones de la Reclutar archivos. los
el uso de un árbol de exportación facilita este objetivo.

Tenga en cuenta también cómo Cons se ocupa de los pequeños detalles por usted. Todos exportar directorios, para
ejemplo, se hicieron automáticamente. Y los archivos instalados estaban realmente vinculados a la
respectivos directorios de exportación, para ahorrar espacio y tiempo. Esta atención al detalle ahorra
trabajo considerable, y hace que sea aún más fácil producir scripts simples y fáciles de mantener.

Separar fuente y build árboles


A menudo es deseable mantener los archivos derivados de la compilación completamente separados del
archivos fuente. Esto hace que sea mucho más fácil realizar un seguimiento de lo que es un archivo fuente y
también hace que sea más fácil de manejar variante compilaciones, especialmente si desea que la variante compile
coexistir.

Separar build y fuente directorios usando las Enlace comando

Contras proporciona un mecanismo simple que maneja todos estos requisitos. El 'enlace'
El comando se invoca como en este ejemplo:

Enlace 'build' => 'src';

Los directorios especificados están `` vinculados '' al directorio de origen especificado. Supongamos
que configuras un directorio de origen, src, con los subdirectorios mundo y ¡Hola Por debajo de eso,
como en el ejemplo anterior. A continuación, puede sustituir las líneas de construcción originales por
siguientes:

Construir qw (
construir / mundo / Recluta
construir / hola / reclutar
);

Observe que trata el Reclutar archivo como si existiera en el directorio de compilación. Ahora si
escribe el mismo comando que antes, obtendrá los siguientes resultados:

% contras de exportación
Instale build / world / world.h como export / include / world.h
cc -Iexport / include -c build / hello / hello.c -o build / hello / hello.o
cc -Iexport / include -c build / world / world.c -o build / world / world.o
ar r build / world / libworld.a build / world / world.o
ar: creando build / world / libworld.a
ranlib build / world / libworld.a
Instale build / world / libworld.a como export / lib / libworld.a
cc -o build / hello / hello build / hello / hello.o -Lexport / lib -lworld
Instale build / hello / hello como export / bin / hello

Una vez más, Cons se ha encargado de los detalles por usted. En particular, notará que todos
las compilaciones se realizan utilizando archivos de origen y archivos de objeto del directorio de compilación. Para
ejemplo, build / world / world.o se compila a partir de build / world / world.cy
exportar / incluir / mundo.h se instala desde build / world / world.h. Esto se logra en la mayoría
sistemas por el simple recurso de vincular `` duro '' los archivos requeridos de cada fuente
directorio en el directorio de compilación apropiado.

Cons mantiene los enlaces correctamente, sin importar lo que haga en el directorio de origen.
Si modifica un archivo fuente, su editor puede hacer esto `` en su lugar '' o puede cambiarle el nombre
primero y cree un nuevo archivo. En este último caso, se perderá cualquier vínculo físico. Los contras
detectará esta condición la próxima vez que se necesite el archivo de origen y lo volverá a vincular
apropiadamente.

También notarás, por cierto, que no Se requirieron cambios en el subyacente Reclutar
archivos. Y podemos ir más allá, como veremos en el siguiente apartado.

Variante construye


Hola, ¡Mundo! para Plátano y Durazno sistemas operativos

Las compilaciones variantes solo requieren otra extensión simple. Tomemos como ejemplo un
requisito para permitir compilaciones para los sistemas operativos baNaNa y peAcH. En este caso,
estamos utilizando un sistema de archivos distribuido, como NFS, para acceder al sistema en particular, y
sólo uno u otro de los sistemas tiene que ser compilado para cualquier invocación de
'contras'. Aquí hay una forma en que podríamos configurar el Construcción archivo para nuestro Hola, ¡Mundo!
solicitud:

# Construir archivo para Hello, World!

die qq (se debe especificar el sistema operativo) a menos que $ OS = $ ARG {OS};
die qq (el SO debe ser "melocotón" o "plátano")
si $ OS ne "melocotón" && $ OS ne "plátano";

# Dónde poner todos nuestros productos compartidos.
$ EXPORT = "# export / $ OS";

Exportar qw (CONS INCLUYE LIB BIN);

# Directorios estándar para compartir productos.
$ INCLUDE = "$ EXPORTAR / incluir";
$ LIB = "$ EXPORTAR / lib";
$ BIN = "$ EXPORTAR / contenedor";

# Un entorno de construcción estándar.
$ CONTRAS = nuevas contras (
CPPPATH => $ INCLUDE, # Incluir ruta para compilaciones C
LIBPATH => $ LIB, # Ruta de la biblioteca para vincular programas
LIBS => '-lworld', # Lista de bibliotecas estándar
);

# $ BUILD es donde derivaremos todo.
$ BUILD = "# compilación / $ OS";

# Dile a los contras dónde están los archivos fuente de $ BUILD.
Enlace $ BUILD => 'src';

Construir (
"$ BUILD / hola / Recluta",
"$ BUILD / world / Conscript",
);

Ahora, si iniciamos sesión en un sistema peAcH, podemos construir nuestro Hola, ¡Mundo! aplicación para eso
plataforma:

% cons export OS = melocotón
Instale build / peach / world / world.h como export / peach / include / world.h
cc -Iexport / peach / include -c build / peach / hello / hello.c -o build / peach / hello / hello.o
cc -Iexport / peach / include -c build / peach / world / world.c -o build / peach / world / world.o
ar r build / peach / world / libworld.a build / peach / world / world.o
ar: creando build / peach / world / libworld.a
ranlib build / peach / world / libworld.a
Instale build / peach / world / libworld.a como export / peach / lib / libworld.a
cc -o compilación / melocotón / hola / hola compilación / melocotón / hola / hola.o -Lexport / melocotón / lib -lworld
Instale build / peach / hello / hello como export / peach / bin / hello

Variaciones on a tema

Son posibles otras variaciones de este modelo. Por ejemplo, puede decidir que quiere
para separar sus archivos de inclusión en archivos dependientes de la plataforma e independientes de la plataforma.
En este caso, tendría que definir una alternativa a '$ INCLUDE' para dependientes de la plataforma
archivos. La mayoría Reclutar archivos, generando archivos de inclusión puramente independientes de la plataforma,
no tiene que cambiar.

Es posible que también desee poder compilar todo su sistema con depuración o creación de perfiles,
por ejemplo, habilitado. Puede hacer esto con las opciones de línea de comando adecuadas, como
`DEBUG = activado '. Esto luego se traduciría en la plataforma apropiada específica
requisitos para habilitar la depuración (esto puede incluir desactivar la optimización, para
ejemplo). Opcionalmente, puede variar el espacio de nombres para estos diferentes tipos de sistemas,
pero, como veremos en la siguiente sección, no es esencial para hacer esto, ya que Contras es bastante
inteligente sobre la reconstrucción de cosas cuando cambia las opciones.

Firmas


MD5 criptográfico firmas

Siempre que Cons crea un archivo derivado, almacena un firma para ese archivo. La firma
se almacena en un archivo separado, uno por directorio. Después de compilar el ejemplo anterior,
las .consignar presentar en el construir / melocotón / mundo directorio se veía así:

world.o:834179303 23844c0b102ecdc0b4548d1cd1cbd8c6
libworld.a:834179304 9bf6587fa06ec49d864811a105222c00

El primer número es una marca de tiempo; para un sistema UNIX, este suele ser el número de
segundos desde el 1 de enero de 1970. El segundo valor es una suma de comprobación MD5. los Mensaje Digest
Algoritmo es un algoritmo que, dada una cadena de entrada, calcula un fuerte criptográfico
firma para esa cadena. La suma de comprobación MD5 almacenada en el .consignar archivo es, en efecto, un
resumen de toda la información de dependencia para el archivo especificado. Entonces, por ejemplo, para el
mundo.o archivo, esto incluye al menos el mundo.c archivo, y también cualquier archivo de encabezado que Contras
sabe que están incluidos, directa o indirectamente, por mundo.c. No solo eso, sino el
línea de comando real que se utilizó para generar mundo.o también se alimenta en el cálculo de
la firma. Similar, libworld.a obtiene una firma que `` incluye '' todos los
firmas de sus constituyentes (y, por tanto, transitivamente, las firmas de su
constituyentes), así como la línea de comando que creó el archivo.

La firma de un archivo no derivado se calcula, por defecto, tomando el actual
la hora de modificación del archivo y el nombre de entrada del archivo (a menos que haya un
corriente .consignar entrada para ese archivo, en cuyo caso se utiliza esa firma).

Tenga en cuenta que no es necesario que un archivo derivado dependa de ningún Construcción or
Reclutar archivo: si los cambios en estos archivos afectan al archivo en cuestión, esto será
reflejada automáticamente en su firma, ya que las partes relevantes de la línea de comando son
incluido en la firma. Los cambios no relacionados no tendrán ningún efecto.

Cuando Cons considera si derivar un archivo en particular, primero calcula el
firma esperada del archivo. Luego compara la hora de la última modificación del archivo con
el tiempo registrado en el .consignar entrada, si existe. Si estos tiempos coinciden, entonces el
firma almacenada en el .consignar El archivo se considera exacto. Si el archivo es anterior
la firma no coincide con la nueva firma esperada, entonces el archivo debe ser rederivado.

Tenga en cuenta que un archivo se volverá a derivar siempre que cambie algo sobre un archivo dependiente. En
particular, observe que cualquier cambio a la hora de modificación de un dependiente (reenviar o
hacia atrás en el tiempo) forzará la recompilación del archivo derivado.

El uso de estas firmas es un método extremadamente simple, eficiente y efectivo de
mejorando - dramáticamente - la reproducibilidad de un sistema.

Lo demostraremos con un ejemplo simple:

# Simple "¡Hola, mundo!" Construir archivo
$ CFLAGS = '-g' si $ ARG {DEBUG} eq 'activado';
$ CONTRAS = nuevas desventajas (CFLAGS => $ CFLAGS);
Programa $ CONS 'hola', 'hola.c';

Observe cómo Cons recompila en los momentos adecuados:

% contras hola
cc -c hola.c -o hola.o
cc -o hola hola. o
% contras hola
contras: "hola" está actualizado.
% contra DEBUG = en hola
cc -g -c hola.c -o hola.o
cc -o hola hola. o
% contra DEBUG = en hola
contras: "hola" está actualizado.
% contras hola
cc -c hola.c -o hola.o
cc -o hola hola. o

Código Repositorios


Muchas organizaciones de desarrollo de software tendrán uno o más directorios de repositorios centrales
árboles que contienen el código fuente actual para uno o más proyectos, así como el derivado
archivos de objeto, bibliotecas y ejecutables. Para reducir la recopilación innecesaria,
Es útil usar archivos del repositorio para construir software de desarrollo, asumiendo que
Por supuesto, que no existe ningún archivo de dependencia más nuevo en el árbol de compilación local.

Repositorio

Contras proporciona un mecanismo para especificar una lista de repositorios de código que se buscarán,
en orden, para archivos de origen y archivos derivados que no se encuentran en el árbol del directorio de compilación local.

Las siguientes líneas en un Construcción El archivo indicará a Cons que busque primero debajo del
/ usr / experiment / repository directorio y luego bajo el / usr / product / repository directorio:

Repositorio qw (
/ usr / experiment / repository
/ usr / product / repository
);

Los directorios del repositorio especificados pueden contener archivos fuente, archivos derivados (objetos,
bibliotecas y ejecutables), o ambos. Si no hay un archivo local (fuente o derivado) bajo
el directorio en el que se ejecuta Cons, luego se encuentra la primera copia de un archivo del mismo nombre
bajo un directorio de repositorio se utilizará para construir cualquier archivo derivado local.

Cons mantiene una lista global de directorios de repositorios. Los contras eliminarán el
directorio actual, y cualquier directorio no existente, de la lista.

Encontrar las Construcción presentar in a Repositorio

Los contras también buscarán Construcción y Reclutar archivos en el árbol o árboles del repositorio.
Sin embargo, esto conduce a una situación de la gallina y el huevo: ¿cómo se ve en un árbol de repositorio?
para agendar una Construcción archivo si el Construcción el archivo le dice dónde está el repositorio? Llegar
en torno a esto, los repositorios se pueden especificar a través de las opciones '-R' en la línea de comando:

% cons -R / usr / experiment / repository -R / usr / product / repository.

Cualquier directorio de repositorio especificado en el Construcción or Reclutar los archivos se adjuntarán
a los directorios del repositorio especificados por las opciones de línea de comandos '-R'.

Repositorio fuente archivos

Si el código fuente (incluya el Reclutar archivo) para la versión de biblioteca del Hola,
¡Mundo! La aplicación C está en un repositorio (sin archivos derivados), Cons usará el
archivos de origen del repositorio para crear los archivos de objetos locales y el archivo ejecutable:

% cons -R / usr / src_only / repository hola
gcc -c /usr/src_only/repository/hello.c -o hola.o
gcc -c /usr/src_only/repository/world.c -o mundo.o
ar r libworld.un mundo.o
ar: creando libworld.a
ranlib libworld.a
gcc -o hola hola.o libworld.a

La creación de un archivo de origen local hará que Cons reconstruya el archivo derivado apropiado o
archivos:

% pico mundo.c
[EDITAR]
% cons -R / usr / src_only / repository hola
gcc -c mundo.c -o mundo.o
ar r libworld.un mundo.o
ar: creando libworld.a
ranlib libworld.a
gcc -o hola hola.o libworld.a

Y eliminar el archivo de origen local hará que Cons vuelva a construir el derivado
archivos de la fuente del repositorio:

% rm mundo.c
% cons -R / usr / src_only / repository hola
gcc -c /usr/src_only/repository/world.c -o mundo.o
ar r libworld.un mundo.o
ar: creando libworld.a
ranlib libworld.a
gcc -o hola hola.o libworld.a

Repositorio derivado archivos

Si un árbol de repositorio contiene archivos derivados (generalmente archivos de objetos, bibliotecas o
ejecutables), Cons realizará su cálculo de firma normal para decidir si el
El archivo del repositorio está actualizado o se debe crear un archivo derivado localmente. Esto significa que,
Para garantizar el cálculo correcto de la firma, un árbol de repositorio también debe contener la
.consignar archivos que fueron creados por Cons al generar los archivos derivados.

Esto generalmente se lograría compilando el software en el repositorio (o,
alternativamente, en un directorio de compilación y luego copiando el resultado en el repositorio):

% cd / usr / all / repository
% contras hola
gcc -c hola.c -o hola.o
gcc -c mundo.c -o mundo.o
ar r libworld.un mundo.o
ar: creando libworld.a
ranlib libworld.a
gcc -o hola hola.o libworld.a

(Esto es seguro incluso si el Construcción archivo enumera el / usr / all / repository directorio en un
Comando `Repository 'porque Cons eliminará el directorio actual del repositorio
lista.)

Ahora si queremos construir una copia de la aplicación con nuestra propia Hola C archivo, solo necesitamos
para crear el único archivo fuente necesario, y use la opción '-R' para que Contras use otros
archivos del repositorio:

% mkdir $ HOME / build1
% cd $ HOME / build1
% ed hola.c
[EDITAR]
% contras -R / usr / all / repository hola
gcc -c hola.c -o hola.o
gcc -o hola hola.o /usr/all/repository/libworld.a

Tenga en cuenta que Cons no se ha molestado en recrear un local libworld.a biblioteca (o recompilar la
mundo.o módulo), pero en su lugar utiliza la versión ya compilada del repositorio.

Porque las firmas MD5 que Cons pone en el .consignar El archivo contiene marcas de tiempo para el
archivos derivados, las marcas de tiempo de la firma deben coincidir con las marcas de tiempo del archivo para que una firma
ser considerado válido.

Algunos sistemas de software pueden alterar las marcas de tiempo en los archivos del repositorio (copiándolos,
ej.), en cuyo caso Cons asumirá, de forma predeterminada, que las firmas del repositorio no son válidas
y reconstruir archivos innecesariamente. Este comportamiento puede modificarse especificando:

Repositorio_Sig_Times_OK 0;

Esto le dice a Cons que ignore las marcas de tiempo al decidir si una firma es válida. (Nota
que evitar esta comprobación de cordura significa que debe haber un control adecuado sobre el repositorio
árbol para garantizar que los archivos derivados no se puedan modificar sin actualizar el .consignar
firma.)

Al Cliente copias of archivos

Si el árbol del repositorio contiene los resultados completos de una compilación, y tratamos de compilar a partir de
el repositorio sin ningún archivo en nuestro árbol local, algo moderadamente sorprendente
sucede:

% mkdir $ HOME / build2
% cd $ HOME / build2
% contras -R / usr / all / repository hola
contras: "hola" está actualizado.

¿Por qué Cons dice que el ¡Hola El programa está actualizado cuando no hay ¡Hola programa en
el directorio de compilación local? Debido a que el repositorio (no el directorio local) contiene el
hasta a la fecha ¡Hola programa, y ​​Contras determina correctamente que no es necesario hacer nada para
reconstruya esta copia actualizada del archivo.

Sin embargo, hay muchas ocasiones en las que es apropiado asegurarse de que una copia local de un
el archivo siempre existe. Un script de empaquetado o prueba, por ejemplo, puede suponer que ciertos
los archivos generados existen localmente. En lugar de hacer que estos guiones subsidiarios conozcan la
directorio del repositorio, el comando `Local 'se puede agregar a un Construcción or Reclutar presentar a la
especificar que un determinado archivo o archivos deben aparecer en el directorio de compilación local:

Qw local (
¡Hola
);

Luego, si volvemos a ejecutar el mismo comando, Cons hará una copia local del programa desde el
copia del repositorio (indicándole que lo está haciendo):

% contras -R / usr / all / repository hola
Copia local de hello de / usr / all / repository / hello
contras: "hola" está actualizado.

Tenga en cuenta que, debido a que el acto de hacer la copia local no se considera una "construcción" del
¡Hola , Cons todavía informa que está actualizado.

La creación de copias locales es más útil para los archivos que se instalan en un
directorio intermedio (para compartir con otros directorios) mediante el comando `Instalar '.
Acompañar el comando 'Instalar' para un archivo con un comando 'Local' complementario es tan
Es común que Cons proporcione un comando `Install_Local 'como una forma conveniente de hacer ambas cosas:

Install_Local $ env, '#export', 'hola';

es exactamente equivalente a:

Instale $ env '#export', 'hola';
Local '# exportar / hola';

Tanto los comandos 'Local' como 'Install_Local' actualizan el .consignar presentar ante la
firmas de archivo adecuadas, para que las futuras compilaciones se realicen correctamente.

Repositorio dependencia análisis

Debido a su escaneo incorporado, Cons buscará en los árboles de repositorio especificados para
.h archivos. Sin embargo, a menos que el compilador también conozca los árboles del repositorio, será
incapaz de encontrar .h archivos que solo existen en un repositorio. Si, por ejemplo, el Hola C
archivo incluye el Hola h archivo en su directorio actual:

% contras -R / usr / all / repository hola
gcc -c /usr/all/repository/hello.c -o hola.o
/usr/all/repository/hello.c:1: hello.h: No existe tal archivo o directorio

La solución de este problema impone algunos requisitos a la forma en que se desarrollan los entornos de construcción.
definido y en la forma en que se usa la directiva del preprocesador C `#include 'para incluir archivos.

Para informar al compilador acerca de los árboles del repositorio, Cons agregará el "-I" apropiado
banderas a los comandos de compilación. Esto significa que la variable 'CPPPATH' en el
El entorno de construcción debe especificar explícitamente todos los subdirectorios en los que se buscará.
para los archivos incluidos, incluido el directorio actual. En consecuencia, podemos arreglar lo anterior.
ejemplo cambiando la creación del entorno en el Construcción archivo de la siguiente manera:

$ env = nuevos contras (
CC => 'gcc',
CPPPATH => '.',
LIBS => 'libworld.a',
);

Debido a la definición de la variable 'CPPPATH', esto cede, cuando volvemos a ejecutar la
mando:

% contras -R / usr / all / repository hola
gcc -c -I. -I / usr / all / repository /usr/all/repository/hello.c -o hola.o
gcc -o hola hola.o /usr/all/repository/libworld.a

El orden de las banderas '-I' replica, para el preprocesador C, el mismo repositorio-
ruta de búsqueda de directorio que Cons usa para su propio análisis de dependencia. Si hay
múltiples repositorios y múltiples directorios `CPPPATH ', Cons agregará el repositorio
directorios al principio de cada directorio `CPPPATH ', multiplicando rápidamente el número
de banderas "-I". Como ejemplo extremo, un Construcción archivo que contiene:

Repositorio qw (
/ u1
/ u2
);

$ env = nuevos contras (
CPPPATH => 'a: b: c',
);

Daría un comando de compilación de:

cc -Ia -I / u1 / a -I / u2 / a -Ib -I / u1 / b -I / u2 / b -Ic -I / u1 / c -I / u2 / c -c hola.c -o hola.

Porque Cons se basa en las banderas '-I' del compilador para comunicar el orden en que
Los directorios del repositorio deben ser buscados, el manejo de Cons de los directorios del repositorio es
fundamentalmente incompatible con el uso de comillas dobles en las directivas '#include' en su C
código fuente:

#include "file.h" / * NO USE DOBLES CITAS COMO ESTA * /

Esto se debe a que la mayoría de los preprocesadores de C, cuando se enfrentan a una directiva de este tipo, siempre
busque el directorio que contiene el archivo fuente. Esto socava el elaborado '-I'
opciones que Cons construye para que el preprocesador se ajuste a su búsqueda preferida
camino.

En consecuencia, cuando se utilizan árboles de repositorio en Cons, hacerlo utilice soportes angulares para
archivos:

#incluir / * UTILICE SOPORTES ANGULARES EN SU LUGAR * /

Lista_de_repositorios

Contras proporciona un comando `Repository_List 'para devolver una lista de todos los directorios del repositorio
en su orden de búsqueda actual. Esto se puede usar para depurar o para hacer Perl más complejo.
cosas:

@list = Lista_de_repositorios;
print join ('', @list), "\ n";

Repositorio interacción otros Desventajas Características

El manejo de los árboles de repositorio de Contras interactúa correctamente con otras características de Contras, que es
decir, generalmente hace lo que cabría esperar.

En particular, los árboles de repositorio interactúan correctamente y de manera bastante poderosa con el 'Enlace'
mando. Un árbol de repositorio puede contener uno o más subdirectorios para compilaciones de versiones.
establecido a través de "Enlace" a un subdirectorio de origen. Los contras buscarán archivos derivados en
los subdirectorios de compilación adecuados en el árbol del repositorio.

Predeterminado tiene como objetivo


Hasta ahora, hemos demostrado invocar Cons con un objetivo explícito para construir:

% contras hola

Normalmente, Cons no crea nada a menos que se especifique un objetivo, pero especificando '.'
(el directorio actual) construirá todo:

% cons # no construye nada

% contras . # construye todo en el directorio de nivel superior

Añadiendo el método "Predeterminado" a cualquier Construcción or Reclutar archivo agregará el especificado
destinos a una lista de destinos predeterminados. Los contras construirán estos valores predeterminados si no hay
destinos especificados en la línea de comando. Entonces agregando la siguiente línea al nivel superior
Construcción file imitará el comportamiento típico de Make de construir todo por defecto:

Defecto '.';

Lo siguiente agregaría el ¡Hola y adiós comandos (en el mismo directorio que el
Construcción or Reclutar archivo) a la lista predeterminada:

Qw predeterminado (
¡Hola
adiós
);

El método "Predeterminado" se puede utilizar más de una vez para agregar objetivos a la lista predeterminada.

Selectivo construye


Contras proporciona dos métodos para reducir el tamaño de una compilación determinada. La primera es especificando
objetivos en la línea de comando, y el segundo es un método para podar el árbol de construcción. Bien
considere primero la especificación del objetivo.

Selectivo orientación

Al igual que make, Cons permite la especificación de `` objetivos '' en la línea de comando. Objetivos contras
pueden ser archivos o directorios. Cuando se especifica un directorio, esto es simplemente una
notación manual para cada producto derivable - que Cons conoce - en el especificado
directorio y a continuación. Por ejemplo:

% cons build / hola / hola.o

significa construir hola o y todo lo que hola o podria necesitar. Esto es de un anterior
versión de la Hola, ¡Mundo! programa en el que hola o dependió de
exportar / incluir / mundo.h. Si ese archivo no está actualizado (porque alguien modificó
src / world / world.h), luego se reconstruirá, aunque esté en un directorio remoto desde
construir / hola.

En este ejemplo:

% de construcción de contras

Todo en el build se construye el directorio, si es necesario. Nuevamente, esto puede causar más archivos
para ser construido. En particular, ambos exportar / incluir / mundo.h y export / lib / libworld.a en
requerido por el construir / hola directorio, por lo que se construirán si están desactualizados.

Si lo hacemos, en cambio:

% contras de exportación

entonces solo se reconstruirán los archivos que deben instalarse en el directorio de exportación, si
necesario, y luego instalado allí. Tenga en cuenta que 'cons build' podría generar archivos que 'cons
export 'no construye, y viceversa.

No `` especial '' tiene como objetivo

Con Contras, no se requieren objetivos `` especiales '' de estilo de marca. El análogo más simple con Contras
es usar especial exportar directorios, en su lugar. Supongamos, por ejemplo, que tiene un
toda una serie de pruebas unitarias asociadas con su código. Las pruebas viven en el
directorio fuente cerca del código. Sin embargo, normalmente no desea crear estas pruebas.
Una solución es proporcionar todas las instrucciones de compilación para crear las pruebas y luego
instale las pruebas en una parte separada del árbol. Si instalamos las pruebas en un nivel superior
directorio llamado pruebas, entonces:

% de pruebas de contras

construirá todas las pruebas.

% contras de exportación

construirá la versión de producción del sistema (pero no las pruebas), y:

% de construcción de contras

probablemente debería evitarse (ya que compilará pruebas innecesariamente).

Si desea crear solo una prueba, puede nombrar explícitamente la prueba (en
o bien el pruebas directorio o el build directorio). También puede agregar las pruebas
en una jerarquía conveniente dentro del directorio de pruebas. Esta jerarquía no necesita
coincidir necesariamente con la jerarquía de origen, de la misma manera que la jerarquía de inclusión
probablemente no coincide con la jerarquía de origen (es poco probable que la jerarquía de inclusión sea más
de dos niveles de profundidad, para programas C).

Si desea construir absolutamente todo en el árbol (sujeto a las opciones que desee
seleccionar), puede utilizar:

% contras .

Esto no es particularmente eficiente, ya que recorrerá todos los árboles de manera redundante,
incluido el árbol de origen. El árbol de origen, por supuesto, puede tener objetos compilables en
it - nada le impide hacer esto, incluso si normalmente construye en una compilación separada
árbol.

Construcción Poda


Junto con la selección de objetivos, build poda se puede utilizar para reducir el alcance de la
construir. En el ejemplo anterior de peAcH y baNaNa, ya hemos visto cómo las
La poda de construcción se puede usar para hacer que solo la mitad de la construcción potencial esté disponible para cualquier
invocación de "contras". Contras también proporciona, como una conveniencia, una convención de línea de comando que
le permite especificar qué Reclutar los archivos realmente se `` construyen '', es decir, se incorporan
en el árbol de construcción. Por ejemplo:

% contras construir + mundo

El argumento '+' introduce una expresión regular de Perl. Esto, por supuesto, debe citarse en
el nivel de shell si hay metacaracteres de shell dentro de la expresión. los
la expresión se compara con cada Reclutar archivo que se ha mencionado en una "compilación"
declaración, y solo aquellos scripts con nombres coincidentes se incorporan realmente en la
construir árbol. Se permiten múltiples argumentos de este tipo, en cuyo caso una coincidencia con cualquiera de ellos
es suficiente para hacer que se incluya un script.

En el ejemplo anterior, el ¡Hola programa no se construirá, ya que Cons no tendrá
conocimiento del guion hola / recluta. libworld.a Sin embargo, el archivo se construirá si
necesita ser.

Hay un par de usos para la poda de compilación a través de la línea de comandos. Quizás el más útil
es la capacidad de realizar cambios locales, y luego, con el conocimiento suficiente de la
consecuencias de esos cambios, restringir el tamaño del árbol de compilación para acelerar
el tiempo de reconstrucción. Un segundo uso para la poda de construcción es prevenir activamente la recompilación
de ciertos archivos que sabe que se volverán a compilar debido, por ejemplo, a un archivo de encabezado modificado.
Es posible que sepa que los cambios en el archivo de encabezado son irrelevantes o que el
los cambios se pueden ignorar de forma segura para la mayor parte del árbol, con fines de prueba.
opinión es que es pragmático admitir este tipo de comportamiento, en el entendimiento de que
en la próxima construcción completa estará todo lo que necesita ser reconstruido. No hay equivalente
a un comando de `` toque '', para marcar archivos como permanentemente actualizados. Entonces cualquier riesgo que sea
incurrido por la poda de construcción se mitiga. Para un trabajo de calidad de lanzamiento, obviamente, recomendamos
que no usas la poda de compilación (está perfectamente bien usarla durante la integración, sin embargo,
para comprobar la compilación, etc. Solo asegúrese de realizar una compilación sin restricciones antes de realizar
la integración).

Temporal anula


Contras proporciona un mecanismo muy simple para anular aspectos de una compilación. La esencia es
que escribe un archivo de anulación que contiene uno o más comandos de anulación, y
especifique esto en la línea de comando, cuando ejecute `contras ':

% cons -o sobre exportación

construirá el exportar directorio, con todos los archivos derivados sujetos a las anulaciones presentes
existentes Más de expediente. Si omite la opción `-o ', entonces todo lo necesario para eliminar
todas las anulaciones serán reconstruidas.

Primordial entorno las variables

El archivo de anulación puede contener dos tipos de anulaciones. El primero es el entorno entrante.
variables. Estos son normalmente accesibles por el Construcción archivo del hash '% ENV'
variable. Estos pueden anularse trivialmente en el archivo de anulación configurando el
elementos apropiados de '% ENV' (estos también podrían anularse en el entorno del usuario,
por supuesto).

El Anular comando

El segundo tipo de anulación se logra con el comando 'Anular', que parece
modo:

Anular , => , => , ...;

La expresión regular regexp se compara con todos los archivos derivados que son candidatos
para la construcción. Si el archivo derivado coincide, los pares de variable / valor se utilizan para
anula los valores del entorno de construcción asociados con el archivo derivado.

Supongamos que tenemos un entorno de construcción como este:

$ CONTRAS = nuevas contras (
COPT => '',
CDBG => '-g',
CFLAGS => '% COPT% CDBG',
);

Entonces, si tenemos un archivo de anulación Más de que contiene este comando:

Anular '\ .o $', COPT => '-O', CDBG => '';

luego cualquier invocación de "contras" con "-o over" que cree .o archivos a través de este entorno
hacer que se compilen con `-O 'y no con` -g'. La anulación podría, por supuesto, ser
restringido a un solo directorio mediante la selección adecuada de una expresión regular.

Aquí está la versión original de Hello, World! programa, construido con este entorno.
Tenga en cuenta que Cons reconstruye las piezas apropiadas cuando se aplica o elimina la anulación:

% contras hola
cc -g -c hola.c -o hola.o
cc -o hola hola. o
% contra -o sobre hola
cc -O -c hola.c -o hola.o
cc -o hola hola. o
% contra -o sobre hola
contras: "hola" está actualizado.
% contras hola
cc -g -c hola.c -o hola.o
cc -o hola hola. o

Es importante que el comando "Override" solo se utilice para
anulaciones necesarias para el desarrollo porque las anulaciones no son independientes de la plataforma y
porque confían demasiado en un conocimiento íntimo del funcionamiento de los guiones. Para
uso temporal, sin embargo, son exactamente lo que desea.

Tenga en cuenta que sigue siendo útil proporcionar, por ejemplo, la capacidad de crear un
versión de un sistema para uso en producción - desde el Construcción y Reclutar archivos. De esta manera
puede adaptar el sistema optimizado a la plataforma. Donde deben estar las compensaciones del optimizador
hecho (es posible que determinados archivos no se compilen con optimización completa, por ejemplo),
estos pueden registrarse para la posteridad (y reproducibilidad) directamente en los guiones.

Más on construcción ambientes


Predeterminado construcción las variables

Hemos mencionado y utilizado el concepto de construcción entorno, muchas veces en el
páginas anteriores. Ahora es el momento de hacer esto un poco más concreto. Con lo siguiente
declaración:

$ env = new cons ();

Se crea una referencia a un nuevo entorno de construcción predeterminado. Esto contiene un número
de variables de construcción y algunos métodos. En el momento actual, la lista predeterminada de
Las variables de construcción se definen de la siguiente manera:

CC => 'cc',
CFLAGS => '',
CCCOM => '% CC% CFLAGS% _IFLAGS -c% <-o%>',
INCDIRPREFIX => '-I',
CXX => '% CC',
CXXFLAGS => '% CFLAGS',
CXXCOM => '% CXX% CXXFLAGS% _IFLAGS -c% <-o%>',
LINK => '% CXX',
LINKCOM => '% LINK% LDFLAGS -o%>% <% _LDIRS% LIBS',
LINKMODULECOM => '% LD -r -o%>% <',
LIBDIRPREFIX => '-L',
AR => 'ar',
ARFLAGS => 'r',
ARCOM => "% AR% ARFLAGS%>% <\ n% RANLIB%>",
RANLIB => 'ranlib',
AS => 'como',
ASFLAGS => '',
ASCOM => '% AS% ASFLAGS% <-o%>',
LD => 'ld',
LDFLAGS => '',
PREFLIB => 'lib',
SUFLIB => '.a',
SUFLIBS => '.so: .a',
SUFOBJ => '.o',
ENV => {'RUTA' => '/compartimiento:/ usr / bin'},

En los sistemas Win32 (Windows NT), las siguientes variables de construcción se anulan en el
por defecto:

CC => 'cl',
CFLAGS => '/ nologo',
CCCOM => '% CC% CFLAGS% _IFLAGS / c% </ Fo%>',
CXXCOM => '% CXX% CXXFLAGS% _IFLAGS / c% </ Fo%>',
INCDIRPREFIX => '/ I',
LINK => 'enlace',
LINKCOM => '% LINK% LDFLAGS / out:%>% <% _LDIRS% LIBS',
LINKMODULECOM => '% LD / r / o%>% <',
LIBDIRPREFIX => '/ LIBPATH:',
AR => 'lib',
ARFLAGS => '/ nologo',
ARCOM => "% AR% ARFLAGS / out:%>% <",
RANLIB => '',
LD => 'enlace',
LDFLAGS => '/ nologo',
PREFLIB => '',
SUFEXE => '.exe',
SUFLIB => '.lib',
SUFLIBS => '.dll: .lib',
SUFOBJ => '.obj',

Estas variables son utilizadas por los diversos métodos asociados con el entorno, en
En particular, cualquier método que en última instancia invoque un comando externo sustituirá a estos
variables en el comando final, según corresponda. Por ejemplo, el método "Objetos" toma
varios archivos fuente y se encarga de derivar, si es necesario, el objeto correspondiente
archivos. Por ejemplo:

Objetos $ env 'foo.c', 'bar.c';

Esto se encargará de producir, si es necesario, foo.o y bar.o. El comando invocado es simplemente
'% CCCOM', que se expande mediante sustitución, al comando externo apropiado requerido
para construir cada objeto. Exploraremos las reglas de sustitución más a fondo en el "Comando"
método, a continuación.

Las variables de construcción también se utilizan para otros fines. Por ejemplo, "CPPPATH" es
se utiliza para especificar una ruta de directorios de inclusión separados por dos puntos. Estos están destinados a ser
pasados ​​al preprocesador C y también son utilizados por la maquinaria de escaneo de archivos C para
determinar las dependencias involucradas en una compilación de C. Variables que comienzan con
subrayado, se crean mediante varios métodos y normalmente deben considerarse `` internos ''
variables. Por ejemplo, cuando se llama a un método que requiere la creación de un objeto
de una fuente C, se crea la variable '_IFLAGS': esto corresponde a los interruptores '-I'
requerido por el compilador de C para representar los directorios especificados por 'CPPPATH'.

Tenga en cuenta que, para cualquier entorno en particular, el valor de una variable se establece una vez y luego
nunca restablecer (para cambiar una variable, debe crear un nuevo entorno. Se proporcionan métodos
para copiar entornos existentes para este propósito). Algunas variables internas, como
Los '_IFLAGS' se crean bajo demanda, pero una vez configurados, permanecen fijos durante la vida útil del
ambiente.

Las variables 'CFLAGS', 'LDFLAGS' y 'ARFLAGS' proporcionan un lugar para pasar opciones a
el compilador, el cargador y el archivador, respectivamente. Menos obvio, el 'INCDIRPREFIX'
variable especifica la cadena de opciones que se agregará al principio de cada inclusión
directorio para que el compilador sepa dónde encontrar .h archivos. Del mismo modo, el
La variable 'LIBDIRPREFIX' especifica la cadena de opciones que se agregará al principio de
cada directorio que el vinculador debe buscar bibliotecas.

Otra variable, 'ENV', se utiliza para determinar el entorno del sistema durante la ejecución.
de un comando externo. De forma predeterminada, la única variable de entorno que se establece es 'PATH',
que es la ruta de ejecución de un comando de UNIX. Para obtener la máxima reproducibilidad, debe
realmente arregle para establecer su propia ruta de ejecución, en su nivel superior Construcción archivo (o
quizás importando un paquete de construcción apropiado con el comando Perl `use '). los
Las variables predeterminadas están pensadas para despegar.

Interpolando construcción las variables

Las variables del entorno de construcción se pueden interpolar en los nombres de los archivos de origen y de destino.
prefijando el nombre de la variable de construcción con '%'.

$ env = nuevos contras (
DESTDIR => 'programas',
SRCDIR => 'src',
);
Programa $ env '% DESTDIR / hola', '% SRCDIR / hola.c';

La expansión de las variables de construcción es recursiva, es decir, el archivo nombre (s) serán reenviados
expandido hasta que no se puedan hacer más sustituciones. Si una variable de construcción no es
definido en el entorno, se sustituirá la cadena nula.

Predeterminado construcción métodos


La lista de métodos de construcción predeterminados incluye lo siguiente:

El 'nuevo' constructor

El método "nuevo" es un constructor de objetos de Perl. Es decir, no se invoca mediante una referencia.
a un entorno de construcción existente referencia, pero, de forma bastante estática, usando el nombre
de la Perl paquete donde se define el constructor. El método se invoca así:

$ env = nuevos contras ( );

El entorno que recupera está bendecido en el paquete `contras ', lo que significa que
han asociado los métodos predeterminados que se describen a continuación. Construcción individual
las variables se pueden anular proporcionando pares de nombre / valor en una lista de anulación. Tenga en cuenta que
para anular cualquier variable de entorno de comando (es decir, cualquier cosa bajo 'ENV'), tendrá que
anular todos ellos. Puede sortear esta dificultad utilizando el método "copiar" en un
Entorno de construcción existente.

El 'clon' Método

El método "clon" crea un clon de un entorno de construcción existente, y puede ser
llamado como en el siguiente ejemplo:

$ env2 = $ env1-> clon ( );

Puede proporcionar anulaciones de la manera habitual para crear un entorno diferente del
original. Si solo desea un nuevo nombre para el mismo entorno (que puede ser útil cuando
exportar entornos a componentes existentes), puede utilizar una asignación simple.

El 'copiar' Método

El método 'copiar' extrae las variables de construcción definidas externamente de un
entorno y los devuelve como una lista de pares de nombre / valor. Las anulaciones también pueden ser
siempre que, en cuyo caso, se devuelvan los valores anulados, según corresponda. los
La lista devuelta se puede asignar a un hash, como se muestra en el prototipo, a continuación, pero también
ser manipulado de otras formas:

% env = $ env1-> copiar ( );

El valor de 'ENV', que en sí mismo es un hash, también se copia en un nuevo hash, por lo que puede ser
cambiado sin temor a afectar el entorno original. Entonces, por ejemplo, si realmente
desea anular solo la variable 'PATH' en el entorno predeterminado, puede hacer lo
siguientes:

% cons = new cons () -> copy ();
$ contras {ENV} {RUTA} = " ";
$ contras = nuevos contras (% contras);

Esto dejará cualquier otra cosa que pueda estar en el entorno de ejecución predeterminado.
imperturbable.

El `Instalar ' Método

El método `Instalar 'organiza la instalación de los archivos especificados en el
directorio. La instalación está optimizada: el archivo no se copia si se puede vincular. Si
este no es el comportamiento deseado, deberá utilizar un método diferente para instalar el
expediente. Se llama de la siguiente manera:

Instalar $ env , ;

Tenga en cuenta que, si bien los archivos que se instalarán pueden tener un nombre arbitrario, solo el último
El componente de cada nombre se utiliza para el nombre de destino instalado. Entonces, por ejemplo, si
arreglar para instalar foo / bar in baz, esto creará un de caramelos presentar en el baz directorio (no
foo / bar).

El `Instalar como ' Método

El método `InstallAs 'organiza la fuente especificada presentar(s) que se instalarán como
objetivo especificado presentar(s). Se deben especificar varios archivos como una lista de archivos. los
la instalación está optimizada: el archivo no se copia si se puede vincular. Si este no es el
comportamiento deseado, deberá utilizar un método diferente para instalar el archivo. Está
llamado de la siguiente manera:

`InstallAs 'funciona de dos formas:

Instalación de un solo archivo:

InstallAs $ env TgtFile, SrcFile;

Instalación de varios archivos:

InstallAs $ env ['tgt1', 'tgt2'], ['src1', 'src2'];

O incluso como:

@srcs = qw (src1 src2 src3);
@tgts = qw (tgt1 tgt2 tgt3);
InstallAs $ env [@tgts], [@srcs];

Tanto la lista de fuentes como la de destino deben tener la misma longitud.

El 'Precioso' Método

El método 'Precious' pide a los contras que no eliminen el archivo especificado o la lista de archivos antes
construyéndolos de nuevo. Se invoca como:

Precioso ;

Esto es especialmente útil para permitir actualizaciones incrementales de bibliotecas o depurar
archivos de información que se actualizan en lugar de reconstruir de nuevo cada vez. Los contras seguirán
borre los archivos cuando se especifique la bandera '-r'.

El 'Comando' Método

El método `Command 'es un método general que se puede utilizar para organizar cualquier
comando que se llamará para actualizar el destino. Para este comando, un archivo de destino y una lista de
Se proporcionan entradas. Además, se proporciona una línea de comando de construcción, o líneas, como un
cadena (esta cadena puede tener varios comandos incrustados dentro de ella, separados por nuevos
líneas). 'Command' se llama de la siguiente manera:

Comando $ env , , ;

El destino depende de la lista de archivos de entrada especificada, y las entradas deben
construirse con éxito o los Cons no intentarán construir el objetivo.

Dentro del comando de construcción, cualquier variable del entorno de construcción puede ser
introducido prefijando el nombre de la variable de construcción con '%'. Esto es recursivo:
el comando se expande hasta que no se pueden realizar más sustituciones. Si una construccion
variable no está definida en el entorno, entonces se sustituirá la cadena nula. A
"%%" duplicado será reemplazado por un solo "%" en el comando de construcción.

Hay varias pseudovariables que también se expandirán:

%> El nombre del archivo de destino (en un comando de múltiples destinos, este es siempre el primer destino
mencionado).

% 0 Igual que '%>'.

% 1,% 2, ...,% 9
Se refieren al archivo de entrada primero al noveno, respectivamente.

% <El conjunto completo de entradas. Si alguno de estos se ha utilizado en cualquier otro lugar del
línea de comando actual (a través de '% 1', '% 2', etc.), entonces se eliminarán de la
lista proporcionada por '% <'. Considere el siguiente comando que se encuentra en un Reclutar presentar
existentes test directorio:

Comando $ env 'tgt', qw (foo bar baz), qq (
echo% <-i% 1>%>
echo% <-i% 2 >>%>
echo% <-i% 3 >>%>
);

If TGT necesita ser actualizado, entonces esto daría lugar a la ejecución de la
siguientes comandos, asumiendo que no se ha establecido ninguna reasignación para el test
directorio:

prueba de eco / prueba de barra / baz -i prueba / foo> prueba / tgt
prueba de eco / prueba de foo / baz -i prueba / bar >> prueba / tgt
prueba de eco / prueba de foo / bar -i prueba / baz >> prueba / tgt

Cualquiera de las pseudovariables anteriores puede ir seguida inmediatamente por una de las siguientes
sufijos para seleccionar una parte del nombre de ruta expandido:

: a la ruta absoluta al nombre del archivo
: b el directorio más el nombre del archivo sin ningún sufijo
: d el directorio
: f el nombre del archivo
: s el sufijo del nombre del archivo
: F el nombre del archivo sin ningún sufijo

Continuando con el ejemplo anterior, `% <: f 'se expandiría a` foo bar baz', y `% ': d>
expandir para "probar".

Es posible reescribir parte del comando mediante programación adjuntando parte de él.
entre '% [' y '%]'. Esto llamará a la variable de construcción nombrada como la primera palabra
entre corchetes como referencia de código Perl; se utilizarán los resultados de esta convocatoria
para reemplazar el contenido de los corchetes en la línea de comando. Por ejemplo, dado un
archivo de entrada existente llamado tgt.en:

@palabras clave = qw (foo bar baz);
$ env = new contras (X_COMMA => sub {join (",", @_)});
Comando $ env 'tgt', 'tgt.in', qq (
echo '# Palabras clave:% [X_COMMA @keywords%]'>%>
gato% <>>%>
);

Esto ejecutará:

echo '# Palabras clave: foo, bar, baz'> tgt
cat tgt.in >> tgt

Una vez que se produce la sustitución, las cadenas de espacios en blanco se convierten en espacios en blanco únicos y
Se eliminan los espacios en blanco iniciales y finales. Por tanto, no es posible introducir
espacio en blanco de longitud variable en cadenas pasadas a un comando, sin recurrir a algunos
una especie de cita de concha.

Si se proporciona una cadena de comandos de varias líneas, los comandos se ejecutan secuencialmente. Si alguna
de los comandos falla, entonces ninguno de los demás se ejecuta y el objetivo no está marcado como
actualizado, es decir, no se almacena una nueva firma para el objetivo.

Normalmente, si todos los comandos tienen éxito y devuelven un estado cero (o cualquier plataforma-
se requiere una indicación específica de éxito), luego se almacena una nueva firma para el
objetivo. Si un comando informa erróneamente de éxito incluso después de una falla, los Cons
suponga que el archivo de destino creado por ese comando es preciso y está actualizado.

Se supone que la primera palabra de cada cadena de comando, después de la expansión, es un ejecutable
comando buscó en la variable de entorno 'PATH' (que, a su vez, es especificada por el
Variable de construcción 'ENV'). Si este comando se encuentra en la ruta, entonces el objetivo
dependa de ello: por lo tanto, el comando se generará automáticamente, según sea necesario. Es
es posible escribir comandos de varias partes en algunos shells, separados por punto y coma. Solo el
Sin embargo, se dependerá de la primera palabra de comando, por lo que si escribe sus cadenas de comando
de esta manera, debe configurar explícitamente una dependencia (con el método `Depende '), o
asegúrese de que el comando que está utilizando sea un comando del sistema que se espera que sea
disponible. Si no está disponible, obtendrá, por supuesto, un error.

Si algún comando (incluso uno dentro de un comando de varias líneas) comienza con '[perl]', el resto
de esa línea de comando será evaluada por el Perl en ejecución en lugar de ser bifurcada por el
cascarón. Si ocurre un error al analizar Perl o si la expresión de Perl devuelve 0 o
undef, se considerará que el comando ha fallado. Por ejemplo, aquí hay un sencillo
comando que crea un archivo 'foo' directamente desde Perl:

$ env = new cons ();
Comando $ env 'foo',
qq ([perl] abrir (FOO, '> foo'); imprimir FOO "hola \\ n"; cerrar (FOO); 1);

Tenga en cuenta que cuando se ejecuta el comando, está en el mismo paquete que cuando Construcción
or Reclutar archivo fue leído, por lo que puede llamar a las funciones de Perl que ha definido en el mismo
Construcción or Reclutar archivo en el que aparece el 'Comando':

$ env = new cons ();
sub crear_archivo {
mi $ archivo = turno;
open (ARCHIVO, "> $ archivo");
imprimir ARCHIVO "hola \ n";
cerrar el archivo);
1 regresar;
}
Comando $ env 'foo', "[perl] & create_file ('%>')";

La cadena de Perl se utilizará para generar la firma para el archivo derivado, por lo que si
cambie la cadena, el archivo se reconstruirá. El contenido de las subrutinas que llame,
sin embargo, no forman parte de la firma, por lo que si modifica una subrutina llamada como
'create_file' arriba, el objetivo no ser reconstruido. Usuario de advertencia.

Cons normalmente imprime un comando antes de ejecutarlo. Este comportamiento se suprime si el
el primer carácter del comando es '@'. Tenga en cuenta que es posible que deba separar el '@' de
el nombre del comando o escapar de él para evitar que `@cmd 'se vea como una matriz en la cita de Perl
operadores que realizan interpolación:

# La primera línea de comando es incorrecta,
# porque "@cp" parece una matriz
# a la función Perl qq //.
# Utilice el segundo formulario en su lugar.
Comando $ env 'foo', 'foo.in', qq (
@cp% <archivo temporal
@ cp tempfile%>
);

Si hay metacaracteres de shell en cualquier lugar de la línea de comando expandida, como `<',
`> ', comillas o punto y coma, entonces el comando se ejecutará invocando un
cascarón. Esto significa que un comando como:

CD Foo

solo normalmente fallará, ya que no hay un comando 'cd' en la ruta. Pero el comando
cuerda:

cd $ <: d; tar cf $>: f $ <: f

cuando se expanda todavía contendrá el punto y coma del meta carácter de shell, y un shell será
invocado para interpretar el comando. Dado que 'cd' es interpretado por este sub-shell, el comando
se ejecutará como se esperaba.

Para especificar un comando con varios objetivos, puede especificar una referencia a una lista de
objetivos. En Perl, se puede crear una referencia de lista encerrando una lista entre corchetes.
De ahí el siguiente comando:

Comando $ env ['foo.h', 'foo.c'], 'foo.template', q (
gen% 1
);

podría usarse en un caso donde el comando `gen 'crea dos archivos, ambos foo.h y foo.c.

El 'Objetos' Método

El método de 'Objetos' organiza la creación de archivos de objeto que corresponden a la especificación
archivos fuente. Se invoca como se muestra a continuación:

@files = Objetos $ env ;

En Unix, los archivos de origen que terminan en .s y .c actualmente son compatibles y se compilarán
en un nombre del mismo archivo que termina en .o. De forma predeterminada, todos los archivos se crean invocando
el comando externo que resulta de expandir la variable de construcción 'CCCOM', con
`% <'y`%>' establecidos en los archivos fuente y objeto, respectivamente (ver el método `Command '
para detalles de expansión). La variable 'CPPPATH' también se usa al escanear archivos de origen
para dependencias. Esta es una lista de nombres de ruta separados por dos puntos, y también se utiliza para crear
la variable de construcción '_IFLAGS', que contendrá la lista apropiada de -`I '
opciones para la compilación. Cualquier nombre de ruta relativo en 'CPPPATH' se interpreta como relativo
al directorio en el que se creó el entorno de construcción asociado (absoluta
y también se pueden usar nombres relativos superiores). Esta variable es utilizada por 'CCCOM'. El comportamiento
de este comando se puede modificar cambiando cualquiera de las variables que se interpolan
en 'CCCOM', como 'CC', 'CFLAGS' e, indirectamente, 'CPPPATH'. También es posible
reemplace el valor de 'CCCOM', en sí mismo. Para su comodidad, este archivo devuelve la lista de
nombres de archivo de objeto.

El `Programa ' Método

El método "Programa" se arregla para vincular el programa especificado con el objeto especificado
archivos. Se invoca de la siguiente manera:

Programa $ env , ;

El nombre del programa tendrá el valor de la variable de construcción 'SUFEXE' adjunta (por
predeterminado, `.exe 'en sistemas Win32, nada en sistemas Unix) si el sufijo aún no está
presente.

Los archivos de origen se pueden especificar en lugar de los archivos de objetos; el método "Objetos" será
invocado para organizar la conversión de todos los archivos en archivos de objeto, y por lo tanto todos los
Las observaciones sobre el método de 'Objetos', arriba, se aplican a este método también.

La vinculación real del programa será manejada por un comando externo que da como resultado
de expandir la variable de construcción 'LINKCOM', con '% <' establecido en los archivos de objeto para
estar vinculado (en el orden presentado), y '%>' establecido en el objetivo (ver el método de 'Comando'
para detalles de expansión). El usuario puede establecer variables adicionales en la construcción.
entorno, incluyendo 'LINK', para definir qué programa usar para vincular, 'LIBPATH', un
lista separada por dos puntos de rutas de búsqueda de bibliotecas, para usar con las especificaciones de la biblioteca
formulario -llib, y 'LIBS', especificando la lista de bibliotecas con las que enlazar (ya sea en -llib
formulario o simplemente como nombres de ruta. Los nombres de ruta relativos tanto en 'LIBPATH' como en 'LIBS' se interpretan
relativo al directorio en el que se crea el entorno de construcción asociado
(también se pueden usar nombres absolutos y relativos superiores). Contras se configura automáticamente
dependencias en cualquier biblioteca mencionada en 'LIBS': esas bibliotecas se construirán antes
el comando está vinculado.

El 'Biblioteca' Método

El método 'Biblioteca' organiza la creación de la biblioteca especificada a partir del objeto especificado
archivos. Se invoca de la siguiente manera:

Biblioteca $ env , ;

El nombre de la biblioteca tendrá el valor de la variable de construcción 'SUFLIB' adjunta (por
predeterminado, '.lib' en sistemas Win32, '.a' en sistemas Unix) si el sufijo no está ya
presente.

Los archivos de origen se pueden especificar en lugar de los archivos de objetos; el método "Objetos" será
invocado para organizar la conversión de todos los archivos en archivos de objeto, y por lo tanto todos los
Las observaciones sobre el método de 'Objetos', arriba, se aplican a este método también.

La creación real de la biblioteca será manejada por un comando externo que da como resultado
de expandir la variable de construcción 'ARCOM', con '% <' establecido en los miembros de la biblioteca (en
el orden presentado), y '%>' a la biblioteca que se creará (consulte el método `Command 'para
detalles de expansión). El usuario puede establecer variables en el entorno de construcción que
afectar el funcionamiento del comando. Estos incluyen 'AR', el programa de archivo a usar,
'ARFLAGS', que se puede utilizar para modificar las banderas dadas al programa especificado por 'AR',
y 'RANLIB', el nombre de un programa de generación de índices de archivo, si es necesario (si el
La necesidad no requiere la última funcionalidad, entonces 'ARCOM' debe redefinirse para no
referencia 'RANLIB').

El método "Biblioteca" permite especificar la misma biblioteca en varios métodos
invocaciones. Todos los objetos contribuyentes de todas las invocaciones (que pueden ser de
diferentes directorios) se combinan y generan mediante un solo comando de archivo. Nota,
Sin embargo, si poda una compilación de modo que solo se especifique una parte de una biblioteca, solo
se generará esa parte de la biblioteca (¡el resto desaparecerá!).

El 'Módulo' Método

El método "Módulo" es una combinación de los métodos "Programa" y "Comando". En vez de
generando un programa ejecutable directamente, este comando le permite especificar su propio
comando para generar realmente un módulo. El método se invoca de la siguiente manera:

Módulo $ env , , ;

Este comando es útil en los casos en los que desea crear, por ejemplo, dinámicamente
módulos cargados o bibliotecas de código vinculadas estáticamente.

El 'Depende' Método

El método `Depende 'le permite especificar dependencias adicionales para un objetivo. Está
invocado de la siguiente manera:

Depende de $ env , ;

Esto puede ser útil ocasionalmente, especialmente en los casos en los que no existe un escáner (o no
escribible) para tipos particulares de archivos. Normalmente, las dependencias se calculan
automáticamente a partir de una combinación de las dependencias explícitas configuradas por el método
invocación o escaneando archivos de origen.

Se puede especificar un conjunto de dependencias idénticas para múltiples objetivos usando una referencia a
una lista de objetivos. En Perl, se puede crear una referencia de lista adjuntando una lista en cuadrados
soportes. De ahí el siguiente comando:

Depende de $ env ['foo', 'bar'], 'input_file_1', 'input_file_2';

especifica que tanto el foo y de caramelos los archivos dependen de los archivos de entrada enumerados.

El 'Ignorar' Método

El método 'Ignore' le permite ignorar explícitamente las dependencias que Cons infiere en su
propio. Se invoca de la siguiente manera:

Ignorar ;

Esto se puede usar para evitar recompilaciones debido a cambios en los archivos de encabezado del sistema o
utilidades que se sabe que no afectan a los objetivos generados.

Si, por ejemplo, un programa está construido en un directorio montado en NFS en varios sistemas que
tener diferentes copias de estudio h, las diferencias afectarán las firmas de todos
objetivos derivados construidos a partir de archivos fuente que `#incluyen '. Esto causará todo
esos objetivos deben reconstruirse al cambiar de sistema. Si este no es un comportamiento deseable,
entonces la siguiente línea eliminará las dependencias en el estudio h archivo:

Ignore '^ / usr / include / stdio \ .h $';

Tenga en cuenta que los argumentos del método 'Ignorar' son expresiones regulares, por lo que son especiales
los caracteres deben ser de escape y es posible que desee anclar el principio o el final de la
expresión con caracteres `^ 'o` $'.

El 'Sal' Método

El método 'Salt' agrega un valor constante al cálculo de la firma para cada derivado
expediente. Se invoca de la siguiente manera:

Sal $ cadena;

Cambiar el valor de Salt forzará una reconstrucción completa de cada archivo derivado. Esto puede ser
utilizado para forzar reconstrucciones en determinadas circunstancias deseadas. Por ejemplo,

Sal `uname -s`;

Forzaría una reconstrucción completa de cada archivo derivado siempre que el sistema operativo
que se realiza la compilación (según lo informado por 'uname -s') cambia.

El `UseCache ' Método

El método 'UseCache' instruye a Cons para mantener una caché de archivos derivados, para ser compartidos
entre árboles de construcción separados del mismo proyecto.

UseCache ("caché / ") ⎪⎪ warn (" directorio de caché no encontrado ");

El `SourcePath ' Método

El método 'SourcePath' devuelve el nombre de la ruta de origen real de un archivo, en oposición al
nombre de ruta dentro de un directorio de compilación. Se invoca de la siguiente manera:

$ ruta = SourcePath ;

El `ConsPath ' Método

El método 'ConsPath' devuelve verdadero si la ruta proporcionada es un archivo derivable y devuelve
undef (falso) de lo contrario. Se invoca de la siguiente manera:

$ resultado = ConsPath ;

El "SplitPath" Método

El método 'SplitPath' busca varios nombres de ruta en una cadena separada por el valor predeterminado
separador de ruta para el sistema operativo (':' en sistemas UNIX, ';' en Windows NT), y
devuelve los nombres completos. Se invoca de la siguiente manera:

@rutas = SplitPath ;

El método 'SplitPath' convertirá los nombres con el prefijo '#' a la compilación de nivel superior adecuada
name (sin el '#') y convertirá los nombres relativos en nombres de nivel superior.

El `DirPath ' Método

El método 'DirPath' devuelve la ruta de construcción nombre (s) de un directorio o lista de directorios.
Se invoca de la siguiente manera:

$ cwd = DirPath ;

El uso más común del método `DirPath 'es:

$ cwd = DirPath '.';

para buscar la ruta al directorio actual de una subsidiaria Reclutar archivo.

El `FilePath ' Método

El método 'FilePath' devuelve la ruta de construcción nombre (s) de un archivo o lista de archivos. Está
invocado de la siguiente manera:

$ file = FilePath ;

El 'Ayuda' Método

El método "Ayuda" especifica el texto de ayuda que se mostrará cuando el usuario invoca "contras".
-h '. Esto se puede utilizar para proporcionar documentación de objetivos, valores, compilación
opciones, etc. para el árbol de construcción. Se invoca de la siguiente manera:

Ayudar ;

El método "Ayuda" sólo se puede llamar una vez y, por lo general, debe especificarse en la parte superior.
nivel Construcción archivo.

Extensión Desventajas


Primordial construcción las variables

Hay varias formas de ampliar los contras, que varían en grado de dificultad. Lo más simple
El método es definir su propio entorno de construcción, basado en el entorno predeterminado,
pero modificado para reflejar sus necesidades particulares. Esto a menudo será suficiente para
aplicaciones. Puede utilizar el constructor "new" y los métodos "clone" y "copy" para
crear entornos híbridos. Estos cambios pueden ser completamente transparentes para el subyacente
Reclutar archivos.

Adición nueva métodos

Para cambios un poco más exigentes, es posible que desee agregar nuevos métodos a los 'contras'
paquete. Aquí hay un ejemplo de una extensión muy simple, `InstallScript ', que instala un
tcl en una ubicación solicitada, pero edita el script primero para reflejar una plataforma
ruta dependiente que debe instalarse en el script:

# contras :: InstallScript - Crea una versión dependiente de la plataforma de un shell
# script reemplazando la cadena `` #! your-path-here '' con la plataforma específica
# ruta $ BIN_DIR.

sub cons :: InstallScript {
mi ($ env, $ dst, $ src) = @_;
Comando $ env $ dst, $ src, qq (
sed s + tu-ruta-aquí + $ BIN_DIR +% <>%>
chmod oug + x%>
);
}

Tenga en cuenta que este método se define directamente en el paquete `cons '(con el prefijo del nombre
con `contras :: '). Un cambio realizado de esta manera será globalmente visible para todos los entornos,
y podría llamarse como en el siguiente ejemplo:

InstallScript $ env "$ BIN / foo", "foo.tcl";

Para una pequeña mejora en la generalidad, la variable 'BINDIR' podría pasarse como un
argumento o tomado del entorno de construcción - como '% BINDIR'.

Primordial métodos

En lugar de agregar el método al espacio de nombres 'contras', podría definir un nuevo paquete
que hereda los métodos existentes del paquete `cons 'y anula o agrega otros. Esta
se puede hacer usando los mecanismos de herencia de Perl.

El siguiente ejemplo define un nuevo paquete `cons :: switch 'que anula el estándar
Método de la biblioteca. El método anulado crea módulos de biblioteca vinculados, en lugar de biblioteca
archivo. Se proporciona un nuevo constructor. Los entornos creados con este constructor
tener el nuevo método de biblioteca; otros no lo harán.

contras del paquete :: interruptor;
EMPEZAR {@ISA = 'contras'}

sub nuevo {
cambiar;
bendecir nuevos contras (@_);
}

sub biblioteca {
mi ($ env) = turno;
mi ($ lib) = turno;
my (@objs) = Objetos $ env @_;
Comando $ env $ lib, @objs, q (
% LD -r% LDFLAGS% <-o%>
);
}

Esta funcionalidad podría invocarse como en el siguiente ejemplo:

$ env = new cons :: switch (@overrides);
...
Biblioteca $ env 'lib.o', 'foo.c', 'bar.c';

Invocando Desventajas


El comando `cons 'generalmente se invoca desde la raíz del árbol de construcción. A Construcción presentar
debe existir en ese directorio. Si se usa el argumento '-f', entonces una alternativa Construcción
se puede usar un archivo (y, posiblemente, una raíz alternativa, ya que `cons ' Construcción
directorio que contiene el archivo).

Si se invoca `cons 'desde un hijo de la raíz del árbol de construcción con el argumento` -t',
subirá por la jerarquía del directorio en busca de un Construcción expediente. (Un nombre alternativo puede
todavía se especificará con `-f '.) Los destinos proporcionados en la línea de comando serán modificados
ser relativo a lo descubierto Construcción expediente. Por ejemplo, de un directorio que contiene
un nivel superior Construcción archivo, la siguiente invocación:

% cd libfoo / subdir
% cons -t objetivo

es exactamente equivalente a:

% cons libfoo / subdir / target

Si hay objetivos 'predeterminados' especificados en la jerarquía de directorios Construcción or
Reclutar archivos, solo los destinos predeterminados en o debajo del directorio desde el cual `cons -t '
se invocó se construirá.

El comando se invoca de la siguiente manera:

contras -

donde argumentos puede ser cualquiera de los siguientes, en cualquier orden:

dirigidos Construye el objetivo especificado. Si dirigidos es un directorio, luego compila recursivamente
todo dentro de ese directorio.

+ patrón Limitar el Reclutar archivos considerados solo aquellos que coinciden patrón, cual es
una expresión regular de Perl. Se aceptan múltiples argumentos '+'.

nombre =
Sets nombre valorar val en el hash 'ARG' pasado al nivel superior Construcción archivo.

`-cc 'Muestra el comando que se habría ejecutado, al recuperar de la caché. No
se da una indicación de que el archivo ha sido recuperado; esto es útil para
generar registros de compilación que se puedan comparar con registros de compilación reales.

`-cd 'Desactiva todo el almacenamiento en caché. No lo recupere de la caché ni lo vacíe en la caché.

`-cr 'Construye dependencias en orden aleatorio. Esto es útil al construir múltiples
árboles similares con almacenamiento en caché habilitado.

`-cs 'Sincroniza los destinos de compilación existentes que se encuentran actualizados con el caché.
Esto es útil si el almacenamiento en caché se ha deshabilitado con -cc o se ha habilitado recientemente.
con UseCache.

`-d 'Habilita la depuración de dependencias.

`-f '
Utilice el archivo especificado en lugar de Construcción (pero primero cambie a contener
directorio de presentar).

`-h 'Muestra un mensaje de ayuda local a la compilación actual si hay uno definido, y sale.

`-k 'Continúe avanzando lo más lejos posible después de los errores.

`-o '
Leer archivo de anulación presentar.

`-p 'Muestra productos de construcción en árboles específicos. No se intenta construir.

`-pa 'Muestra productos de construcción y acciones asociadas. No se intenta construir.

`-pw 'Muestra los productos y dónde están definidos. No se intenta construir.

`-q 'No sea detallado acerca de la instalación y eliminación de destinos.

`-r 'Elimina los productos de construcción asociados con . No se intenta construir.

"-R"
Buscar archivos en repos. Múltiple -R repos Los directorios se buscan en el
orden especificada.

`-t 'Recorre la jerarquía de directorios en busca de un Construcción archivo, si no existe
en el directorio actual. Los objetivos se modificarán para que sean relativos a la
Construcción archivo.

`-v 'Muestra la versión` contras' y continúa procesando.

`-V 'Muestra la versión` contras' y sale.

`-wf '
Escriba todos los nombres de archivo considerados en presentar.

`-x 'Muestra un mensaje de ayuda similar a este y sale.

Y construir-argumentos puede ser cualquier argumento que desee procesar en el Construcción archivo.
Tenga en cuenta que debe haber un -- separando los argumentos de los contras y los argumentos que usted
desea procesar en el Construcción archivo.

Procesamiento de construir-argumentos se puede hacer con cualquier paquete estándar como Optar o su
variantes, o cualquier paquete definido por el usuario. cons pasará en el construir-argumentos as @ARGV y
no intentará interpretar nada después de la --.

% cons -R / usr / local / repository -d os = solaris + controlador - -c prueba -f DEBUG

pasaría lo siguiente a los contras

-R / usr / local / repository -d os = solaris + controlador

y lo siguiente, al nivel superior Construcción archivo como @ARGV

-c prueba -f DEPURACIÓN

Tenga en cuenta que 'cons -r.' es equivalente a un recursivo completo "hacer limpio", pero no requiere
apoyo en el Construcción archivo o cualquier Reclutar archivos. Esto es más útil si está
compilar archivos en directorios de origen (si separa los build y exportar directorios,
entonces puede eliminar los directorios).

Las opciones `-p ',` -pa' y `-pw 'son extremadamente útiles para usar como ayuda en la lectura
scripts o depurándolos. Si quieres saber qué script instala exportar / incluir / foo.h,
por ejemplo, simplemente escriba:

% cons -pw export / include / foo.h

Usar y la escritura dependencia escáneres


QuickScan permite configurar escáneres sencillos independientes del destino para los archivos de origen. Solamente
un escáner QuickScan puede estar asociado con cualquier archivo de origen y entorno determinados.

QuickScan se invoca de la siguiente manera:

QuickScan CONSENV CODEREF, NOMBRE DE ARCHIVO [, RUTA]

Se espera que la subrutina a la que hace referencia CODEREF devuelva una lista de nombres de archivos incluidos
directamente por ARCHIVO. Estos nombres de archivo, a su vez, serán escaneados. El argumento PATH opcional
proporciona una ruta de búsqueda para encontrar NOMBRE DE ARCHIVO y / o archivos devueltos por el usuario proporcionado
subrutina. La RUTA puede ser una referencia a una matriz de nombres de directorios de búsqueda, o una
cadena de nombres separados por el carácter separador del sistema (':' en sistemas UNIX, ';' en
WindowsNT).

La subrutina se llama una vez para cada línea del archivo, con $ _ establecido en la línea actual.
Si la subrutina necesita buscar líneas adicionales o, para el caso, el archivo completo,
luego puede leerlos él mismo, desde el identificador de archivo SCAN. También puede terminar el ciclo, si
sabe que no hay más información de inclusión disponible al cerrar el identificador de archivo.

Ya sea que se proporcione una ruta de búsqueda o no, QuickScan primero intenta buscar el archivo
relativo al directorio actual (para el archivo de nivel superior proporcionado directamente a QuickScan),
o desde el directorio que contiene el archivo que hace referencia al archivo. Esto no es muy
general, pero parece lo suficientemente bueno, especialmente si tiene el lujo de escribir su propio
utilidades y puede controlar el uso de la ruta de búsqueda de forma estándar. Finalmente, el
La ruta de búsqueda está, actualmente, separada por dos puntos. Es posible que esto no haga feliz al campamento del NT.

Aquí hay un ejemplo real, tomado de un Construcción archivar aquí:

sub contras :: SMFgen {
my ($ env, @tables) = @_;
foreach $ t (@tables) {
$ env-> QuickScan (sub {/\b\S*?\.smf\b/g}, "$ t.smf",
$ env -> {SMF_INCLUDE_PATH});
$ env-> Comando (
["$ t.smdb.cc", "$ t.smdb.h", "$ t.snmp.cc", "$ t.ami.cc", "$ t.http.cc"],
"$ t.smf",
q(
smfgen% (% SMF_INCLUDE_OPT%)%
)
);
}
}

[TENGA EN CUENTA que la forma `$ env-> QuickScan ... 'y` $ env-> Command ...' no debe ser
necesario, pero, por alguna razón, es necesario para esta invocación en particular. Esto parece
ser un error en Perl o un malentendido de mi parte; este estilo de invocación no
siempre parece ser necesario.]

Esto encuentra todos los nombres del formulario. .smf en el archivo. Devolverá los nombres incluso si
se encuentran dentro de los comentarios, pero eso está bien (el mecanismo es indulgente con los archivos adicionales;
simplemente se ignoran en el supuesto de que el archivo que falta se notará cuando el
program, en este ejemplo, smfgen, se invoca realmente).

Un escáner solo se invoca para un archivo de origen determinado si algún destino lo necesita en el
árbol. Solo se invoca una vez para un archivo fuente determinado.

Aquí hay otra forma de construir el mismo escáner. Este usa una referencia de código explícita,
y también (innecesariamente, en este caso) lee todo el archivo en sí:

sub myscan {
mi (@incluye);
hacer {
empujar (@incluye, /\b\S*?\.smf\b/g);
} tiempo ;
@incluye
}

Tenga en cuenta que el orden del bucle se invierte, con la prueba del bucle al final. Este es
porque la primera línea ya está leída. Este escáner se puede conectar a una fuente
archivar por:

QuickScan $ env \ myscan, "$ _. Smf";

SOPORTE Y SUGERENCIAS


Contras es mantenido por la comunidad de usuarios. Para suscribirse, envíe un correo a contras discutir
[email protected] con cuerpo Suscríbase.

Informe cualquier sugerencia a través del [email protected] mailing list.

Utilice los contras en línea utilizando los servicios de onworks.net


Servidores y estaciones de trabajo gratuitos

Descargar aplicaciones de Windows y Linux

  • 1
    turcodevops
    turcodevops
    TurkDevOps a ? K kaynak yaz? L? M
    geli? tirici topluluklar? Equipo DevTurks
    Taraf?ndan desteklenmektedir..
    Características: https://github.com/turkdevops https://turkdevops.g...
    Descargar turkdevops
  • 2
    asamdf
    asamdf
    * asammdf * es un analizador rápido de Python y
    editor de ASAM (Asociación para
    Estandarización de Automatización y
    Sistemas de medición) MDF / MF4
    (Formato de datos de medición ...
    Descargar asammdf
  • 3
    LAME (Lame no es un codificador MP3)
    LAME (Lame no es un codificador MP3)
    LAME es una herramienta educativa para ser utilizada
    para obtener información sobre la codificación de MP3. Él
    El objetivo del proyecto LAME es mejorar
    la psicoacústica, calidad y velocidad
    de diputado...
    Descargar LAME (Lame no es un codificador de MP3)
  • 4
    wxPython
    wxPython
    Un conjunto de módulos de extensión de Python que
    envuelva las clases GUI multiplataforma de
    wxWidgets.. Audiencia: Desarrolladores. Usuario
    Interfaz: Sistema X Window (X11), Win32...
    Descargar wxPython
  • 5
    administrador de archivos de paquete
    administrador de archivos de paquete
    Este es el administrador de archivos del paquete Total War
    proyecto, a partir de la versión 1.7. A
    breve introducción a Warscape
    modificación: ...
    Descargar administrador de archivos de paquete
  • 6
    IPerf2
    IPerf2
    Una herramienta de tráfico de red para medir
    Rendimiento de TCP y UDP con métricas
    en torno al rendimiento y la latencia. los
    Los objetivos incluyen mantener un activo
    iperf bacalao ...
    Descargar IPerf2
  • Más "

Comandos de Linux

Ad