Proyectos TOML
Un manifiesto de proyecto selecciona grupos ordenados de fuentes Erlang y configura cada destino (target) de forma independiente. Todas las acciones de la CLI aceptan proyectos. Véase el ejemplo funcional.
Manifiesto (esquema 1)
schema_version = 1
[[targets]]
name = "app"
sources = ["main.erl", "src/workers/*.erl", "shared/**/*.erl"]
source_dirs = ["src/support"]
output = "build/app"
entry = "main:main"
build_dir = "build"
[targets.options]
source_search_paths = ["src", "generated"]
include_dirs = ["include", "vendor/include"]
defines = ["DEBUG", "LIMIT=100", 'LABEL="demo"']
enable_features = ["maybe_expr"]
disable_features = ["compr_assign"]
ignore_dirs = ["src/legacy", "deps/*/test"]
ignore_modules = ["telemetry", "*_SUITE"]
keep_exports = false
shell = false
cache_inference_in_dirs = ["deps/*"]
[targets.options.applications]
my_dependency = "vendor/my_dependency"
- Son obligatorios
schema_version = 1y un arraytargetsno vacío. Se rechazan las claves desconocidas, los tipos incorrectos, los nombres de destino duplicados y las cadenas vacías; no hay conversión de tipos. Se valida el manifiesto completo, incluidos los destinos no seleccionados. - Nombres de destino: ASCII
[A-Za-z0-9_][A-Za-z0-9_.-]*con distinción de mayúsculas y minúsculas, únicos. Un nombre es un destino de compilación, no una tripleta de LLVM. sources(archivos y patrones comodín) ysource_dirs(búsqueda recursiva de.erly.abstr) son opcionales, pero un destino necesita al menos una entrada. Los archivos explícitos deben terminar en.erl, o en.abstrpara formas en formato abstracto (transformaciones); las cabeceras son dependencias, no entradas.- Los grupos
[[targets.asn1]]compilan especificaciones ASN.1 (sources,options,outdir) en módulos que se incorporan al destino (ASN.1). parse_transforms(nombres de módulo) ytransform_paths(directorios o patrones de archivos.beamprecompilados) enoptionsaplican parse transforms a los módulos del destino (transformaciones).ignore_dirs(rutas) eignore_modules(nombres de módulo), ambos con comodines, enoptionsdejan fuentes fuera de la compilación (fuentes ignorados).keep_exports = trueenoptionsmantiene invocables todas las exportaciones del ejecutable del destino, como hace--keep-exportspara cada destino seleccionado (vida de las exportaciones). Debe ser un booleano.shell = trueenoptionsenlaza la shell interactiva en el ejecutable del destino, como hace--shell(shell interactiva). Debe ser un booleano.cache_inference_in_dirs(comodines de directorio) enoptionsañade directorios cuyos módulos conservan sus resultados de inferencia en la caché de compilación (caché de inferencia).- Los campos de
optionsson opciones tipadas opcionales del frontend.definesusaNAME(=true) oNAME=ERLANG_LITERAL_TERM; los duplicados son errores. Una funcionalidad no puede aparecer en ambas listas de funcionalidades. entry(opcional) selecciona la entrada del ejecutableMODULE[:FUNCTION[/ARITY]]; véase ejecutables. El--entryde la CLI la sustituye para un único destino seleccionado.build_dir(opcional) es el directorio de compilación del destino, por defecto<manifest-dir>/build.outputes el destino del ejecutable, por defecto<manifest-dir>/build/<target>(.exeen Windows). Un destino conoutputoentryes un destino ejecutable (ejecutables);--emity los modos de comprobación/impresión ignoran las salidas de ambas claves.- No soportado: valores por defecto en la raíz, herencia, dependencias entre destinos, importaciones, perfiles, paquetes, vigilancia de cambios, compilaciones en paralelo. Los campos solo se añaden junto con su comportamiento.
CLI y selección de destinos
clau [options] <source.erl>...
clau [options] --project <path> [--target <name>]...
clau --new-project <filename>
- Los fuentes posicionales y
--projectson mutuamente excluyentes. Un solo--project, cualquier número de--target, en cualquier orden. - Sin
--target: todos los destinos en el orden del manifiesto. Los selectores conservan su orden y su primera aparición. Los nombres desconocidos fallan antes de cualquier trabajo del frontend y enumeran los nombres disponibles. --project test1cargatest1.tomlcuandotest1no existe.- Las opciones de frontend de la CLI se aplican a todos los destinos seleccionados. Las rutas relativas de la CLI mantienen su significado respecto al directorio de invocación; las rutas del manifiesto son relativas al manifiesto.
- Sin
--emitni una acción de comprobación/impresión, los destinos ejecutables se enlazan en sus salidas (ejecutables); los demás destinos se compilan en memoria. -o/--outputenlaza el destino en esa ruta en lugar de suoutput(enlazado); requiere exactamente un destino seleccionado.--verbosetraza en stderr los archivos/includes[pp]y los fuentes[parse].--print-inputsejecuta cada destino seleccionado hasta la compilación: preprocesa y analiza los fuentes tras la búsqueda y después añade los módulos que estos nombran desde la biblioteca ysource_search_paths, como hace una compilación. Imprime los fuentes del destino (rutas absolutas), uno por línea, y después cada fuente añadido como<path> (referenced at <file>:<line>), el primer lugar del módulo que lo referencia donde se nombra; los fuentes añadidos se exploran a su vez. No se compila nada. Con varios destinos, cada lista sigue a una línea[target <name>]. Las entradas posicionales se imprimen tal como se dan. Los diagnósticos van a stderr; un error de análisis detiene la adición de módulos referenciados y termina con código 1. Sustituye a las demás acciones de comprobación/impresión y, como ellas, es incompatible con-o,--entryy los conmutadores de compilación.--print-envimprime la invocación completa como TOML: una tabla[[targets]]por destino seleccionado con sus fuentes resueltos, sus directorios de búsqueda/inclusión y sus opciones efectivas (informe del entorno).- Código de salida 2: errores de uso y destinos desconocidos. Código 1: fallos de manifiesto, de búsqueda, del frontend o de creación. Código 0: éxito (se permiten advertencias).
Cada destino seleccionado es un lote de compilación independiente con sus
propias sesiones de preprocesado. La planificación (decodificar, seleccionar,
buscar, comprobar colisiones de salida) termina antes de procesar ningún
fuente; después la ejecución procesa los destinos/archivos en orden y retiene
los fallos. La salida de contenido va a stdout en orden de destino/archivo sin
encabezados (salvo las líneas de destino de --print-inputs); el contexto y
los diagnósticos van a stderr. Un destino con diagnósticos se nombra una sola
vez, en una línea <manifest> [target <name>]: antes del primero; los propios
diagnósticos (error: file:line:col: message) no llevan prefijo de
herramienta ni de destino.
./build/debug/bin/clau --parse-check --project examples/project/project.toml
./build/debug/bin/clau --print-ast --project examples/project/project.toml --target tests --target app
Ejecutables
clau --project FILE [--target T]... (sin --emit ni acción de
comprobación/impresión) enlaza cada destino seleccionado que tenga una clave
output o entry, o al que se dirijan -o/--entry de la CLI, en un
ejecutable por destino:
- Destino del archivo:
-ode la CLI (relativo a la invocación); si no,output(relativo al manifiesto); si no,<manifest-dir>/build/<target>. Los destinos Windows añaden.exea un nombre sin extensión. Los directorios que faltan de las salidas del manifiesto se crean; un directorio-oexplícito debe existir. - Entrada:
--entryde la CLI,entrydel manifiesto o, si no, detección (selección de la entrada). - Los destinos sin
output,entry,-oni--entryson bibliotecas: se compilan en memoria y no escriben nada, aunque un módulo exportemain/1. - La planificación rechaza los destinos seleccionados con el mismo destino de
archivo; las salidas que solo coinciden tras añadir
.exese rechazan antes de la publicación. Una salida no debe coincidir con un fuente seleccionado ni con el manifiesto. - Cada destino se compila y enlaza en su propio directorio de preparación. Las salidas solo se reemplazan cuando todos los destinos seleccionados han tenido éxito, en orden de destino; cualquier fallo deja intactas todas las salidas existentes. Un fallo al reemplazar una salida posterior puede dejar las anteriores ya reemplazadas.
--linkery--runtime-libraryse aplican a todos los destinos enlazados (enlazado).
./build/debug/bin/clau --project tests/fixtures/linking/project/project.toml
Crear un proyecto
--new-project <filename> escribe un manifiesto comentado y nada más.
- Añade
.tomlsalvo que el nombre ya termine en.toml(sin distinguir mayúsculas y minúsculas en ASCII):demo→demo.toml,demo.config→demo.config.toml. - Rechaza los nombres vacíos o con forma de directorio, la repetición y
cualquier combinación con fuentes,
--project,--target,-o, modos de comprobación/impresión u opciones del frontend. - El directorio padre debe existir. Nunca sobrescribe (creación exclusiva); elimina su propio archivo parcial si falla la escritura. Imprime la ruta creada en caso de éxito.
- El contenido es UTF-8/LF determinista con comentarios: un destino
app,sources = [],source_dirs = ["src"], listas de opciones vacías y la salida por defecto de la plataforma. Se decodifica de inmediato; el usuario añade los fuentes bajosrc.
Directorio de compilación
Cada destino de proyecto tiene un directorio de compilación donde Clause guarda
sus propios archivos temporales y sus cachés: el build_dir del destino,
relativo al manifiesto, por defecto <manifest-dir>/build. --build-dir DIR
(relativo a la invocación) lo sustituye para todos los destinos seleccionados.
Las entradas posicionales no tienen ninguno salvo que se indique --build-dir.
- Los archivos temporales van bajo
<build_dir>/tmp: los espacios de trabajo del cargador de parse transforms (transformaciones). Cada ejecución elimina los suyos; puede quedar untmpvacío. Sin directorio de compilación van al directorio temporal del sistema. - La preparación del enlazado (
.clause-link-*) permanece junto a la salida del ejecutable, porque el renombrado final debe quedarse en el volumen de la salida (enlazado). - Los modos de comprobación e impresión (
--parse-check,--print-ast, ...) no escriben nada fuera del directorio de compilación; las comprobaciones posicionales sin--build-dirno escriben ningún archivo. --print-envimprime elbuild_dirde cada destino (""cuando no hay ninguno).
Cachés de compilación
Los resultados que merece la pena conservar entre ejecuciones viven bajo
<build_dir>/cache; --no-cache ni los lee ni los escribe. Son las respuestas
del cargador de parse transforms y la lista de módulos sticky del OTP
anfitrión, de modo que una compilación en caliente no arranca ningún erl
anfitrión para los módulos cuyas entradas de transformación no han cambiado,
el resultado de compilación de cada lote y los
resultados de inferencia de los módulos de los directorios
configurados.
- Interfaz. Los llamadores usan un único almacén interno del proyecto
(
compiler/src/cache/ store.hpp):get/putpor directorio de entrada, nombre de archivo, tipo de resultado y clave, además deinvalidateyprune; nunca ven rutas. Un valor es la versión de formato del llamador y una lista de partes con nombre (una ejecución de transformación:replyyoutput; un resultado de compilación:failed, cadadiagnosticy, con salidas,triple,extensiony una parte por objeto de módulo), de modo que ningún llamador necesita un códec propio. Ungetcon otra versión de formato es un fallo de caché. Toda operación es segura desde varios hilos a la vez. - Disposición.
cache/v2/cache.dbes una base de datos SQLite 3.54: tablaentries(directorio de entrada, archivo, tipo, clave, formato, último uso; única por dirección) y tablaparts(entrada, orden, nombre, tamaño, suma de comprobación xxh3-64, y los bytes o el nombre de un archivo blob). Las partes mayores de 256 KB viven encache/v2/blobs/<xxh3-128 of the bytes>, de modo que las partes iguales (los objetos idénticos de un lote compilado con dos conjuntos de opciones) se almacenan una sola vez; 256 KB es el punto en el que las lecturas medidas dejan de favorecer a la base de datos y las escrituras empiezan a favorecer a los archivos (cache_store benchentests/compiler/cache). Un archivo blob se escribe como archivo temporal y se renombra antes de que se confirme la fila que lo nombra, de modo que una fila nunca nombra un archivo incompleto; un fallo en medio solo deja un archivo huérfano. - Claves. Una clave es el hash de contenido de 128 bits de todo aquello de
lo que depende el resultado, nunca una marca de tiempo: la versión y el
ejecutable de
clau(ruta, tamaño, fecha de modificación, de modo que unclaurecompilado falla en la caché), el tipo de resultado y, para una ejecución de transformación, la solicitud enviada aerl(las formas preprocesadas del módulo y sus opciones de compilación: directorios de inclusión, defines, funcionalidades), la versión del OTP anfitrión (erly los archivosreleases/*/OTP_VERSIONjunto a él), cada fuente de transformación del proyecto compilado para la ejecución con los archivos que incluye, y cada.beamde las rutas de código de las transformaciones. La versión de formato del almacén es el directoriov<format>; la versión de formato propia de un valor se guarda en su fila. Como la clave cubre las formas preprocesadas, un cambio en una cabecera, un define o una funcionalidad, o una cabecera nueva que oculta una incluida, provoca fallos de caché exactamente en los módulos cuyas formas u opciones cambian; los defines y las funcionalidades son opciones de compilación que ve toda transformación, así que provocan fallos en todos los módulos transformados; un.beammodificado provoca fallos en todos los módulos cuyas transformaciones se ejecutan con esa ruta de código. - Concurrencia. La base de datos funciona en modo de registro de escritura
anticipada (write-ahead log) con
synchronous=NORMAL: los lectores se ejecutan junto a un escritor, y los escritores (una transacción porput) se esperan entre sí hasta 30 s. Varios procesosclauque comparten un directorio de compilación conservan todas las entradas. Dentro de un proceso, un mutex serializa los hilos que comparten un almacén. - Daños. Las partes llevan tamaños y sumas de comprobación, y los archivos
blob se comprueban frente a sus nombres: una parte dañada o un archivo blob
ausente es un fallo de caché (
damaged entry) y su entrada se descarta. Uncache.dbbasura, truncado o ajeno (SQLite lo notifica como corrupto o como no base de datos, o su application id o versión de esquema difieren) se renombra acache.db.damagedy se crea de nuevo; cuando eso no es posible, la ejecución continúa sin caché. Nada de esto es un error, y--verboselo anota como[cache] .... - Sistemas de archivos de red. El registro de escritura anticipada necesita
memoria compartida entre procesos, que los sistemas de archivos de red no
proporcionan. Cuando SQLite no puede entrar en modo WAL, el almacén usa su
diario de reversión (rollback journal; los lectores esperan entonces a un
escritor) y
--verboselo indica una vez; cuando ningún modo de diario funciona, la ejecución continúa sin caché. - Poda. Al final de una ejecución que escribió en un almacén, se eliminan
las entradas no usadas en 30 días, después los archivos blob que ninguna
entrada nombra (una vez que tienen más de 10 minutos, para que sobreviva el
archivo nuevo de un escritor concurrente), y las páginas liberadas se
devuelven al sistema de archivos (vacuum incremental). Cada ejecución elimina
un árbol
cache/v1sobrante del antiguo backend de archivos. - Observabilidad.
--print-stage-timesmarca las etapas reutilizadas ([time] transform src/a.erl: 7.254 ms (cached));--verboseimprime[cache] hit|miss <kind> <file>con el motivo de un fallo de caché (no entry,inputs changed,damaged entry). Los diagnósticos y la salida de las transformaciones son los mismos con y sin acierto: se almacenan con la entrada. - Sin caché: el preprocesado y el análisis sintáctico (cargar un resultado
en caché a través de las formas abstractas,
transforms/import, resultó más lento en las mediciones que volver a analizar), y las exploraciones de directorios: la planificación está dominada por la apertura e identificación de cada fuente, que una caché de exploración no puede evitar.
Caché de inferencia
Los módulos de biblioteca (los fuentes de stdlib, kernel, compiler y
syntax_tools de OTP encontrados a través de source_search_paths, y la
biblioteca propia de Clause) rara vez cambian, por lo que los
módulos de los directorios configurados conservan sus resultados de inferencia
de tipos en la caché de compilación, por módulo, y las compilaciones
posteriores los reutilizan en lugar de volver a inferirlos.
- Directorios: los patrones implícitos de aplicaciones de OTP
*/stdlib,*/stdlib-*,*/kernel,*/kernel-*,*/compiler,*/compiler-*,*/syntax_toolsy*/syntax_tools-*, después elcache_inference_in_dirsdel destino y después cada--cache-inference-in-dirs PATTERN(repetible; también para entradas posicionales). Los patrones usan los comodines desources; se aceptan los separadores de Windows. - Un módulo queda cubierto cuando un directorio que contiene su fuente encaja
con un patrón. Un patrón relativo encaja con los directorios finales de
cualquier ruta, no con rutas bajo el directorio del manifiesto:
*/stdlibcubre/usr/lib/erlang/lib/stdlib/src/lists.erlyreferences/otp/lib/stdlib/src/lists.erl, mientras que un.../lib/stdlib-7.0/src/lists.erlinstalado necesita*/stdlib-*. Un patrón absoluto encaja con la ruta completa del directorio (C:/Program Files/Erlang OTP/lib/*). El encaje es léxico y distingue mayúsculas y minúsculas. Los patrones implícitos cubren también un directorio propio del proyecto con uno de esos nombres (apps/compiler), lo que solo almacena más entradas: la reutilización es correcta para cualquier módulo. --print-envimprime la lista efectiva comocache_inference_in_dirs, con los patrones implícitos primero. Una construcción no soportada ([,{,!) es un error de manifiesto, o un error de uso (código 2) en la línea de órdenes.- La reutilización necesita un directorio de compilación (todo destino de
proyecto; entradas posicionales con
--build-dir) y se desactiva con--no-cache. Funciona para toda acción que analiza (compilación, ejecutables,--print-types, inspecciones del IR), también cuando la caché de compilación del lote falla. - Clave: la identidad de
clau, la huella del módulo y las de todos los módulos del lote que nombran sus átomos, de forma transitiva (llamadas remotas,fun M:F/A,apply, cualquier átomo que sea un nombre de módulo); véase semántica: caché de inferencia para saber por qué solo de eso dependen sus hechos. Editar un módulo de usuario conserva por tanto los aciertos de la biblioteca salvo que un módulo de biblioteca lo nombre; editar un módulo de biblioteca provoca un fallo en él y en todo módulo cubierto que lo alcanza. - Las entradas se guardan por directorio de fuentes, archivo y destino de
proyecto (tipo
inference@<target>,inference@positional); un valor es una parteresults(semantic/types/inference_store: nodos del grafo, resúmenes y entradas locales por función, hechos de expresiones por posición sintáctica). Los resultados guardados por una compilación con más funciones vivas (por ejemplo--print-types) sirven a un ejecutable que conserva menos. --verboseimprime[cache] hit|miss inference <file>por módulo cubierto (motivos de fallo:no entry,inputs changed,damaged entry,results do not fitpara resultados guardados a los que les falta una función que ahora está viva);--print-stage-timesimprime las fasesinference-cache(conN of M covered modules reused) einference-store.
Rutas y búsqueda
- La ruta del proyecto se resuelve respecto al directorio de invocación; el
padre léxico del manifiesto es la base de todas las rutas del manifiesto
(incluso a través de un enlace simbólico). Las rutas absolutas siguen siendo
absolutas; se permite
... No hay expansión de shell, de entorno ni de tilde. Para rutas de Windows se usa/o cadenas literales de TOML. - Los fuentes relativos literales prueban primero la base y después
source_search_pathsen orden. Un candidato existente pero ilegible es un error. Las rutas de búsqueda no enumeran módulos ni afectan a los includes. - Cuando los fuentes del destino nombran un módulo que ninguno de ellos define
(una llamada remota,
fun M:F/A,applycon un módulo literal,-behaviouro-import), se buscaModule.erlprimero en la biblioteca de Clause y después en las rutas de búsqueda en orden (un OTP instalado nunca sustituye a un módulo de Clause, y un módulo que Clause registra como ausente nunca se toma de una ruta de búsqueda: resolución); un archivo encontrado se une al destino como un fuente enumerado, y sus propias referencias se resuelven de la misma manera. Un fuente enumerado con el nombre de un módulo de Clause lo sustituye, con una advertencia. - Comodines:
*y?dentro de un componente,**como componente completo. Se rechazan corchetes, llaves, negación y escapes. El encaje distingue mayúsculas y minúsculas;?es un escalar Unicode de un nombre UTF-8 válido. - Se incluyen las entradas ocultas; los enlaces simbólicos a directorios descubiertos se omiten (las raíces explícitas pueden ser enlaces simbólicos); los enlaces simbólicos a archivos se siguen.
- Orden: las entradas de
sourcesen orden, las coincidencias de cada patrón ordenadas por los bytes UTF-8 de la ruta, y después cada expansión desource_dirsordenada de la misma manera. Los literales ausentes, los patrones sin coincidencias y los destinos vacíos son errores. - La deduplicación dentro de un destino usa la identidad del sistema de archivos (enlaces simbólicos, enlaces duros, alias por mayúsculas), y conserva la primera grafía. Un mismo archivo en dos destinos se compila dos veces porque las opciones pueden diferir.
- Solo los destinos seleccionados acceden al sistema de archivos.
Índice de directorios
Las búsquedas por nombre no prueban cada directorio candidato. Un único índice
por invocación de clau, compartido por todos los destinos, guarda los nombres
de las entradas de cada directorio explorado: se enumera una vez, de forma no
recursiva, cuando una búsqueda lo necesita por primera vez, o lo registran los
recorridos recursivos que expanden ** en sources, source_dirs,
source_search_paths, include_dirs y transform_paths, de modo que ningún
directorio se enumera dos veces. Responde a los fallos de la búsqueda de
módulos (la biblioteca y después source_search_paths), a los fuentes de
transformaciones, a los sources literales encontrados a través de
source_search_paths y a la resolución de includes (el directorio del archivo
que incluye, el directorio de trabajo, los directorios de inclusión en orden y
después las aplicaciones de include_lib); un candidato que contiene el índice
se sigue abriendo o comprobando como antes, por lo que la precedencia,
ignore_dirs y los informes de error no cambian. Los nombres de include con
partes de directorio (sub/x.hrl) se buscan en el directorio que nombran; los
nombres con pasos .., los nombres absolutos, los directorios relativos y las
enumeraciones que fallan se prueban como antes.
- Las claves de nombre de archivo pliegan las mayúsculas ASCII en Windows y
macOS, cuyos volúmenes ignoran por defecto la diferencia entre mayúsculas y
minúsculas, de modo que
Foo.hrlsigue encontrandofoo.hrl; en los demás sistemas las claves son exactas. Los nombres que el plegado no puede emparejar con exactitud (allí los nombres no ASCII y, en Windows, los nombres que terminan en.o en un espacio o que contienen~, que pueden ser nombres cortos 8.3) se prueban. - El índice es una instantánea de una invocación: los archivos que aparecen
mientras
clause ejecuta (preparación del enlazado, salidas) nunca son entradas de búsqueda. --verbosetermina con[index] listed=N walked=N lookups=N misses=N probes=N(directorios enumerados bajo demanda, enumeraciones registradas por recorridos, búsquedas que respondió el índice y los fallos entre ellas, búsquedas que quedaron para una prueba).
Fuentes ignorados
ignore_dirs e ignore_modules mantienen fuentes fuera de un destino sin
quitarlos del árbol, por ejemplo pruebas incluidas de terceros, código heredado
o módulos que solo importan con OTP. Un fuente ignorado se omite en silencio:
nunca se lee, analiza, compila ni enlaza, por lo que puede incluso contener
errores de sintaxis.
ignore_dirs: rutas relativas al manifiesto (o absolutas) con los comodines desources. Un fuente se ignora cuando su ruta, o un directorio que lo contiene, encaja:src/legacy,deps/*/test,**/test(cualquier directoriotest),src/*_SUITE.erl. El encaje es léxico; un patrón no tiene por qué encajar con nada.ignore_modules: nombres de módulo, o patrones de nombre con*y?que se comparan con el nombre completo (*_SUITE,legacy_*,prim_???). Un fuente llamado<Module>.erl(o.abstr) se ignora cuando una entrada encaja con<Module>, y un módulo referenciado que encaja nunca se busca. Esto incluye los módulos de biblioteca de Clause.- Un fuente que
sourcesenumera literalmente (sin comodín) nunca se ignora: las reglas no tienen efecto sobre él, y la compilación adviertelisted in sources but matched by ignore_modules or ignore_dirs; ignoring it has no effect. Las coincidencias de comodines ysource_dirsse ignoran como se ha descrito. - Ambos se aplican a
sources,source_dirs, los fuentes literales encontrados a través desource_search_paths, la búsqueda de módulos ensource_search_pathsy en la biblioteca, y la búsqueda de fuentes de parse transforms. Una búsqueda pasa por alto unModule.erlignorado y sigue buscando en los directorios posteriores. - Un módulo se ignora cuando
ignore_moduleslo nombra, o cuando ningún fuente del lote lo define y los únicos fuentes encontrados para él se ignoraron (por búsqueda, u omitidos de los fuentes del destino, por nombre de archivo). Un módulo definido por un fuente compilado nunca se ignora. - Las referencias a un módulo ignorado (
M:F(...),-import,fun M:F/A,apply(M, F, [...])con nombres literales) llegan a un módulo de reemplazo generadoMque exporta cada función nombrada de esta forma; cada una devuelve{module_ignored, M}en lugar de ejecutarse. Una función que el lote nunca nombra literalmente sigue siendoundefpara las llamadas dinámicas. Un tipo de un módulo ignorado nombrado en un spec o un tipo (helper:result()) advierteattempt to import a type from a module ignored in project settings: helper:resulty se trata comoterm().-behaviour(M)con unMignorado adviertebehaviour M undefined. --print-inputsenumera cada módulo referenciado ignorado después de los fuentes añadidos comoignored module <name> (referenced at <file>:<line>);--print-envimprime ambas claves.
[targets.options]
source_search_paths = ["deps/**"]
ignore_dirs = ["deps/*/test", "src/legacy"]
ignore_modules = ["telemetry", "*_SUITE"]
Opciones efectivas
| Ajuste | Combinación de manifiesto y CLI |
|---|---|
include_dirs | Orden del manifiesto, después de -I de la CLI (el último -I de la CLI se busca primero); una entrada con comodines (deps/*/include, apps/**/include) se expande en su sitio a los directorios existentes con los que encaja, ordenados por los bytes UTF-8 de la ruta (** también encaja con ninguno, los enlaces simbólicos a directorios se omiten); un patrón sin coincidencias es un error |
source_search_paths | Raíces de reserva para los fuentes literales y para los módulos que el destino nombra pero no enumera; los patrones se expanden como en include_dirs (sin coincidencias: unmatched source search path pattern) |
defines | Primero el manifiesto, después la CLI; los duplicados entre ambos son errores |
applications | Map del manifiesto; las entradas de la CLI reemplazan los nombres coincidentes |
| Listas de funcionalidades | Ajustes del manifiesto, después los cambios ordenados de la CLI; prevalece la CLI |
output | Por destino, solo destinos ejecutables; -o de la CLI lo sustituye para un único destino seleccionado |
entry | Por destino; --entry de la CLI lo sustituye para un único destino seleccionado |
cache_inference_in_dirs | Patrones implícitos de OTP, después los del manifiesto y después --cache-inference-in-dirs de la CLI (caché de inferencia) |
Dependencia de compilación
toml++ 3.4.0 (MIT), privado del compilador, solo cabeceras, con excepciones y
con la sintaxis no publicada desactivada. SHA-256 del archivo
8517f65938a4faae9ccf8ebb36631a38c1cadfb5efa85d9a72e15b9e97d25155.
- macOS: se detecta
brew install tomlplusplus(fórmula 3.4.0). - Windows: CMake descarga y verifica la versión publicada en
thirdparty/. - En otros sistemas: instalarlo, extraerlo en
thirdparty/tomlplusplus-3.4.0o pasar-DCLAUSE_TOML_ROOT=<path>(tiene prioridad y desactiva la descarga). - Las compilaciones solo del runtime no lo buscan.
La caché de compilación usa la amalgamación de SQLite 3.54.0
(dominio público), compilada solo en la biblioteca de caché del compilador
(clause_sqlite, sin los flags de advertencias del proyecto). CMake descarga
https://www.sqlite.org/2026/sqlite-amalgamation-3540000.zip en
thirdparty/ en todos los anfitriones y verifica su SHA-256
68e913b0fe8ec6b4e5f391c594a28872884e80d6cd042a1e50c957be46b5aa4d;
-DCLAUSE_SQLITE_ROOT=<directory with sqlite3.c and sqlite3.h> tiene
prioridad y desactiva la descarga.
Límites
Tamaño del manifiesto 1 MiB; como máximo 1.024 destinos y 100.000 nodos TOML. Cada expansión de fuentes permite 100.000 entradas visitadas, 128 niveles de directorio y 16.000.000 de transiciones de comodines. El agotamiento es un error explícito; son límites de trabajo, no plazos de E/S.
Clause