Я начинаю использовать Bazel в качестве системы сборки проекта C ++.
Однако я застрял со следующей проблемой:
Я нахожусь в сценарии, где я автоматически генерирую file.hpp file.cpp (грамотное программирование).
Чтобы воспроизвести мою проблему, можно просто использовать этот минимальный генератор:
-- file.sh --
#!/bin/sh
echo "int foo();" >> file.hpp
echo "#include \"myLib/file.hpp\"\n\nint foo() { return 2017; }" >> file.cpp
Мой репозиторий проекта: (WORKSPACE — пустой файл)
├── myLib
│ ├── BUILD
│ └── file.sh
└── WORKSPACE
Файл BUILD
genrule(
name = "tangle_file",
srcs = ["file.sh"],
outs = ["file.cpp","file.hpp"],
cmd = "./$(location file.sh);cp file.cpp $(@D);cp file.hpp $(@D);")
cc_library(
name = "file",
srcs = ["file.cpp"],
hdrs = ["file.hpp"],
# deps = [":tangle_file"],
visibility = ["//bin:__pkg__"],
)
У меня две проблемы:
Вопрос (A), касающийся части genrule ():
Тот факт, что я должен использовать
cmd = "./$(location file.sh);cp file.cpp $(@D);cp file.hpp $(@D);"
довольно таинственно
Моя первая попытка была:
cmd = "./$(location file.sh)"
Однако в этом случае я получаю следующую ошибку:
объявленный вывод ‘myLib / file.cpp’ не был создан genrule. Вероятно, это связано с тем, что genrule фактически не создавал этот вывод, или потому что вывод был каталогом, и genrule запускался удаленно (обратите внимание, что только содержимое объявленных выходных файлов копируется из genrules, запускаемого удаленно)
Вопрос (B), касающийся части cc_library ()
Я не знаю, как заставить Базеля осознать, что :файл цель зависит от : tangle_file цель.
Если я раскомментирую:
deps = [":tangle_file"],
Я получаю следующую ошибку:
в атрибуте deps правила cc_library // myLib: file: genrule rule ‘// myLib: tangle_file’ здесь неуместно (ожидается cc_inc_library, cc_library, objc_library, экспериментальный_objc_library или cc_proto_library).
Ошибка, которую вы видите, состоит в том, что genrule cmd не запускается внутри своего выходного каталога. Если вы жестко закодированы bazel-out/local-fastbuild/genfiles/myLib/file.cpp
вместо file.cpp
в вашем file.sh
сценарий, это будет работать. Тем не менее, рекомендуемый подход заключается в том, что ваш сценарий принимает свой выходной каталог в качестве аргумента.
Например,
genrule(
name = "tangle_file",
srcs = ["file.sh"],
outs = ["file.cpp","file.hpp"],
cmd = "./$(location file.sh) $(@D)")
а также
#!/bin/sh
echo "int foo();" >> $1/file.hpp
echo "#include \"myLib/file.hpp\"\n\nint foo() { return 2017; }" >> $1/file.cpp
Тот факт, что у вас есть
srcs = ["file.cpp"],
hdrs = ["file.hpp"],
в вашем cc_library
это то, что говорит Базель, что это зависит от genrule
, так как genrule
создает эти файлы. Если вы хотите сделать это более явным, вы можете использовать синтаксис меток, который делает то же самое:
srcs = ["//myLib:file.cpp"],
hdrs = ["//myLib:file.hpp"],
Других решений пока нет …