cmake: added suport for add_custom_command in the trace parser
This commit is contained in:
parent
c78c9ee65e
commit
b07d3804fc
|
@ -18,8 +18,9 @@
|
|||
from .common import CMakeException
|
||||
from .. import mlog
|
||||
|
||||
from typing import List, Tuple
|
||||
from typing import List, Tuple, Optional
|
||||
import re
|
||||
import os
|
||||
|
||||
class CMakeTraceLine:
|
||||
def __init__(self, file, line, func, args):
|
||||
|
@ -47,6 +48,13 @@ class CMakeTarget:
|
|||
propSTR += " '{}': {}\n".format(i, self.properies[i])
|
||||
return s.format(self.name, self.type, propSTR)
|
||||
|
||||
class CMakeGeneratorTarget:
|
||||
def __init__(self):
|
||||
self.outputs = [] # type: List[str]
|
||||
self.command = [] # type: List[List[str]]
|
||||
self.working_dir = None # type: Optional[str]
|
||||
self.depends = [] # type: List[str]
|
||||
|
||||
class CMakeTraceParser:
|
||||
def __init__(self, permissive: bool = False):
|
||||
# Dict of CMake variables: '<var_name>': ['list', 'of', 'values']
|
||||
|
@ -56,7 +64,7 @@ class CMakeTraceParser:
|
|||
self.targets = {}
|
||||
|
||||
# List of targes that were added with add_custom_command to generate files
|
||||
self.custom_targets = []
|
||||
self.custom_targets = [] # type: List[CMakeGeneratorTarget]
|
||||
|
||||
self.permissive = permissive # type: bool
|
||||
|
||||
|
@ -202,6 +210,65 @@ class CMakeTraceParser:
|
|||
|
||||
self.targets[args[0]] = CMakeTarget(args[0], args[1], {})
|
||||
|
||||
def _cmake_add_custom_command(self, tline: CMakeTraceLine):
|
||||
# DOC: https://cmake.org/cmake/help/latest/command/add_custom_command.html
|
||||
args = list(tline.args) # Make a working copy
|
||||
|
||||
if not args:
|
||||
return self._gen_exception('add_custom_command', 'requires at least 1 argument', tline)
|
||||
|
||||
# Skip the second function signature
|
||||
if args[0] == 'TARGET':
|
||||
return self._gen_exception('add_custom_command', 'TARGET syntax is currently not supported', tline)
|
||||
|
||||
magic_keys = ['OUTPUT', 'COMMAND', 'MAIN_DEPENDENCY', 'DEPENDS', 'BYPRODUCTS',
|
||||
'IMPLICIT_DEPENDS', 'WORKING_DIRECTORY', 'COMMENT', 'DEPFILE',
|
||||
'JOB_POOL', 'VERBATIM', 'APPEND', 'USES_TERMINAL', 'COMMAND_EXPAND_LISTS']
|
||||
|
||||
target = CMakeGeneratorTarget()
|
||||
|
||||
def handle_output(key: str, target: CMakeGeneratorTarget) -> None:
|
||||
target.outputs += [key]
|
||||
|
||||
def handle_command(key: str, target: CMakeGeneratorTarget) -> None:
|
||||
target.command[-1] += [key]
|
||||
|
||||
def handle_depends(key: str, target: CMakeGeneratorTarget) -> None:
|
||||
target.depends += [key]
|
||||
|
||||
def handle_working_dir(key: str, target: CMakeGeneratorTarget) -> None:
|
||||
if target.working_dir is None:
|
||||
target.working_dir = key
|
||||
else:
|
||||
target.working_dir += ' '
|
||||
target.working_dir += key
|
||||
|
||||
fn = None
|
||||
|
||||
for i in args:
|
||||
if i in magic_keys:
|
||||
if i == 'OUTPUT':
|
||||
fn = handle_output
|
||||
elif i == 'DEPENDS':
|
||||
fn = handle_depends
|
||||
elif i == 'WORKING_DIRECTORY':
|
||||
fn = handle_working_dir
|
||||
elif i == 'COMMAND':
|
||||
fn = handle_command
|
||||
target.command += [[]]
|
||||
else:
|
||||
fn = None
|
||||
continue
|
||||
|
||||
if fn is not None:
|
||||
fn(i, target)
|
||||
|
||||
target.outputs = self._guess_files(target.outputs)
|
||||
target.depends = self._guess_files(target.depends)
|
||||
target.command = [self._guess_files(x) for x in target.command]
|
||||
|
||||
self.custom_targets += [target]
|
||||
|
||||
def _cmake_add_custom_target(self, tline: CMakeTraceLine):
|
||||
# DOC: https://cmake.org/cmake/help/latest/command/add_custom_target.html
|
||||
# We only the first parameter (the target name) is interesting
|
||||
|
@ -330,3 +397,35 @@ class CMakeTraceParser:
|
|||
args = list(map(lambda x: reg_genexp.sub('', x), args)) # Remove generator expressions
|
||||
|
||||
yield CMakeTraceLine(file, line, func, args)
|
||||
|
||||
def _guess_files(self, broken_list: List[str]) -> List[str]:
|
||||
#Try joining file paths that contain spaces
|
||||
|
||||
reg_start = re.compile(r'^/.*/[^./]+$')
|
||||
reg_end = re.compile(r'^.*\.[a-zA-Z]+$')
|
||||
|
||||
fixed_list = [] # type: List[str]
|
||||
curr_str = None # type: Optional[str]
|
||||
|
||||
for i in broken_list:
|
||||
if curr_str is None:
|
||||
curr_str = i
|
||||
elif os.path.isfile(curr_str):
|
||||
# Abort concatination if curr_str is an existing file
|
||||
fixed_list += [curr_str]
|
||||
curr_str = i
|
||||
elif not reg_start.match(curr_str):
|
||||
# Abort concatination if curr_str no longer matches the regex
|
||||
fixed_list += [curr_str]
|
||||
curr_str = i
|
||||
elif reg_end.match(i):
|
||||
# File detected
|
||||
curr_str = '{} {}'.format(curr_str, i)
|
||||
fixed_list += [curr_str]
|
||||
curr_str = None
|
||||
else:
|
||||
curr_str = '{} {}'.format(curr_str, i)
|
||||
|
||||
if curr_str:
|
||||
fixed_list += [curr_str]
|
||||
return fixed_list
|
||||
|
|
Loading…
Reference in New Issue