Reduce build times (especially on windows) by symlinking directories (#983)

This commit is contained in:
jheaff1 2022-11-09 00:14:43 +00:00 committed by GitHub
parent 78acc733fb
commit 6425a21252
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 126 additions and 59 deletions

View File

@ -51,7 +51,7 @@ def _create_ninja_script(configureParameters):
script = []
root = detect_root(ctx.attr.lib_source)
script.append("##symlink_contents_to_dir## $$EXT_BUILD_ROOT$$/{} $$BUILD_TMPDIR$$".format(root))
script.append("##symlink_contents_to_dir## $$EXT_BUILD_ROOT$$/{} $$BUILD_TMPDIR$$ False".format(root))
data = ctx.attr.data + ctx.attr.build_data

View File

@ -670,10 +670,10 @@ def _copy_deps_and_tools(files):
if files.tools_files:
lines.append("##mkdirs## $$EXT_BUILD_DEPS$$/bin")
for tool in files.tools_files:
lines.append("##symlink_to_dir## $$EXT_BUILD_ROOT$$/{} $$EXT_BUILD_DEPS$$/bin/".format(tool))
lines.append("##symlink_to_dir## $$EXT_BUILD_ROOT$$/{} $$EXT_BUILD_DEPS$$/bin/ False".format(tool))
for ext_dir in files.ext_build_dirs:
lines.append("##symlink_to_dir## $$EXT_BUILD_ROOT$$/{} $$EXT_BUILD_DEPS$$".format(_file_path(ext_dir)))
lines.append("##symlink_to_dir## $$EXT_BUILD_ROOT$$/{} $$EXT_BUILD_DEPS$$ True".format(_file_path(ext_dir)))
lines.append("##children_to_path## $$EXT_BUILD_DEPS$$/bin")
lines.append("##path## $$EXT_BUILD_DEPS$$/bin")
@ -692,7 +692,7 @@ def _symlink_contents_to_dir(dir_name, files_list):
path = _file_path(file).strip()
if path:
lines.append("##symlink_contents_to_dir## \
$$EXT_BUILD_ROOT$$/{} $$EXT_BUILD_DEPS$$/{}".format(path, dir_name))
$$EXT_BUILD_ROOT$$/{} $$EXT_BUILD_DEPS$$/{} True".format(path, dir_name))
return lines

View File

@ -227,6 +227,7 @@ PLATFORM_COMMANDS = {
doc = "Source directory, immediate children of which are symlinked, or file to be symlinked.",
),
_argument_info(name = "target", data_type = type(""), doc = "Target directory"),
_argument_info(name = "replace_in_files", data_type = type(""), doc = "True if all transitive files in the source directory should have replace_in_files run"),
],
doc = (
"Symlink contents of the directory to target directory (create the target directory if needed). " +
@ -241,6 +242,7 @@ PLATFORM_COMMANDS = {
doc = "Source directory",
),
_argument_info(name = "target", data_type = type(""), doc = "Target directory"),
_argument_info(name = "replace_in_files", data_type = type(""), doc = "True if all transitive files in the source directory should have replace_in_files run"),
],
doc = (
"Symlink all files from source directory to target directory (create the target directory if needed). " +

View File

@ -109,7 +109,7 @@ find "{target}" -type f -exec touch -r "{source}" "{{}}" \\;
target = target,
)
def symlink_contents_to_dir(source, target):
def symlink_contents_to_dir(source, target, replace_in_files):
text = """\
if [[ -z "$1" ]]; then
echo "arg 1 to symlink_contents_to_dir is unexpectedly empty"
@ -121,24 +121,25 @@ if [[ -z "$2" ]]; then
fi
local target="$2"
mkdir -p "$target"
local replace_in_files="${3:-}"
if [[ -f "$1" ]]; then
##symlink_to_dir## "$1" "$target"
##symlink_to_dir## "$1" "$target" "$replace_in_files"
elif [[ -L "$1" && ! -d "$1" ]]; then
local actual=$(readlink "$1")
##symlink_contents_to_dir## "$actual" "$target"
##symlink_contents_to_dir## "$actual" "$target" "$replace_in_files"
elif [[ -d "$1" ]]; then
SAVEIFS=$IFS
IFS=$'\n'
local children=($(find "$1/" -maxdepth 1 -mindepth 1))
IFS=$SAVEIFS
for child in "${children[@]:-}"; do
##symlink_to_dir## "$child" "$target"
##symlink_to_dir## "$child" "$target" "$replace_in_files"
done
fi
"""
return FunctionAndCallInfo(text = text)
def symlink_to_dir(source, target):
def symlink_to_dir(source, target, replace_in_files):
text = """\
if [[ -z "$1" ]]; then
echo "arg 1 to symlink_to_dir is unexpectedly empty"
@ -150,6 +151,7 @@ if [[ -z "$2" ]]; then
fi
local target="$2"
mkdir -p "$target"
local replace_in_files="${3:-}"
if [[ -f "$1" ]]; then
# In order to be able to use `replace_in_files`, we ensure that we create copies of specfieid
# files so updating them is possible.
@ -162,6 +164,13 @@ if [[ -f "$1" ]]; then
elif [[ -L "$1" && ! -d "$1" ]]; then
cp -pR "$1" "$2"
elif [[ -d "$1" ]]; then
# If not replacing in files, simply create a symbolic link rather than traversing tree of files, which can result in very slow builds
if [[ "$replace_in_files" = False ]]; then
ln -s -f "$1" "$target"
return
fi
SAVEIFS=$IFS
IFS=$'\n'
local children=($(find "$1/" -maxdepth 1 -mindepth 1))
@ -170,7 +179,7 @@ elif [[ -d "$1" ]]; then
mkdir -p "$target/$dirname"
for child in "${children[@]:-}"; do
if [[ -n "$child" && "$dirname" != *.ext_build_deps ]]; then
##symlink_to_dir## "$child" "$target/$dirname"
##symlink_to_dir## "$child" "$target/$dirname" "$replace_in_files"
fi
done
else

View File

@ -91,7 +91,7 @@ def copy_dir_contents_to_dir(source, target):
target = target,
)
def symlink_contents_to_dir(source, target):
def symlink_contents_to_dir(source, target, replace_in_files):
text = """\
if [[ -z "$1" ]]; then
echo "arg 1 to symlink_contents_to_dir is unexpectedly empty"
@ -103,24 +103,25 @@ if [[ -z "$2" ]]; then
fi
local target="$2"
mkdir -p "$target"
local replace_in_files="${3:-}"
if [[ -f "$1" ]]; then
##symlink_to_dir## "$1" "$target"
##symlink_to_dir## "$1" "$target" "$replace_in_files"
elif [[ -L "$1" ]]; then
local actual=$(readlink "$1")
##symlink_contents_to_dir## "$actual" "$target"
##symlink_contents_to_dir## "$actual" "$target" "$replace_in_files"
elif [[ -d "$1" ]]; then
SAVEIFS=$IFS
IFS=$'\n'
local children=($(find -H "$1" -maxdepth 1 -mindepth 1))
IFS=$SAVEIFS
for child in "${children[@]:-}"; do
##symlink_to_dir## "$child" "$target"
##symlink_to_dir## "$child" "$target" "$replace_in_files"
done
fi
"""
return FunctionAndCallInfo(text = text)
def symlink_to_dir(source, target):
def symlink_to_dir(source, target, replace_in_files):
text = """\
if [[ -z "$1" ]]; then
echo "arg 1 to symlink_to_dir is unexpectedly empty"
@ -132,6 +133,7 @@ if [[ -z "$2" ]]; then
fi
local target="$2"
mkdir -p "$target"
local replace_in_files="${3:-}"
if [[ -f "$1" ]]; then
# In order to be able to use `replace_in_files`, we ensure that we create copies of specfieid
# files so updating them is possible.
@ -144,6 +146,13 @@ if [[ -f "$1" ]]; then
elif [[ -L "$1" && ! -d "$1" ]]; then
cp -pR "$1" "$2"
elif [[ -d "$1" ]]; then
# If not replacing in files, simply create a symbolic link rather than traversing tree of files, which can result in very slow builds
if [[ "$replace_in_files" = False ]]; then
ln -s -f "$1" "$target"
return
fi
SAVEIFS=$IFS
IFS=$'\n'
local children=($(find -H "$1" -maxdepth 1 -mindepth 1))
@ -152,7 +161,7 @@ elif [[ -d "$1" ]]; then
mkdir -p "$target/$dirname"
for child in "${children[@]:-}"; do
if [[ -n "$child" && "$dirname" != *.ext_build_deps ]]; then
##symlink_to_dir## "$child" "$target/$dirname"
##symlink_to_dir## "$child" "$target/$dirname" "$replace_in_files"
fi
done
else

View File

@ -100,7 +100,7 @@ find "{target}" -type f -exec touch -r "{source}" "{{}}" \\;
target = target,
)
def symlink_contents_to_dir(source, target):
def symlink_contents_to_dir(source, target, replace_in_files):
text = """\
if [[ -z "$1" ]]; then
echo "arg 1 to symlink_contents_to_dir is unexpectedly empty"
@ -112,24 +112,25 @@ if [[ -z "$2" ]]; then
fi
local target="$2"
mkdir -p "$target"
local replace_in_files="${3:-}"
if [[ -f "$1" ]]; then
##symlink_to_dir## "$1" "$target"
##symlink_to_dir## "$1" "$target" "$replace_in_files"
elif [[ -L "$1" && ! -d "$1" ]]; then
local actual=$(readlink "$1")
##symlink_contents_to_dir## "$actual" "$target"
##symlink_contents_to_dir## "$actual" "$target" "$replace_in_files"
elif [[ -d "$1" ]]; then
SAVEIFS=$IFS
IFS=$'\n'
local children=($(find "$1/" -maxdepth 1 -mindepth 1))
IFS=$SAVEIFS
for child in "${children[@]:-}"; do
##symlink_to_dir## "$child" "$target"
##symlink_to_dir## "$child" "$target" "$replace_in_files"
done
fi
"""
return FunctionAndCallInfo(text = text)
def symlink_to_dir(source, target):
def symlink_to_dir(source, target, replace_in_files):
text = """\
if [[ -z "$1" ]]; then
echo "arg 1 to symlink_to_dir is unexpectedly empty"
@ -141,6 +142,7 @@ if [[ -z "$2" ]]; then
fi
local target="$2"
mkdir -p "$target"
local replace_in_files="${3:-}"
if [[ -f "$1" ]]; then
# In order to be able to use `replace_in_files`, we ensure that we create copies of specfieid
# files so updating them is possible.
@ -153,6 +155,13 @@ if [[ -f "$1" ]]; then
elif [[ -L "$1" && ! -d "$1" ]]; then
cp -pR "$1" "$2"
elif [[ -d "$1" ]]; then
# If not replacing in files, simply create a symbolic link rather than traversing tree of files, which can result in very slow builds
if [[ "$replace_in_files" = False ]]; then
ln -s -f "$1" "$target"
return
fi
SAVEIFS=$IFS
IFS=$'\n'
local children=($(find "$1/" -maxdepth 1 -mindepth 1))
@ -161,7 +170,7 @@ elif [[ -d "$1" ]]; then
mkdir -p "$target/$dirname"
for child in "${children[@]:-}"; do
if [[ -n "$child" && "$dirname" != *.ext_build_deps ]]; then
##symlink_to_dir## "$child" "$target/$dirname"
##symlink_to_dir## "$child" "$target/$dirname" "$replace_in_files"
fi
done
else

View File

@ -95,7 +95,7 @@ def copy_dir_contents_to_dir(source, target):
target = target,
)
def symlink_contents_to_dir(source, target):
def symlink_contents_to_dir(source, target, replace_in_files):
text = """\
if [[ -z "$1" ]]; then
echo "arg 1 to symlink_contents_to_dir is unexpectedly empty"
@ -107,24 +107,25 @@ if [[ -z "$2" ]]; then
fi
local target="$2"
mkdir -p "$target"
local replace_in_files="${3:-}"
if [[ -f "$1" ]]; then
##symlink_to_dir## "$1" "$target"
##symlink_to_dir## "$1" "$target" "$replace_in_files"
elif [[ -L "$1" ]]; then
local actual=$(readlink "$1")
##symlink_contents_to_dir## "$actual" "$target"
##symlink_contents_to_dir## "$actual" "$target" "$replace_in_files"
elif [[ -d "$1" ]]; then
SAVEIFS=$IFS
IFS=$'\n'
local children=($($REAL_FIND -H "$1" -maxdepth 1 -mindepth 1))
IFS=$SAVEIFS
for child in "${children[@]}"; do
##symlink_to_dir## "$child" "$target"
##symlink_to_dir## "$child" "$target" "$replace_in_files"
done
fi
"""
return FunctionAndCallInfo(text = text)
def symlink_to_dir(source, target):
def symlink_to_dir(source, target, replace_in_files):
text = """\
if [[ -z "$1" ]]; then
echo "arg 1 to symlink_to_dir is unexpectedly empty"
@ -136,6 +137,7 @@ if [[ -z "$2" ]]; then
fi
local target="$2"
mkdir -p "$target"
local replace_in_files="${3:-}"
if [[ -f "$1" ]]; then
# In order to be able to use `replace_in_files`, we ensure that we create copies of specfieid
# files so updating them is possible.
@ -147,8 +149,15 @@ if [[ -f "$1" ]]; then
fi
elif [[ -L "$1" ]]; then
local actual=$(readlink "$1")
##symlink_to_dir## "$actual" "$target"
##symlink_to_dir## "$actual" "$target" "$replace_in_files"
elif [[ -d "$1" ]]; then
# If not replacing in files, simply create a symbolic link rather than traversing tree of files, which can result in very slow builds
if [[ "$replace_in_files" = False ]]; then
ln -s -f "$1" "$target"
return
fi
SAVEIFS=$IFS
IFS=$'\n'
local children=($($REAL_FIND -H "$1" -maxdepth 1 -mindepth 1))
@ -156,7 +165,7 @@ elif [[ -d "$1" ]]; then
local dirname=$(basename "$1")
for child in "${children[@]}"; do
if [[ -n "$child" && "$dirname" != *.ext_build_deps ]]; then
##symlink_to_dir## "$child" "$target/$dirname"
##symlink_to_dir## "$child" "$target/$dirname" "$replace_in_files"
fi
done
else

View File

@ -16,7 +16,7 @@ def create_make_script(
script = pkgconfig_script(ext_build_dirs)
script.append("##symlink_contents_to_dir## $$EXT_BUILD_ROOT$$/{} $$BUILD_TMPDIR$$".format(root))
script.append("##symlink_contents_to_dir## $$EXT_BUILD_ROOT$$/{} $$BUILD_TMPDIR$$ False".format(root))
script.append("##enable_tracing##")
configure_vars = get_make_env_vars(workspace_name, tools, flags, env_vars, deps, inputs)

View File

@ -14,7 +14,7 @@ utils_test_suite()
shell_script_helper_test_rule(
name = "shell_script_inner_fun",
out = "inner_fun_text.txt",
script = ["##symlink_contents_to_dir## $$SOURCE_DIR$$ $$TARGET_DIR$$"],
script = ["##symlink_contents_to_dir## $$SOURCE_DIR$$ $$TARGET_DIR$$ False"],
)
# TODO: This should not be necessary but there appears to be some inconsistent

View File

@ -70,8 +70,8 @@ def _replace_vars_win_test(ctx):
return unittest.end(env)
def _funny_fun(a, b):
return a + "_" + b
def _funny_fun(a, b, c):
return a + "_" + b + "_" + c
def _echo(text):
return "echo1 " + text
@ -109,7 +109,7 @@ def _do_function_call_test(ctx):
cases = {
"##echo## \"\ntext\n\"": "echo1 \"\ntext\n\"",
"##script_prelude##": "set -euo pipefail",
"##symlink_contents_to_dir## 1 2": "1_2",
"##symlink_contents_to_dir## 1 2 3": "1_2_3",
"export ROOT=\"A B C\"": "export1 ROOT=\"A B C\"",
"export ROOT=\"ABC\"": "export1 ROOT=\"ABC\"",
"export ROOT=ABC": "export1 ROOT=ABC",
@ -196,22 +196,23 @@ fi
return unittest.end(env)
def _symlink_contents_to_dir(source, target):
def _symlink_contents_to_dir(source, target, replace_in_files):
text = """local target="$2"
mkdir -p $target
local replace_in_files="${3:-}"
if [[ -f $1 ]]; then
##symlink_to_dir## $1 $target
##symlink_to_dir## $1 $target $replace_in_files
return 0
fi
local children=$(find $1 -maxdepth 1 -mindepth 1)
for child in $children; do
##symlink_to_dir## $child $target
##symlink_to_dir## $child $target $replace_in_files
done
"""
return FunctionAndCallInfo(text = text)
def _symlink_to_dir(source, target):
def _symlink_to_dir(source, target, replace_in_files):
text = """local target="$2"
mkdir -p ${target}
@ -229,18 +230,19 @@ fi
def _script_conversion_test(ctx):
env = unittest.begin(ctx)
script = ["##symlink_contents_to_dir## a b"]
script = ["##symlink_contents_to_dir## a b False"]
expected = """function symlink_contents_to_dir() {
local target="$2"
mkdir -p $target
local replace_in_files="${3:-}"
if [[ -f $1 ]]; then
symlink_to_dir $1 $target
symlink_to_dir $1 $target $replace_in_files
return 0
fi
local children=$(find $1 -maxdepth 1 -mindepth 1)
for child in $children; do
symlink_to_dir $child $target
symlink_to_dir $child $target $replace_in_files
done
}
@ -259,7 +261,7 @@ echo "Can not copy $1"
fi
}
symlink_contents_to_dir a b"""
symlink_contents_to_dir a b False"""
shell_ = struct(
symlink_contents_to_dir = _symlink_contents_to_dir,
symlink_to_dir = _symlink_to_dir,

View File

@ -9,11 +9,12 @@ exit 1
fi
local target="$2"
mkdir -p "$target"
local replace_in_files="${3:-}"
if [[ -f "$1" ]]; then
symlink_to_dir "$1" "$target"
symlink_to_dir "$1" "$target" "$replace_in_files"
elif [[ -L "$1" ]]; then
local actual=$(readlink "$1")
symlink_contents_to_dir "$actual" "$target"
symlink_contents_to_dir "$actual" "$target" "$replace_in_files"
elif [[ -d "$1" ]]; then
SAVEIFS=$IFS
IFS=$'
@ -21,7 +22,7 @@ IFS=$'
local children=($(find -H "$1" -maxdepth 1 -mindepth 1))
IFS=$SAVEIFS
for child in "${children[@]:-}"; do
symlink_to_dir "$child" "$target"
symlink_to_dir "$child" "$target" "$replace_in_files"
done
fi
}
@ -36,6 +37,7 @@ exit 1
fi
local target="$2"
mkdir -p "$target"
local replace_in_files="${3:-}"
if [[ -f "$1" ]]; then
# In order to be able to use `replace_in_files`, we ensure that we create copies of specfieid
# files so updating them is possible.
@ -48,6 +50,13 @@ fi
elif [[ -L "$1" && ! -d "$1" ]]; then
cp -pR "$1" "$2"
elif [[ -d "$1" ]]; then
# If not replacing in files, simply create a symbolic link rather than traversing tree of files, which can result in very slow builds
if [[ "$replace_in_files" = False ]]; then
ln -s -f "$1" "$target"
return
fi
SAVEIFS=$IFS
IFS=$'
'
@ -57,11 +66,11 @@ local dirname=$(basename "$1")
mkdir -p "$target/$dirname"
for child in "${children[@]:-}"; do
if [[ -n "$child" && "$dirname" != *.ext_build_deps ]]; then
symlink_to_dir "$child" "$target/$dirname"
symlink_to_dir "$child" "$target/$dirname" "$replace_in_files"
fi
done
else
echo "Can not copy $1"
fi
}
symlink_contents_to_dir $SOURCE_DIR $TARGET_DIR
symlink_contents_to_dir $SOURCE_DIR $TARGET_DIR False

View File

@ -9,11 +9,12 @@ exit 1
fi
local target="$2"
mkdir -p "$target"
local replace_in_files="${3:-}"
if [[ -f "$1" ]]; then
symlink_to_dir "$1" "$target"
symlink_to_dir "$1" "$target" "$replace_in_files"
elif [[ -L "$1" && ! -d "$1" ]]; then
local actual=$(readlink "$1")
symlink_contents_to_dir "$actual" "$target"
symlink_contents_to_dir "$actual" "$target" "$replace_in_files"
elif [[ -d "$1" ]]; then
SAVEIFS=$IFS
IFS=$'
@ -21,7 +22,7 @@ IFS=$'
local children=($(find "$1/" -maxdepth 1 -mindepth 1))
IFS=$SAVEIFS
for child in "${children[@]:-}"; do
symlink_to_dir "$child" "$target"
symlink_to_dir "$child" "$target" "$replace_in_files"
done
fi
}
@ -36,6 +37,7 @@ exit 1
fi
local target="$2"
mkdir -p "$target"
local replace_in_files="${3:-}"
if [[ -f "$1" ]]; then
# In order to be able to use `replace_in_files`, we ensure that we create copies of specfieid
# files so updating them is possible.
@ -48,6 +50,13 @@ fi
elif [[ -L "$1" && ! -d "$1" ]]; then
cp -pR "$1" "$2"
elif [[ -d "$1" ]]; then
# If not replacing in files, simply create a symbolic link rather than traversing tree of files, which can result in very slow builds
if [[ "$replace_in_files" = False ]]; then
ln -s -f "$1" "$target"
return
fi
SAVEIFS=$IFS
IFS=$'
'
@ -57,11 +66,11 @@ local dirname=$(basename "$1")
mkdir -p "$target/$dirname"
for child in "${children[@]:-}"; do
if [[ -n "$child" && "$dirname" != *.ext_build_deps ]]; then
symlink_to_dir "$child" "$target/$dirname"
symlink_to_dir "$child" "$target/$dirname" "$replace_in_files"
fi
done
else
echo "Can not copy $1"
fi
}
symlink_contents_to_dir $SOURCE_DIR $TARGET_DIR
symlink_contents_to_dir $SOURCE_DIR $TARGET_DIR False

View File

@ -9,11 +9,12 @@ exit 1
fi
local target="$2"
mkdir -p "$target"
local replace_in_files="${3:-}"
if [[ -f "$1" ]]; then
symlink_to_dir "$1" "$target"
symlink_to_dir "$1" "$target" "$replace_in_files"
elif [[ -L "$1" && ! -d "$1" ]]; then
local actual=$(readlink "$1")
symlink_contents_to_dir "$actual" "$target"
symlink_contents_to_dir "$actual" "$target" "$replace_in_files"
elif [[ -d "$1" ]]; then
SAVEIFS=$IFS
IFS=$'
@ -21,7 +22,7 @@ IFS=$'
local children=($(find "$1/" -maxdepth 1 -mindepth 1))
IFS=$SAVEIFS
for child in "${children[@]:-}"; do
symlink_to_dir "$child" "$target"
symlink_to_dir "$child" "$target" "$replace_in_files"
done
fi
}
@ -36,6 +37,7 @@ exit 1
fi
local target="$2"
mkdir -p "$target"
local replace_in_files="${3:-}"
if [[ -f "$1" ]]; then
# In order to be able to use `replace_in_files`, we ensure that we create copies of specfieid
# files so updating them is possible.
@ -48,6 +50,13 @@ fi
elif [[ -L "$1" && ! -d "$1" ]]; then
cp -pR "$1" "$2"
elif [[ -d "$1" ]]; then
# If not replacing in files, simply create a symbolic link rather than traversing tree of files, which can result in very slow builds
if [[ "$replace_in_files" = False ]]; then
ln -s -f "$1" "$target"
return
fi
SAVEIFS=$IFS
IFS=$'
'
@ -57,11 +66,11 @@ local dirname=$(basename "$1")
mkdir -p "$target/$dirname"
for child in "${children[@]:-}"; do
if [[ -n "$child" && "$dirname" != *.ext_build_deps ]]; then
symlink_to_dir "$child" "$target/$dirname"
symlink_to_dir "$child" "$target/$dirname" "$replace_in_files"
fi
done
else
echo "Can not copy $1"
fi
}
symlink_contents_to_dir $SOURCE_DIR $TARGET_DIR
symlink_contents_to_dir $SOURCE_DIR $TARGET_DIR False

View File

@ -11,8 +11,8 @@ def _symlink_contents_to_dir_test_rule_impl(ctx):
dir2 = detect_root(ctx.attr.dir2)
script_lines = [
"##mkdirs## aaa",
"##symlink_contents_to_dir## %s aaa" % dir1,
"##symlink_contents_to_dir## %s aaa" % dir2,
"##symlink_contents_to_dir## %s aaa False" % dir1,
"##symlink_contents_to_dir## %s aaa False" % dir2,
"ls -R aaa > %s" % out.path,
]
converted_script = convert_shell_script(ctx, script_lines)