| Атрибуты |
name | Имя; обязательно Уникальное имя для этой цели. |
deps | Список меток; значение по умолчанию [] Список других библиотек, от которых зависит цель. См. общие замечания о deps в Типичные атрибуты, определённые большинством правил построения. |
hdrs | Список меток; значение по умолчанию [] Список заголовочных файлов, опубликованных этой предварительно скомпилированной библиотекой, для непосредственного включения в исходные файлы в зависимых правилах. |
alwayslink | Булево значение; значение по умолчанию False Если 1, любой двоичный файл, который зависит (прямо или косвенно) от этой предварительно скомпилированной C++ библиотеки, будет подключать все объектные файлы, архивированные в статической библиотеке, даже если некоторые не содержат символы, на которые ссылается двоичный файл. Это полезно, если ваш код не вызывается явно кодом в двоичном файле, например, если ваш код регистрируется для получения какого-либо обратного вызова, предоставляемого некоторой службой. Если alwayslink не работает с VS 2017 в Windows, это связано с известной проблемой, пожалуйста, обновите VS 2017 до последней версии. |
includes | Список строк; значение по умолчанию [] Список директорий включения, которые необходимо добавить в строку компиляции. Подлежит замене переменной "Make". Каждая строка предваряется путем пакета и передаётся инструменту C++ для расширения через функцию CROSSTOOL "include_paths". Инструмент, работающий в системе POSIX со стандартными определениями функций, будет производить -isystem path_to_package/include_entry. Это следует использовать только для сторонних библиотек, которые не соответствуют стилю Google по написанию инструкций #include. В отличие от COPTS, эти флаги добавляются для этого правила и каждого правила, которое от него зависит. (Примечание: не правила, от которых оно зависит!) Будьте очень осторожны, так как это может иметь далеко идущие последствия. В случае сомнений добавьте флаги "-I" в COPTS вместо этого. Путь по умолчанию include не включает сгенерированные файлы. Если вам нужно #include сгенерированный заголовочный файл, перечислите его в srcs. |
interface_library | Метка; значение по умолчанию None Единственная библиотека интерфейса для подключения динамической библиотеки. Разрешенные типы файлов: .ifso, .tbd, .lib, .so или .dylib |
linkopts | Список строк; значение по умолчанию [] Добавьте эти флаги в команду C++ линковщика. Подлежит замене "Make" переменной, токенизация оболочки Bourne и расширение меток. Каждая строка в этом атрибуте добавляется к LINKOPTS перед подключением двоичной цели. Каждый элемент этого списка, который не начинается с $ или -, предполагается, что это метка цели в deps. Список файлов, сгенерированных этой целью, добавляется к параметрам линковщика. Ошибка сообщается, если метка неверна или не объявлена в deps. |
objects | Список меток; значение по умолчанию [] |
pic_objects | Список меток; значение по умолчанию [] |
pic_static_library | Метка; значение по умолчанию None |
shared_library | Метка; значение по умолчанию None Одна предварительно скомпилированная динамическая библиотека. Bazel гарантирует, что она будет доступна двоичному файлу, который от неё зависит, во время выполнения. Разрешенные типы файлов: .so, .dll или .dylib |
static_library | Метка; значение по умолчанию None Одна предварительно скомпилированная статическая библиотека. Разрешенные типы файлов: .a, .pic.a или .lib |
system_provided | Булево значение; значение по умолчанию False Если 1, это указывает, что динамическая библиотека, необходимая во время выполнения, предоставляется системой. В этом случае следует указать interface_library, а shared_library должно быть пустым. |
cc_library
cc_library(name, deps, srcs, data, hdrs, additional_compiler_inputs, additional_linker_inputs, alwayslink, compatible_with, conlyopts, copts, cxxopts, defines, deprecation, distribs, exec_compatible_with, exec_properties, features, hdrs_check, implementation_deps, include_prefix, includes, licenses, linkopts, linkstamp, linkstatic, local_defines, module_interfaces, restricted_to, strip_include_prefix, tags, target_compatible_with, testonly, textual_hdrs, toolchains, visibility, win_def_file)
Используйте cc_library() для C++-компилируемых библиотек. Результатом является .so, .lo, или .a, в зависимости от необходимых данных.
Если вы создаёте что-то со статическим подключением, что зависит от cc_library, выходом правила зависимой библиотеки является файл .a. Если вы укажете alwayslink=True, вы получите файл .lo.
Фактическое имя выходного файла libfoo.so для динамической библиотеки, где foo — имя правила. Другие типы библиотек оканчиваются на .lo и .a соответственно. Если вам нужно конкретное имя динамической библиотеки, например, для определения модуля Python, используйте genrule для копирования библиотеки в нужное имя.
Проверка включения заголовков
Все заголовочные файлы, используемые в сборке, должны быть объявлены в hdrs или srcs правил cc_*. Это обязательное требование.
Для правил cc_library, заголовки в hdrs составляют публичный интерфейс библиотеки и могут быть непосредственно включены как из файлов в hdrs и srcs самой библиотеки, так и из файлов в hdrs и srcs правил cc_*, которые перечисляют библиотеку в своих deps. Заголовки в srcs должны быть включены только непосредственно из файлов в hdrs и srcs самой библиотеки. При решении, куда поместить заголовок — в hdrs или srcs, вы должны спросить, хотите ли вы, чтобы потребители этой библиотеки могли напрямую включать его. Это примерно соответствует решению между видимостью public и private в языках программирования.
Правила cc_binary и cc_test не имеют экспортируемого интерфейса, поэтому у них также нет атрибута hdrs. Все заголовки, которые принадлежат непосредственно двоичному файлу или тесту, должны быть перечислены в srcs.
Для иллюстрации этих правил, рассмотрите следующий пример.
cc_binary(
name = "foo",
srcs = [
"foo.cc",
"foo.h",
],
deps = [":bar"],
)
cc_library(
name = "bar",
srcs = [
"bar.cc",
"bar-impl.h",
],
hdrs = ["bar.h"],
deps = [":baz"],
)
cc_library(
name = "baz",
srcs = [
"baz.cc",
"baz-impl.h",
],
hdrs = ["baz.h"],
)
Разрешенные прямые включения в этом примере перечислены в таблице ниже. Например, foo.cc может напрямую включать foo.h и bar.h, но не baz.h.
| Включаемый файл |
Разрешенные включения |
| foo.h |
bar.h |
| foo.cc |
foo.h bar.h |
| bar.h |
bar-impl.h baz.h |
| bar-impl.h |
bar.h baz.h |
| bar.cc |
bar.h bar-impl.h baz.h |
| baz.h |
baz-impl.h |
| baz-impl.h |
baz.h |
| baz.cc |
baz.h baz-impl.h |
Правила проверки включения применяются только к прямым включениям. В примере выше foo.cc разрешено включать bar.h, которое может включать baz.h, которое, в свою очередь, может включать baz-impl.h. Технически, компиляция файла .cc может транзитивно включать любой заголовочный файл в hdrs или srcs в любом cc_library в транзитивном deps замкнутом множестве. В этом случае компилятор может прочитать baz.h и baz-impl.h при компиляции foo.cc, но foo.cc не должен содержать #include "baz.h". Для этого baz должно быть добавлено в deps правила foo.
Bazel полагается на поддержку инструментария для обеспечения соблюдения правил проверки включения. Функция layering_check должна поддерживаться инструментом и быть явно запрошена, например, через флаг командной строки --features=layering_check или параметр features функции package. Предоставляемые Bazel инструменты поддерживают эту функцию только с clang в Unix и macOS.
Примеры
Мы используем флаг alwayslink для принудительного подключения этого кода линковщиком, даже если код основного двоичного файла не ссылается на него.
cc_library(
name = "ast_inspector_lib",
srcs = ["ast_inspector_lib.cc"],
hdrs = ["ast_inspector_lib.h"],
visibility = ["//visibility:public"],
deps = ["//third_party/llvm/llvm/tools/clang:frontend"],
# alwayslink as we want to be able to call things in this library at
# debug time, even if they aren't used anywhere in the code.
alwayslink = 1,
)
Следующий пример взят из third_party/python2_4_3/BUILD. Некоторые части кода используют библиотеку dl (для загрузки другой, динамической библиотеки), поэтому в этом правиле указан параметр подключения -ldl для подключения библиотеки dl.
cc_library(
name = "python2_4_3",
linkopts = [
"-ldl",
"-lutil",
],
deps = ["//third_party/expat"],
)
Следующий пример взят из third_party/kde/BUILD. Мы храним предварительно скомпилированные .so файлы в хранилище. Заголовочные файлы находятся в подкаталоге с именем include.
cc_library(
name = "kde",
srcs = [
"lib/libDCOP.so",
"lib/libkdesu.so",
"lib/libkhtml.so",
"lib/libkparts.so",
...more .so files...,
],
includes = ["include"],
deps = ["//third_party/X11"],
)
Следующий пример взят из third_party/gles/BUILD. Сторонние библиотеки часто требуют определённых defines и linkopts.
cc_library(
name = "gles",
srcs = [
"GLES/egl.h",
"GLES/gl.h",
"ddx.c",
"egl.c",
],
defines = [
"USE_FLOAT",
"__GL_FLOAT",
"__GL_COMMON",
],
linkopts = ["-ldl"], # uses dlopen(), dl library
deps = [
"es",
"//third_party/X11",
],
)
Аргументы