aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2019-11-25 20:07:04 +0200
committerGitHub <noreply@github.com>2019-11-25 20:07:04 +0200
commit696358957617dff59f40d5ff7befa9924982578c (patch)
treeda76c96b706913218d213391884e3b31139c77d1
parent7677a38e1a8679b44a818bf3782a3fa6472e17f8 (diff)
parentf2114fa167363925791e8f10cfc793b3bc317690 (diff)
downloadmeson-696358957617dff59f40d5ff7befa9924982578c.zip
meson-696358957617dff59f40d5ff7befa9924982578c.tar.gz
meson-696358957617dff59f40d5ff7befa9924982578c.tar.bz2
Merge pull request #6213 from mensinda/cmNameFix
cmake: Uniform target name handling and custom target fixes
-rwxr-xr-xmesonbuild/cmake/data/run_ctgt.py1
-rw-r--r--mesonbuild/cmake/interpreter.py145
-rw-r--r--test cases/cmake/2 advanced/installed_files.txt8
-rw-r--r--test cases/cmake/3 advanced no dep/installed_files.txt12
-rw-r--r--test cases/cmake/5 object library/subprojects/cmObjLib/CMakeLists.txt1
-rw-r--r--test cases/cmake/6 object library no dep/subprojects/cmObjLib/CMakeLists.txt1
6 files changed, 110 insertions, 58 deletions
diff --git a/mesonbuild/cmake/data/run_ctgt.py b/mesonbuild/cmake/data/run_ctgt.py
index 4e85b86..d4e3259 100755
--- a/mesonbuild/cmake/data/run_ctgt.py
+++ b/mesonbuild/cmake/data/run_ctgt.py
@@ -28,6 +28,7 @@ for i in args.commands:
commands += [[]]
continue
+ i = i.replace('"', '') # Remove lefover quotes
commands[-1] += [i]
# Execute
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
index 12db810..8098bdb 100644
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -25,7 +25,7 @@ from ..environment import Environment
from ..mesonlib import MachineChoice, version_compare
from ..compilers.compilers import lang_suffixes, header_suffixes, obj_suffixes, lib_suffixes, is_header
from subprocess import Popen, PIPE
-from typing import Any, List, Dict, Optional, TYPE_CHECKING
+from typing import Any, List, Dict, Optional, Union, TYPE_CHECKING
from threading import Thread
from enum import Enum
import os, re
@@ -126,6 +126,8 @@ blacklist_link_libs = [
'advapi32.lib'
]
+generated_target_name_prefix = 'cm_'
+
# Utility functions to generate local keys
def _target_key(tgt_name: str) -> str:
return '__tgt_{}__'.format(tgt_name)
@@ -143,6 +145,7 @@ class ConverterTarget:
self.src_dir = target.src_dir
self.build_dir = target.build_dir
self.name = target.name
+ self.cmake_name = target.name
self.full_name = target.full_name
self.type = target.type
self.install = target.install
@@ -196,6 +199,10 @@ class ConverterTarget:
std_regex = re.compile(r'([-]{1,2}std=|/std:v?|[-]{1,2}std:)(.*)')
def postprocess(self, output_target_map: dict, root_src_dir: str, subdir: str, install_prefix: str, trace: CMakeTraceParser) -> None:
+ # Convert the target name to a valid meson target name
+ self.name = self.name.replace('-', '_')
+ self.name = generated_target_name_prefix + self.name
+
# Detect setting the C and C++ standard
for i in ['c', 'cpp']:
if i not in self.compile_opts:
@@ -221,15 +228,15 @@ class ConverterTarget:
# Use the CMake trace, if required
if self.type.upper() in target_type_requires_trace:
- if self.name in trace.targets:
- props = trace.targets[self.name].properties
+ if self.cmake_name in trace.targets:
+ props = trace.targets[self.cmake_name].properties
self.includes += props.get('INTERFACE_INCLUDE_DIRECTORIES', [])
self.public_compile_opts += props.get('INTERFACE_COMPILE_DEFINITIONS', [])
self.public_compile_opts += props.get('INTERFACE_COMPILE_OPTIONS', [])
self.link_flags += props.get('INTERFACE_LINK_OPTIONS', [])
else:
- mlog.warning('CMake: Target', mlog.bold(self.name), 'not found in CMake trace. This can lead to build errors')
+ mlog.warning('CMake: Target', mlog.bold(self.cmake_name), 'not found in CMake trace. This can lead to build errors')
# Fix link libraries
def try_resolve_link_with(path: str) -> Optional[str]:
@@ -351,7 +358,7 @@ class ConverterTarget:
return target_type_map.get(self.type.upper())
def log(self) -> None:
- mlog.log('Target', mlog.bold(self.name))
+ mlog.log('Target', mlog.bold(self.name), '({})'.format(self.cmake_name))
mlog.log(' -- artifacts: ', mlog.bold(str(self.artifacts)))
mlog.log(' -- full_name: ', mlog.bold(self.full_name))
mlog.log(' -- type: ', mlog.bold(self.type))
@@ -391,11 +398,13 @@ class CustomTargetReference:
class ConverterCustomTarget:
tgt_counter = 0 # type: int
+ out_counter = 0 # type: int
def __init__(self, target: CMakeGeneratorTarget):
self.name = 'custom_tgt_{}'.format(ConverterCustomTarget.tgt_counter)
self.original_outputs = list(target.outputs)
self.outputs = [os.path.basename(x) for x in self.original_outputs]
+ self.conflict_map = {}
self.command = target.command
self.working_dir = target.working_dir
self.depends_raw = target.depends
@@ -407,7 +416,7 @@ class ConverterCustomTarget:
def __repr__(self) -> str:
return '<{}: {}>'.format(self.__class__.__name__, self.outputs)
- def postprocess(self, output_target_map: dict, root_src_dir: str, subdir: str, build_dir: str) -> None:
+ def postprocess(self, output_target_map: dict, root_src_dir: str, subdir: str, build_dir: str, all_outputs: List[str]) -> None:
# Default the working directory to the CMake build dir. This
# is not 100% correct, since it should be the value of
# ${CMAKE_CURRENT_BINARY_DIR} when add_custom_command is
@@ -431,6 +440,20 @@ class ConverterCustomTarget:
return os.path.normpath(os.path.join(build_dir, x))
self.original_outputs = [ensure_absolute(x) for x in self.original_outputs]
+ # Ensure that there is no duplicate output in the project so
+ # that meson can handle cases where the same filename is
+ # generated in multiple directories
+ temp_outputs = [] # type: List[str]
+ for i in self.outputs:
+ if i in all_outputs:
+ old = str(i)
+ i = 'c{}_{}'.format(ConverterCustomTarget.out_counter, i)
+ ConverterCustomTarget.out_counter += 1
+ self.conflict_map[old] = i
+ all_outputs += [i]
+ temp_outputs += [i]
+ self.outputs = temp_outputs
+
# Check if the command is a build target
commands = []
for i in self.command:
@@ -438,6 +461,8 @@ class ConverterCustomTarget:
cmd = []
for j in i:
+ if not j:
+ continue
target_key = _target_key(j)
if target_key in output_target_map:
cmd += [output_target_map[target_key]]
@@ -465,6 +490,8 @@ class ConverterCustomTarget:
def get_ref(self, fname: str) -> Optional[CustomTargetReference]:
try:
+ if fname in self.conflict_map:
+ fname = self.conflict_map[fname]
idx = self.outputs.index(os.path.basename(fname))
return CustomTargetReference(self, idx)
except ValueError:
@@ -472,12 +499,13 @@ class ConverterCustomTarget:
def log(self) -> None:
mlog.log('Custom Target', mlog.bold(self.name))
- mlog.log(' -- command: ', mlog.bold(str(self.command)))
- mlog.log(' -- outputs: ', mlog.bold(str(self.outputs)))
- mlog.log(' -- working_dir: ', mlog.bold(str(self.working_dir)))
- mlog.log(' -- depends_raw: ', mlog.bold(str(self.depends_raw)))
- mlog.log(' -- inputs: ', mlog.bold(str(self.inputs)))
- mlog.log(' -- depends: ', mlog.bold(str(self.depends)))
+ mlog.log(' -- command: ', mlog.bold(str(self.command)))
+ mlog.log(' -- outputs: ', mlog.bold(str(self.outputs)))
+ mlog.log(' -- conflict_map: ', mlog.bold(str(self.conflict_map)))
+ mlog.log(' -- working_dir: ', mlog.bold(str(self.working_dir)))
+ mlog.log(' -- depends_raw: ', mlog.bold(str(self.depends_raw)))
+ mlog.log(' -- inputs: ', mlog.bold(str(self.inputs)))
+ mlog.log(' -- depends: ', mlog.bold(str(self.depends)))
class CMakeAPI(Enum):
SERVER = 1
@@ -512,6 +540,7 @@ class CMakeInterpreter:
# Generated meson data
self.generated_targets = {}
+ self.internal_name_map = {}
def configure(self, extra_cmake_options: List[str]) -> None:
for_machine = MachineChoice.HOST # TODO make parameter
@@ -698,8 +727,9 @@ class CMakeInterpreter:
object_libs = []
# First pass: Basic target cleanup
+ custom_target_outputs = [] # type: List[str]
for i in self.custom_targets:
- i.postprocess(output_target_map, self.src_dir, self.subdir, self.build_dir)
+ i.postprocess(output_target_map, self.src_dir, self.subdir, self.build_dir, custom_target_outputs)
for i in self.targets:
i.postprocess(output_target_map, self.src_dir, self.subdir, self.install_prefix, self.trace)
if i.type == 'OBJECT_LIBRARY':
@@ -746,32 +776,28 @@ class CMakeInterpreter:
args = ArgumentNode(token())
if not isinstance(elements, list):
elements = [args]
- args.arguments += [nodeify(x) for x in elements]
+ args.arguments += [nodeify(x) for x in elements if x is not None]
return ArrayNode(args, 0, 0, 0, 0)
def function(name: str, args=None, kwargs=None) -> FunctionNode:
- if args is None:
- args = []
- if kwargs is None:
- kwargs = {}
+ args = [] if args is None else args
+ kwargs = {} if kwargs is None else kwargs
args_n = ArgumentNode(token())
if not isinstance(args, list):
args = [args]
- args_n.arguments = [nodeify(x) for x in args]
- args_n.kwargs = {k: nodeify(v) for k, v in kwargs.items()}
+ args_n.arguments = [nodeify(x) for x in args if x is not None]
+ args_n.kwargs = {k: nodeify(v) for k, v in kwargs.items() if v is not None}
func_n = FunctionNode(self.subdir, 0, 0, 0, 0, name, args_n)
return func_n
def method(obj: BaseNode, name: str, args=None, kwargs=None) -> MethodNode:
- if args is None:
- args = []
- if kwargs is None:
- kwargs = {}
+ args = [] if args is None else args
+ kwargs = {} if kwargs is None else kwargs
args_n = ArgumentNode(token())
if not isinstance(args, list):
args = [args]
- args_n.arguments = [nodeify(x) for x in args]
- args_n.kwargs = {k: nodeify(v) for k, v in kwargs.items()}
+ args_n.arguments = [nodeify(x) for x in args if x is not None]
+ args_n.kwargs = {k: nodeify(v) for k, v in kwargs.items() if v is not None}
return MethodNode(self.subdir, 0, 0, obj, name, args_n)
def assign(var_name: str, value: BaseNode) -> AssignmentNode:
@@ -788,18 +814,29 @@ class CMakeInterpreter:
# Add the targets
processed = {}
+ name_map = {}
+
+ def extract_tgt(tgt: Union[ConverterTarget, ConverterCustomTarget, CustomTargetReference]) -> IdNode:
+ tgt_name = None
+ if isinstance(tgt, (ConverterTarget, ConverterCustomTarget)):
+ tgt_name = tgt.name
+ elif isinstance(tgt, CustomTargetReference):
+ tgt_name = tgt.ctgt.name
+ assert(tgt_name is not None and tgt_name in processed)
+ res_var = processed[tgt_name]['tgt']
+ return id_node(res_var) if res_var else None
def resolve_ctgt_ref(ref: CustomTargetReference) -> BaseNode:
- tgt_var = processed[ref.ctgt.name]['tgt']
+ tgt_var = extract_tgt(ref)
if len(ref.ctgt.outputs) == 1:
- return id_node(tgt_var)
+ return tgt_var
else:
- return indexed(id_node(tgt_var), ref.index)
+ return indexed(tgt_var, ref.index)
def process_target(tgt: ConverterTarget):
# First handle inter target dependencies
link_with = []
- objec_libs = []
+ objec_libs = [] # type: List[IdNode]
sources = []
generated = []
generated_filenames = []
@@ -808,12 +845,12 @@ class CMakeInterpreter:
assert(isinstance(i, ConverterTarget))
if i.name not in processed:
process_target(i)
- link_with += [id_node(processed[i.name]['tgt'])]
+ link_with += [extract_tgt(i)]
for i in tgt.object_libs:
assert(isinstance(i, ConverterTarget))
if i.name not in processed:
process_target(i)
- objec_libs += [processed[i.name]['tgt']]
+ objec_libs += [extract_tgt(i)]
# Generate the source list and handle generated sources
for i in tgt.sources + tgt.generated:
@@ -847,14 +884,12 @@ class CMakeInterpreter:
raise CMakeException('Unknown target type "{}"'.format(tgt.type))
# Determine the variable names
- base_name = str(tgt.name)
- base_name = base_name.replace('-', '_')
- inc_var = '{}_inc'.format(base_name)
- dir_var = '{}_dir'.format(base_name)
- sys_var = '{}_sys'.format(base_name)
- src_var = '{}_src'.format(base_name)
- dep_var = '{}_dep'.format(base_name)
- tgt_var = base_name
+ inc_var = '{}_inc'.format(tgt.name)
+ dir_var = '{}_dir'.format(tgt.name)
+ sys_var = '{}_sys'.format(tgt.name)
+ src_var = '{}_src'.format(tgt.name)
+ dep_var = '{}_dep'.format(tgt.name)
+ tgt_var = tgt.name
# Generate target kwargs
tgt_kwargs = {
@@ -864,7 +899,7 @@ class CMakeInterpreter:
'install': tgt.install,
'install_dir': tgt.install_dir,
'override_options': tgt.override_options,
- 'objects': [method(id_node(x), 'extract_all_objects') for x in objec_libs],
+ 'objects': [method(x, 'extract_all_objects') for x in objec_libs],
}
# Handle compiler args
@@ -894,21 +929,22 @@ class CMakeInterpreter:
del dep_kwargs['link_with']
dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs))
node_list += [dep_node]
- src_var = ''
- tgt_var = ''
+ src_var = None
+ tgt_var = None
else:
src_node = assign(src_var, function('files', sources))
- tgt_node = assign(tgt_var, function(tgt_func, [base_name, [id_node(src_var)] + generated], tgt_kwargs))
+ tgt_node = assign(tgt_var, function(tgt_func, [tgt_var, [id_node(src_var)] + generated], tgt_kwargs))
node_list += [src_node, tgt_node]
if tgt_func in ['static_library', 'shared_library']:
dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs))
node_list += [dep_node]
else:
- dep_var = ''
+ dep_var = None
# Add the nodes to the ast
root_cb.lines += node_list
processed[tgt.name] = {'inc': inc_var, 'src': src_var, 'dep': dep_var, 'tgt': tgt_var, 'func': tgt_func}
+ name_map[tgt.cmake_name] = tgt.name
def process_custom_target(tgt: ConverterCustomTarget) -> None:
# CMake allows to specify multiple commands in a custom target.
@@ -922,7 +958,7 @@ class CMakeInterpreter:
if isinstance(x, ConverterTarget):
if x.name not in processed:
process_target(x)
- return id_node(x.name)
+ return extract_tgt(x)
elif isinstance(x, CustomTargetReference):
if x.ctgt.name not in processed:
process_custom_target(x.ctgt)
@@ -960,12 +996,25 @@ class CMakeInterpreter:
process_target(i)
self.generated_targets = processed
+ self.internal_name_map = name_map
return root_cb
def target_info(self, target: str) -> Optional[Dict[str, str]]:
- if target in self.generated_targets:
+ # Try resolving the target name
+ # start by checking if there is a 100% match (excluding the name prefix)
+ prx_tgt = generated_target_name_prefix + target
+ if prx_tgt in self.generated_targets:
+ return self.generated_targets[prx_tgt]
+ # check if there exists a name mapping
+ if target in self.internal_name_map:
+ target = self.internal_name_map[target]
+ assert(target in self.generated_targets)
return self.generated_targets[target]
return None
def target_list(self) -> List[str]:
- return list(self.generated_targets.keys())
+ prx_str = generated_target_name_prefix
+ prx_len = len(prx_str)
+ res = [x for x in self.generated_targets.keys()]
+ res = [x[prx_len:] if x.startswith(prx_str) else x for x in res]
+ return res
diff --git a/test cases/cmake/2 advanced/installed_files.txt b/test cases/cmake/2 advanced/installed_files.txt
index 8cbdcd7..4965cd1 100644
--- a/test cases/cmake/2 advanced/installed_files.txt
+++ b/test cases/cmake/2 advanced/installed_files.txt
@@ -1,4 +1,4 @@
-usr/?lib/libcmModLib?so
-?cygwin:usr/lib/libcmModLib?implib
-?!cygwin:usr/bin/libcmModLib?implib
-usr/bin/testEXE?exe \ No newline at end of file
+usr/?lib/libcm_cmModLib?so
+?cygwin:usr/lib/libcm_cmModLib?implib
+?!cygwin:usr/bin/libcm_cmModLib?implib
+usr/bin/cm_testEXE?exe
diff --git a/test cases/cmake/3 advanced no dep/installed_files.txt b/test cases/cmake/3 advanced no dep/installed_files.txt
index e16e27d..453c6c0 100644
--- a/test cases/cmake/3 advanced no dep/installed_files.txt
+++ b/test cases/cmake/3 advanced no dep/installed_files.txt
@@ -1,6 +1,6 @@
-usr/?lib/libcmModLib?so
-?cygwin:usr/lib/libcmModLib?implib
-?!cygwin:usr/bin/libcmModLib?implib
-?msvc:usr/bin/cmModLib.pdb
-?msvc:usr/bin/testEXE.pdb
-usr/bin/testEXE?exe \ No newline at end of file
+usr/?lib/libcm_cmModLib?so
+?cygwin:usr/lib/libcm_cmModLib?implib
+?!cygwin:usr/bin/libcm_cmModLib?implib
+?msvc:usr/bin/cm_cmModLib.pdb
+?msvc:usr/bin/cm_testEXE.pdb
+usr/bin/cm_testEXE?exe \ No newline at end of file
diff --git a/test cases/cmake/5 object library/subprojects/cmObjLib/CMakeLists.txt b/test cases/cmake/5 object library/subprojects/cmObjLib/CMakeLists.txt
index ee9be47..a47fa59 100644
--- a/test cases/cmake/5 object library/subprojects/cmObjLib/CMakeLists.txt
+++ b/test cases/cmake/5 object library/subprojects/cmObjLib/CMakeLists.txt
@@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.7)
+project(cmObject)
find_package(ZLIB REQUIRED)
diff --git a/test cases/cmake/6 object library no dep/subprojects/cmObjLib/CMakeLists.txt b/test cases/cmake/6 object library no dep/subprojects/cmObjLib/CMakeLists.txt
index 08c6a18..5e0b0b1 100644
--- a/test cases/cmake/6 object library no dep/subprojects/cmObjLib/CMakeLists.txt
+++ b/test cases/cmake/6 object library no dep/subprojects/cmObjLib/CMakeLists.txt
@@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.7)
+project(cmObject)
add_library(lib_obj OBJECT libA.cpp libB.cpp)
add_library(lib_sha SHARED $<TARGET_OBJECTS:lib_obj>)