Aprenda a construir bazel del sistema desde cero (1)

que es bazel

Bazel es una herramienta de compilación y prueba de código abierto similar a Make, Maven y Gradle. Utiliza un lenguaje de construcción de alto nivel legible por humanos. Bazel admite proyectos en varios idiomas y genera resultados para varias plataformas. Bazel admite una gran cantidad de bases de código en múltiples bases de código y una gran cantidad de usuarios.

Conceptos básicos de Bazel

archivo ESPACIO DE TRABAJO

Antes de construir el proyecto, necesitamos configurar el espacio de trabajo. La función del espacio de trabajo es almacenar los archivos fuente del proyecto y el directorio de la salida de compilación de Bazel. El archivo WORKSPACE es el archivo que identifica el directorio y su contenido como El espacio de trabajo de Bazel Debe estar ubicado en el proyecto En la raíz de la estructura de directorios, este archivo puede estar vacío, pero generalmente contiene declaraciones para repositorios externos que extraen otras dependencias de la red o del sistema de archivos local.

CONSTRUIR archivo

Un proyecto contiene uno o más archivos BUILD. BUILD se usa principalmente para decirle a Bazel cómo construir el proyecto. El directorio que contiene un archivo BUILD en el espacio de trabajo es un paquete de software. Como se mencionó en el artículo anterior, Bazel es un sistema de compilación basado en artefactos, y los artefactos pueden entenderse como Bazel compilando los archivos en este directorio de acuerdo con las reglas de compilación en el archivo de compilación. El paquete puede contener subpaquetes o subdirectorios de archivos de CONSTRUCCIÓN para formar una jerarquía de paquetes de software.

Los archivos BUILD contienen varios tipos diferentes de directivas aplicables a Bazel, cada archivo BUILD debe contener al menos una regla (como cc_library) como un conjunto de directivas para indicarle a Bazel cómo crear la salida deseada, como un archivo ejecutable o una biblioteca Cada instancia de una regla de compilación en un archivo BUILD se denomina objetivo y apunta a un conjunto específico de dependencias y archivos de origen, y un objetivo también puede apuntar a otros objetivos. El siguiente es un ejemplo de un archivo BUILD simple.

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
)

En este ejemplo, el objetivo hello-world instancia la regla cc_binary integrada de Bazel. Esta regla le dice a Bazel que cree un ejecutable independiente sin dependencias del archivo fuente hello-world.cc.

Ejemplo de C++ de Bazel

Bazel proporciona oficialmente este ejemplo, y la dirección de github es git clone https://github.com/bazelbuild/examples

objetivo único, paquete único

Comencemos con el ejemplo más simple, que solo contiene un archivo fuente, que debe integrarse en un archivo ejecutable, y su directorio de archivos es el siguiente.

examples
└── cpp-tutorial
    └──stage1
       ├── main
       │   ├── BUILD
       │   └── hello-world.cc
       └── WORKSPACE

El contenido del archivo BUILD es el siguiente

load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
)

Luego ingrese al directorio cpp-tutorial/stage1 y ejecute el siguiente comando para construir

bazel build //main:hello-world

Se imprimirá la siguiente información para indicar que la compilación se realizó correctamente

Starting local Bazel server and connecting to it...
INFO: Analyzed target //main:hello-world (37 packages loaded, 255 targets configured).
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 28.089s, Critical Path: 2.78s
INFO: 6 processes: 4 internal, 2 darwin-sandbox.
INFO: Build completed successfully, 6 total actions

Luego puede usar el siguiente comando para probar, imprimirá Hello world

bazel-bin/main/hello-world

Sus dependencias son las siguientes

Paquete único, objetivos múltiples

Si bien un solo objetivo es suficiente para proyectos pequeños, el desarrollo real puede requerir dividir proyectos más grandes en múltiples objetivos y paquetes. Esto permite compilaciones incrementales rápidas (es decir, Bazel reconstruye solo lo que cambió) y acelera las compilaciones al compilar varias partes del proyecto de una sola vez. En esta etapa del tutorial, agregará objetivos y luego paquetes.

El siguiente archivo BUILD le indicará a Bazel que construya primero la biblioteca hello-greet (usando la biblioteca cc_library incorporada de Bazel) y luego construya el archivo binario hello-world. biblioteca.

load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")

cc_library(
    name = "hello-greet",
    srcs = ["hello-greet.cc"],
    hdrs = ["hello-greet.h"],
)

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
    deps = [
        ":hello-greet",
    ],
)

la recopilacion es la siguiente

INFO: Analyzed target //main:hello-world (36 packages loaded, 258 targets configured).
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 15.548s, Critical Path: 2.39s
INFO: 8 processes: 4 internal, 4 darwin-sandbox.
INFO: Build completed successfully, 8 total actions

Si modifica hello-greet.cc y reconstruye el proyecto ahora, Bazel solo volverá a compilar el archivo y los resultados de la compilación son los siguientes (el proceso de compilación específico se puede imprimir con la opción -s)

INFO: Analyzed target //main:hello-world (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
SUBCOMMAND: # //main:hello-greet [action 'Compiling main/hello-greet.cc', configuration: a42135a42aad3da7e3af209ce54745fb0d0306dc29e1f3dc84d7d58372421fc9, execution platform: @local_config_platform//:host]
(cd /private/var/tmp/_bazel_qiming/e4d33fbb5ee1f924b3cb079f19abf4eb/execroot/__main__ && \
  exec env - \
    APPLE_SDK_PLATFORM=MacOSX \
    APPLE_SDK_VERSION_OVERRIDE=13.1 \
    PATH=/Users/qiming/Library/Caches/bazelisk/downloads/bazelbuild/bazel-6.0.0-darwin-x86_64/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin \
    XCODE_VERSION_OVERRIDE=14.2.0.14C18 \
    ZERO_AR_DATE=1 \
  external/local_config_cc/wrapped_clang_pp '-D_FORTIFY_SOURCE=1' -fstack-protector -fcolor-diagnostics -Wall -Wthread-safety -Wself-assign -fno-omit-frame-pointer -O0 -DDEBUG '-std=c++11' 'DEBUG_PREFIX_MAP_PWD=.' -iquote . -iquote bazel-out/darwin-fastbuild/bin -MD -MF bazel-out/darwin-fastbuild/bin/main/_objs/hello-greet/hello-greet.d '-DBAZEL_CURRENT_REPOSITORY=""' '-frandom-seed=bazel-out/darwin-fastbuild/bin/main/_objs/hello-greet/hello-greet.o' -isysroot __BAZEL_XCODE_SDKROOT__ -F__BAZEL_XCODE_SDKROOT__/System/Library/Frameworks -F__BAZEL_XCODE_DEVELOPER_DIR__/Platforms/MacOSX.platform/Developer/Library/Frameworks -no-canonical-prefixes -pthread -no-canonical-prefixes -Wno-builtin-macro-redefined '-D__DATE__="redacted"' '-D__TIMESTAMP__="redacted"' '-D__TIME__="redacted"' -target x86_64-apple-macosx13.1 -c main/hello-greet.cc -o bazel-out/darwin-fastbuild/bin/main/_objs/hello-greet/hello-greet.o)
# Configuration: a42135a42aad3da7e3af209ce54745fb0d0306dc29e1f3dc84d7d58372421fc9
# Execution platform: @local_config_platform//:host
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 0.750s, Critical Path: 0.58s
INFO: 2 processes: 1 internal, 1 darwin-sandbox.
INFO: Build completed successfully, 2 total actions

que depende de la siguiente figura

Múltiples paquetes, múltiples objetivos

¿Qué pasa con la compilación cuando se incluyen varios paquetes? Su estructura es la siguiente:

└──stage3
   ├── main
   │   ├── BUILD
   │   ├── hello-world.cc
   │   ├── hello-greet.cc
   │   └── hello-greet.h
   ├── lib
   │   ├── BUILD
   │   ├── hello-time.cc
   │   └── hello-time.h
   └── WORKSPACE

El archivo BUILD en el directorio lib es el siguiente

load("@rules_cc//cc:defs.bzl", "cc_library")

cc_library(
    name = "hello-time",
    srcs = ["hello-time.cc"],
    hdrs = ["hello-time.h"],
    visibility = ["//main:__pkg__"],
)

El archivo BUILD en el directorio principal es el siguiente

load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")

cc_library(
    name = "hello-greet",
    srcs = ["hello-greet.cc"],
    hdrs = ["hello-greet.h"],
)

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
    deps = [
        ":hello-greet",
        "//lib:hello-time",
    ],
)

El destino hello-world en el paquete principal depende del destino hello-time en el paquete lib (de ahí la etiqueta de destino //lib:hello-time) - Bazel lo sabe a través de la propiedad deps. Esto se refleja en el gráfico de dependencia:

Para una compilación fluida, use el atributo de visibilidad para hacer que el destino //lib:hello-time en lib/BUILD sea explícitamente visible para el destino en main/BUILD. Esto se debe a que, de forma predeterminada, un objetivo solo es visible para otros objetivos en el mismo archivo BUILD. Bazel usa la visibilidad de destino para evitar problemas como bibliotecas que contienen detalles de implementación que se filtran a la API pública.

por fin

Este artículo presenta principalmente el uso simple del sistema de construcción bazel. Para más artículos, puede prestar atención a la cuenta oficial QStack.

おすすめ

転載: blog.csdn.net/QStack/article/details/128858900