add license_files kwarg to project

Hook this up to installed dependency manifests. This is often needed
above and beyond just an SPDX string -- e.g. many licenses have custom
copyright lines.
pull/11164/head
Eli Schwartz 2 years ago
parent 26b83eee94
commit 2fa0749175
No known key found for this signature in database
GPG Key ID: CEB167EFB5722BD6
  1. 5
      docs/markdown/snippets/license_files_project_info.md
  2. 12
      docs/yaml/builtins/meson.yaml
  3. 8
      mesonbuild/backend/backends.py
  4. 3
      mesonbuild/build.py
  5. 17
      mesonbuild/interpreter/interpreter.py
  6. 8
      mesonbuild/interpreter/mesonmain.py
  7. 4
      test cases/common/42 subproject/meson.build
  8. 0
      test cases/common/42 subproject/mylicense.txt
  9. 4
      test cases/common/42 subproject/subprojects/sublib/meson.build
  10. 0
      test cases/common/42 subproject/subprojects/sublib/sublicense1.txt
  11. 0
      test cases/common/42 subproject/subprojects/sublib/sublicense2.txt
  12. 5
      test cases/common/42 subproject/test.json

@ -0,0 +1,5 @@
## The project function now supports setting the project license files
This goes together with the license name. The license files can be
automatically installed via [[meson.install_dependency_manifest]],
or queried via [[meson.project_license_files]].

@ -317,8 +317,11 @@ methods:
returns: void
description: |
Installs a manifest file
containing a list of all subprojects, their versions and license
files to the file name given as the argument.
containing a list of all subprojects, their versions and license names
to the file name given as the argument.
If license files are defined as well, they will be copied next to the
manifest and referenced in it.
posargs:
output_name:
@ -406,6 +409,11 @@ methods:
since: 0.45.0
description: Returns the array of licenses specified in [[project]] function call.
- name: project_license_files
returns: list[file]
since: 1.1.0
description: Returns the array of license files specified in the [[project]] function call.
- name: project_name
returns: str
description: Returns the project name specified in the [[project]] function call.

@ -1191,7 +1191,9 @@ class Backend:
return
ifilename = os.path.join(self.environment.get_build_dir(), 'depmf.json')
ofilename = os.path.join(self.environment.get_prefix(), self.build.dep_manifest_name)
odirname = os.path.join(self.environment.get_prefix(), os.path.dirname(self.build.dep_manifest_name))
out_name = os.path.join('{prefix}', self.build.dep_manifest_name)
out_dir = os.path.join('{prefix}', os.path.dirname(self.build.dep_manifest_name))
mfobj = {'type': 'dependency manifest', 'version': '1.0',
'projects': {k: v.to_json() for k, v in self.build.dep_manifest.items()}}
with open(ifilename, 'w', encoding='utf-8') as f:
@ -1199,6 +1201,12 @@ class Backend:
# Copy file from, to, and with mode unchanged
d.data.append(InstallDataBase(ifilename, ofilename, out_name, None, '',
tag='devel', data_type='depmf'))
for m in self.build.dep_manifest.values():
for ifilename, name in m.license_files:
ofilename = os.path.join(odirname, name.relative_name())
out_name = os.path.join(out_dir, name.relative_name())
d.data.append(InstallDataBase(ifilename, ofilename, out_name, None,
m.subproject, tag='devel', data_type='depmf'))
def get_regen_filelist(self) -> T.List[str]:
'''List of all files whose alteration means that the build

@ -216,11 +216,14 @@ class InstallDir(HoldableObject):
class DepManifest:
version: str
license: T.List[str]
license_files: T.List[T.Tuple[str, File]]
subproject: str
def to_json(self) -> T.Dict[str, T.Union[str, T.List[str]]]:
return {
'version': self.version,
'license': self.license,
'license_files': [l[1].relative_name() for l in self.license_files],
}

@ -1132,7 +1132,8 @@ class Interpreter(InterpreterBase, HoldableObject):
validator=_project_version_validator,
convertor=lambda x: x[0] if isinstance(x, list) else x,
),
KwargInfo('license', ContainerTypeInfo(list, str), default=['unknown'], listify=True),
KwargInfo('license', (ContainerTypeInfo(list, str), NoneType), default=None, listify=True),
KwargInfo('license_files', ContainerTypeInfo(list, str), default=[], listify=True, since='1.1.0'),
KwargInfo('subproject_dir', str, default='subprojects'),
)
def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str]], kwargs: 'kwtypes.Project') -> None:
@ -1198,8 +1199,20 @@ class Interpreter(InterpreterBase, HoldableObject):
if self.build.project_version is None:
self.build.project_version = self.project_version
if kwargs['license'] is None:
proj_license = ['unknown']
if kwargs['license_files']:
raise InvalidArguments('Project `license` name must be specified when `license_files` is set')
else:
proj_license = kwargs['license']
self.build.dep_manifest[proj_name] = build.DepManifest(self.project_version, proj_license)
proj_license_files = []
for i in self.source_strings_to_files(kwargs['license_files']):
ifname = i.absolute_path(self.environment.source_dir,
self.environment.build_dir)
proj_license_files.append((ifname, i))
self.build.dep_manifest[proj_name] = build.DepManifest(self.project_version, proj_license,
proj_license_files, self.subproject)
if self.subproject in self.build.projects:
raise InvalidCode('Second call to project().')

@ -1,6 +1,7 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2012-2021 The Meson development team
# Copyright © 2021 Intel Corporation
from __future__ import annotations
import os
import typing as T
@ -74,6 +75,7 @@ class MesonMain(MesonInterpreterObject):
'override_find_program': self.override_find_program_method,
'project_version': self.project_version_method,
'project_license': self.project_license_method,
'project_license_files': self.project_license_files_method,
'version': self.version_method,
'project_name': self.project_name_method,
'get_cross_property': self.get_cross_property_method,
@ -400,6 +402,12 @@ class MesonMain(MesonInterpreterObject):
def project_license_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> T.List[str]:
return self.build.dep_manifest[self.interpreter.active_projectname].license
@FeatureNew('meson.project_license_files()', '1.1.0')
@noPosargs
@noKwargs
def project_license_files_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[mesonlib.File]:
return [l[1] for l in self.build.dep_manifest[self.interpreter.active_projectname].license_files]
@noPosargs
@noKwargs
def version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> MesonVersionString:

@ -1,6 +1,8 @@
project('subproj user', 'c',
version : '2.3.4',
license : 'mylicense')
license : 'mylicense',
license_files: 'mylicense.txt',
)
assert(meson.project_name() == 'subproj user', 'Incorrect project name')

@ -1,6 +1,8 @@
project('subproject', 'c',
version : '1.0.0',
license : ['sublicense1', 'sublicense2'])
license : ['sublicense1', 'sublicense2'],
license_files: ['sublicense1.txt', 'sublicense2.txt'],
)
if not meson.is_subproject()
error('Claimed to be master project even though we are a subproject.')

@ -2,6 +2,9 @@
"installed": [
{"type": "exe", "file": "usr/bin/user"},
{"type": "pdb", "file": "usr/bin/user"},
{"type": "file", "file": "usr/share/sublib/sublib.depmf"}
{"type": "file", "file": "usr/share/sublib/sublib.depmf"},
{"type": "file", "file": "usr/share/sublib/mylicense.txt"},
{"type": "file", "file": "usr/share/sublib/subprojects/sublib/sublicense1.txt"},
{"type": "file", "file": "usr/share/sublib/subprojects/sublib/sublicense2.txt"}
]
}

Loading…
Cancel
Save