Skip to content

Instantly share code, notes, and snippets.

@TeresaP
Last active June 24, 2020 06:12
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TeresaP/c95be67e6389e34deac0d2dd5a07cf42 to your computer and use it in GitHub Desktop.
Save TeresaP/c95be67e6389e34deac0d2dd5a07cf42 to your computer and use it in GitHub Desktop.
Profdata Code Coverage
// Forward-declare LLVM (profdata) methods for usage below
// For documentation, see: http://clang.llvm.org/docs/SourceBasedCodeCoverage.html
int __llvm_profile_write_file(void);
void __llvm_profile_initialize_file(void);
void __llvm_profile_set_filename(const char *Name);
/**
* Generate profraw (profdata) code coverage
*/
- (BOOL)beginCodeCoverage:(NSString*)fullFilePath
{
__llvm_profile_set_filename([fullFilePath UTF8String]);
__llvm_profile_initialize_file();
// llvm_profile_write_file returns 0 on success and 'something else' if unsuccessful
return (__llvm_profile_write_file() == 0);
}
# Contains the methods for generating profdata coverage
# First we generate a profraw file, which we then need to convert to the profdata format
# Documentation here: http://clang.llvm.org/docs/SourceBasedCodeCoverage.html
class CodeCoverage
class Profdata
@app_name = 'YourAppNameHere'
@build_path = CODE_COVERAGE_BUILD_PARENT_PATH ||= ''
@code_coverage_folder_path = File.join(@build_path, 'CodeCoverage/')
@project_intermediates = CODE_COVERAGE_INTERMEDIATES_DIR ||= nil
# Check to see if we are set up to collect code coverage
# @return [Boolean] True if code coverage is on (CODE_COVERAGE_BUILD_PARENT_PATH was set to something), false if not
def self.on?
return !@build_path.empty?
end
# Generates code coverage at the specified path with the specified filename
# @param [String] code_coverage_output_path The path to the output file
# @param [String] code_coverage_filename The name of the file you want to generate
def self.generate_llvm_coverage(code_coverage_output_path = @code_coverage_folder_path, code_coverage_filename = 'UIAutomationCoverage.profraw')
if self.on?
code_coverage_output_full_path = File.join(code_coverage_output_path, code_coverage_filename)
success = backdoor('beginCodeCoverage:', code_coverage_output_full_path)
if success
log_message("[CODE COVERAGE] Code coverage data saved to #{code_coverage_output_full_path}")
else
log_failure("[CODE COVERAGE] Attempted to save code coverage to #{code_coverage_output_full_path}, but it was not successful.")
end
end
end
end
end
# This should be set to the parent directory containing the build folders such as /viewer-ios/
CODE_COVERAGE_BUILD_PARENT_PATH = ENV['CODE_COVERAGE_BUILD_PARENT_PATH']
if CODE_COVERAGE_BUILD_PARENT_PATH
xc_workspace_path=Dir["#{CODE_COVERAGE_BUILD_PARENT_PATH}/*.xcworkspace"].first
schema='YourSchemaHere-cal'
intermediates_dir=`xcodebuild -showBuildSettings -workspace #{xc_workspace_path} -scheme #{schema} | grep -m 1 'PROJECT_TEMP_ROOT' | sed -n -e 's/^.*PROJECT_TEMP_ROOT = //p'`
CODE_COVERAGE_INTERMEDIATES_DIR=intermediates_dir.strip
end
/////////////////////////////////////
// Apple LLVM 7.0 - Code Generation
/////////////////////////////////////
// Sets -fprofile-instr-generate
CLANG_INSTRUMENT_FOR_OPTIMIZATION_PROFILING = YES
GCC_OPTIMIZATION_LEVEL = 0
// Activating this setting causes a 'notes' file to be produced that the gcov code-coverage utility can use to show program coverage.
GCC_GENERATE_TEST_COVERAGE_FILES = NO
// Activating this setting indicates that code should be added so program flow arcs are instrumented.
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO
@JoeSSS
Copy link

JoeSSS commented Dec 28, 2016

Cool stuff! But the APP doesn't compile.. I'm getting linker errors like

Undefined symbols for architecture x86_64:
  "___llvm_profile_write_file", referenced from:
      -[XNGViewController viewDidLoad] in XNGViewController.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Should smth else be done to a project?

@JoeSSS
Copy link

JoeSSS commented Dec 28, 2016

I think that I got a .profraw file in the sample project. Could you give an idea how to parse it? :)

@JoeSSS
Copy link

JoeSSS commented Dec 30, 2016

Looks like int __llvm_profile_write_file(void) works for Obj C projects in pair with CLANG_INSTRUMENT_FOR_OPTIMIZATION_PROFILING. But as long as you add one swift file in the project swift will complain.. Swift does not support profile guided optimization.. Are there any workarounds?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment