feat: write_source_files windows implementation
This commit is contained in:
parent
ba8b737c24
commit
2195e1c69a
|
@ -8,30 +8,14 @@ _write_source_files_attrs = {
|
|||
"is_windows": attr.bool(mandatory = True),
|
||||
}
|
||||
|
||||
def _write_source_files_impl(ctx):
|
||||
if ctx.attr.is_windows:
|
||||
fail("write_source_file is not yet implemented for windows")
|
||||
|
||||
if (len(ctx.attr.in_files) != len(ctx.attr.out_files)):
|
||||
fail("in_files and out_files must be the same length")
|
||||
|
||||
for i in range(len(ctx.attr.in_files)):
|
||||
out_file_label = ctx.attr.out_files[i].label
|
||||
if is_external_label(out_file_label):
|
||||
fail("out file %s must be a source file in the user workspace" % out_file_label)
|
||||
|
||||
if not ctx.files.out_files[i].is_source:
|
||||
fail("out file %s must be a source file, not a generated file" % out_file_label)
|
||||
|
||||
if out_file_label.package != ctx.label.package:
|
||||
fail("out file %s (in package '%s') must be a source file within the target's package: '%s'" % (out_file_label, out_file_label.package, ctx.label.package))
|
||||
|
||||
def _write_source_files_sh(ctx):
|
||||
updater = ctx.actions.declare_file(
|
||||
ctx.label.name + "_update.sh",
|
||||
)
|
||||
|
||||
ctx.actions.write(
|
||||
output = updater,
|
||||
is_executable = True,
|
||||
content = """
|
||||
#!/usr/bin/env bash
|
||||
set -o errexit -o nounset -o pipefail
|
||||
|
@ -54,6 +38,67 @@ chmod 644 "$out"
|
|||
]),
|
||||
)
|
||||
|
||||
return updater
|
||||
|
||||
def _write_source_files_bat(ctx):
|
||||
updater = ctx.actions.declare_file(
|
||||
ctx.label.name + "_update.bat",
|
||||
)
|
||||
|
||||
content = """
|
||||
@rem Generated by write_source_files.bzl, do not edit.
|
||||
@echo off
|
||||
set runfiles_dir=%cd%
|
||||
if defined BUILD_WORKSPACE_DIRECTORY (
|
||||
cd %BUILD_WORKSPACE_DIRECTORY%
|
||||
)
|
||||
""" + "\n".join(["""
|
||||
set in=%runfiles_dir%\\{in_file}
|
||||
set out={out_file}
|
||||
|
||||
if not defined BUILD_WORKSPACE_DIRECTORY (
|
||||
@rem Because there's no sandboxing in windows, if we copy over the target
|
||||
@rem file's symlink it will get copied back into the source directory
|
||||
@rem during tests. Work around this in tests by deleting the target file
|
||||
@rem symlink before copying over it.
|
||||
del %out%
|
||||
)
|
||||
|
||||
echo Copying %in% to %out% in %cd%
|
||||
copy %in% %out% >NUL
|
||||
""".format(in_file = ctx.files.in_files[i].short_path.replace("/", "\\"), out_file = ctx.files.out_files[i].short_path).replace("/", "\\")
|
||||
for i in range(len(ctx.attr.in_files))
|
||||
])
|
||||
|
||||
content = content.replace("\n", "\r\n")
|
||||
|
||||
ctx.actions.write(
|
||||
output = updater,
|
||||
is_executable = True,
|
||||
content = content,
|
||||
)
|
||||
return updater
|
||||
|
||||
def _write_source_files_impl(ctx):
|
||||
if (len(ctx.attr.in_files) != len(ctx.attr.out_files)):
|
||||
fail("in_files and out_files must be the same length")
|
||||
|
||||
for i in range(len(ctx.attr.in_files)):
|
||||
out_file_label = ctx.attr.out_files[i].label
|
||||
if is_external_label(out_file_label):
|
||||
fail("out file %s must be a source file in the user workspace" % out_file_label)
|
||||
|
||||
if not ctx.files.out_files[i].is_source:
|
||||
fail("out file %s must be a source file, not a generated file" % out_file_label)
|
||||
|
||||
if out_file_label.package != ctx.label.package:
|
||||
fail("out file %s (in package '%s') must be a source file within the target's package: '%s'" % (out_file_label, out_file_label.package, ctx.label.package))
|
||||
|
||||
if ctx.attr.is_windows:
|
||||
updater = _write_source_files_bat(ctx)
|
||||
else:
|
||||
updater = _write_source_files_sh(ctx)
|
||||
|
||||
return DefaultInfo(
|
||||
executable = updater,
|
||||
runfiles = ctx.runfiles(files = ctx.files.in_files),
|
||||
|
|
|
@ -9,7 +9,7 @@ _write_source_files = rule(
|
|||
executable = True,
|
||||
)
|
||||
|
||||
def _impl(ctx):
|
||||
def _impl_sh(ctx):
|
||||
test = ctx.actions.declare_file(
|
||||
ctx.label.name + "_test.sh",
|
||||
)
|
||||
|
@ -55,9 +55,86 @@ assert_same() {
|
|||
]),
|
||||
)
|
||||
|
||||
return test
|
||||
|
||||
def _impl_bat(ctx):
|
||||
test = ctx.actions.declare_file(
|
||||
ctx.label.name + "_test.bat",
|
||||
)
|
||||
|
||||
# BUG: Windows is having trouble executing the symlink to the write_source_files executable,
|
||||
# but it is able to execute the actual output script so point to that for now.
|
||||
#
|
||||
# What we would use if this bug didn't exist:
|
||||
# write_source_files = ctx.executable.write_source_files_target.short_path.replace("/", "\\")
|
||||
#
|
||||
# Instead back out of the runfiles execution directory:
|
||||
# write_to_source_files_test_test.bat.runfiles/aspect_bazel_lib
|
||||
# And point to the output script.
|
||||
write_source_files = "..\\..\\%s" % ctx.executable.write_source_files_target.basename
|
||||
|
||||
content = """
|
||||
@rem Generated by copy_to_directory.bzl, do not edit.
|
||||
@echo off
|
||||
@rem Check that in and out files are different
|
||||
""" + "\n".join(["""
|
||||
call :assert_different {in_file}, {out_file}
|
||||
if %errorlevel% neq 0 exit /b 1
|
||||
""".format(
|
||||
in_file = ctx.files.in_files[i].short_path.replace("/", "\\"),
|
||||
out_file = ctx.files.out_files[i].short_path.replace("/", "\\"),
|
||||
)
|
||||
for i in range(len(ctx.files.in_files))
|
||||
]) + """
|
||||
@rem Write to the source files
|
||||
call {write_source_files}
|
||||
if %errorlevel% neq 0 exit /b 1
|
||||
|
||||
@rem Check that in and out files are the same
|
||||
""".format(write_source_files = write_source_files) + "\n".join(["""
|
||||
call :assert_same {in_file}, {out_file}
|
||||
if %errorlevel% neq 0 exit /b 1
|
||||
""".format(
|
||||
in_file = ctx.files.in_files[i].short_path.replace("/", "\\"),
|
||||
out_file = ctx.files.out_files[i].short_path.replace("/", "\\"),
|
||||
)
|
||||
for i in range(len(ctx.files.in_files))
|
||||
]) + """
|
||||
exit /b 0
|
||||
|
||||
:assert_different
|
||||
fc /b %~1 %~2 > nul
|
||||
if %errorlevel% equ 1 exit /b 0
|
||||
echo Error: %~1 and %~2 are not different
|
||||
exit /b 1
|
||||
|
||||
:assert_same
|
||||
fc /b %~1 %~2 > nul
|
||||
if %errorlevel% equ 0 exit /b 0
|
||||
echo Error: %~1 and %~2 are not the same
|
||||
exit /b 1
|
||||
"""
|
||||
content = content.replace("\n", "\r\n")
|
||||
|
||||
ctx.actions.write(
|
||||
output = test,
|
||||
is_executable = True,
|
||||
content = content
|
||||
)
|
||||
|
||||
return test
|
||||
|
||||
def _impl(ctx):
|
||||
if ctx.attr.is_windows:
|
||||
test = _impl_bat(ctx)
|
||||
else:
|
||||
test = _impl_sh(ctx)
|
||||
|
||||
return DefaultInfo(
|
||||
executable = test,
|
||||
runfiles = ctx.runfiles(files = [ctx.file.write_source_files_target] + ctx.files.in_files + ctx.files.out_files),
|
||||
runfiles = ctx.runfiles(
|
||||
files = [ctx.executable.write_source_files_target] + ctx.files.in_files + ctx.files.out_files,
|
||||
),
|
||||
)
|
||||
|
||||
_write_source_files_test = rule(
|
||||
|
@ -66,7 +143,9 @@ _write_source_files_test = rule(
|
|||
"write_source_files_target": attr.label(
|
||||
allow_single_file = True,
|
||||
executable = True,
|
||||
cfg = "exec",
|
||||
# Should be cfg = "exec" but a bazel bug causes a wrong executable symlink on windows
|
||||
cfg = "target",
|
||||
mandatory = True,
|
||||
),
|
||||
"out_files": attr.label_list(
|
||||
allow_files = True,
|
||||
|
@ -78,6 +157,7 @@ _write_source_files_test = rule(
|
|||
allow_empty = False,
|
||||
mandatory = True,
|
||||
),
|
||||
"is_windows": attr.bool(mandatory = True),
|
||||
},
|
||||
test = True,
|
||||
)
|
||||
|
@ -89,7 +169,10 @@ def write_source_files_test(name, in_files, out_files):
|
|||
name = name + "_updater",
|
||||
out_files = out_files,
|
||||
in_files = in_files,
|
||||
is_windows = False,
|
||||
is_windows = select({
|
||||
"@bazel_tools//src/conditions:host_windows": True,
|
||||
"//conditions:default": False,
|
||||
}),
|
||||
)
|
||||
|
||||
# Note that for testing we update the source files in the sandbox,
|
||||
|
@ -99,4 +182,8 @@ def write_source_files_test(name, in_files, out_files):
|
|||
write_source_files_target = name + "_updater",
|
||||
out_files = out_files,
|
||||
in_files = in_files,
|
||||
is_windows = select({
|
||||
"@bazel_tools//src/conditions:host_windows": True,
|
||||
"//conditions:default": False,
|
||||
}),
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue