Idioma: 日本語 | Español | Français | Português | 中文 | English
Anterior | Siguiente | Índice | Original en inglés (gnu.org)

10 Uso de las reglas implícitas

Ciertas maneras estándar de rehacer archivos objetivo se usan con mucha frecuencia. Por ejemplo, una manera habitual de crear un archivo objeto es a partir de un archivo fuente en C usando el compilador de C, cc.

Las reglas implícitas (implicit rules) le indican a make cómo emplear técnicas habituales, de modo que no tenga que especificarlas en detalle cuando quiera usarlas. Por ejemplo, existe una regla implícita para la compilación de C. Los nombres de archivo determinan qué reglas implícitas se ejecutan. Por ejemplo, la compilación de C suele tomar un archivo .c y producir un archivo .o. Por eso make aplica la regla implícita para la compilación de C cuando ve esta combinación de terminaciones de nombre de archivo.

Una cadena de reglas implícitas puede aplicarse en secuencia; por ejemplo, make rehará un archivo .o a partir de un archivo .y pasando por un archivo .c.

Las reglas implícitas incorporadas usan varias variables en sus recetas (recipes), de modo que, cambiando los valores de las variables, se puede cambiar la forma en que funciona la regla implícita. Por ejemplo, la variable CFLAGS controla los indicadores que la regla implícita para la compilación de C entrega al compilador de C.

Puede definir sus propias reglas implícitas escribiendo reglas de patrón (pattern rules).

Las reglas de sufijo (suffix rules) son una manera más limitada de definir reglas implícitas. Las reglas de patrón son más generales y claras, pero las reglas de sufijo se conservan por compatibilidad.

10.1 Uso de las reglas implícitas

Para que make encuentre un método habitual de actualizar un archivo objetivo, todo lo que tiene que hacer es abstenerse de especificar usted mismo las recetas. Escriba una regla sin receta, o no escriba ninguna regla en absoluto. Entonces make determinará qué regla implícita usar en función de qué tipo de archivo fuente existe o puede crearse.

Por ejemplo, suponga que el makefile tiene este aspecto:

foo : foo.o bar.o
        cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)

Como menciona foo.o pero no da una regla para él, make buscará automáticamente una regla implícita que indique cómo actualizarlo. Esto ocurre exista o no actualmente el archivo foo.o.

Si se encuentra una regla implícita, puede proporcionar tanto una receta como uno o más prerrequisitos (prerequisites) (los archivos fuente). Le convendría escribir una regla sin receta para foo.o si necesita especificar prerrequisitos adicionales —como archivos de cabecera— que la regla implícita no puede proporcionar.

Cada regla implícita tiene un patrón de objetivo y patrones de prerrequisito. Puede haber muchas reglas implícitas con el mismo patrón de objetivo. Por ejemplo, numerosas reglas crean archivos «.o»: una, a partir de un archivo «.c» con el compilador de C; otra, a partir de un archivo «.p» con el compilador de Pascal; y así sucesivamente. La regla que realmente se aplica es aquella cuyos prerrequisitos existen o pueden crearse. Así, si tiene un archivo foo.c, make ejecutará el compilador de C; de lo contrario, si tiene un archivo foo.p, make ejecutará el compilador de Pascal; y así sucesivamente.

Por supuesto, cuando escribe el makefile, usted sabe qué regla implícita quiere que make use, y sabe que elegirá esa porque sabe qué posibles archivos de prerrequisito se supone que existen. Consulte Catálogo de reglas incorporadas para ver un catálogo de todas las reglas implícitas predefinidas.

Más arriba dijimos que una regla implícita se aplica si los prerrequisitos requeridos «existen o pueden crearse». Un archivo «puede crearse» si se menciona explícitamente en el makefile como objetivo o prerrequisito, o si puede encontrarse recursivamente una regla implícita para crearlo. Cuando un prerrequisito implícito es el resultado de otra regla implícita, decimos que está ocurriendo encadenamiento (chaining). Consulte Cadenas de reglas implícitas.

En general, make busca una regla implícita para cada objetivo, y para cada regla de doble dos puntos, que no tenga receta. Un archivo que se menciona solo como prerrequisito se considera un objetivo cuya regla no especifica nada, así que para él también ocurre la búsqueda de reglas implícitas. Consulte Algoritmo de búsqueda de reglas implícitas para los detalles de cómo se realiza la búsqueda.

Tenga en cuenta que los prerrequisitos explícitos no influyen en la búsqueda de reglas implícitas. Por ejemplo, considere esta regla explícita:

foo.o: foo.p

El prerrequisito sobre foo.p no significa necesariamente que make vaya a rehacer foo.o según la regla implícita que crea un archivo objeto, un archivo .o, a partir de un archivo fuente de Pascal, un archivo .p. Por ejemplo, si también existe foo.c, se usa en su lugar la regla implícita que crea un archivo objeto a partir de un archivo fuente en C, porque aparece antes que la regla de Pascal en la lista de reglas implícitas predefinidas (consulte Catálogo de reglas incorporadas).

Si no quiere que se use una regla implícita para un objetivo que no tiene receta, puede dar a ese objetivo una receta vacía escribiendo un punto y coma (consulte Definición de recetas vacías).

10.2 Catálogo de reglas incorporadas

Aquí está un catálogo de reglas implícitas predefinidas que siempre están disponibles a menos que el makefile las anule o cancele explícitamente. Consulte Cancelación de reglas implícitas para información sobre cómo cancelar o anular una regla implícita. La opción «-r» o «--no-builtin-rules» cancela todas las reglas predefinidas.

Este manual solo documenta las reglas predeterminadas disponibles en sistemas operativos basados en POSIX. Otros sistemas operativos, como VMS, Windows, OS/2, etc., pueden tener conjuntos distintos de reglas predeterminadas. Para ver la lista completa de reglas y variables predeterminadas disponibles en su versión de GNU make, ejecute «make -p» en un directorio sin makefile.

No todas estas reglas estarán siempre definidas, incluso cuando no se da la opción «-r». Muchas de las reglas implícitas predefinidas están implementadas en make como reglas de sufijo, de modo que cuáles se definen depende de la lista de sufijos (la lista de prerrequisitos del objetivo especial .SUFFIXES). La lista de sufijos predeterminada es: .out, .a, .ln, .o, .c, .cc, .C, .cpp, .p, .f, .F, .m, .r, .y, .l, .ym, .lm, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch .web, .sh, .elc, .el. Todas las reglas implícitas descritas a continuación cuyos prerrequisitos tienen uno de estos sufijos son en realidad reglas de sufijo. Si modifica la lista de sufijos, las únicas reglas de sufijo predefinidas en efecto serán las nombradas por uno o dos de los sufijos que estén en la lista que especifique; las reglas cuyos sufijos no estén en la lista quedan deshabilitadas. Consulte Reglas de sufijo a la antigua usanza para todos los detalles sobre las reglas de sufijo.

Compilación de programas en C

n.o se crea automáticamente a partir de n.c con una receta de la forma «$(CC) $(CPPFLAGS) $(CFLAGS) -c».

Compilación de programas en C++

n.o se crea automáticamente a partir de n.cc, n.cpp o n.C con una receta de la forma «$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c». Le recomendamos usar el sufijo «.cc» o «.cpp» para los archivos fuente de C++ en lugar de «.C», para dar mejor soporte a los sistemas de archivos que no distinguen mayúsculas de minúsculas.

Compilación de programas en Pascal

n.o se crea automáticamente a partir de n.p con la receta «$(PC) $(PFLAGS) -c».

Compilación de programas en Fortran y Ratfor

n.o se crea automáticamente a partir de n.r, n.F o n.f ejecutando el compilador de Fortran. La receta precisa que se usa es la siguiente:

«.f»

«$(FC) $(FFLAGS) -c».

«.F»

«$(FC) $(FFLAGS) $(CPPFLAGS) -c».

«.r»

«$(FC) $(FFLAGS) $(RFLAGS) -c».

Preprocesamiento de programas en Fortran y Ratfor

n.f se crea automáticamente a partir de n.r o n.F. Esta regla ejecuta solo el preprocesador para convertir un programa Ratfor o un programa Fortran preprocesable en un programa Fortran estricto. La receta precisa que se usa es la siguiente:

«.F»

«$(FC) $(CPPFLAGS) $(FFLAGS) -F».

«.r»

«$(FC) $(FFLAGS) $(RFLAGS) -F».

Compilación de programas en Modula-2

n.sym se crea a partir de n.def con una receta de la forma «$(M2C) $(M2FLAGS) $(DEFFLAGS)». n.o se crea a partir de n.mod; la forma es: «$(M2C) $(M2FLAGS) $(MODFLAGS)».

Ensamblado y preprocesamiento de programas en ensamblador

n.o se crea automáticamente a partir de n.s ejecutando el ensamblador, as. La receta precisa es «$(AS) $(ASFLAGS)».

n.s se crea automáticamente a partir de n.S ejecutando el preprocesador de C, cpp. La receta precisa es «$(CPP) $(CPPFLAGS)».

Enlazado de un único archivo objeto

n se crea automáticamente a partir de n.o ejecutando el compilador de C para enlazar el programa. La receta precisa que se usa es «$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)».

Esta regla hace lo correcto para un programa sencillo con un único archivo fuente. También hará lo correcto si hay varios archivos objeto (provenientes presumiblemente de varios otros archivos fuente), uno de los cuales tiene un nombre que coincide con el del archivo ejecutable. Así,

x: y.o z.o

cuando x.c, y.c y z.c existen todos, ejecutará:

cc -c x.c -o x.o
cc -c y.c -o y.o
cc -c z.c -o z.o
cc x.o y.o z.o -o x
rm -f x.o
rm -f y.o
rm -f z.o

En casos más complicados, como cuando no hay ningún archivo objeto cuyo nombre derive del nombre del archivo ejecutable, debe escribir una receta explícita para el enlazado.

Cada tipo de archivo que se convierte automáticamente en archivos objeto «.o» se enlazará automáticamente usando el compilador («$(CC)», «$(FC)» o «$(PC)»; el compilador de C «$(CC)» se usa para ensamblar los archivos «.s») sin la opción «-c». Esto podría hacerse usando los archivos objeto «.o» como intermedios, pero es más rápido hacer la compilación y el enlazado en un solo paso, así que así es como se hace.

Yacc para programas en C

n.c se crea automáticamente a partir de n.y ejecutando Yacc con la receta «$(YACC) $(YFLAGS)».

Lex para programas en C

n.c se crea automáticamente a partir de n.l ejecutando Lex. La receta real es «$(LEX) $(LFLAGS)».

Lex para programas en Ratfor

n.r se crea automáticamente a partir de n.l ejecutando Lex. La receta real es «$(LEX) $(LFLAGS)».

La convención de usar el mismo sufijo «.l» para todos los archivos de Lex, independientemente de si producen código C o código Ratfor, hace imposible que make determine automáticamente cuál de los dos lenguajes está usando en un caso concreto. Si se le pide a make que rehaga un archivo objeto a partir de un archivo «.l», tiene que adivinar qué compilador usar. Adivinará el compilador de C, porque es más común. Si usa Ratfor, asegúrese de que make lo sepa mencionando n.r en el makefile. O bien, si usa Ratfor exclusivamente, sin archivos C, elimine «.c» de la lista de sufijos de reglas implícitas con:

.SUFFIXES:
.SUFFIXES: .o .r .f .l …
Creación de bibliotecas Lint a partir de programas en C, Yacc o Lex

n.ln se crea a partir de n.c ejecutando lint. La receta precisa es «$(LINT) $(LINTFLAGS) $(CPPFLAGS) -i». La misma receta se usa sobre el código C producido a partir de n.y o n.l.

TeX y Web

n.dvi se crea a partir de n.tex con la receta «$(TEX)». n.tex se crea a partir de n.web con «$(WEAVE)», o a partir de n.w (y de n.ch si existe o puede crearse) con «$(CWEAVE)». n.p se crea a partir de n.web con «$(TANGLE)» y n.c se crea a partir de n.w (y de n.ch si existe o puede crearse) con «$(CTANGLE)».

Texinfo e Info

n.dvi se crea a partir de n.texinfo, n.texi o n.txinfo con la receta «$(TEXI2DVI) $(TEXI2DVI_FLAGS)». n.info se crea a partir de n.texinfo, n.texi o n.txinfo con la receta «$(MAKEINFO) $(MAKEINFO_FLAGS)».

RCS

Cualquier archivo n se extrae si es necesario de un archivo RCS llamado n,v o RCS/n,v. La receta precisa que se usa es «$(CO) $(COFLAGS)». n no se extraerá de RCS si ya existe, aunque el archivo RCS sea más reciente. Las reglas para RCS son terminales (consulte Reglas de patrón que coinciden con todo), de modo que los archivos RCS no pueden generarse a partir de otra fuente; deben existir realmente.

SCCS

Cualquier archivo n se extrae si es necesario de un archivo SCCS llamado s.n o SCCS/s.n. La receta precisa que se usa es «$(GET) $(GFLAGS)». Las reglas para SCCS son terminales (consulte Reglas de patrón que coinciden con todo), de modo que los archivos SCCS no pueden generarse a partir de otra fuente; deben existir realmente.

En beneficio de SCCS, un archivo n se copia de n.sh y se hace ejecutable (por todos). Esto es para los scripts de shell que están registrados en SCCS. Como RCS conserva el permiso de ejecución de un archivo, no necesita usar esta característica con RCS.

Le recomendamos evitar el uso de SCCS. Se considera ampliamente que RCS es superior, y además es libre. Al elegir software libre en lugar de software propietario comparable (o inferior), usted apoya el movimiento del software libre.

Normalmente, solo querrá cambiar las variables enumeradas en la tabla anterior, que se documentan en la sección siguiente.

Sin embargo, las recetas de las reglas implícitas incorporadas en realidad usan variables como COMPILE.c, LINK.p y PREPROCESS.S, cuyos valores contienen las recetas enumeradas arriba.

make sigue la convención de que la regla para compilar un archivo fuente .x usa la variable COMPILE.x. De manera similar, la regla para producir un ejecutable a partir de un archivo .x usa LINK.x; y la regla para preprocesar un archivo .x usa PREPROCESS.x.

Toda regla que produce un archivo objeto usa la variable OUTPUT_OPTION. make define esta variable, según una opción de tiempo de compilación, para que contenga «-o $@» o para que esté vacía. Necesita la opción «-o» para asegurar que la salida vaya al archivo correcto cuando el archivo fuente está en un directorio distinto, como al usar VPATH (consulte Búsqueda de directorios para los prerrequisitos). Sin embargo, los compiladores de algunos sistemas no aceptan un conmutador «-o» para los archivos objeto. Si usa un sistema así, y usa VPATH, algunas compilaciones pondrán su salida en el lugar equivocado. Una posible solución alternativa para este problema es dar a OUTPUT_OPTION el valor «; mv $*.o $@».

10.3 Variables usadas por las reglas implícitas

Las recetas de las reglas implícitas incorporadas hacen un uso abundante de ciertas variables predefinidas. Puede alterar los valores de estas variables en el makefile, con argumentos a make o en el entorno, para alterar cómo funcionan las reglas implícitas sin redefinir las reglas mismas. Puede cancelar todas las variables usadas por las reglas implícitas con la opción «-R» o «--no-builtin-variables».

Por ejemplo, la receta usada para compilar un archivo fuente en C en realidad dice «$(CC) -c $(CFLAGS) $(CPPFLAGS)». Los valores predeterminados de las variables usadas son «cc» y nada, lo que da como resultado la orden «cc -c». Al redefinir «CC» como «ncc», podría hacer que se use «ncc» para todas las compilaciones de C que realice la regla implícita. Al redefinir «CFLAGS» como «-g», podría pasar la opción «-g» a cada compilación. Todas las reglas implícitas que hacen compilación de C usan «$(CC)» para obtener el nombre del programa del compilador y todas incluyen «$(CFLAGS)» entre los argumentos dados al compilador.

Las variables usadas en las reglas implícitas se dividen en dos clases: las que son nombres de programas (como CC) y las que contienen argumentos para los programas (como CFLAGS). (El «nombre de un programa» también puede contener algunos argumentos de orden, pero debe comenzar con un nombre de programa ejecutable real.) Si el valor de una variable contiene más de un argumento, sepárelos con espacios.

Las tablas siguientes describen algunas de las variables predefinidas de uso más común. Esta lista no es exhaustiva, y los valores predeterminados que se muestran aquí pueden no ser los que make seleccione para su entorno. Para ver la lista completa de variables predefinidas de su instancia de GNU make, puede ejecutar «make -p» en un directorio sin makefiles.

Aquí está una tabla de algunas de las variables más comunes usadas como nombres de programas en las reglas incorporadas:

AR

Programa de mantenimiento de archivos de archivo (archive); predeterminado «ar».

AS

Programa para compilar archivos en ensamblador; predeterminado «as».

CC

Programa para compilar programas en C; predeterminado «cc».

CXX

Programa para compilar programas en C++; predeterminado «g++».

CPP

Programa para ejecutar el preprocesador de C, con los resultados a la salida estándar; predeterminado «$(CC) -E».

FC

Programa para compilar o preprocesar programas en Fortran y Ratfor; predeterminado «f77».

M2C

Programa que se usa para compilar código fuente en Modula-2; predeterminado «m2c».

PC

Programa para compilar programas en Pascal; predeterminado «pc».

CO

Programa para extraer un archivo de RCS; predeterminado «co».

GET

Programa para extraer un archivo de SCCS; predeterminado «get».

LEX

Programa que se usa para convertir las gramáticas de Lex en código fuente; predeterminado «lex».

YACC

Programa que se usa para convertir las gramáticas de Yacc en código fuente; predeterminado «yacc».

LINT

Programa que se usa para ejecutar lint sobre el código fuente; predeterminado «lint».

MAKEINFO

Programa para convertir un archivo fuente de Texinfo en un archivo Info; predeterminado «makeinfo».

TEX

Programa para crear archivos DVI de TeX a partir de fuente TeX; predeterminado «tex».

TEXI2DVI

Programa para crear archivos DVI de TeX a partir de fuente Texinfo; predeterminado «texi2dvi».

WEAVE

Programa para traducir Web a TeX; predeterminado «weave».

CWEAVE

Programa para traducir C Web a TeX; predeterminado «cweave».

TANGLE

Programa para traducir Web a Pascal; predeterminado «tangle».

CTANGLE

Programa para traducir C Web a C; predeterminado «ctangle».

RM

Orden para eliminar un archivo; predeterminado «rm -f».

Aquí está una tabla de variables cuyos valores son argumentos adicionales para los programas anteriores. El valor predeterminado de todas ellas es la cadena vacía, salvo que se indique lo contrario.

ARFLAGS

Indicadores para dar al programa de mantenimiento de archivos de archivo (archive); predeterminado «rv».

ASFLAGS

Indicadores adicionales para dar al ensamblador (cuando se invoca explícitamente sobre un archivo «.s» o «.S»).

CFLAGS

Indicadores adicionales para dar al compilador de C.

CXXFLAGS

Indicadores adicionales para dar al compilador de C++.

COFLAGS

Indicadores adicionales para dar al programa co de RCS.

CPPFLAGS

Indicadores adicionales para dar al preprocesador de C y a los programas que lo usan (los compiladores de C y de Fortran).

FFLAGS

Indicadores adicionales para dar al compilador de Fortran.

GFLAGS

Indicadores adicionales para dar al programa get de SCCS.

LDFLAGS

Indicadores adicionales para dar a los compiladores cuando se supone que invocan al enlazador, «ld», como -L. Las bibliotecas (-lfoo) deberían añadirse a la variable LDLIBS en su lugar.

LDLIBS

Indicadores o nombres de bibliotecas dados a los compiladores cuando se supone que invocan al enlazador, «ld». LOADLIBES es una alternativa obsoleta (pero aún admitida) a LDLIBS. Los indicadores de enlazado que no sean de biblioteca, como -L, deberían ir en la variable LDFLAGS.

LFLAGS

Indicadores adicionales para dar a Lex.

YFLAGS

Indicadores adicionales para dar a Yacc.

PFLAGS

Indicadores adicionales para dar al compilador de Pascal.

RFLAGS

Indicadores adicionales para dar al compilador de Fortran para los programas en Ratfor.

LINTFLAGS

Indicadores adicionales para dar a lint.

10.4 Cadenas de reglas implícitas

A veces, un archivo puede crearse mediante una secuencia de reglas implícitas. Por ejemplo, un archivo n.o podría crearse a partir de n.y ejecutando primero Yacc y luego cc. Tal secuencia se llama cadena.

Si el archivo n.c existe, o se menciona en el makefile, no se requiere ninguna búsqueda especial: make descubre que el archivo objeto puede crearse por compilación de C a partir de n.c; más tarde, al considerar cómo crear n.c, se usa la regla para ejecutar Yacc. Finalmente se actualizan tanto n.c como n.o.

Sin embargo, aunque n.c no exista y no se mencione, ¡make sabe imaginarlo como el eslabón perdido entre n.o y n.y! En este caso, n.c se llama un archivo intermedio (intermediate file). Una vez que make ha decidido usar el archivo intermedio, se registra en la base de datos como si se hubiera mencionado en el makefile, junto con la regla implícita que indica cómo crearlo.

Los archivos intermedios se rehacen usando sus reglas igual que todos los demás archivos. Pero los archivos intermedios reciben un trato distinto en dos aspectos.

La primera diferencia es lo que ocurre si el archivo intermedio no existe. Si un archivo ordinario b no existe, y make considera un objetivo que depende de b, invariablemente crea b y luego actualiza el objetivo a partir de b. Pero si b es un archivo intermedio, entonces make puede dejar las cosas como están: no creará b a menos que alguno de sus prerrequisitos esté desactualizado. Esto significa que el objetivo que depende de b tampoco se reconstruirá, salvo que haya alguna otra razón para actualizar ese objetivo: por ejemplo, que el objetivo no exista o que un prerrequisito distinto sea más reciente que el objetivo.

La segunda diferencia es que, si make crea b para actualizar otra cosa, lo elimina más tarde, una vez que ya no es necesario. Por lo tanto, un archivo intermedio que no existía antes de make tampoco existe después de make. make le informa de la eliminación mostrando una orden «rm» que indica qué archivo está eliminando.

Puede marcar explícitamente un archivo como intermedio enumerándolo como prerrequisito del objetivo especial .INTERMEDIATE. Esto surte efecto incluso si el archivo se menciona explícitamente de alguna otra manera.

Un archivo no puede ser intermedio si se menciona en el makefile como objetivo o prerrequisito, así que una manera de evitar la eliminación de los archivos intermedios es añadirlo como prerrequisito de algún objetivo. Sin embargo, hacerlo puede provocar que make haga trabajo adicional al buscar reglas de patrón (consulte Algoritmo de búsqueda de reglas implícitas).

Como alternativa, enumerar un archivo como prerrequisito del objetivo especial .NOTINTERMEDIATE hace que no se considere intermedio (igual que cualquier otra mención del archivo lo haría). Además, enumerar el patrón de objetivo de una regla de patrón como prerrequisito de .NOTINTERMEDIATE asegura que ningún objetivo generado usando esa regla de patrón se considere intermedio.

Puede deshabilitar por completo los archivos intermedios en su makefile proporcionando .NOTINTERMEDIATE como objetivo sin prerrequisitos: en ese caso se aplica a todos los archivos del makefile.

Si no quiere que make cree un archivo simplemente porque todavía no existe, pero tampoco quiere que make elimine automáticamente el archivo, puede marcarlo como archivo secundario (secondary). Para ello, enumérelo como prerrequisito del objetivo especial .SECONDARY. Marcar un archivo como secundario también lo marca como intermedio.

Una cadena puede involucrar más de dos reglas implícitas. Por ejemplo, es posible crear un archivo foo a partir de RCS/foo.y,v ejecutando RCS, Yacc y cc. Entonces tanto foo.y como foo.c son archivos intermedios que se eliminan al final.

Ninguna regla implícita por sí sola puede aparecer más de una vez en una cadena. Esto significa que make ni siquiera considerará algo tan ridículo como crear foo a partir de foo.o.o ejecutando el enlazador dos veces. Esta restricción tiene el beneficio adicional de impedir cualquier bucle infinito en la búsqueda de una cadena de reglas implícitas.

Hay algunas reglas implícitas especiales para optimizar ciertos casos que de otro modo se manejarían mediante cadenas de reglas. Por ejemplo, crear foo a partir de foo.c podría manejarse compilando y enlazando con reglas encadenadas separadas, usando foo.o como archivo intermedio. Pero lo que realmente ocurre es que una regla especial para este caso hace la compilación y el enlazado con una sola orden cc. La regla optimizada se usa con preferencia a la cadena paso a paso porque aparece antes en el orden de las reglas.

Por último, por razones de rendimiento, make no considerará las reglas no terminales que coinciden con todo (es decir, «%:») al buscar una regla para construir un prerrequisito de una regla implícita (consulte Reglas de patrón que coinciden con todo).

10.5 Definición y redefinición de reglas de patrón

Una regla implícita se define escribiendo una regla de patrón (pattern rule). Una regla de patrón se parece a una regla ordinaria, salvo que su objetivo contiene el carácter «%» (exactamente uno). El objetivo se considera un patrón para hacer coincidir nombres de archivo; el «%» puede coincidir con cualquier subcadena no vacía, mientras que los demás caracteres solo coinciden consigo mismos. Los prerrequisitos también usan «%» para mostrar cómo se relacionan sus nombres con el nombre del objetivo.

Así, una regla de patrón «%.o : %.c» indica cómo crear cualquier archivo stem.o a partir de otro archivo stem.c.

Tenga en cuenta que la expansión usando «%» en las reglas de patrón ocurre después de cualquier expansión de variables o funciones, que tiene lugar cuando se lee el makefile. Consulte Cómo usar las variables y Funciones para transformar texto.

10.5.1 Introducción a las reglas de patrón

Una regla de patrón contiene el carácter «%» (exactamente uno) en el objetivo; por lo demás, se ve exactamente igual que una regla ordinaria. El objetivo es un patrón para hacer coincidir nombres de archivo; el «%» coincide con cualquier subcadena no vacía, mientras que los demás caracteres solo coinciden consigo mismos.

Por ejemplo, «%.c» como patrón coincide con cualquier nombre de archivo que termina en «.c». «s.%.c» como patrón coincide con cualquier nombre de archivo que comienza con «s.», termina en «.c» y tiene al menos cinco caracteres de longitud. (Debe haber al menos un carácter para coincidir con el «%».) La subcadena con la que coincide el «%» se llama raíz (stem).

El «%» en un prerrequisito de una regla de patrón representa la misma raíz con la que coincidió el «%» del objetivo. Para que la regla de patrón se aplique, su patrón de objetivo debe coincidir con el nombre de archivo en consideración y todos sus prerrequisitos (tras la sustitución del patrón) deben nombrar archivos que existan o puedan crearse. Estos archivos se convierten en prerrequisitos del objetivo.

Así, una regla de la forma

%.o : %.c ; recipe

especifica cómo crear un archivo n.o, con otro archivo n.c como prerrequisito, siempre que n.c exista o pueda crearse.

También puede haber prerrequisitos que no usen «%»; tal prerrequisito se adjunta a todos los archivos creados por esta regla de patrón. Estos prerrequisitos invariables resultan útiles de vez en cuando.

Una regla de patrón no necesita tener ningún prerrequisito que contenga «%», ni de hecho ningún prerrequisito en absoluto. Tal regla es, en efecto, un comodín general. Proporciona una manera de crear cualquier archivo que coincida con el patrón de objetivo. Consulte Definición de reglas predeterminadas de último recurso.

Más de una regla de patrón puede coincidir con un objetivo. En ese caso, make elegirá la regla que «mejor encaja». Consulte Cómo coinciden los patrones.

Las reglas de patrón pueden tener más de un objetivo; sin embargo, cada objetivo debe contener un carácter %. Los múltiples patrones de objetivo en las reglas de patrón siempre se tratan como objetivos agrupados (consulte Múltiples objetivos en una regla), independientemente de si usan el separador : o &:.

Hay una sola excepción. Si un objetivo de patrón está desactualizado o no existe pero el makefile no necesita construirlo, ese objetivo no hace que los demás objetivos se consideren desactualizados. Tenga en cuenta que esta excepción histórica está prevista para ser eliminada en una versión futura de GNU make, así que no debería confiar en ella. Si make detecta esta situación, emite una advertencia pattern recipe did not update peer target (la receta de patrón no actualizó el objetivo asociado). Sin embargo, make no puede detectar todas esas situaciones. Asegúrese de que, cuando se ejecute la receta, se actualicen todos los patrones de objetivo.

10.5.2 Ejemplos de reglas de patrón

Aquí están algunos ejemplos de reglas de patrón que en realidad están predefinidas en make. Primero, la regla que compila archivos «.c» en archivos «.o»:

%.o : %.c
        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

Esto define una regla que puede crear cualquier archivo x.o a partir de x.c. La receta usa las variables automáticas «$@» y «$<» para sustituir los nombres del archivo objetivo y del archivo fuente en cada caso en que se aplica la regla (consulte Variables automáticas).

Una segunda regla incorporada:

% :: RCS/%,v
        $(CO) $(COFLAGS) $<

Esto define una regla que puede crear cualquier archivo x, sea cual sea, a partir del archivo correspondiente x,v en el subdirectorio RCS. Como el objetivo es «%», esta regla se aplica a cualquier archivo siempre que exista el archivo de prerrequisito apropiado. El doble dos puntos hace que esta regla sea terminal (terminal); esto significa que su prerrequisito no puede ser un archivo intermedio (consulte Reglas de patrón que coinciden con todo).

Esta regla de patrón tiene dos objetivos:

%.tab.c %.tab.h: %.y
        bison -d $<

Esto le indica a make que la receta «bison -d x.y» crea tanto x.tab.c como x.tab.h. Si el archivo foo depende de los archivos parse.tab.o y scan.o, y además el archivo scan.o depende del archivo parse.tab.h, entonces, cuando parse.y cambia, la receta «bison -d parse.y» se ejecuta una sola vez y se satisfacen los prerrequisitos tanto de parse.tab.o como de scan.o. (Probablemente, el archivo parse.tab.o se recompila a partir de parse.tab.c y el archivo scan.o a partir de scan.c, mientras que foo se enlaza a partir de parse.tab.o, scan.o y sus demás prerrequisitos, y a partir de entonces sigue funcionando felizmente.)

10.5.3 Variables automáticas

Suponga que está escribiendo una regla de patrón para compilar un archivo «.c» en un archivo «.o». ¿Cómo escribir la orden «cc» de modo que opere sobre el nombre correcto del archivo fuente? No puede escribir ese nombre en la receta, porque el nombre es distinto cada vez que se aplica la regla implícita.

Para eso se usa una característica especial de make: las variables automáticas (automatic variables). Estas variables se vuelven a calcular de nuevo para cada regla que se ejecuta, a partir del objetivo y los prerrequisitos de esa regla. En este ejemplo, usaría «$@» para el nombre del archivo objeto y «$<» para el nombre del archivo fuente.

Es muy importante reconocer que las variables automáticas tienen un alcance limitado en el que sus valores están disponibles: solo tienen valor dentro de la receta. En particular, no puede usarlas en ninguna parte de la lista de objetivos de una regla; ahí carecen de valor y se expanden a la cadena vacía. Tampoco puede acceder a ellas directamente en la lista de prerrequisitos de una regla. Un error común es intentar usar $@ en la lista de prerrequisitos; eso no funcionará. Sin embargo, GNU make tiene una característica especial, la expansión secundaria (consulte Expansión secundaria), que le permite usar los valores de las variables automáticas en la lista de prerrequisitos.

Aquí está una tabla de las variables automáticas:

$@

El nombre de archivo del objetivo de la regla. Si el objetivo es un miembro de archivo de archivo (archive), «$@» es el nombre del archivo de archivo. En las reglas de patrón que tienen múltiples objetivos (consulte Introducción a las reglas de patrón), «$@» es el nombre del objetivo que provocó que se ejecutara la receta de la regla.

$%

El nombre de miembro del objetivo, cuando el objetivo es un miembro de archivo de archivo (archive). Consulte Uso de make para actualizar archivos de archivo. Por ejemplo, si el objetivo es foo.a(bar.o), «$%» es bar.o y «$@» es foo.a. «$%» está vacío cuando el objetivo no es un miembro de archivo de archivo.

$<

El nombre del primer prerrequisito. Si el objetivo obtuvo su receta de una regla implícita, este será el primer prerrequisito añadido por la regla implícita (consulte Uso de las reglas implícitas).

$?

Los nombres de todos los prerrequisitos más recientes que el objetivo, separados por espacios. Si el objetivo no existe, se incluyen todos los prerrequisitos. Para los prerrequisitos que son miembros de archivo de archivo (archive), solo se usa el miembro indicado (consulte Uso de make para actualizar archivos de archivo).

«$?» también resulta útil incluso en reglas explícitas cuando desea operar solo sobre los prerrequisitos que han cambiado. Por ejemplo, suponga que un archivo de archivo llamado lib debe contener copias de varios archivos objeto. Esta regla copia en el archivo de archivo solo los archivos objeto que han cambiado:

lib: foo.o bar.o lose.o win.o
        ar r lib $?
$^

Los nombres de todos los prerrequisitos, separados por espacios. Para los prerrequisitos que son miembros de archivo de archivo (archive), solo se usa el miembro indicado (consulte Uso de make para actualizar archivos de archivo). Un objetivo tiene un solo prerrequisito por cada archivo del que depende, sin importar cuántas veces se enumere cada archivo como prerrequisito. Así, si enumera el mismo prerrequisito más de una vez para un objetivo, el valor de $^ contiene una sola copia de ese nombre. Esta lista no incluye los prerrequisitos de solo orden; para esos, consulte la variable «$|» que se describe más abajo.

$+

Esto es parecido a «$^», pero los prerrequisitos enumerados más de una vez se duplican en el orden en que se enumeran en el makefile. Esto resulta útil principalmente en las órdenes de enlazado, donde tiene sentido repetir los nombres de los archivos de biblioteca en un orden concreto.

$|

Los nombres de todos los prerrequisitos de solo orden, separados por espacios.

$*

La raíz con la que coincidió una regla implícita (consulte Cómo coinciden los patrones). Si el objetivo es dir/a.foo.b y el patrón de objetivo es a.%.b, la raíz es dir/foo. La raíz resulta útil para construir los nombres de archivos relacionados.

En las reglas de patrón estáticas, la raíz es la parte del nombre de archivo con la que coincidió el «%» del patrón de objetivo.

Las reglas explícitas no tienen raíz, así que «$*» no puede determinarse de esa manera. En su lugar, si el nombre del objetivo termina con un sufijo reconocido (consulte Reglas de sufijo a la antigua usanza), «$*» se fija al nombre del objetivo sin ese sufijo. Por ejemplo, si el nombre del objetivo es «foo.c», entonces «$*» se fija a «foo», ya que «.c» es un sufijo. GNU make hace esta cosa tan extraña solo por compatibilidad con otras implementaciones de make. En general, debería evitar usar «$*» fuera de las reglas implícitas o las reglas de patrón estáticas.

Si en una regla explícita el nombre del objetivo no termina con un sufijo reconocido, «$*» se fija a la cadena vacía en esa regla.

De las variables mencionadas arriba, cuatro tienen como valor un único nombre de archivo y tres tienen como valor una lista de nombres de archivo. Estas siete variables tienen variantes que obtienen solo el nombre de directorio del archivo o solo el nombre de archivo dentro del directorio. Los nombres de las variantes se forman añadiendo «D» o «F», respectivamente, al final. Las funciones dir y notdir producen un efecto similar (consulte Funciones para nombres de archivo). No obstante, tenga en cuenta que todas las variantes «D» omiten la barra final; la salida de la función dir siempre incluye una barra final. Aquí está una tabla de las variantes:

«$(@D)»

La parte de directorio del nombre de archivo del objetivo, con la barra final eliminada. Si el valor de «$@» es dir/foo.o, entonces «$(@D)» es dir. Este valor es . si «$@» no contiene ninguna barra.

«$(@F)»

La parte de nombre de archivo dentro del directorio del nombre de archivo del objetivo. Si el valor de «$@» es dir/foo.o, entonces «$(@F)» es foo.o. «$(@F)» es equivalente a «$(notdir $@)».

«$(*D)»
«$(*F)»

Las partes de directorio y de nombre de archivo dentro del directorio de la raíz; en este ejemplo, dir y foo.

«$(%D)»
«$(%F)»

Las partes de directorio y de nombre de archivo dentro del directorio del nombre de miembro de archivo de archivo del objetivo. Esto solo tiene sentido para objetivos de miembro de archivo de archivo de la forma archive(member) y solo resulta útil cuando member puede contener un nombre de directorio. (Consulte Miembros de archivo de archivo como objetivos.)

«$(<D)»
«$(<F)»

Las partes de directorio y de nombre de archivo dentro del directorio del primer prerrequisito.

«$(^D)»
«$(^F)»

Las listas de partes de directorio y de partes de nombre de archivo dentro del directorio de todos los prerrequisitos.

«$(+D)»
«$(+F)»

Las listas de partes de directorio y de partes de nombre de archivo dentro del directorio de todos los prerrequisitos, incluidas las múltiples instancias de prerrequisitos duplicados.

«$(?D)»
«$(?F)»

Las listas de partes de directorio y de partes de nombre de archivo dentro del directorio de todos los prerrequisitos más recientes que el objetivo.

Tenga en cuenta que usamos una convención estilística especial al hablar de estas variables automáticas; no escribimos «la variable <», como escribiríamos al hablar de variables ordinarias como objects y CFLAGS, sino que escribimos «el valor de “$<”». Creemos que esta convención se ve más natural en este caso especial. No tome esto como si tuviera algún significado profundo; «$<» se refiere a la variable llamada <, igual que «$(CFLAGS)» se refiere a la variable llamada CFLAGS. Podría usar «$(<)» en lugar de «$<» con exactamente el mismo resultado.

10.5.4 Cómo coinciden los patrones

Un patrón de objetivo se compone colocando un «%» entre un prefijo y un sufijo, cualquiera de los cuales —o ambos— puede estar vacío. El patrón coincide con un nombre de archivo solo si el nombre de archivo comienza con el prefijo y termina con el sufijo, sin que ambos se solapen. El texto entre el prefijo y el sufijo se llama raíz. Así, cuando el patrón «%.o» coincide con el nombre de archivo test.o, la raíz es «test». Los prerrequisitos de la regla de patrón se convierten en nombres de archivo reales sustituyendo el carácter «%» por la raíz. Así, en el mismo ejemplo, si uno de los prerrequisitos se escribe «%.c», se expande a «test.c».

Cuando el patrón de objetivo no contiene una barra (y normalmente no la contiene), los nombres de directorio del nombre de archivo se eliminan de este antes de compararlo con el prefijo y el sufijo del objetivo. Tras la comparación del nombre de archivo con el patrón de objetivo, los nombres de directorio, junto con la barra que los termina, se añaden a los nombres de archivo de prerrequisito generados a partir del patrón de prerrequisito de la regla de patrón y del nombre de archivo. Los directorios se ignoran solo a efectos de encontrar la regla implícita que se va a usar, no en la aplicación de esa regla. Así, «e%t» coincide con el nombre de archivo src/eat, con «src/a» como raíz. Cuando los prerrequisitos se convierten en nombres de archivo, los directorios de la raíz se añaden al principio, mientras que el resto de la raíz se sustituye por el «%». La raíz «src/a» con el patrón de prerrequisito «c%r» da el nombre de archivo src/car.

Una regla de patrón puede usarse para construir un archivo dado solo si hay un patrón de objetivo que coincide con su nombre de archivo y todos los prerrequisitos de esa regla existen o pueden construirse. Las reglas que usted escribe tienen prioridad sobre las reglas incorporadas. No obstante, tenga en cuenta que una regla cuyos prerrequisitos pueden satisfacerse sin encadenar otras reglas implícitas (por ejemplo, una regla sin prerrequisitos, o cuyos prerrequisitos ya existen o se mencionan) siempre tiene prioridad sobre una regla con prerrequisitos que deben crearse encadenando otras reglas implícitas.

Puede haber más de una regla de patrón que cumpla estos criterios. En ese caso, make elegirá la regla con la raíz más corta (es decir, el patrón que coincide de la forma más específica). Si hay varias reglas de patrón con la raíz más corta, make elegirá la primera que encuentre en el makefile.

Como resultado de este algoritmo, las reglas más específicas tienen prioridad sobre las más generales. Por ejemplo:

%.o: %.c
        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

%.o : %.f
        $(COMPILE.F) $(OUTPUT_OPTION) $<

lib/%.o: lib/%.c
        $(CC) -fPIC -c $(CFLAGS) $(CPPFLAGS) $< -o $@

Con estas reglas, cuando se le pide construir bar.o y existen tanto bar.c como bar.f, make elige la primera regla y compila bar.c en bar.o. En la misma situación, si bar.c no existe, make elige la segunda regla y compila bar.f en bar.o.

Cuando se le pide a make construir lib/bar.o y existen tanto lib/bar.c como lib/bar.f, se elige la tercera regla, porque la raíz de esta regla («bar») es más corta que la raíz de la primera regla («lib/bar»). Si lib/bar.c no existe, la tercera regla deja de ser elegible y se usa la segunda regla, aunque su raíz sea más larga.

10.5.5 Reglas de patrón que coinciden con todo

Cuando el objetivo de una regla de patrón es simplemente «%», coincide con cualquier nombre de archivo, sea cual sea. A estas reglas las llamamos reglas que coinciden con todo (match-anything). Resultan muy útiles, pero a make puede llevarle mucho tiempo considerarlas, porque debe considerar todas esas reglas para cada nombre de archivo enumerado como objetivo o prerrequisito.

Suponga que el makefile menciona foo.c. Para este objetivo, make tendría que considerar crearlo enlazando un archivo objeto foo.c.o, o haciendo la compilación y el enlazado de C en un solo paso a partir de foo.c.c, o haciendo la compilación y el enlazado de Pascal a partir de foo.c.p, y muchas otras posibilidades.

Sabemos que estas posibilidades son ridículas, porque foo.c es un archivo fuente en C, no un archivo ejecutable. Aunque make considerara estas posibilidades, acabaría rechazándolas porque archivos como foo.c.o y foo.c.p no existen. Pero estas posibilidades son tan numerosas que, si make tuviera que considerarlas, sería muy lento.

Para acelerar las cosas, hemos puesto varias restricciones a la manera en que make considera las reglas que coinciden con todo. Hay dos clases de restricciones que pueden aplicarse, y cada vez que define una regla que coincide con todo debe elegir una u otra para esa regla.

Una opción es marcar la regla que coincide con todo como terminal definiéndola con un doble dos puntos. Cuando una regla es terminal, no se aplica a menos que sus prerrequisitos existan realmente. Los prerrequisitos que podrían crearse con otras reglas implícitas no bastan. En otras palabras, no se permite más encadenamiento más allá de una regla terminal.

Por ejemplo, las reglas implícitas incorporadas que extraen las fuentes de archivos RCS y SCCS son terminales; en consecuencia, si el archivo foo.c,v no existe, make ni siquiera considerará intentar crearlo como archivo intermedio a partir de foo.c,v.o o de RCS/SCCS/s.foo.c,v. Los archivos RCS y SCCS son, en general, archivos fuente últimos, que no deberían rehacerse a partir de ningún otro archivo; por lo tanto, make puede ahorrar tiempo no buscando maneras de rehacerlos.

Si no marca como terminal una regla que coincide con todo, entonces es no terminal. Una regla que coincide con todo no terminal no puede aplicarse a un prerrequisito de una regla implícita, ni a un nombre de archivo que indica un tipo concreto de datos. Un nombre de archivo indica un tipo concreto de datos si alguno de los objetivos de una regla implícita que no coincide con todo coincide con él.

Por ejemplo, el nombre de archivo foo.c coincide con el objetivo de la regla de patrón «%.c : %.y» (la regla que ejecuta Yacc). Independientemente de si esta regla es realmente aplicable (lo que ocurre solo si existe un archivo foo.y), el solo hecho de que su objetivo coincida basta para impedir que se consideren reglas que coinciden con todo no terminales para el archivo foo.c. Así, make ni siquiera considerará intentar crear foo.c como archivo ejecutable a partir de foo.c.o, foo.c.c, foo.c.p, etc.

La motivación de esta restricción es la siguiente: las reglas que coinciden con todo no terminales se usan para crear archivos que contienen un tipo concreto de datos (como archivos ejecutables), mientras que un nombre de archivo con un sufijo reconocido indica otro tipo concreto de datos (como un archivo fuente en C).

Existen reglas de patrón ficticias incorporadas especiales con el único fin de reconocer ciertos nombres de archivo, de modo que no se consideren reglas que coinciden con todo no terminales. Estas reglas ficticias no tienen prerrequisitos ni recetas, y se ignoran para cualquier otro propósito. Por ejemplo, la regla implícita incorporada

%.p :

existe para hacer que los archivos fuente de Pascal como foo.p coincidan con un patrón de objetivo concreto y evitar así que se pierda tiempo buscando foo.p.o o foo.p.c.

Se crean reglas de patrón ficticias como la de «%.p» para cada sufijo enumerado como válido para su uso en reglas de sufijo (consulte Reglas de sufijo a la antigua usanza).

10.5.6 Cancelación de reglas implícitas

Puede anular una regla implícita incorporada (o una que usted mismo haya definido) definiendo una nueva regla de patrón con el mismo objetivo y prerrequisitos, pero con una receta distinta. Cuando se define la nueva regla, se reemplaza la incorporada. La posición de la nueva regla en el orden de las reglas implícitas viene determinada por el lugar donde escriba la nueva regla.

Puede cancelar una regla implícita incorporada definiendo una regla de patrón con el mismo objetivo y prerrequisitos, pero sin receta. Por ejemplo, lo siguiente cancela la regla que ejecuta el ensamblador:

%.o : %.s

10.6 Definición de reglas predeterminadas de último recurso

Puede definir una regla implícita de último recurso escribiendo una regla de patrón terminal que coincide con todo y no tiene prerrequisitos (consulte Reglas de patrón que coinciden con todo). Es exactamente igual que cualquier otra regla de patrón; lo único especial es que coincide con cualquier objetivo. Por eso, la receta de tal regla se usa para todos los objetivos y prerrequisitos que no tienen receta propia y a los que no se aplica ninguna otra regla implícita.

Por ejemplo, al probar un makefile, puede que no le importe si los archivos fuente contienen datos reales, solo que existan. Entonces puede hacer lo siguiente:

%::
        touch $@

Esto hace que todos los archivos fuente necesarios (como prerrequisitos) se creen automáticamente.

Como alternativa, puede definir una receta que se use para los objetivos que no tienen ninguna regla en absoluto, incluso para los que no especifican receta. Esto se hace escribiendo una regla para el objetivo .DEFAULT. La receta de tal regla se usa para todos los prerrequisitos que no aparecen como objetivo de ninguna regla explícita y a los que no se aplica ninguna regla implícita. Naturalmente, no hay regla .DEFAULT a menos que la escriba usted mismo.

Si usa .DEFAULT sin receta ni prerrequisitos:

.DEFAULT:

se borra la receta que se hubiera almacenado anteriormente para .DEFAULT. Entonces make se comporta como si nunca hubiera definido .DEFAULT.

Si no quiere que un objetivo obtenga su receta de una regla de patrón que coincide con todo o de .DEFAULT, pero tampoco quiere que se ejecute ninguna receta para ese objetivo, puede darle una receta vacía (consulte Definición de recetas vacías).

Puede usar una regla de último recurso para anular parte de otro makefile. Consulte Anular parte de otro makefile.

10.7 Reglas de sufijo a la antigua usanza

Las reglas de sufijo (suffix rules) son la manera a la antigua de definir reglas implícitas para make. Las reglas de sufijo están anticuadas, porque las reglas de patrón son más generales y claras. GNU make las admite por compatibilidad con makefiles antiguos. Hay dos tipos de reglas de sufijo: de doble sufijo (double-suffix) y de sufijo único (single-suffix).

Una regla de doble sufijo se define por un par de sufijos: el sufijo de objetivo y el sufijo de fuente. Coincide con cualquier archivo cuyo nombre termina con el sufijo de objetivo. El prerrequisito implícito correspondiente se forma reemplazando el sufijo de objetivo del nombre de archivo por el sufijo de fuente. Una regla de dos sufijos «.c.o» (cuyos sufijos de objetivo y de fuente son «.o» y «.c», respectivamente) es equivalente a la regla de patrón «%.o : %.c».

Una regla de sufijo único se define por un solo sufijo, que es el sufijo de fuente. Coincide con cualquier nombre de archivo, y el nombre de prerrequisito implícito correspondiente se forma añadiendo el sufijo de fuente al final. Una regla de sufijo único cuyo sufijo de fuente es «.c» es equivalente a la regla de patrón «% : %.c».

Las definiciones de reglas de sufijo se reconocen comparando el objetivo de cada regla con una lista predefinida de sufijos conocidos. Cuando make encuentra una regla cuyo objetivo es un sufijo conocido, considera esa regla como una regla de sufijo único. Cuando make encuentra una regla cuyo objetivo es la concatenación de dos sufijos conocidos, considera esa regla como una regla de doble sufijo.

Por ejemplo, «.c» y «.o» están ambos en la lista predeterminada de sufijos conocidos. Por lo tanto, si define una regla cuyo objetivo es «.c.o», make la considera una regla de doble sufijo cuyo sufijo de fuente es «.c» y cuyo sufijo de objetivo es «.o». Aquí está la manera a la antigua de definir la regla que compila un archivo fuente en C:

.c.o:
        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

Las reglas de sufijo no pueden tener prerrequisitos propios. Si los tienen, se tratan como archivos ordinarios con nombres extraños, no como reglas de sufijo. Así, la regla:

.c.o: foo.h
        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

indica cómo crear el archivo .c.o a partir del archivo de prerrequisito foo.h, y no se parece en nada a la regla de patrón:

%.o: %.c foo.h
        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

Esta última indica cómo crear un archivo «.o» a partir de un archivo «.c» y, al mismo tiempo, hace que todos los archivos «.o» creados con esta regla de patrón dependan también de foo.h.

Una regla de sufijo sin receta tampoco tiene sentido. No elimina reglas anteriores, a diferencia de una regla de patrón sin receta (consulte Cancelación de reglas implícitas). Simplemente registra el sufijo, o el par de sufijos concatenados, como objetivo en la base de datos.

Los sufijos conocidos no son más que los nombres de los prerrequisitos del objetivo especial .SUFFIXES. Puede añadir sus propios sufijos escribiendo una regla que añada prerrequisitos a .SUFFIXES. De esta manera:

.SUFFIXES: .hack .win

Esto añade «.hack» y «.win» al final de la lista de sufijos.

Si quiere eliminar los sufijos conocidos predeterminados en lugar de añadir a ellos, escriba una regla para .SUFFIXES sin prerrequisitos. Por una disposición especial, esto elimina todos los prerrequisitos existentes de .SUFFIXES. Después puede escribir otra regla para añadir los sufijos que quiera. Por ejemplo:

.SUFFIXES:            # Eliminar los sufijos predeterminados
.SUFFIXES: .c .o .h   # Definir nuestra propia lista de sufijos

La opción «-r» o «--no-builtin-rules» vacía la lista de sufijos predeterminada.

La variable SUFFIXES se define con la lista de sufijos predeterminada antes de que make lea cualquier makefile. Puede cambiar la lista de sufijos con una regla para el objetivo especial .SUFFIXES, pero eso no cambia esta variable.

10.8 Algoritmo de búsqueda de reglas implícitas

Aquí está el procedimiento que sigue make para buscar una regla implícita para un objetivo t. Este procedimiento se sigue para cada regla de doble dos puntos sin receta, para cada objetivo de las reglas ordinarias que tampoco tienen receta, y para cada prerrequisito que no es objetivo de ninguna regla. También se sigue recursivamente para los prerrequisitos que provienen de reglas implícitas, en la búsqueda de una cadena de reglas.

Las reglas de sufijo no se mencionan en este algoritmo porque se convierten en reglas de patrón equivalentes una vez leído el makefile.

Para un objetivo de miembro de archivo de archivo de la forma «archive(member)», el siguiente algoritmo se ejecuta dos veces: la primera, usando el nombre completo del objetivo t; y, si no se encuentra ninguna regla en la primera, la segunda, usando «(member)» como objetivo t.

  1. Divida t en una parte de directorio (llamada d) y el resto (llamado n). Por ejemplo, si t es «src/foo.o», entonces d es «src/» y n es «foo.o».
  2. Cree una lista de todas las reglas de patrón uno de cuyos objetivos coincide con t o n. Si el patrón de objetivo contiene una barra, se compara con t; en caso contrario, con n.
  3. Si en la lista hay alguna regla que no es una regla que coincide con todo, o si t es un prerrequisito de una regla implícita, elimine de la lista todas las reglas que coinciden con todo no terminales.
  4. Elimine de la lista todas las reglas que no tienen receta.
  5. Para cada regla de patrón de la lista:
    1. Encuentre la raíz s, que es la parte no vacía de t o n con la que coincidió el «%» del patrón de objetivo.
    2. Calcule los nombres de los prerrequisitos sustituyendo s por el «%». Si el patrón de objetivo no contiene una barra, añada d al principio de cada nombre de prerrequisito.
    3. Compruebe si todos los prerrequisitos existen o deberían existir. (Decimos que un nombre de archivo debería existir si se menciona en el makefile como objetivo o como prerrequisito explícito de un objetivo T.)

      Si todos los prerrequisitos existen o deberían existir, o si no hay prerrequisitos, esta regla se aplica.

  6. Si hasta aquí no se ha encontrado ninguna regla de patrón, esfuércese más. Para cada regla de patrón de la lista:
    1. Si la regla es terminal, ignórela y pase a la siguiente regla.
    2. Calcule los nombres de los prerrequisitos como antes.
    3. Compruebe si todos los prerrequisitos existen o deberían existir.
    4. Para cada prerrequisito que no existe, siga este algoritmo recursivamente para ver si el prerrequisito puede crearse con una regla implícita.
    5. Si todos los prerrequisitos existen, deberían existir o pueden crearse con una regla implícita, esta regla se aplica.
  7. Si todavía no se ha encontrado ninguna regla de patrón, pruebe de nuevo los pasos 5 y 6 modificando la definición de «debería existir»: es decir, considere que un nombre de archivo debería existir si se menciona como objetivo o como prerrequisito explícito de cualquier objetivo. Esta comprobación existe solo por compatibilidad con versiones antiguas de GNU Make; no le recomendamos confiar en ella.
  8. Si no se aplica ninguna regla implícita, se aplica la regla para .DEFAULT, si la hay. En ese caso, a t se le da la misma receta que tiene .DEFAULT. En caso contrario, t no tiene receta.

Una vez que se encuentra una regla que se aplica, para cada patrón de objetivo de la regla distinto del que coincidió con t o n, el «%» del patrón se sustituye por s y el nombre de archivo resultante se guarda hasta que se ejecuta la receta para rehacer el archivo objetivo t. Después de ejecutar la receta, cada uno de estos nombres de archivo guardados se registra en la base de datos y se marca como actualizado y con el mismo estado de actualización que el archivo t.

Cuando se ejecuta la receta de una regla de patrón para t, las variables automáticas se fijan en correspondencia con el objetivo y los prerrequisitos. Consulte Variables automáticas.


Anterior | Siguiente | Índice | Original en inglés (gnu.org)