-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Fix line-directive tool to work around Windows command line max limit #6464
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the @
sigil, it should be possible to merge the tool into the existing line-directive
tool, shouldnt it?
# Python utility script (line-directive-file), which reads the list of file paths, | ||
# passing them to the old Python utility script, line-directive. | ||
set(line_directive_tool "${SWIFT_SOURCE_DIR}/utils/line-directive-file") | ||
set(line_directive_arguments, "${CMAKE_CURRENT_BINARY_DIR}/line-directive-file.txt") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That , probably is not desired.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that it would be nicer to follow the traditional response file naming convention of @name
to indicate that the file should be read and expanded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was an unused variable (dead code). Removed
set(source_files_string "") | ||
foreach(file ${source_files}) | ||
set(source_files_string "${source_files_string} ${file}") | ||
endforeach() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if these 4 lines are used elsewhere in the build system. It really seems ripe for moving into ListUtils.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've moved it into SwiftList.cmake
. I think we can add uses of the new list_join
function as we find them
Thanks for the review. For the |
There's a merge conflict here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change that you split out into a wrapper tool can be condensed enough to place into the original tool and simplify things.
# Python utility script (line-directive-file), which reads the list of file paths, | ||
# passing them to the old Python utility script, line-directive. | ||
set(line_directive_tool "${SWIFT_SOURCE_DIR}/utils/line-directive-file") | ||
set(file_path "${CMAKE_CURRENT_BINARY_DIR}/line-directive.tmp") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that I like this. Just feels like the could be a collision of there are parallel builds. Can we use a generated name?
"${swift_compiler_tool}" "-emit-module" "-o" "${module_file}" ${swift_flags} | ||
"${source_files}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that I would rather that we keep the old behavior in tact. Can you use "@${file_path}" here?
"${swift_compiler_tool}" "${main_command}" ${swift_flags} | ||
${output_option} ${embed_bitcode_option} "${source_files}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that I would rather we keep the old behavior. Can you use "@${file_path}" here?
add_custom_command_target( | ||
dependency_target | ||
COMMAND | ||
"${line_directive_tool}" "${source_files}" -- | ||
"${PYTHON_EXECUTABLE}" "${line_directive_tool}" "${file_path}" -- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that I would rather keep the tool compatible with the previous invocation. Can you use the @ sigil to indicate that the contents of the file should be read as options?
"${swift_compiler_tool}" "-emit-sib" "-o" "${sib_file}" ${swift_flags} -Onone | ||
"${source_files}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar
"${swift_compiler_tool}" "-emit-sibgen" "-o" "${sibgen_file}" ${swift_flags} | ||
"${source_files}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here
# achieved by writing the list of file paths to a file, passing that file to a new | ||
# Python utility script (line-directive-file), which reads the list of file paths, | ||
# passing them to the old Python utility script, line-directive. | ||
set(line_directive_tool "${SWIFT_SOURCE_DIR}/utils/line-directive-file") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the change needed is small enough that we can collapse of into the tool itself.
# that we need to have a way to bypass the command line to pass files to | ||
# line-directive. An alternative is reading a file written by CMake and | ||
# forwarding the arguments via Python. | ||
with open(sys.argv[1], 'r') as files: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding a:
if sys.argv[0][0] == '@':
means that we can integrate this into the original tool and makes it behave more like other tools.
if len(sys.argv) > 2: | ||
# We need to append the list of files again (for swiftc) | ||
args = sys.argv[2:] | ||
args.extend(sources) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this flip the order? We want the previously read options to precede the subsequent options.
Thanks Saleem for your review. I've updated the PR to your comments. This PR now depends on #6824 being merged |
@@ -518,9 +530,9 @@ function(_compile_swift_files | |||
add_custom_command_target( | |||
sibopt_dependency_target | |||
COMMAND | |||
"${PYTHON_EXECUTABLE}" "${line_directive_tool}" "${source_files}" -- | |||
"${line_directive_tool}" "@${file_path}" -- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think that this is right. Why are you dropping the use of ${PYTHON_EXECUTABLE}
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops, mad merge conflict resolution
command_args[0] = os.path.normpath(command_args[0]) | ||
|
||
last_index = len(command_args) - 1 | ||
if command_args[last_index][0] == '@': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be written as if command_args[-1][0] == '@'
if command_args[last_index][0] == '@': | ||
# Read sources from a file. | ||
command_args = command_args[0:last_index] | ||
command_args.extend(sources) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason that we want the response file to be the last entry always? I think that we should expand any and in place.
I've updated the PR to fix the bad merge, and consolidate response file expansion |
@swift-ci please test |
Build failed |
Build failed |
@compnerd any more comments or is this good to go? |
# in the Python script. | ||
string(RANDOM file_name) | ||
set(file_path "${CMAKE_CURRENT_BINARY_DIR}/${file_name}.txt") | ||
list_join("${source_files}" ";" source_files_string) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you are joining the list with ;
(which does make it easier to deal with paths which may have spaces, although it is less like traditional response files), then the list_join
is equivalent to "${source_files}"
as CMake will implicitly ;
the list when converting it to a string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I found that things glitched out and broken in a path with spaces, so replaced with ';'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I just discovered ";" is a legal character in a Windows file path. I've replaced uses of ';' with '|' which is illegal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What am I misunderstanding? The separator is still ;
on the diff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
;
is legal on Unix too. I'm pretty sure cmake is hopelessly doomed if any file path actually uses ;
so we don't need to work around that threat here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Derp, I didn't push the commit changing ';' to '|'
Fair enough actually - I'll keep ';' and follow your suggestion
@swift-ci please smoke test |
@swift-ci please smoke test |
@@ -154,6 +154,21 @@ def map_line_from_source_file(source_filename, source_line_num, target_filename) | |||
return result + 1 | |||
raise RuntimeError("line not found") | |||
|
|||
def read_response_file(file_path): | |||
with open(file_path, 'r') as files: | |||
return filter(None, files.read().split(';')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here.
@swift-ci please smoke test |
Windows has an 8000 character limit for
commands executed from the shell. We exceed this limit when compiling the standard library.
This means that we need to work around this:
line-directive-file
script into a list of files.line-directive-file
via Python.Extracted from #5904