2017-07-25 56 views
0

我試圖在Bazel中實現自定義c_library()規則,它將一堆.c文件作爲輸入並生成.a靜態庫。在我的實現中,.c文件生成.o對象,然後歸檔爲.a庫。但似乎.o文件沒有得到生成。 這裏是習俗c_library()規則(rules.bzl文件):Bazel:處理ctx.action中的中間文件

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 $1 %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之間保留中間文件?

回答

3

您應爲每個.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]) 
    ) 
+0

這個工作!在我的代碼中的問題是在命令行中使用'File.basename',在您的代碼中更正時應該是'File.path'。謝謝 !! –