Aqui você vai encontrar alguns dos casos de uso mais comuns para criar projetos em C++ com o Bazel. Comece a criar projetos C++ com o Bazel concluindo o tutorial Introdução ao Bazel: criar um projeto em C++, caso ainda não tenha feito isso.
Para mais informações sobre os arquivos principais cc_library e hdrs, consulte cc_library.
Como incluir vários arquivos em um destino
É possível incluir vários arquivos em um único destino com glob. Exemplo:
cc_library(
name = "build-all-the-files",
srcs = glob(["*.cc"]),
hdrs = glob(["*.h"]),
)
Com esse destino, o Bazel vai criar todos os arquivos .cc
e .h
que encontrar no
mesmo diretório que o arquivo BUILD
que contém esse destino (excluindo
subdiretórios).
O uso de inclusões transitivas
Se um arquivo incluir um cabeçalho, qualquer regra com esse arquivo como origem (ou seja,
que tem esse arquivo no atributo srcs
, hdrs
ou textual_hdrs
) precisa
depender da regra da biblioteca do cabeçalho incluído. Por outro lado, apenas as dependências
diretas precisam ser especificadas como dependências. Por exemplo, suponha que
sandwich.h
inclua bread.h
e bread.h
inclua flour.h
. sandwich.h
não inclui flour.h
(quem quer farinha no sanduíche?), então o arquivo BUILD
teria esta aparência:
cc_library(
name = "sandwich",
srcs = ["sandwich.cc"],
hdrs = ["sandwich.h"],
deps = [":bread"],
)
cc_library(
name = "bread",
srcs = ["bread.cc"],
hdrs = ["bread.h"],
deps = [":flour"],
)
cc_library(
name = "flour",
srcs = ["flour.cc"],
hdrs = ["flour.h"],
)
Aqui, a biblioteca sandwich
depende da biblioteca bread
, que depende
da biblioteca flour
.
Como adicionar caminhos de inclusão
Às vezes, não é possível (ou não quer) incluir caminhos na raiz do espaço de trabalho. As bibliotecas atuais já podem ter um diretório de inclusão que não corresponde ao caminho dela no espaço de trabalho. Por exemplo, suponha que você tenha a seguinte estrutura de diretórios:
└── my-project
├── legacy
│ └── some_lib
│ ├── BUILD
│ ├── include
│ │ └── some_lib.h
│ └── some_lib.cc
└── WORKSPACE
O Bazel espera que some_lib.h
seja incluído como
legacy/some_lib/include/some_lib.h
, mas suponha que some_lib.cc
inclua
"some_lib.h"
. Para tornar esse caminho de inclusão válido, legacy/some_lib/BUILD
precisará especificar que o diretório some_lib/include
é um diretório de inclusão:
cc_library(
name = "some_lib",
srcs = ["some_lib.cc"],
hdrs = ["include/some_lib.h"],
copts = ["-Ilegacy/some_lib/include"],
)
Isso é especialmente útil para dependências externas, porque os arquivos principais
precisam ser incluídos com um prefixo /
.
Incluir bibliotecas externas
Suponha que você esteja usando o Teste do Google
{: .external}.
Use uma das funções de repositório no arquivo WORKSPACE
para
fazer o download do Google Test e disponibilizá-la no seu repositório:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "gtest",
url = "https://github.com/google/googletest/archive/release-1.10.0.zip",
sha256 = "94c634d499558a76fa649edb13721dce6e98fb1e7018dfaeba3cd7a083945e91",
build_file = "@//:gtest.BUILD",
)
Em seguida, crie gtest.BUILD
, um arquivo BUILD
usado para compilar o Google Test.
O Google Test tem vários requisitos "especiais" que tornam a regra cc_library
mais complicada:
googletest-release-1.10.0/googletest/src/gtest-all.cc
#include
s todos os outros arquivos emgoogletest-release-1.10.0/googletest/src/
: exclua-o da compilação para evitar erros de link para símbolos duplicados.Ela usa arquivos principais relativos ao diretório
googletest-release-1.10.0/googletest/include/
("gtest/gtest.h"
). Portanto, você precisa adicionar esse diretório aos caminhos de inclusão.Ele precisa ser vinculado a
pthread
, então adicione-o como umlinkopt
.
A regra final será assim:
cc_library(
name = "main",
srcs = glob(
["googletest-release-1.10.0/googletest/src/*.cc"],
exclude = ["googletest-release-1.10.0/googletest/src/gtest-all.cc"]
),
hdrs = glob([
"googletest-release-1.10.0/googletest/include/**/*.h",
"googletest-release-1.10.0/googletest/src/*.h"
]),
copts = [
"-Iexternal/gtest/googletest-release-1.10.0/googletest/include",
"-Iexternal/gtest/googletest-release-1.10.0/googletest"
],
linkopts = ["-pthread"],
visibility = ["//visibility:public"],
)
Isso é um pouco confuso: tudo é prefixado com googletest-release-1.10.0
como um subproduto da estrutura do arquivo. É possível fazer com que http_archive
remova
esse prefixo adicionando o atributo strip_prefix
:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "gtest",
url = "https://github.com/google/googletest/archive/release-1.10.0.zip",
sha256 = "94c634d499558a76fa649edb13721dce6e98fb1e7018dfaeba3cd7a083945e91",
build_file = "@//:gtest.BUILD",
strip_prefix = "googletest-release-1.10.0",
)
O gtest.BUILD
ficaria assim:
cc_library(
name = "main",
srcs = glob(
["googletest/src/*.cc"],
exclude = ["googletest/src/gtest-all.cc"]
),
hdrs = glob([
"googletest/include/**/*.h",
"googletest/src/*.h"
]),
copts = [
"-Iexternal/gtest/googletest/include",
"-Iexternal/gtest/googletest",
],
linkopts = ["-pthread"],
visibility = ["//visibility:public"],
)
Agora, as regras cc_
podem depender de @gtest//:main
.
Como criar e executar testes C++
Por exemplo, você pode criar um teste ./test/hello-test.cc
, como:
#include "gtest/gtest.h"
#include "main/hello-greet.h"
TEST(HelloTest, GetGreet) {
EXPECT_EQ(get_greet("Bazel"), "Hello Bazel");
}
Em seguida, crie um arquivo ./test/BUILD
para os testes:
cc_test(
name = "hello-test",
srcs = ["hello-test.cc"],
copts = [
"-Iexternal/gtest/googletest/include",
"-Iexternal/gtest/googletest",
],
deps = [
"@gtest//:main",
"//main:hello-greet",
],
)
Para tornar hello-greet
visível para hello-test
, adicione
"//test:__pkg__",
ao atributo visibility
em ./main/BUILD
.
Agora, use bazel test
para executar o teste.
bazel test test:hello-test
Isso produz a seguinte saída:
INFO: Found 1 test target...
Target //test:hello-test up-to-date:
bazel-bin/test/hello-test
INFO: Elapsed time: 4.497s, Critical Path: 2.53s
//test:hello-test PASSED in 0.3s
Executed 1 out of 1 tests: 1 test passes.
Adicionar dependências em bibliotecas pré-compiladas
Se você quiser usar uma biblioteca da qual você só tem uma versão compilada (por
exemplo, cabeçalhos e um arquivo .so
), envolva-a em uma regra cc_library
:
cc_library(
name = "mylib",
srcs = ["mylib.so"],
hdrs = ["mylib.h"],
)
Dessa forma, outros destinos C++ no seu espaço de trabalho podem depender dessa regra.