diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 7b8515948..1242af70d 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -216,7 +216,7 @@ class Dependency(HoldableObject): def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, configtool: T.Optional[str] = None, internal: T.Optional[str] = None, default_value: T.Optional[str] = None, - pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]: + pkgconfig_define: T.Optional[T.List[str]] = None) -> str: if default_value is not None: return default_value raise DependencyException(f'No default provided for dependency {self!r}, which is not pkg-config, cmake, or config-tool based.') @@ -232,7 +232,7 @@ class InternalDependency(Dependency): libraries: T.List[T.Union['BuildTarget', 'CustomTarget']], whole_libraries: T.List[T.Union['BuildTarget', 'CustomTarget']], sources: T.Sequence[T.Union['FileOrString', 'CustomTarget', StructuredSources]], - ext_deps: T.List[Dependency], variables: T.Dict[str, T.Any], + ext_deps: T.List[Dependency], variables: T.Dict[str, str], d_module_versions: T.List[str], d_import_dirs: T.List['IncludeDirs']): super().__init__(DependencyTypeName('internal'), {}) self.version = version @@ -301,16 +301,10 @@ class InternalDependency(Dependency): def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, configtool: T.Optional[str] = None, internal: T.Optional[str] = None, default_value: T.Optional[str] = None, - pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]: + pkgconfig_define: T.Optional[T.List[str]] = None) -> str: val = self.variables.get(internal, default_value) if val is not None: - # TODO: Try removing this assert by better typing self.variables - if isinstance(val, str): - return val - if isinstance(val, list): - for i in val: - assert isinstance(i, str) - return val + return val raise DependencyException(f'Could not get an internal variable and no default provided for {self!r}') def generate_link_whole_dependency(self) -> Dependency: diff --git a/mesonbuild/dependencies/cmake.py b/mesonbuild/dependencies/cmake.py index e9a4aa3ea..1ae70710f 100644 --- a/mesonbuild/dependencies/cmake.py +++ b/mesonbuild/dependencies/cmake.py @@ -627,17 +627,23 @@ class CMakeDependency(ExternalDependency): def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, configtool: T.Optional[str] = None, internal: T.Optional[str] = None, default_value: T.Optional[str] = None, - pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]: + pkgconfig_define: T.Optional[T.List[str]] = None) -> str: if cmake and self.traceparser is not None: try: v = self.traceparser.vars[cmake] except KeyError: pass else: - if len(v) == 1: - return v[0] - elif v: - return v + # CMake does NOT have a list datatype. We have no idea whether + # anything is a string or a string-separated-by-; Internally, + # we treat them as the latter and represent everything as a + # list, because it is convenient when we are mostly handling + # imported targets, which have various properties that are + # actually lists. + # + # As a result we need to convert them back to strings when grabbing + # raw variables the user requested. + return ';'.join(v) if default_value is not None: return default_value raise DependencyException(f'Could not get cmake variable and no default provided for {self!r}') diff --git a/mesonbuild/dependencies/configtool.py b/mesonbuild/dependencies/configtool.py index 7dccee4b6..3e8f212a6 100644 --- a/mesonbuild/dependencies/configtool.py +++ b/mesonbuild/dependencies/configtool.py @@ -155,7 +155,7 @@ class ConfigToolDependency(ExternalDependency): def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, configtool: T.Optional[str] = None, internal: T.Optional[str] = None, default_value: T.Optional[str] = None, - pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]: + pkgconfig_define: T.Optional[T.List[str]] = None) -> str: if configtool: # In the not required case '' (empty string) will be returned if the # variable is not found. Since '' is a valid value to return we diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index 55a364cd1..1777f3a9a 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -478,7 +478,7 @@ class PkgConfigDependency(ExternalDependency): def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, configtool: T.Optional[str] = None, internal: T.Optional[str] = None, default_value: T.Optional[str] = None, - pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]: + pkgconfig_define: T.Optional[T.List[str]] = None) -> str: if pkgconfig: try: return self.get_pkgconfig_variable(pkgconfig, pkgconfig_define or [], default_value) diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index 6cc636be2..39085e5f9 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -479,7 +479,7 @@ class DependencyHolder(ObjectHolder[Dependency]): KwargInfo('default_value', (str, NoneType)), KwargInfo('pkgconfig_define', ContainerTypeInfo(list, str, pairs=True), default=[], listify=True), ) - def variable_method(self, args: T.Tuple[T.Optional[str]], kwargs: 'kwargs.DependencyGetVariable') -> T.Union[str, T.List[str]]: + def variable_method(self, args: T.Tuple[T.Optional[str]], kwargs: 'kwargs.DependencyGetVariable') -> str: default_varname = args[0] if default_varname is not None: FeatureNew('Positional argument to dependency.get_variable()', '0.58.0').use(self.subproject, self.current_node) diff --git a/test cases/unit/63 cmake parser/meson.build b/test cases/unit/63 cmake parser/meson.build index 061bab0b6..472561d69 100644 --- a/test cases/unit/63 cmake parser/meson.build +++ b/test cases/unit/63 cmake parser/meson.build @@ -12,8 +12,8 @@ assert(dep.get_variable(cmake : 'VAR_WITH_SPACES_PS') == 'With Spaces', 'set(PAR assert(dep.get_variable(cmake : 'VAR_THAT_IS_UNSET', default_value : 'sentinal') == 'sentinal', 'set() to unset is incorrect') assert(dep.get_variable(cmake : 'CACHED_STRING_NS') == 'foo', 'set(CACHED) without spaces is incorrect') assert(dep.get_variable(cmake : 'CACHED_STRING_WS') == 'foo bar', 'set(CACHED STRING) with spaces is incorrect') -assert(dep.get_variable(cmake : 'CACHED_STRING_ARRAY_NS') == ['foo', 'bar'], 'set(CACHED STRING) without spaces is incorrect') -assert(dep.get_variable(cmake : 'CACHED_STRING_ARRAY_WS') == ['foo', 'foo bar', 'bar'], 'set(CACHED STRING[]) with spaces is incorrect') +assert(dep.get_variable(cmake : 'CACHED_STRING_ARRAY_NS') == 'foo;bar', 'set(CACHED STRING) without spaces is incorrect') +assert(dep.get_variable(cmake : 'CACHED_STRING_ARRAY_WS') == 'foo;foo bar;bar', 'set(CACHED STRING[]) with spaces is incorrect') # We don't support this, so it should be unset. -assert(dep.get_variable(cmake : 'ENV{var}', default_value : 'sentinal') == 'sentinal', 'set(ENV) should be ignored') \ No newline at end of file +assert(dep.get_variable(cmake : 'ENV{var}', default_value : 'sentinal') == 'sentinal', 'set(ENV) should be ignored')