-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Change stdlib swiftc's to depend on .swiftmodule's instead of .o's #5472
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
Fantastic! |
@swift-ci please smoke test |
Yay! Thanks Pete. |
Would love a review from someone more familiar with our CMake setup. |
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.
It pretty much all looks fine to me; just a few comments here and there. I hadn't even thought to come at this from this side because I was still thinking of type-checking as the main slowdown. This does do some extra work and spawns more processes, but with an optimized stdlib it's probably a win. (Less sure about a debug compiler / debug stdlib combination, but that's not very common.)
Thanks, Pete!
@@ -1320,6 +1329,8 @@ function(add_swift_library name) | |||
# Configure variables for this subdirectory. | |||
set(VARIANT_SUFFIX "-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}") | |||
set(VARIANT_NAME "${name}${VARIANT_SUFFIX}") | |||
set(MODULE_VARIANT_SUFFIX "-swiftmodule-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}") |
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.
Should it just get this from the regular VARIANT_SUFFIX?
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.
Do you mean the "${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}" part in MODULE_VARIANT_SUFFIX? If so, then yeah, I'll fix that.
@@ -1384,6 +1389,15 @@ function(add_swift_library name) | |||
endif() | |||
endforeach() | |||
|
|||
set(swiftlib_framework_depends_flattened ${SWIFTLIB_FRAMEWORK_DEPENDS}) |
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.
Why move this?
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 if it is just a move, can you do the move in a separate commit?
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 it didn't move. It the diff not really knowing how I applied the changes.
What we have before was a loop to set swiftlib_module_dependency_targets, then later a loop to set swiftlib_framework_depends_flattened, and finally a loop for swiftlib_private_link_libraries_targets.
In the original code, swiftlib_private_link_libraries_targets was initialized to swiftlib_module_dependency_targets, but we don't want that any more. This is because swiftlib_module_dependency_targets now contains references to the swift module files, and we want swiftlib_private_link_libraries_targets to reference the linked images. So I changed swiftlib_private_link_libraries_targets to initialise to empty instead of swiftlib_module_dependency_targets then added appends to this loop to set it appropriately.
And yes, I could definitely move the in a separate commit then only make the change the following a change in a new commit:
list(APPEND swiftlib_module_dependency_targets
"swift${mod}${VARIANT_SUFFIX}")
to
list(APPEND swiftlib_module_dependency_targets
"swift${mod}${MODULE_VARIANT_SUFFIX}")
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.
There definitely is a move here: the ICU section and the swiftlib_framework_depends_flattened switched. I do see that it makes a little more sense.
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.
Sorry, yes there's a move. I still had the 'git diff' my local machine shows in my head. In it, it appears that the loop over swiftlib_framework_depends_flattened moves, which it didn't really. What actually moved was the content I described above.
list(APPEND module_command | ||
"-emit-module" | ||
"-emit-module-path" "${module_file}" | ||
"-o" "${module_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.
You shouldn't need both -emit-module-path
and -o
here. Either one should be fine.
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.
Oddly it didn't work with only -emit-module and no -o. No error or anything, just a lack of anything being written to disk. If I can remove the -emit-module-path then that would be fine for now. I should file a bug for the lack of -o causing there to be no writes to disk and no errors.
if (NOT ${num_apinotes_outputs} EQUAL 0) | ||
add_custom_command_target( | ||
api_notes_dependency_target | ||
${command_create_dirs} |
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.
Creating directories needs to be done regardless, no?
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.
Yep, thats a mistake. Good catch. I might just always have this target run, but in some cases it will only create directories and in others it will create directories and api notes. If you have a preference for something else i'm also totally fine with alternatives.
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 seems good enough. Creating API notes is very cheap.
endif() | ||
|
||
# First generate the api notes if we need them. | ||
list(LENGTH command_create_apinotes num_apinotes_outputs) |
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.
Should this be measuring apinotes_outputs
instead?
Is there any reason to not just use if (apinotes_outputs)
?
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 (apinotes_outputs) is much better. I'll use that. I just don't know enough CMake to know if thats ok or not. I figured it would be on a string but wasn't sure about a list.
DEPENDS | ||
${swift_compiler_tool_dep} | ||
${source_files} ${SWIFTFILE_DEPENDS} | ||
${swift_ide_test_dependency} ${depends_create_apinotes} |
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 should actually only depend on depends_create_apinotes
. API notes are completely independent from any of the Swift stuff.
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.
Good catch. Will fix that.
${swift_compiler_tool_dep} | ||
${source_files} ${SWIFTFILE_DEPENDS} | ||
${swift_ide_test_dependency} ${api_notes_dependency_target} | ||
COMMENT "Compiling ${first_output}") |
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.
Different comment, maybe?
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.
Yep, I should put in "Generating {module_name}" instead.
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.
Meta request. Can you make sure that before/after if you do a clean build nothing is rebuilt. From what I understand ChrisB got us to that point and I would like to stay that way = ).
@@ -536,7 +536,7 @@ endfunction() | |||
# | |||
# source1 ... | |||
# Sources to add into this library | |||
function(_add_swift_library_single target name) | |||
function(_add_swift_library_single target module_target name) |
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.
Can you add documentation to the header for what module_target is. Also, even better, can you change these options here to be cmake_parse_argument Arguments. Then below when you use "" for the module_target name, it would be at least self documenting that it is not a bug (see question below).
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.
Sure, will add documentation.
I can try out adding a parse argument. Will need to also change 'target' above as I only added 'module_target' in this way to be consistent.
Would you prefer that change first, then land the rest of this?
@@ -1384,6 +1389,15 @@ function(add_swift_library name) | |||
endif() | |||
endforeach() | |||
|
|||
set(swiftlib_framework_depends_flattened ${SWIFTLIB_FRAMEWORK_DEPENDS}) |
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 if it is just a move, can you do the move in a separate commit?
@@ -700,6 +701,13 @@ function(_add_swift_library_single target name) | |||
INSTALL_IN_COMPONENT "${SWIFTLIB_INSTALL_IN_COMPONENT}") | |||
add_swift_source_group("${SWIFTLIB_SINGLE_EXTERNAL_SOURCES}") | |||
|
|||
# If there were any swift sources, then a .swiftmodule may have been created. | |||
# If that is the case, then add a target which is an alias of the module files. | |||
if(NOT "${module_target}" STREQUAL "" AND NOT "${swift_module_dependency_target}" STREQUAL "") |
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 made module_target a cmake_parse_arguments target, then this would be cleaner. Specifically, you could do:
if (NOT "${SWIFTLIB_MODULE_TARGET}" AND NOT "${swift_module_dependency_target}")
endif()
Then it would be clear that module_target is an argument due to the SWIFTLIB_* prefix.
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 see. Yeah the prefix would be better than what we have today.
set(swiftlib_module_dependency_targets) | ||
set(swiftlib_private_link_libraries_targets) |
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.
Unless I am missing something, isn't the variable swiftlib_private_link_libraries_targets dead?
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.
Didn't see to be. I had issues with this when I was writing the patch. Ultimately it makes its way to the following which causes dylibs to be on the link line:
function(_add_swift_library_single
...
target_link_libraries("${target}" PRIVATE
${SWIFTLIB_SINGLE_PRIVATE_LINK_LIBRARIES})
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.
Right, it's still a dependency of the link target for each module.
@@ -1603,6 +1618,7 @@ function(add_swift_library name) | |||
|
|||
_add_swift_library_single( | |||
${name} | |||
"" |
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 is why I would suggest adding a named argument /assuming/ that is the correct thing to do here.
Then it would be clear that this is not a bug since you would have:
MODULE_TARGET ""
That being said, if you do what I suggested above, then this argument could be removed.
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.
Ah yeah, i like the self documentation there. Much better.
@@ -274,6 +280,7 @@ function(_compile_swift_files dependency_target_out_var_name) | |||
set(module_file) | |||
set(module_doc_file) | |||
|
|||
set(module_command) | |||
if(NOT SWIFTFILE_IS_MAIN) |
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 section may make sense to refactor into its own function... thoughts?
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.
My reasoning is that in the general flow of things, adding swift_flags -parse-as-library where you adding it, seems funky. That being said, this isn't that big of a deal.
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.
It was actually just a move as the previous code had use adding '-emit-module ... -parse-as-library' on one branch and '-parse-as-library' on the other. But I agree that this is getting a little unwieldy at its current size. Thats probably worth someone refactoring a whole bunch of stuff though, which is better left to who is going to own it long term.
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.
Ok. I am fine with that.
${name} | ||
${SWIFTLIB_SHARED_keyword} | ||
${SWIFTLIB_STATIC_keyword} | ||
${SWIFTLIB_OBJECT_LIBRARY_keyword} | ||
${SWIFTLIB_SOURCES} | ||
MODULE_TARGET "" |
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 should be no longer necessary.
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.
Thanks. You're right. Just removed it.
I think you have answered all of my concerns. Removing my request. |
Before you commit though, can you do a rebase/squash to prettify the history on your branch? |
Thanks Michael! Yeah, will squash the commits and make it all pretty. Should I do one last swift-ci just to verify, or does that get done automatically for me when the PR is merged? |
…wiftc deps. Currently SwiftOnoneSupport.o waits on Swift.o to finish compiling before we start compiling SwiftOnoneSupport.o. We don't need the .o for compilation but instead just need Swift.swiftmodule which we were generating anyway. This change causes .o and { .swiftmodule, .swiftdoc } to be built independently of each other. Downstream compiles only wait on the module while downstream links wait on the .o. Given that .apinotes are sometimes used by swiftc invocations, this also separates out apinotes in to its own step which these other commands can both depend on. The result of this is a 30% improvement in building the stdlib with -R and 20% with -d. Specifically, -R drops from 3m to 2m and -d drops from 12m to just under 10m.
6a8722b
to
53ecbf2
Compare
@swift-ci Please test and merge |
…rating module command. We need to actually have a module name and outputs or else the add_custom_command will try to generate multiple commands all with the name NOTFOUND. Note, this bug was introduced in 5834df3 via PR swiftlang#5472.
Currently SwiftOnoneSupport.o waits on Swift.o to finish compiling before we start
compiling SwiftOnoneSupport.o. We don't need the .o for compilation but instead just
need Swift.swiftmodule which we were generating anyway.
This change causes .o and { .swiftmodule, .swiftdoc } to be built independently of each
other. Downstream compiles only wait on the module while downstream links wait on the .o.
Given that .apinotes are sometimes used by swiftc invocations, this also separates out
apinotes in to its own step which these other commands can both depend on.
The result of this is a 30% improvement in building the stdlib with -R and 20% with -d.
Specifically, -R drops from 3m to 2m and -d drops from 12m to just under 10m.
This was tested with --validation-test which uncovered a missing dependency. After adding that
in, we now pass the tests.