From 2039cb708bddc1bd8f3b936485e57278e4578a3d Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Fri, 22 Feb 2019 14:05:22 +0100 Subject: [PATCH] cmake: get CMake inputs --- mesonbuild/cmake/client.py | 70 +++++++++++++++++++++++++++++++-- mesonbuild/cmake/interpreter.py | 12 +++++- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/mesonbuild/cmake/client.py b/mesonbuild/cmake/client.py index 2fbb89ace..037a3b705 100644 --- a/mesonbuild/cmake/client.py +++ b/mesonbuild/cmake/client.py @@ -38,6 +38,8 @@ CMAKE_MESSAGE_TYPES = { CMAKE_REPLY_TYPES = { 'handshake': [], + 'configure': [], + 'cmakeInputs': ['buildFiles', 'cmakeRootDirectory', 'sourceDirectory'] } # Base CMake server message classes @@ -93,7 +95,8 @@ class Message(MessageBase): self.message = message def log(self) -> None: - mlog.log(mlog.bold('CMake:'), self.message) + #mlog.log(mlog.bold('CMake:'), self.message) + pass class Progress(MessageBase): def __init__(self, cookie: str): @@ -137,12 +140,55 @@ class RequestHandShake(RequestBase): 'protocolVersion': vers } +class RequestConfigure(RequestBase): + def __init__(self, args: Optional[List[str]] = None): + super().__init__('configure') + self.args = args + + def to_dict(self) -> dict: + res = super().to_dict() + if self.args: + res['cacheArguments'] = self.args + return res + +class RequestCMakeInputs(RequestBase): + def __init__(self): + super().__init__('cmakeInputs') + # Reply classes class ReplyHandShake(ReplyBase): def __init__(self, cookie: str): super().__init__(cookie, 'handshake') +class ReplyConfigure(ReplyBase): + def __init__(self, cookie: str): + super().__init__(cookie, 'configure') + +class CMakeBuildFile: + def __init__(self, file: str, is_cmake: bool, is_temp: bool): + self.file = file + self.is_cmake = is_cmake + self.is_temp = is_temp + + def __repr__(self): + return '<{}: {}; cmake={}; temp={}>'.format(self.__class__.__name__, self.file, self.is_cmake, self.is_temp) + +class ReplyCMakeInputs(ReplyBase): + def __init__(self, cookie: str, cmake_root: str, src_dir: str, build_files: List[CMakeBuildFile]): + super().__init__(cookie, 'cmakeInputs') + self.cmake_root = cmake_root + self.src_dir = src_dir + self.build_files = build_files + + def log(self) -> None: + mlog.log('CMake root: ', mlog.bold(self.cmake_root)) + mlog.log('Source dir: ', mlog.bold(self.src_dir)) + mlog.log('Build files:', mlog.bold(str(len(self.build_files)))) + with mlog.nested(): + for i in self.build_files: + mlog.log(str(i)) + class CMakeClient: def __init__(self, env: Environment): self.env = env @@ -158,6 +204,8 @@ class CMakeClient: self.reply_map = { 'handshake': lambda data: ReplyHandShake(data['cookie']), + 'configure': lambda data: ReplyConfigure(data['cookie']), + 'cmakeInputs': self.resolve_reply_cmakeInputs, } def readMessageRaw(self) -> dict: @@ -209,6 +257,15 @@ class CMakeClient: reply.log() + def query_checked(self, request: RequestBase, message: str) -> ReplyBase: + reply = self.query(request) + h = mlog.green('SUCCEEDED') if reply.type == 'reply' else mlog.red('FAILED') + mlog.log(message, h) + if reply.type != 'reply': + reply.log() + raise CMakeException('CMake server query failed') + return reply + def do_handshake(self, src_dir: str, build_dir: str, generator: str, vers_major: int, vers_minor: Optional[int] = None) -> None: # CMake prints the hello message on startup msg = self.readMessage() @@ -219,9 +276,9 @@ class CMakeClient: reply = self.query(request) if not isinstance(reply, ReplyHandShake): reply.log() - mlog.log('CMake server handshake:', mlog.red('FAILED')) + mlog.log('CMake server handshake', mlog.red('FAILED')) raise CMakeException('Failed to perform the handshake with the CMake server') - mlog.log('CMake server handshake:', mlog.green('OK')) + mlog.log('CMake server handshake', mlog.green('SUCCEEDED')) def resolve_type_reply(self, data: dict) -> ReplyBase: reply_type = data['inReplyTo'] @@ -233,6 +290,13 @@ class CMakeClient: raise CMakeException('Key "{}" is missing from CMake server message type {}'.format(i, type)) return func(data) + def resolve_reply_cmakeInputs(self, data: dict) -> ReplyCMakeInputs: + files = [] + for i in data['buildFiles']: + for j in i['sources']: + files += [CMakeBuildFile(j, i['isCMake'], i['isTemporary'])] + return ReplyCMakeInputs(data['cookie'], data['cmakeRootDirectory'], data['sourceDirectory'], files) + @contextmanager def connect(self): self.startup() diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index e12c15ac1..ff7c1dc22 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -16,7 +16,7 @@ # or an interpreter-based tool. from .common import CMakeException -from .client import CMakeClient +from .client import CMakeClient, RequestCMakeInputs, RequestConfigure, ReplyCMakeInputs from .. import mlog from ..build import Build from ..environment import Environment @@ -101,7 +101,17 @@ class CMakeInterpreter: raise CMakeException('Failed to configure the CMake subproject') def run(self) -> None: + # Run configure the old way becuse doing it + # with the server doesn't work for some reason self.configure() + with self.client.connect(): generator = CMAKE_BACKEND_GENERATOR_MAP[self.backend_name] self.client.do_handshake(self.src_dir, self.build_dir, generator, 1) + + # Do a second configure to initialise the server + self.client.query_checked(RequestConfigure(), 'CMake server configure') + + # Get CMake build system files + bs_reply = self.client.query_checked(RequestCMakeInputs(), 'Querying build system files') + bs_reply.log()