Изолировать Bazel C ++ build от системных включенных каталогов - PullRequest
0 голосов
/ 11 декабря 2018

Я бы хотел сделать свою сборку Bazel C ++ независимой от /usr/include, /usr/local/include и т. Д. По умолчанию, как описано в этой теме , все файлы в /usr/include будут доступны, когдакомпиляция программ на C ++, а не только стандартных.

Каков наилучший способ добиться этого?

Один из вариантов - поместить стандартные заголовочные файлы в тарбол и разместить его где-нибудь по HTTP,затем добавьте new_http_repository и запустите gcc с -nostdinc -isysroot.

1 Ответ

0 голосов
/ 20 декабря 2018

Решение состоит из трех частей:

  • создание пользовательского определения цепочки инструментов C ++
  • , убеждая Bazel использовать эту цепочку инструментов
  • , убеждая компилятор игнорировать его значение по умолчаниюиспользуйте системные заголовки

Вот ссылка, которая вам понадобится:

https://docs.bazel.build/versions/master/crosstool-reference.html https://docs.bazel.build/versions/master/tutorial/crosstool.html

Вот особенно хороший учебник:

https://github.com/bazelbuild/bazel/wiki/Yet-Another-CROSSTOOL-Writing-Tutorial

И еще несколько учебных пособий, я не знаю, насколько они актуальны:

https://github.com/bazelbuild/bazel/wiki/About-the-CROSSTOOL https://github.com/bazelbuild/bazel/wiki/Building-with-a-custom-toolchain


Вот как я работал с Linux на GCC:

  1. Создайте новое рабочее пространство с фиктивным правилом cc_binary в нем.

    mkdir /tmp/bar && cd /tmp/bar
    touch WORKSPACE
    echo "cc_binary(name='x',srcs=['x.cc'])" > BUILD
    echo -e "#include <stdio.h>\nint main(void) { return 0; }" > x.cc
    
  2. Создайте фиктивную цель.

    bazel build //:x
    

    Поскольку это правило cc_ *, Bazel инициализирует цепочку инструментов C ++.Это включает в себя автоматическую генерацию файла CROSSTOOL.Это текстовый файл, описывающий интерфейс компилятора, поэтому Bazel знает, как с ним общаться.

  3. Создайте пакет для своего пользовательского кросс-инструмента, скопируйте туда автоматически сгенерированные файлы CROSSTOOL и BUILD.

    mkdir /tmp/bar/my_toolchain
    touch /tmp/bar/my_toolchain/WORKSPACE
    cat $(bazel info output_base)/external/local_config_cc/CROSSTOOL > /tmp/bar/my_toolchain/CROSSTOOL
    cat $(bazel info output_base)/external/local_config_cc/BUILD > /tmp/bar/my_toolchain/BUILD
    

    Мы будем использовать автоматически созданные файлы в качестве шаблонов для запуска.

  4. Добавить правило внешнего репозитория в файл WORKSPACE.

    echo "local_repository(name='my_toolchain', path='/tmp/bar/my_toolchain')" >> WORKSPACE
    

    Таким образом, вы можете ссылаться на свой пользовательский набор инструментов с помощью метки сборки Bazel.

  5. Попробуйте использовать свой собственный кросс-инструмент.

    bazel build --crosstool_top=@my_toolchain//:toolchain //:x
    

    Поскольку он такой же, как и сгенерированный автоматическисборка должна завершиться успешно.

  6. Редактировать пути системных заголовков из "локальной" цепочки инструментов в пользовательском CROSSTOOL.

    Примечание : вам может понадобитьсяредактировать другую цепочку инструментов, если это то, что будет выбрано.См. Выбор набора инструментов здесь: https://docs.bazel.build/versions/master/crosstool-reference.html#toolchain-selection

    В текстовом редакторе откройте /tmp/bar/my_toolchain/CROSSTOOL, найдите запись "toolchain", у которой "toolchain_identifier" является "local", и закомментируйте ее записи "cxx_builtin_include_directory" (комментарийсимвол «#»).

    Затем добавьте новый «cxx_builtin_include_directory» для вашего каталога инструментов:

    cxx_builtin_include_directory: "/tmp/bar/my_toolchain"
    

    Вы только что сказали Bazel, где находятся системные заголовки, поэтому, когда он проверяет заголовоквключения, он будет знать, что заголовки по этому пути являются системными заголовками и могут быть включены.

  7. Добавить флаг компилятора для объявления расположения системных заголовков.

    Ниже только что добавленной строки "cxx_builtin_include_directory" добавьте следующее:

    compiler_flag: "-isystem=/tmp/bar/my_toolchain"
    

    Вы только что сказали Bazel сообщить компилятору, откуда он должен искать системные заголовки.

  8. Добавьте заголовки к стандартному набору входов действий компиляции.

    В текстовом редакторе откройте /tmp/bar/my_toolchain/BUILD, найдите файловую группу "compiler_deps" и отредактируйте ее "атрибут srcs, например, так:

    srcs = glob(["**/*.h"]),
    

    Вы только что сказали Bazel всегда включать эти файлы в действия компиляции C ++, чтобы сборка работала с песочницей и удаленным выполнением, а Bazel перестроил правила C ++если какой-либо из системных заголовков (те, которые вы только что добавили в srcs) изменился.

  9. Создайте макет stdc-predef.h.

    Это файл заголовкакомпилятор всегда хочет включить.К счастью, компилятор сначала посмотрит на ваше значение "-isystem", а затем вернется к своему собственному пути по умолчанию (который я не знаю, можете ли вы указать его для ingore), поэтому мы можем смоделировать этот файл следующим образом:

    touch /tmp/bar/my_toolchain/std-predef.h
    
  10. Попробуйте построить с помощью специального кросс-инструмента.

    $ bazel build --crosstool_top=@my_toolchain//:toolchain //:x
    INFO: Build options have changed, discarding analysis cache.
    INFO: Analysed target //:x (0 packages loaded, 61 targets configured).
    INFO: Found 1 target...
    ERROR: /tmp/bar/BUILD:1:1: undeclared inclusion(s) in rule '//:x':
    this rule is missing dependency declarations for the following files included by 'x.cc':
      '/usr/include/stdio.h'
      (...)
    Target //:x failed to build
    Use --verbose_failures to see the command lines of failed build steps.
    INFO: Elapsed time: 0.332s, Critical Path: 0.09s, Remote (0.00% of the time): [queue: 0.00%, setup: 0.00%, process: 0.00%]
    INFO: 0 processes.
    FAILED: Build did NOT complete successfully
    

    Поскольку в нашем каталоге инструментов нет stdio.h, а в собственных каталогах по умолчанию компилятора есть один, он найдет файл и пожалуется на отсутствующие заголовки.Вы можете создать макет stdio.h, чтобы заставить это замолчать.

    Вы можете создать фальшивку stdio.h, чтобы заставить сборку работать, или вы можете удалить строку #include <stdio.h> из x.cc.

  11. Создать поддельный системный заголовок в пользовательской цепочке инструментов.

    Мы будем использовать его для проверки того, что Bazel выбирает файлы из настраиваемой цепочки инструментов.

    echo 'int foo_func(int x) { return x*2; }' > /tmp/bar/my_toolchain/foo.h
    
  12. Переписать исходный файл, включив в него пользовательский системный заголовок.

    echo -e '#include <foo.h>\nint main(int argc, char**) { return foo_func(argc); }' > x.cc
    
  13. Выполнить повторную сборку с помощью пользовательской цепочки инструментов.Теперь все должно работать.

    bazel build --crosstool_top=@my_toolchain//:toolchain //:x
    
  14. Попробуйте запустить встроенный двоичный файл с двумя аргументами (поэтому argc=3):

    bazel-bin/x hello world ; echo $?
    6
    
...