是否可以为 exec 平台构建部分可执行文件并将它们用作目标平台的工具链?

Posted

技术标签:

【中文标题】是否可以为 exec 平台构建部分可执行文件并将它们用作目标平台的工具链?【英文标题】:Is it possible to build part of executables for exec platform and use them as toolchain for target platform? 【发布时间】:2021-11-24 09:58:03 【问题描述】:

我有一些关于 bazel 平台和工具链的问题。我目前正在尝试做以下事情:

通过 Bazel 规则构建 clang 将此 clang 用作 cc_toolchain 的一部分 通过这个新工具链构建与 llvm 工具链无关的其他规则。 通过一个“build bazel ...:*”命令完成上述所有这 3 个步骤。

那么,有可能吗?要为 exec 平台构建可执行文件的某些部分(cc_binary、cc_library),然后使用它们作为工具链的一部分,通过使用一个“bazel build”调用为目标平台构建其他可执行文件?还是只能通过几个 bazel 调用来做这样的事情?

我试图用平台和平台转换来做这样的事情,但不知道该怎么做。 你有什么想法吗?

谢谢

【问题讨论】:

【参考方案1】:

完全可以在一次 Bazel 调用中编译工具以在另一个工具链中使用。我在下面粘贴了一个工具链 + 平台玩具,用于演示。

更棘手的是如何让它与 cc_toolchain 一起工作。与 bazel-discuss@googlegroups.com 联系可能会有所帮助,以了解您目前所拥有的以及无法正常工作的内容。

另请参阅 https://docs.bazel.build/versions/main/tutorial/cc-toolchain-config.html https://docs.bazel.build/versions/main/cc-toolchain-config-reference.html


BUILD:

load(":printself.bzl", "printself_toolchain", "printself_binary")

cc_binary(
  name = "printself_compiler_dos",
  srcs = ["printself_compiler_dos.c"],
)

py_binary(
  name = "printself_compiler_dos_py",
  srcs = ["printself_compiler_dos.py"],
  main = "printself_compiler_dos.py",
)

constraint_setting(name = "os")
constraint_setting(name = "cpu")

constraint_value(
  name = "dos",
  constraint_setting = ":os",
)

constraint_value(
  name = "8086",
  constraint_setting = ":cpu",
)

platform(
  name = "dos_8086",
  constraint_values = [
    ":dos",
    ":8086"
  ],
)

toolchain_type(name = "printself_toolchain_type")

printself_toolchain(
  name = "printself_toolchain",
  compiler = ":printself_compiler_dos",
)

toolchain(
    name = "printself_toolchain_dos_8086",
    target_compatible_with = [
        ":dos",
        ":8086",
    ],
    toolchain = ":printself_toolchain",
    toolchain_type = ":printself_toolchain_type",
)

printself_binary(
  name = "hello",
  src = "input.txt",
)

printself.bzl:


def _printself_impl(ctx):
  compiler = ctx.toolchains["//:printself_toolchain_type"].compiler
  out = ctx.actions.declare_file(ctx.label.name + ".com")
  ctx.actions.run(
      outputs = [out],
      inputs = [ctx.files.src[0]],
      arguments = [ctx.files.src[0].path, out.path],
      executable = compiler.files_to_run,
  )

  return DefaultInfo(files = depset([out]))

printself_binary = rule(
  implementation = _printself_impl,
  attrs = 
    "src": attr.label(mandatory = True, allow_single_file = True),
  ,
  toolchains = ["//:printself_toolchain_type"]
)

def _printself_toolchain_impl(ctx):
    toolchain_info = platform_common.ToolchainInfo(
        compiler = ctx.attr.compiler,
    )
    return [toolchain_info]

printself_toolchain = rule(
    implementation = _printself_toolchain_impl,
    attrs = 
        "compiler": attr.label(mandatory = True, executable = True, cfg = "exec"),
    ,
)

printself_compiler_dos.c:

#include <stdio.h>

// "compiles" a txt file to a "self printing" text file
int main(int argc, char *argv[]) 
  if (argc != 3) 
    printf("input and output filenames needed\n");
    return 1;
  
  printf("compiling %s\n", argv[1]);

  FILE* src = fopen(argv[1], "r");
  if (src == NULL) 
    printf("could not open intput file");
    return 1;
  
  char srcbuff[255];
  if (fgets(srcbuff, 255, src) == NULL) 
    printf("could not read input file");
    fclose(src);
    return 1;
  
  fclose(src);

  char prog[] = 
    /* mov ax, 9   */ 0xB4, 0x09,
    /* mov dx, msg */ 0xBA, 0x08, 0x01, // 0x0108 is byte after ret
    /* int 21h     */ 0xCD, 0x21,
    /* ret         */ 0xC3,
    /* msg: db "$" */ 
  ;
  
  FILE* out = fopen(argv[2], "w");
  fwrite(prog, 1, 8, out);
  fputs(srcbuff, out);
  fputc('$', out); // $ terminated string
  fclose(out);

  printf("wrote %s\n", argv[2]);
  printf("done\n");
  return 0;

WORKSPACE:

register_toolchains("//:printself_toolchain_dos_8086")

input.txt:

hello world!

用法:

bazel build hello --platforms=//:dos_8086
dosbox bazel-bin/hello.com

【讨论】:

感谢您的回答!在我提出问题之后,我尝试使用两个显式 cc 工具链(第一个用于主机工具链,第二个用于自定义 clang 工具链)以及两个具有不同约束的不同平台,并为应该通过 clang 工具链构建的目标使用平台转换,这似乎是工作,但你的解决方案似乎很简单,我也会试试这个,谢谢!

以上是关于是否可以为 exec 平台构建部分可执行文件并将它们用作目标平台的工具链?的主要内容,如果未能解决你的问题,请参考以下文章

“exec:”go “:$ PATH中找不到可执行文件”

是否有 Eclipse 插件来构建用于分发的 python 可执行文件?

Linux系统编程之程序的执行(exec函数族)

exec:“powershell”:在 Terraform 中运行 local-exec 时在 $PATH 中找不到可执行文件

动态链接

Runtime.exec() 的安全问题