Skip to content
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

Merged
merged 42 commits into from
Feb 3, 2016

Conversation

harlanhaskins
Copy link
Contributor

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.

@@ -23,9 +23,9 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
PROPERTIES
LINK_FLAGS "-Wl,-rpath -Wl,@executable_path/../lib")
Copy link
Contributor

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.

@gribozavr
Copy link
Contributor

I also don't see a definition of SWIFT_ANALYZE_CODE_COVERAGE in the top-level CMakeLists.txt, could you add it (with a list of possible values)?

@@ -58,6 +58,10 @@ option(SWIFT_INCLUDE_DOCS
"Create targets for building docs."
TRUE)

option(SWIFT_ANALYZE_CODE_COVERAGE
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, will do.

Copy link
Contributor Author

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?

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

Copy link
Contributor Author

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.

Copy link
Contributor

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".

Copy link
Contributor Author

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. 👍

Copy link
Contributor

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.

@shahmishal
Copy link
Member

@swift-ci Please test

@shahmishal
Copy link
Member

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

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)

Copy link
Contributor Author

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

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:

  1. 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.
  2. 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))
Copy link
Contributor

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...

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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. 👍

@harlanhaskins
Copy link
Contributor Author

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

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. 👍

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 actually found out about it in utils/build-script!

@modocache
Copy link
Contributor

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.

@harlanhaskins
Copy link
Contributor Author

@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!

@harlanhaskins
Copy link
Contributor Author

@gribozavr I think this is good to merge. We should probably run the CI once more, though. (@shahmishal, too)

@shahmishal
Copy link
Member

@swift-ci Please test

gribozavr added a commit that referenced this pull request Feb 3, 2016
[coverage] Automatic merger for LLVM profile data
@gribozavr gribozavr merged commit b728b89 into swiftlang:master Feb 3, 2016
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.

5 participants