bazel midl 规则生成的 c++ 头文件和 winmd 文件位于不同的文件夹中
bazel midl rule generated c++ header file and winmd file locates in different folder
当我使用 bazel 从 midl 文件生成 c++ 头源代码和 winmd 文件时,我发现 MyType.winmd 文件在输出文件夹中,而 MyType.h 与源代码位于同一目录 MyType.idl。我想要的是我生成的头文件与 MyType.winmd 文件位于同一文件夹中。
MyType.idl:
namespace NS
{
[default_interface]
runtimeclass MyType
{
}
}
构建:
load(":cmd.bzl", "midl")
sh_binary(
name = "midlCmd.bat",
srcs = ["midl.bat"],
)
midl(
name = "midlcc.bat",
idl = "MyType.idl",
winmd = "MyType.winmd",
)
cmd.bzl:
def _impl(ctx):
winmd = ctx.outputs.winmd
idl = ctx.file.idl
ctx.actions.run(
inputs = [idl],
outputs = [winmd],
arguments = [winmd.path, idl.path],
progress_message = "Generate winmd from idl file: %s" % idl,
executable = ctx.executable.code_gen_tool,
)
midl = rule(
implementation = _impl,
output_to_genfiles = True,
attrs = {
"idl": attr.label(allow_single_file = True, mandatory = True),
"winmd": attr.output(mandatory = True),
"code_gen_tool": attr.label(
executable = True,
cfg = "exec",
allow_files = True,
default = Label("//cmd:midlCmd.bat"),
),
},
)
midl.bat:
"C:\Program Files (x86)\Windows Kits\bin.0.20206.0\x64\midl.exe" ^
/metadata_dir "%WindowsSdkDir%References\%WindowsSDKVersion%Windows.Foundation.FoundationContract.0.0.0" ^
/reference "%WindowsSdkDir%References\%WindowsSDKVersion%Windows.Foundation.FoundationContract.0.0.0\Windows.Foundation.FoundationContract.winmd" ^
/cpp_cmd "C:\PROGRA~2\MICROS~119\Community\VC\Tools\MSVC.28.29333\bin\Hostx64\x64\cl.exe" ^
/notlb ^
/winrt ^
/nomidl ^
/nologo ^
/enum_class ^
/ns_prefix ^
/client none ^
/server none ^
/winmd %1 %2
运行 命令:
bazel build //cmd:all
在此处生成 MyType.h:
C:\Users\songy\source\repos\tuware\cmd>dir
Directory of C:\Users\songy\source\repos\tuware\cmd
2020-12-02 10:41 PM <DIR> .
2020-12-02 10:40 PM <DIR> ..
2020-12-02 10:41 PM 188 BUILD
2020-12-02 10:33 PM 746 cmd.bzl
2020-12-02 10:30 PM 10,975 midl.bat
2020-12-02 10:41 PM 6,987 MyType.h
2020-11-02 08:41 PM 82 MyType.idl
生成的 MyType.winmd 在这里:
C:\Users\songy\source\repos\tuware\bazel-bin\cmd>dir
2020-12-02 10:30 PM 10,975 midlCmd.bat
2020-12-02 10:40 PM <DIR> midlCmd.bat.runfiles
2020-12-02 10:40 PM 247 midlCmd.bat.runfiles_manifest
2020-12-02 10:41 PM 1,536 MyType.winmd
2020-12-02 10:40 PM <DIR> setupCppDesktopDevEnvironment.bat.runfiles
2020-12-02 10:40 PM 293 setupCppDesktopDevEnvironment.bat.runfiles_manifest
有什么我想念的吗?
我看不出如何使用 bazel 的沙箱将文件输出到源目录中。
我唯一能想到的是 midlCmd.bat
硬编码了绝对路径。
生成器应该基于相对路径。如果需要目录结构,规则可以向生成器的命令行提供ctx.configuration.genfiles_dir.path
。
谢谢@rds 这是我自己的答案。
- 在 midl.bat
中添加 ctx.configuration.genfiles_dir.path
作为 /out 选项值
- 对 winmd 和 .h 生成的文件名使用 ctx.declare_file。
def _impl(ctx):
idl = ctx.file.idl
midl_out_dir = ctx.configuration.genfiles_dir.path
winmd = ctx.actions.declare_file(ctx.label.name + ".winmd")
header = ctx.actions.declare_file(ctx.label.name + ".h")
ctx.actions.run(
executable = ctx.executable.code_gen_tool,
arguments = [midl_out_dir, idl.path],
inputs = [idl],
outputs = [winmd, header],
progress_message = "Generate winmd from idl file: %s" % idl.path,
)
return [DefaultInfo(files=depset([winmd, header]))]
midl = rule(
implementation = _impl,
output_to_genfiles = True,
attrs = {
"idl": attr.label(allow_single_file = True, mandatory = True),
"code_gen_tool": attr.label(
executable = True,
cfg = "exec",
allow_files = True,
default = Label("//cmd:midlCmd.bat"),
),
},
)
midl.bat:
"%WindowsSdkDir%\bin\%WindowsSDKVersion%\%Platform%\midl.exe" ^
/metadata_dir "%WINDOWS_SDK_REFERENCE_PATH%\Windows.Foundation.FoundationContract.0.0.0" ^
/reference "%WINDOWS_SDK_REFERENCE_PATH%\Windows.Foundation.FoundationContract.0.0.0\Windows.Foundation.FoundationContract.winmd" ^
/cpp_cmd "%VSINSTALLDIR%\VC\Tools\MSVC\%VCToolsVersion%\bin\Host%Platform%\%Platform%\cl.exe" ^
/notlb ^
/winrt ^
/nomidl ^
/nologo ^
/enum_class ^
/ns_prefix ^
/client none ^
/server none ^
/out %1 ^
%2
当我使用 bazel 从 midl 文件生成 c++ 头源代码和 winmd 文件时,我发现 MyType.winmd 文件在输出文件夹中,而 MyType.h 与源代码位于同一目录 MyType.idl。我想要的是我生成的头文件与 MyType.winmd 文件位于同一文件夹中。
MyType.idl:
namespace NS
{
[default_interface]
runtimeclass MyType
{
}
}
构建:
load(":cmd.bzl", "midl")
sh_binary(
name = "midlCmd.bat",
srcs = ["midl.bat"],
)
midl(
name = "midlcc.bat",
idl = "MyType.idl",
winmd = "MyType.winmd",
)
cmd.bzl:
def _impl(ctx):
winmd = ctx.outputs.winmd
idl = ctx.file.idl
ctx.actions.run(
inputs = [idl],
outputs = [winmd],
arguments = [winmd.path, idl.path],
progress_message = "Generate winmd from idl file: %s" % idl,
executable = ctx.executable.code_gen_tool,
)
midl = rule(
implementation = _impl,
output_to_genfiles = True,
attrs = {
"idl": attr.label(allow_single_file = True, mandatory = True),
"winmd": attr.output(mandatory = True),
"code_gen_tool": attr.label(
executable = True,
cfg = "exec",
allow_files = True,
default = Label("//cmd:midlCmd.bat"),
),
},
)
midl.bat:
"C:\Program Files (x86)\Windows Kits\bin.0.20206.0\x64\midl.exe" ^
/metadata_dir "%WindowsSdkDir%References\%WindowsSDKVersion%Windows.Foundation.FoundationContract.0.0.0" ^
/reference "%WindowsSdkDir%References\%WindowsSDKVersion%Windows.Foundation.FoundationContract.0.0.0\Windows.Foundation.FoundationContract.winmd" ^
/cpp_cmd "C:\PROGRA~2\MICROS~119\Community\VC\Tools\MSVC.28.29333\bin\Hostx64\x64\cl.exe" ^
/notlb ^
/winrt ^
/nomidl ^
/nologo ^
/enum_class ^
/ns_prefix ^
/client none ^
/server none ^
/winmd %1 %2
运行 命令:
bazel build //cmd:all
在此处生成 MyType.h:
C:\Users\songy\source\repos\tuware\cmd>dir
Directory of C:\Users\songy\source\repos\tuware\cmd
2020-12-02 10:41 PM <DIR> .
2020-12-02 10:40 PM <DIR> ..
2020-12-02 10:41 PM 188 BUILD
2020-12-02 10:33 PM 746 cmd.bzl
2020-12-02 10:30 PM 10,975 midl.bat
2020-12-02 10:41 PM 6,987 MyType.h
2020-11-02 08:41 PM 82 MyType.idl
生成的 MyType.winmd 在这里:
C:\Users\songy\source\repos\tuware\bazel-bin\cmd>dir
2020-12-02 10:30 PM 10,975 midlCmd.bat
2020-12-02 10:40 PM <DIR> midlCmd.bat.runfiles
2020-12-02 10:40 PM 247 midlCmd.bat.runfiles_manifest
2020-12-02 10:41 PM 1,536 MyType.winmd
2020-12-02 10:40 PM <DIR> setupCppDesktopDevEnvironment.bat.runfiles
2020-12-02 10:40 PM 293 setupCppDesktopDevEnvironment.bat.runfiles_manifest
有什么我想念的吗?
我看不出如何使用 bazel 的沙箱将文件输出到源目录中。
我唯一能想到的是 midlCmd.bat
硬编码了绝对路径。
生成器应该基于相对路径。如果需要目录结构,规则可以向生成器的命令行提供ctx.configuration.genfiles_dir.path
。
谢谢@rds 这是我自己的答案。
- 在 midl.bat 中添加
- 对 winmd 和 .h 生成的文件名使用 ctx.declare_file。
ctx.configuration.genfiles_dir.path
作为 /out 选项值
def _impl(ctx):
idl = ctx.file.idl
midl_out_dir = ctx.configuration.genfiles_dir.path
winmd = ctx.actions.declare_file(ctx.label.name + ".winmd")
header = ctx.actions.declare_file(ctx.label.name + ".h")
ctx.actions.run(
executable = ctx.executable.code_gen_tool,
arguments = [midl_out_dir, idl.path],
inputs = [idl],
outputs = [winmd, header],
progress_message = "Generate winmd from idl file: %s" % idl.path,
)
return [DefaultInfo(files=depset([winmd, header]))]
midl = rule(
implementation = _impl,
output_to_genfiles = True,
attrs = {
"idl": attr.label(allow_single_file = True, mandatory = True),
"code_gen_tool": attr.label(
executable = True,
cfg = "exec",
allow_files = True,
default = Label("//cmd:midlCmd.bat"),
),
},
)
midl.bat:
"%WindowsSdkDir%\bin\%WindowsSDKVersion%\%Platform%\midl.exe" ^
/metadata_dir "%WINDOWS_SDK_REFERENCE_PATH%\Windows.Foundation.FoundationContract.0.0.0" ^
/reference "%WINDOWS_SDK_REFERENCE_PATH%\Windows.Foundation.FoundationContract.0.0.0\Windows.Foundation.FoundationContract.winmd" ^
/cpp_cmd "%VSINSTALLDIR%\VC\Tools\MSVC\%VCToolsVersion%\bin\Host%Platform%\%Platform%\cl.exe" ^
/notlb ^
/winrt ^
/nomidl ^
/nologo ^
/enum_class ^
/ns_prefix ^
/client none ^
/server none ^
/out %1 ^
%2