Skip to content

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

Merged
merged 1 commit into from
Jan 26, 2017
Merged

Fix line-directive tool to work around Windows command line max limit #6464

merged 1 commit into from
Jan 26, 2017

Conversation

hughbe
Copy link
Contributor

@hughbe hughbe commented Dec 22, 2016

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:

  • Write a list of the files to compile to a file
  • Read that file in a the new line-directive-file script into a list of files.
  • Invoke the original line-directive-file via Python.

Extracted from #5904

Copy link
Member

@compnerd compnerd left a 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")
Copy link
Member

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.

Copy link
Member

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.

Copy link
Contributor Author

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()
Copy link
Member

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.

Copy link
Contributor Author

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

@hughbe
Copy link
Contributor Author

hughbe commented Dec 26, 2016

Thanks for the review. For the @name comment, I'm not sure I understand. Could you clarify this? I will update the PR accordingly

@slavapestov
Copy link
Contributor

There's a merge conflict here

Copy link
Member

@compnerd compnerd left a 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")
Copy link
Member

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}"
Copy link
Member

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}"
Copy link
Member

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}" --
Copy link
Member

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}"
Copy link
Member

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}"
Copy link
Member

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")
Copy link
Member

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:
Copy link
Member

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)
Copy link
Member

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.

@hughbe
Copy link
Contributor Author

hughbe commented Jan 15, 2017

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}" --
Copy link
Member

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}?

Copy link
Contributor Author

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] == '@':
Copy link
Member

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)
Copy link
Member

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.

@hughbe
Copy link
Contributor Author

hughbe commented Jan 15, 2017

I've updated the PR to fix the bad merge, and consolidate response file expansion

@compnerd
Copy link
Member

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - f443fff5e8c8b1412c9a0b7e3010e7187168657a
Test requested by - @compnerd

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - f443fff5e8c8b1412c9a0b7e3010e7187168657a
Test requested by - @compnerd

@hughbe
Copy link
Contributor Author

hughbe commented Jan 17, 2017

@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)
Copy link
Member

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.

Copy link
Contributor Author

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 ';'

Copy link
Contributor Author

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

Copy link
Member

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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

@hughbe
Copy link
Contributor Author

hughbe commented Jan 18, 2017

@swift-ci please smoke test

@hughbe hughbe dismissed compnerd’s stale review January 19, 2017 16:36

Please re-review

@hughbe
Copy link
Contributor Author

hughbe commented Jan 25, 2017

@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(';'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here.

@hughbe hughbe closed this Jan 26, 2017
@hughbe hughbe reopened this Jan 26, 2017
@hughbe
Copy link
Contributor Author

hughbe commented Jan 26, 2017

@swift-ci please smoke test

@compnerd compnerd merged commit 466ab59 into swiftlang:master Jan 26, 2017
@hughbe hughbe deleted the line-directive-windows branch January 26, 2017 15:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants