Bazel:处理 ctx.action 中的中间文件
Bazel : handle intermediate files in ctx.action
我正在尝试在 Bazel 中实现自定义 c_library()
规则,它将一堆 .c
文件作为输入并生成 .a
静态库。在我的实现中,.c
个文件生成 .o
个对象,然后归档到 .a
个库中。但似乎没有生成 .o
文件。
这是自定义 c_library()
规则(rules.bzl
文件):
def _change_ext_to_x( file_list, x = 'o' ):
# inputs a file list (i.e. string list)
# and changes their extensions to '.{x}'
return [ "".join( onefile.split('.')[:-1] ) + '.' + x \
for onefile in file_list ]
def _str_to_File( ctx, file_list ):
# A constructor of File() object
# pass the context
return [ ctx.new_file( onefile ) for onefile in file_list ]
def _c_library_impl( ctx ):
# implementation of 'c_library' rule
# the source files list ( strings )
in_file_list = []
for onefile in ctx.files.srcs:
in_file_list.append( onefile.basename )
out_file_list = _str_to_File( ctx, # the current context
_change_ext_to_x(in_file_list, x = 'o') )
ctx.action(
inputs = ctx.files.srcs,
outputs = out_file_list,
progress_message = "COMPILING FROM <.c> TO <.o>",
use_default_shell_env = True,
command = "gcc -c -O3 %s" % " ".join( in_file_list )
)
ctx.action(
inputs = out_file_list,
outputs = [ ctx.outputs._libfile ],
progress_message = "ARCHIVING <.o>s to <.a>",
use_default_shell_env = True,
arguments = [ctx.outputs._libfile.basename],
command = "ar cr %s" % " ".join( [onefile.basename
for onefile in out_file_list] )
)
pass
c_library = rule(
# define rule for 'c' library
implementation = _c_library_impl,
attrs = {
"srcs" : attr.label_list( allow_files = True,
mandatory = True,
allow_empty = False ),
"out" : attr.output( mandatory = False )
},
outputs = {
"_libfile" : "lib%{name}.a"
}
)
这是我的 BUILD
文件:
load("//:rules.bzl", "c_library")
c_library(
name = "foo",
srcs = glob(include = ["*.c"], exclude = ["main.c"])
# there are two files 'cmd.c' and 'utils.c' in the package
)
当我执行 bazel build //:foo
时,出现以下错误:
INFO: Found 1 target...
ERROR: /home/spyder/Desktop/project/BUILD:3:1: output 'cmd.o' was not created.
ERROR: /home/spyder/Desktop/project/BUILD:3:1: output 'utils.o' was not created.
ERROR: /home/spyder/Desktop/project/BUILD:3:1: not all outputs were created or valid.
Target //:foo failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 2.249s, Critical Path: 1.94s
如何在两个连续的 ctx.action
之间保留中间文件?
您应该为每个 .c 文件创建一个操作,而不是为所有文件创建一个操作,这也会增加并行度,然后指定输出:
def _c_library_impl( ctx ):
# implementation of 'c_library' rule
out_file_list = []
for f in ctx.files.srcs:
o = ctx.new_file(f.basename + ".o")
out_file_list.append(o)
ctx.action(
inputs = [f],
outputs = [o],
progress_message = "COMPILING FROM <.c> TO <.o>",
use_default_shell_env = True,
command = "gcc -c -O3 %s %s" % (f.path, o.path)
)
ctx.action(
inputs = out_file_list,
outputs = [ ctx.outputs._libfile ],
progress_message = "ARCHIVING <.o>s to <.a>",
use_default_shell_env = True,
command = "ar cr %s %s" % (ctx.outputs._libfile.path,
"\n".join([onefile.basename
for onefile in out_file_list] )
)
我正在尝试在 Bazel 中实现自定义 c_library()
规则,它将一堆 .c
文件作为输入并生成 .a
静态库。在我的实现中,.c
个文件生成 .o
个对象,然后归档到 .a
个库中。但似乎没有生成 .o
文件。
这是自定义 c_library()
规则(rules.bzl
文件):
def _change_ext_to_x( file_list, x = 'o' ):
# inputs a file list (i.e. string list)
# and changes their extensions to '.{x}'
return [ "".join( onefile.split('.')[:-1] ) + '.' + x \
for onefile in file_list ]
def _str_to_File( ctx, file_list ):
# A constructor of File() object
# pass the context
return [ ctx.new_file( onefile ) for onefile in file_list ]
def _c_library_impl( ctx ):
# implementation of 'c_library' rule
# the source files list ( strings )
in_file_list = []
for onefile in ctx.files.srcs:
in_file_list.append( onefile.basename )
out_file_list = _str_to_File( ctx, # the current context
_change_ext_to_x(in_file_list, x = 'o') )
ctx.action(
inputs = ctx.files.srcs,
outputs = out_file_list,
progress_message = "COMPILING FROM <.c> TO <.o>",
use_default_shell_env = True,
command = "gcc -c -O3 %s" % " ".join( in_file_list )
)
ctx.action(
inputs = out_file_list,
outputs = [ ctx.outputs._libfile ],
progress_message = "ARCHIVING <.o>s to <.a>",
use_default_shell_env = True,
arguments = [ctx.outputs._libfile.basename],
command = "ar cr %s" % " ".join( [onefile.basename
for onefile in out_file_list] )
)
pass
c_library = rule(
# define rule for 'c' library
implementation = _c_library_impl,
attrs = {
"srcs" : attr.label_list( allow_files = True,
mandatory = True,
allow_empty = False ),
"out" : attr.output( mandatory = False )
},
outputs = {
"_libfile" : "lib%{name}.a"
}
)
这是我的 BUILD
文件:
load("//:rules.bzl", "c_library")
c_library(
name = "foo",
srcs = glob(include = ["*.c"], exclude = ["main.c"])
# there are two files 'cmd.c' and 'utils.c' in the package
)
当我执行 bazel build //:foo
时,出现以下错误:
INFO: Found 1 target...
ERROR: /home/spyder/Desktop/project/BUILD:3:1: output 'cmd.o' was not created.
ERROR: /home/spyder/Desktop/project/BUILD:3:1: output 'utils.o' was not created.
ERROR: /home/spyder/Desktop/project/BUILD:3:1: not all outputs were created or valid.
Target //:foo failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 2.249s, Critical Path: 1.94s
如何在两个连续的 ctx.action
之间保留中间文件?
您应该为每个 .c 文件创建一个操作,而不是为所有文件创建一个操作,这也会增加并行度,然后指定输出:
def _c_library_impl( ctx ):
# implementation of 'c_library' rule
out_file_list = []
for f in ctx.files.srcs:
o = ctx.new_file(f.basename + ".o")
out_file_list.append(o)
ctx.action(
inputs = [f],
outputs = [o],
progress_message = "COMPILING FROM <.c> TO <.o>",
use_default_shell_env = True,
command = "gcc -c -O3 %s %s" % (f.path, o.path)
)
ctx.action(
inputs = out_file_list,
outputs = [ ctx.outputs._libfile ],
progress_message = "ARCHIVING <.o>s to <.a>",
use_default_shell_env = True,
command = "ar cr %s %s" % (ctx.outputs._libfile.path,
"\n".join([onefile.basename
for onefile in out_file_list] )
)