1
0
Fork 0
llvm-premerge-checks/scripts/run_cmake.py

191 lines
6.4 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
# Copyright 2020 Google LLC
#
# Licensed under the the Apache License v2.0 with LLVM Exceptions (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://llvm.org/LICENSE.txt
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import argparse
from enum import Enum
from git import Repo
import os
import platform
import shutil
import subprocess
2020-04-16 10:30:39 +02:00
import stat
from typing import List, Dict
import yaml
2020-04-16 10:30:39 +02:00
from choose_projects import ChooseProjects
class OperatingSystem(Enum):
Linux = 'linux'
Windows = 'windows'
class Configuration:
"""Configuration for running cmake.
The data is mostly read from the file `run_cmake_config.yaml`
residing in the same folder as this script.
"""
def __init__(self, config_file_path: str):
with open(config_file_path) as config_file:
config = yaml.load(config_file, Loader=yaml.SafeLoader)
self._environment = config['environment'] # type: Dict[OperatingSystem, Dict[str, str]]
self.general_cmake_arguments = config['arguments']['general'] # type: List[str]
self._specific_cmake_arguments = config['arguments'] # type: Dict[OperatingSystem, List[str]]
self.operating_system = self._detect_os() # type: OperatingSystem
@property
def environment(self) -> Dict[str, str]:
return self._environment[self.operating_system.value]
@property
def specific_cmake_arguments(self) -> List[str]:
return self._specific_cmake_arguments[self.operating_system.value]
@property
def default_projects(self) -> str:
"""Get string of projects enabled by default.
This returns all projects in the mono repo minus the project that were
excluded for the current platform.
"""
cp = ChooseProjects(None)
return ';'.join(cp.get_all_enabled_projects())
@staticmethod
def _detect_os() -> OperatingSystem:
"""Detect the current operating system."""
if platform.system() == 'Windows':
return OperatingSystem.Windows
return OperatingSystem.Linux
def _select_projects(config: Configuration, projects: str, repo_path: str) -> str:
"""select which projects to build.
if projects == "default", a default configuraiton will be used.
if project == "detect", ChooseProjects is used to magically detect the projects
based on the files modified in HEAD
"""
if projects == "default" or projects is None or len(projects) == 0:
return config.default_projects
if projects == "detect":
cp = ChooseProjects(repo_path)
repo = Repo('.')
patch = repo.git.diff("HEAD~1")
enabled_projects = ';'.join(cp.choose_projects(patch))
if enabled_projects is None or len(enabled_projects) == 0:
2020-05-11 16:09:27 +02:00
enabled_projects = cp.get_all_enabled_projects()
return enabled_projects
return projects
def _create_env(config: Configuration) -> Dict[str, str]:
"""Generate the environment variables for cmake."""
env = os.environ.copy()
env.update(config.environment)
return env
def _create_args(config: Configuration, llvm_enable_projects: str) -> List[str]:
"""Generate the command line arguments for cmake."""
arguments = [
os.path.join('..', 'llvm'),
'-D LLVM_ENABLE_PROJECTS="{}"'.format(llvm_enable_projects),
]
arguments.extend(config.general_cmake_arguments)
arguments.extend(config.specific_cmake_arguments)
Upgrade Windows agents to Visual Studio 2019 and sccache (#162) * added cmake parameters for sccache * added sccache * removed stray debug output * starting sccache with VS environment * added container for Visual Studio 2019 * fixed comments * considering WIndows version * updated to vs2019 * using MS install method * snapshot of VS2019 experiments * using --installRecommended * cleanup of dockerfile * updated path * fixed dockerfile * dumped version number * exclude for virus scan * added testing option this does not start the agent * write results on failures * added timeouts for pipelines * moving master pipelines to python scripts * added flang to automatic project selection based on #159, this will enable flang for beta testers * added persistent workspace for testing containers * added secure delete function * added better log message * deleting read-only files * checking existence before setting flags * using unlink * deleting recursively * using pathlib for chmod * using custom workspace * fixed drive * separate handling of single files * simplified read-only handling again * removed vsdevcmd calls as it's already set in the docker Entrypoint * renamed container folders * windows version not needed any more * bumped version number * bumped version number * script cleanup * added cmake parameters for sccache * added sccache * starting sccache with VS environment * added container for Visual Studio 2019 * fixed comments * considering WIndows version * updated to vs2019 * using MS install method * snapshot of VS2019 experiments * using --installRecommended * cleanup of dockerfile * updated path * fixed dockerfile * dumped version number * removed vsdevcmd calls as it's already set in the docker Entrypoint * renamed container folders * windows version not needed any more * bumped version number * bumped version number * script cleanup * removed sccache from vs2017 * making windows image configurable * added versioning * created windows BETA pipeline * added Jenkins label for vs2019
2020-04-21 11:46:41 +02:00
# enable sccache
if 'SCCACHE_DIR' in os.environ:
arguments.extend([
'-DCMAKE_C_COMPILER_LAUNCHER=sccache',
'-DCMAKE_CXX_COMPILER_LAUNCHER=sccache',
])
# enable ccache if the path is set in the environment
Upgrade Windows agents to Visual Studio 2019 and sccache (#162) * added cmake parameters for sccache * added sccache * removed stray debug output * starting sccache with VS environment * added container for Visual Studio 2019 * fixed comments * considering WIndows version * updated to vs2019 * using MS install method * snapshot of VS2019 experiments * using --installRecommended * cleanup of dockerfile * updated path * fixed dockerfile * dumped version number * exclude for virus scan * added testing option this does not start the agent * write results on failures * added timeouts for pipelines * moving master pipelines to python scripts * added flang to automatic project selection based on #159, this will enable flang for beta testers * added persistent workspace for testing containers * added secure delete function * added better log message * deleting read-only files * checking existence before setting flags * using unlink * deleting recursively * using pathlib for chmod * using custom workspace * fixed drive * separate handling of single files * simplified read-only handling again * removed vsdevcmd calls as it's already set in the docker Entrypoint * renamed container folders * windows version not needed any more * bumped version number * bumped version number * script cleanup * added cmake parameters for sccache * added sccache * starting sccache with VS environment * added container for Visual Studio 2019 * fixed comments * considering WIndows version * updated to vs2019 * using MS install method * snapshot of VS2019 experiments * using --installRecommended * cleanup of dockerfile * updated path * fixed dockerfile * dumped version number * removed vsdevcmd calls as it's already set in the docker Entrypoint * renamed container folders * windows version not needed any more * bumped version number * bumped version number * script cleanup * removed sccache from vs2017 * making windows image configurable * added versioning * created windows BETA pipeline * added Jenkins label for vs2019
2020-04-21 11:46:41 +02:00
elif 'CCACHE_PATH' in os.environ:
arguments.extend([
'-D LLVM_CCACHE_BUILD=ON',
'-D LLVM_CCACHE_DIR={}'.format(os.environ['CCACHE_PATH']),
'-D LLVM_CCACHE_MAXSIZE=20G',
])
return arguments
2020-03-30 16:01:30 +02:00
def run_cmake(projects: str, repo_path: str, config_file_path: str = None, *, dryrun: bool = False):
"""Use cmake to configure the project.
This version works on all operating systems.
"""
if config_file_path is None:
script_dir = os.path.dirname(__file__)
config_file_path = os.path.join(script_dir, 'run_cmake_config.yaml')
config = Configuration(config_file_path)
build_dir = os.path.abspath(os.path.join(repo_path, 'build'))
2020-03-30 16:01:30 +02:00
if not dryrun:
2020-04-15 18:16:41 +02:00
secure_delete(build_dir)
2020-03-30 16:01:30 +02:00
os.makedirs(build_dir)
env = _create_env(config)
llvm_enable_projects = _select_projects(config, projects, repo_path)
print('Enabled projects: {}'.format(llvm_enable_projects))
arguments = _create_args(config, llvm_enable_projects)
cmd = 'cmake ' + ' '.join(arguments)
print('Running cmake with these arguments:\n{}'.format(cmd), flush=True)
2020-03-30 16:01:30 +02:00
if dryrun:
print('Dryrun, not invoking CMake!')
else:
subprocess.check_call(cmd, env=env, shell=True, cwd=build_dir)
_link_compile_commands(config, repo_path, build_dir)
2020-04-15 18:16:41 +02:00
def secure_delete(path: str):
"""Try do delete a local folder.
2020-04-16 10:30:39 +02:00
Handle read-only files.
2020-04-15 18:16:41 +02:00
"""
2020-04-16 10:30:39 +02:00
if not os.path.exists(path):
return
def del_rw(action, name, exc):
2020-04-16 13:54:50 +02:00
os.chmod(name, stat.S_IWRITE)
os.unlink(name)
2020-04-16 10:30:39 +02:00
shutil.rmtree(path, onerror=del_rw)
2020-04-15 18:16:41 +02:00
def _link_compile_commands(config: Configuration, repo_path: str, build_dir: str):
"""Link compile_commands.json from build to root dir"""
if config.operating_system != OperatingSystem.Linux:
return
source_path = os.path.join(build_dir, 'compile_commands.json')
target_path = os.path.join(repo_path, 'compile_commands.json')
if os.path.exists(target_path):
os.remove(target_path)
os.symlink(source_path, target_path)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Run CMake for LLVM.')
parser.add_argument('projects', type=str, nargs='?', default='default')
parser.add_argument('repo_path', type=str, nargs='?', default=os.getcwd())
2020-03-30 16:01:30 +02:00
parser.add_argument('--dryrun', action='store_true')
args = parser.parse_args()
2020-03-30 16:01:30 +02:00
run_cmake(args.projects, args.repo_path, dryrun=args.dryrun)