-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
[coverage] Automatic merger for LLVM profile data #1126
Conversation
…mands, because we're using LLVM's environment variables
… test run and properly create profile directories. This removes the need for use_profdir.py and removes the valgrind hack from lit.site.cfg.in
… into build-script to propagate the different values
… are three states for SWIFT_ANALYZE_CODE_COVERAGE
…d up the implementation
…plicit choices to --swift-analyze-code-coverage
@@ -23,9 +23,9 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") | |||
PROPERTIES | |||
LINK_FLAGS "-Wl,-rpath -Wl,@executable_path/../lib") |
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 if you change this to append to LINK_FLAGS
, then you won't need to duplicate appending -fprofile-instr-generate
below -- it will come from AddSwift.cmake. Because this call to set_target_properties
does not append, it overwrites the flags set by AddSwift.cmake.
I also don't see a definition of |
…umented options for build-script flag.
@@ -58,6 +58,10 @@ option(SWIFT_INCLUDE_DOCS | |||
"Create targets for building docs." | |||
TRUE) | |||
|
|||
option(SWIFT_ANALYZE_CODE_COVERAGE |
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 use FALSE or NO as the default. See the CMake docs for if.
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's no longer a boolean flag -- it's one of three possibilities, none
, not-merged
, or merged
.
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.
Ugh, I just scrolled down far enough to see that this has modes now. Can you rephrase the description to make that clear?
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, will do.
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.
Though maybe we should use FALSE
as the none
case.
So the values are FALSE
, NOT-MERGED
, and MERGED
?
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 OFF
makes sense, but for consistency's sake I think we should stick with FALSE
. I'll default it to that and make sure it propagates as FALSE
through build-script
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.
However, we still won't be able to revert to if(SWIFT_ANALYZE_CODE_COVERAGE)
because it'll default to FALSE
for all the possible cases.
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.
Huh? "if (<variable>)
: True if the variable is defined to a value that is not a false constant".
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.
Oh! Must've misread that, then. 👍
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.
CMake has a way to specify stringly-typed variables with multiple allowed values, see line 16.
@swift-ci Please test |
@swift-ci Please test |
@@ -129,6 +132,43 @@ if config.test_exec_root is None: | |||
|
|||
### | |||
|
|||
class SwiftTest(lit.formats.ShTest): | |||
def __init__(self, coverage_mode=None, execute_external=True): | |||
lit.formats.ShTest.__init__(self, execute_external=execute_external) |
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 it's preferable to use super
here, as in:
super(SwiftTest, self).__init__(execute_external=excute_external)
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.
👍
stop.set_defaults(func=stop_server) | ||
|
||
args = parser.parse_args() | ||
args.func(args) |
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 would be nice to create a Python module for this, as opposed to a single file. It'd allow you to:
- Add tests for the module. You could also add the tests to the Swift validation test suite, as in [validation-test] Add line-directive doctests #810.
- Split the file up.
Config
,ProfdataMergerProcess
,ProfdataTCPHandler
, and even the argument parser could each get their own file. Where possible, it would be nice to unit test these classes.
# FIXME: This doesn't necessarily always line up with the version | ||
# of clang++ used to build the binaries. | ||
llvm_cmd = ("xcrun llvm-profdata merge -o %s %s" | ||
% (self.profdata_path, cleaned_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.
In addition to not matching the clang++
used to build the binaries, this command also would not work on Linux. Is this not meant to be cross-platform?
Would it be possible to somehow access utils/swift_build_support
? swift_build_support.clang
includes utilities to find the host machine's clang++
. These might be overridden by specifying build-script-impl
args, though, so even that's not foolproof...
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.
We'd love to make it work on Linux, but for right now we're okay with it being OS X-only. This depends on having a suitable version of compiler-rt
installed alongside clang, which we can guarantee with Xcode.
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.
Sounds good! Would it be possible to fail gracefully for Linux, then? I imagine users of this script may be confused to suddenly encounter a subprocess
stack trace where xcrun
is called.
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's gonna print an error and exit -- that's now in main.py. 👍
@modocache I agree that the script would be better off as a module. Let me know what you think, and thanks so much for the review! |
if __name__ == "__main__": | ||
parser = argparse.ArgumentParser() | ||
|
||
subparsers = parser.add_subparsers() |
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.
Wow, I had no idea about add_subparsers()
! Very cool functionality. 👍
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 actually found out about it in utils/build-script
!
Thank you for the fascinating read, @harlanhaskins. And I've never seen anyone address comments so quickly! 😁 My parting thought is that it would be nice if we could verify the behavior of this code without actually building Swift itself--it seems like it would be difficult for someone new to this codebase to verify whether this was working correctly. |
@modocache Thanks for the comprehensive review! I really appreciate your input. The codebase relies really heavily on global out-of-process state, which makes it hard to test, but it's definitely not specific to Swift. This process could be used to merge profile data from instrumented builds of anything, (modulo some hard-coded filenames that explicitly say 'swift'). I could envision a small test runner that compiles a simple C file with profiling and shoots files at the server, then investigates the output, but I don't know if that's on the roadmap for me right away. Thanks again! |
@gribozavr I think this is good to merge. We should probably run the CI once more, though. (@shahmishal, too) |
@swift-ci Please test |
[coverage] Automatic merger for LLVM profile data
When
build-script
is given--swift-analyze-code-coverage merged
, this will fire off this worker which responds to tests and merges generated profile data into a final coverage file in the test results folder.