-
Notifications
You must be signed in to change notification settings - Fork 274
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Added build.py (executable) - Updated the src/coreclr/common.props file to suppress .NET Core Preview warnings - Added a script to run src/coreclr benchmarks against CoreCLr's CoreRun - Updated src/coreclr readme
- Loading branch information
Showing
14 changed files
with
742 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
#!/usr/bin/env python3 | ||
|
||
''' | ||
Builds the CoreClr Benchmarks | ||
''' | ||
|
||
from subprocess import CalledProcessError | ||
from traceback import format_exc | ||
from typing import Tuple | ||
|
||
import argparse | ||
import datetime | ||
import logging | ||
import os | ||
import sys | ||
|
||
from build.common import get_logging_console_handler | ||
from build.common import get_logging_file_handler | ||
from build.common import get_repo_root_path | ||
from build.common import is_supported_version | ||
from build.common import log_start_message | ||
from build.common import LAUNCH_TIME | ||
from build.common import LOGGING_FORMATTER | ||
from build.exception.FatalError import FatalError | ||
from build.parser.TargetFrameworkAction import TargetFrameworkAction | ||
from build.process.DotNet import DotNet | ||
from build.runner.RunCommand import RunCommand | ||
|
||
|
||
def generate_log_file_name() -> str: | ||
'''Generates a unique log file name for the current script''' | ||
log_dir = os.path.join(get_repo_root_path(), 'logs') | ||
if not os.path.exists(log_dir): | ||
os.makedirs(log_dir) | ||
|
||
script_name = os.path.splitext(os.path.basename(sys.argv[0]))[0] | ||
timestamp = datetime.datetime.fromtimestamp(LAUNCH_TIME).strftime( | ||
"%Y%m%d%H%M%S") | ||
log_file_name = '{}-{}-pid{}.log'.format( | ||
timestamp, script_name, os.getpid()) | ||
return os.path.join(log_dir, log_file_name) | ||
|
||
|
||
def init_logging(verbose: bool) -> str: | ||
'''Initializes the loggers used by the script.''' | ||
logging.getLogger().setLevel(logging.INFO) | ||
|
||
log_file_name = generate_log_file_name() | ||
|
||
for logger in ['shell', 'script']: | ||
logging.getLogger(logger).addHandler(get_logging_console_handler( | ||
LOGGING_FORMATTER, verbose)) | ||
logging.getLogger(logger).addHandler(get_logging_file_handler( | ||
log_file_name, LOGGING_FORMATTER)) | ||
logging.getLogger(logger).setLevel(logging.INFO) | ||
|
||
return log_file_name | ||
|
||
|
||
def check_requirements(log_file: str, verbose: bool) -> None: | ||
''' | ||
Checks that the requirements needs to build the CoreClr benchmarks are met. | ||
''' | ||
logging.getLogger('script').info("Making sure dotnet exists...") | ||
try: | ||
cmdline = ['dotnet', '--info'] | ||
RunCommand(log_file, cmdline, verbose=verbose).run('dotnet-info') | ||
except Exception: | ||
raise FatalError("Cannot find dotnet.") | ||
|
||
|
||
def process_arguments() -> Tuple[str, list, bool]: | ||
''' | ||
Function used to parse the command line arguments passed to this script | ||
through the cli. | ||
''' | ||
parser = argparse.ArgumentParser( | ||
description="Builds the CoreClr benchmarks.", | ||
) | ||
parser.add_argument( | ||
'-c', '--configuration', | ||
metavar='CONFIGURATION', | ||
required=False, | ||
default='release', | ||
choices=['debug', 'release'], | ||
type=str.casefold, | ||
help='Configuration use for building the project (default "release").', | ||
) | ||
parser.add_argument( | ||
'-f', '--frameworks', | ||
metavar='FRAMEWORK', | ||
required=False, | ||
nargs='*', | ||
action=TargetFrameworkAction, | ||
default=TargetFrameworkAction.supported_target_frameworks(), | ||
help='Target frameworks to publish for (default all).', | ||
) | ||
parser.add_argument( | ||
'-v', '--verbose', | ||
required=False, | ||
default=False, | ||
action='store_true', | ||
help='Turns on verbosity (default "False")', | ||
) | ||
|
||
# --verbosity <LEVEL> | ||
# ['quiet', 'minimal', 'normal', 'detailed', 'diagnostic'] | ||
|
||
args = parser.parse_args() | ||
return ( | ||
args.configuration, | ||
args.frameworks, | ||
args.verbose | ||
) | ||
|
||
|
||
def build_coreclr( | ||
log_file: str, | ||
configuration: str, | ||
frameworks: list, | ||
verbose: bool) -> None: | ||
'''Builds the CoreClr set of benchmarks (Code Quality).''' | ||
working_directory = os.path.join( | ||
get_repo_root_path(), 'src', 'coreclr', 'PerformanceHarness') | ||
csproj_file = 'PerformanceHarness.csproj' | ||
|
||
dotnet = DotNet(log_file, working_directory, csproj_file, verbose) | ||
dotnet.restore() | ||
for framework in frameworks: | ||
dotnet.publish(configuration, framework, 'CoreClr-Benchmarks') | ||
|
||
|
||
def main() -> int: | ||
'''Script main entry point.''' | ||
try: | ||
if not is_supported_version(): | ||
raise FatalError("Unsupported python version.") | ||
|
||
args = process_arguments() | ||
configuration, frameworks, verbose = args | ||
log_file = init_logging(verbose) | ||
|
||
log_start_message('script') | ||
check_requirements(log_file, verbose) | ||
build_coreclr(log_file, configuration, frameworks, verbose) | ||
|
||
return 0 | ||
except FatalError as ex: | ||
logging.getLogger('script').error(str(ex)) | ||
except CalledProcessError as ex: | ||
logging.getLogger('script').error( | ||
'Command: "%s", exited with status: %s', ex.cmd, ex.returncode) | ||
except IOError as ex: | ||
logging.getLogger('script').error( | ||
"I/O error (%s): %s", ex.errno, ex.strerror) | ||
except SystemExit: # Argparse throws this exception when it exits. | ||
pass | ||
except Exception: | ||
logging.getLogger('script')( | ||
'Unexpected error: {}'.format(sys.exc_info()[0])) | ||
logging.getLogger('script')(format_exc()) | ||
raise | ||
return 1 | ||
|
||
|
||
if __name__ == "__main__": | ||
sys.exit(main()) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
''' | ||
Common functionality used by the .NET Performance Repository build scripts. | ||
''' | ||
|
||
from contextlib import contextmanager | ||
|
||
import datetime | ||
import logging | ||
import os | ||
import sys | ||
import time | ||
|
||
|
||
LAUNCH_TIME = time.time() | ||
LOGGING_FORMATTER = logging.Formatter( | ||
fmt='[%(asctime)s][%(levelname)s] %(message)s', | ||
datefmt="%Y-%m-%d %H:%M:%S") | ||
|
||
|
||
def is_supported_version() -> bool: | ||
'''Checks if the script is running on the supported version (>=3.5).''' | ||
return sys.version_info.major > 2 and sys.version_info.minor > 4 | ||
|
||
|
||
def log_start_message(name) -> None: | ||
'''Used to log a start event message header.''' | ||
start_msg = "Script started at {}".format( | ||
str(datetime.datetime.fromtimestamp(LAUNCH_TIME))) | ||
logging.getLogger(name).info('-' * len(start_msg)) | ||
logging.getLogger(name).info(start_msg) | ||
logging.getLogger(name).info('-' * len(start_msg)) | ||
|
||
|
||
def get_script_path() -> str: | ||
'''Gets this script directory.''' | ||
return sys.path[0] | ||
|
||
|
||
def get_repo_root_path() -> str: | ||
'''Gets repository root directory.''' | ||
return os.path.abspath(os.path.join(get_script_path(), '..')) | ||
|
||
|
||
@contextmanager | ||
def push_dir(path: str = None) -> None: | ||
''' | ||
Adds the specified location to the top of a location stack, then changes to | ||
the specified directory. | ||
''' | ||
if path: | ||
prev = os.getcwd() | ||
try: | ||
logging.getLogger('shell').info('pushd "%s"', path) | ||
os.chdir(path) | ||
yield | ||
finally: | ||
logging.getLogger('shell').info('popd') | ||
os.chdir(prev) | ||
else: | ||
yield | ||
|
||
|
||
def get_logging_console_handler( | ||
fmt: logging.Formatter, | ||
verbose: bool) -> logging.StreamHandler: | ||
''' | ||
Gets a logging console handler (logging.StreamHandler) based on the | ||
specified formatter (logging.Formatter) and verbosity. | ||
''' | ||
console_handler = logging.StreamHandler() | ||
console_handler.setLevel(logging.INFO if verbose else logging.WARNING) | ||
console_handler.setFormatter(fmt) | ||
return console_handler | ||
|
||
|
||
def get_logging_file_handler( | ||
file: str, | ||
fmt: logging.Formatter, | ||
set_formatter: bool = True) -> logging.FileHandler: | ||
''' | ||
Gets a logging file handler (logging.FileHandler) based on the specified | ||
formatter (logging.Formatter). | ||
''' | ||
file_handler = logging.FileHandler(file) | ||
file_handler.setLevel(logging.INFO) | ||
if set_formatter: | ||
file_handler.setFormatter(fmt) | ||
return file_handler |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
''' | ||
Contains the definition of the FatalError exception. | ||
''' | ||
|
||
|
||
class FatalError(Exception): | ||
''' | ||
Raised for various script errors regarding environment and build | ||
requirements. | ||
''' |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
''' | ||
Contains the definition of the TargetFrameworkAction type used to parse | ||
the .NET Cli the supported target frameworks. | ||
''' | ||
|
||
import argparse | ||
|
||
|
||
class TargetFrameworkAction(argparse.Action): | ||
''' | ||
Used by the ArgumentParser to represent the information needed to parse the | ||
supported .NET Core target frameworks argument from the command line. | ||
''' | ||
|
||
def __call__(self, parser, namespace, values, option_string=None): | ||
if values: | ||
wrong_choices = [] | ||
for value in values: | ||
if value not in self.supported_target_frameworks(): | ||
wrong_choices.append(value) | ||
if wrong_choices: | ||
message = ', '.join(wrong_choices) | ||
message = 'Invalid choice(s): {}'.format(message) | ||
raise argparse.ArgumentError(self, message) | ||
setattr(namespace, self.dest, values) | ||
|
||
@staticmethod | ||
def supported_target_frameworks() -> list: | ||
'''List of supported .NET Core target frameworks.''' | ||
return ['netcoreapp1.1', 'netcoreapp2.0', 'netcoreapp2.1', 'net461'] |
Empty file.
Oops, something went wrong.