- Buck2, nuestro nuevo sistema de compilación a gran escala de código abiertoya está disponible en GitHub.
- Buck2 es un sistema de compilación extensible y de alto rendimiento escrito en Rust diseñado para acelerar y mejorar la eficiencia de la compilación.
- En nuestras pruebas internas en Meta, notamos que Buck2 construye 2 veces más rápido que Buck1.
Buck2, el sistema de compilación Meta a gran escala de código abierto, ahora está disponible públicamente a través de Sitio web de Buck2 Y dólar2 repositorio GitHub. Si bien comparte algunos puntos en común con otros sistemas de compilación (como Buck1 y Bazel), Buck2 es una reescritura desde cero. Buck2 presenta una separación completa de reglas básicas y específicas del lenguaje, con mayor concurrencia, integración con sistemas de archivos virtuales y ejecución remota, y salida de consola rediseñada. Todos estos cambios tienen como objetivo ayudar a los ingenieros y desarrolladores a pasar menos tiempo esperando y más tiempo iterando su código.
Miles de desarrolladores en Meta ya usan Buck2 y ejecutan millones de compilaciones por día, y las compilaciones se ejecutan el doble de rápido que con Buck1. Nuestro propio análisis interno mostró que los ingenieros pudieron crear significativamente más código cuando Buck2 realizó sus compilaciones, y esperamos que la industria en general también vea los beneficios.
¿Por qué restaurar Buck?
Los sistemas de compilación se interponen entre un programador y la ejecución de su código, por lo que cualquier cosa que podamos hacer para que el proceso sea más rápido o más productivo tiene una relación directa con la eficiencia que puede tener un desarrollador. El objetivo de Buck2 era mantener lo que nos encantaba de Buck1 (conceptos básicos y flujos de trabajo), inspirarnos en las innovaciones posteriores a Buck1 (que incluyen Basilea, AdaptaciónY agitar) y centrarse en la velocidad y la entrega de nuevas funciones.
El diseño de Buck2 se basa en los siguientes principios:
- El sistema de compilación subyacente no conoce ninguna regla específica del idioma. Si las reglas están separadas del núcleo, son más fáciles de cambiar y comprender. El núcleo de Buck2 está escrito en Rust y sus reglas de lenguaje (como la forma de compilar C++) están escritas en Rust. alondra estrella. Esta división es diferente de Buck1 (donde todas las reglas están escritas en el núcleo) y Bazel (donde C++/Java están escritos en el núcleo).
- El sistema de compilación funciona sobre la base de un único gráfico de dependencia incremental., evitando cualquier fase (a diferencia de Buck1 o Bazel). Esta solución elimina muchos tipos de errores y aumenta la concurrencia.
- La API de reglas contiene funciones avanzadas para mejorar el rendimiento., así como funciones de dependencia dinámicas (o monádicas) para la expresividad. Al mismo tiempo, estas funciones están cuidadosamente limitadas para que otras funciones (como las consultas rápidas o la estrechez) no se vean afectadas.
- La versión de código abierto es casi idéntica a nuestra versión interna.. Las únicas partes que se han reemplazado son las cadenas de herramientas (que apuntan a copias internas de nuestros compiladores) y la ejecución remota (que apuntan a nuestros servidores internos). — ambos tienen alternativas de código abierto. También publicamos todas las reglas exactamente como se usan internamente. Además, hemos separado algunos componentes lógicos en cajas separadas (por ejemplo, alondra estrella, superconsola, asignativo, Hueco) para que puedan usarse fuera de Buck2.
- Buck2 está escrito para integrarse con la ejecución remota, con la capacidad de ejecutar acciones en máquinas remotas. usamos lo mismo API como Basileay probó la ejecución remota con cobertizo de construcción Y EngFlow. Aunque no es obligatorio (y no se espera para las personas que comienzan con el código abierto), podemos calcular resúmenes recursivos de manera eficiente y enviarlos a ejecución remota de manera eficiente.
- Buck2 está escrito para integrarse con sistemas de archivos virtuales., donde el repositorio completo no se obtiene por completo, pero se obtiene a pedido al acceder a los archivos. En particular, apoyamos Sistemas de archivos basados en Sapling. Para una buena integración, monitoreamos las notificaciones de archivos (con sereno) y consultar archivos y resúmenes de archivos sin operaciones directas con archivos. La ventaja es que podemos hacer que los sistemas de archivos virtuales sean tan rápidos como una verificación completa, pero con los beneficios de verificaciones mucho más rápidas y mucho menos uso del disco.
La conclusión clave de todas estas mejoras es que diseñamos Buck2 para que sea rápido. En condiciones del mundo real, dependiendo de la construcción, Buck2 es significativamente más rápido que Buck1. Si no se realizaron cambios en el código fuente, las compilaciones posteriores de Buck2 se ejecutan casi instantáneamente. Si hay mucho trabajo, Buck2 empieza a correr más rápido y tiene más paralelismo. Este aumento de la velocidad es el resultado de muchos de los factores anteriores, así como del cuidado y la atención.
vista personalizada
Para los usuarios finales, Buck2 funciona básicamente igual que Buck1 (que es bastante similar a Bazel en una primera aproximación). El usuario define los objetivos en TANQUE archivo:
rust_binary(nombre=»mi_binario», srcs= [“main.rs”]dependencias = [“:my_library”])
El usuario puede entonces construir con asamblea buck2 //:mi_binario. Significado principal.rs es el archivo fuente y :mi biblioteca es una dependencia definida en el mismo TANQUE archivo. Vale la pena señalar que Buck2 es principalmente compatible con TANQUE Archivos Buck1.
Además del aumento de velocidad, hay dos importantes diferencias adicionales visibles para el usuario en comparación con Buck1.
En primer lugar, la salida de la consola se ha rediseñado además de Biblioteca de superconsola, que hemos desarrollado especialmente para Buck2. La consola muestra algunos detalles más y se ve mucho más agradable de usar:
En segundo lugar, hay un demonio persistente que mantiene un único gráfico de dependencia. cuando cambias TANQUE archivo, dependencia o archivo fuente, invalidamos las cosas apropiadas en el gráfico de dependencia y luego solicitamos los artefactos de salida en la línea de comando. Buck1 tiene varios gráficos de dependencia independientes que conducen a fases como la creación del gráfico de destino, la creación del gráfico de acción y la ejecución del gráfico de acción. También hay algunas operaciones que no se realizan en un gráfico. Si algunas cosas cambian en Buck1, se descartan gráficos completos, en lugar de cancelar fragmentos mínimos. Con un solo gráfico de dependencia, Buck2 es más simple, evitando el trabajo redundante y las fases explícitas. Todo en un gráfico de dependencia tiene una clave (cómo se identifica) y un valor, y una función para calcular un valor basado en la clave y otras claves asociadas (siguiendo el modelo en el artículo «Sistemas de construcción a la carta»).
Vista del autor de la regla
Si bien el modelo personalizado es muy similar a Buck1, el enfoque de las reglas es completamente diferente. Por ejemplo, Buck tiene muchas reglas. óxido_binario usado arriba. Mientras que la regla en Buck1 era una clase de Java integrada en Buck1, la regla en Buck2 es completamente independiente. Buck2 también viene con un «preludio» de reglas que implementan la mayoría de las reglas de Buck1.
Las reglas de Buck1 se han ajustado con el tiempo, tenían muchas optimizaciones de rendimiento y funciones potentes como el recorrido de gráficos, pero también se esperaba que estas reglas obedecieran a muchas invariantes complejas.—a veces rompiendo estas reglas. Para Buck2, la API de reglas reside completamente en Starlark, lo que nos obligó a abstraer estas funciones como API reutilizables en un esfuerzo por hacerlas seguras, expresivas y eficaces.—difícil equilibrio. Nos referiremos a dos de estos ejemplos.
Dependencias de OCaml
La estructura de dependencia de la biblioteca OCaml es difícil de expresar en Buck1. La biblioteca OCaml consta de varios archivos OCaml. Deben compilarse en orden de dependencia.—Así que si A.ml usos B. mldebes compilar B. ml primero. Bazel requiere una dependencia A.ml en B. ml escribirse explícitamente en TANQUE archivo. Buck1 y Buck2 dejan implícita esta dependencia interna y ejecutan la herramienta. okmldep para sacarlo a relucir, lo que requiere menos mantenimiento a medida que cambia la estructura. Lo que hizo Buck1 fue lanzar okmldep inmediatamente después de analizar TANQUE un archivo que en realidad no se resolvió y no rastreaba las dependencias, por lo que si cambiaba demasiado las importaciones, Buck1 generaría fallas de compilación falsas. Con Buck2 podemos usar nuevo primitivo salida_dinámicaque le permite ejecutar un comando, leer la salida del archivo y luego conectar el resto del gráfico.—establecer la relación correcta entre .ml archivos automáticamente.
Dependencias de referencia C++
Considere el modelo de enlace de C++: Para compilar una biblioteca, generalmente necesita agrupar su resultado de compilación junto con el cierre transitivo de su resultado de compilación de dependencia. Si solo duplica el conjunto de dependencias en cada nivel a medida que avanza en el gráfico, obtiene En2) uso de memoria. En Buck1, muchas de las reglas tenían un código personalizado para capturar este patrón, basado en la capacidad de compartir valores de Java en la memoria y en la representación de dependencias en su lugar en la estructura de la regla (porque no había un gráfico de dependencia cosificado). Buck2 tiene límites de abstracción mucho más estrictos, por lo que esta reutilización debería ser más explícita. es por eso que nosotros conjuntos transitivos introducidos (tsets) para capturar este patrón de conjuntos que representan el cierre transitivo. Al hacer que tset sea más abstracto, también pudimos relacionar tset directamente con el gráfico de dependencia subyacente, lo que significa que la representación es eficiente tanto en memoria como en tiempo de cálculo.
Prueba Buck2 ahora
Estamos interesados en que la gente pruebe Buck2 y nos encantaría escuchar sus comentarios (Problemas con GitHub La mejor manera). Esperamos que Buck2 sea de mayor interés para proyectos multilingües de tamaño mediano. visita Página de inicio de Buck2 Para más información.