modules/gnome: replace yelphelper with run and custom targets

This is basically a rewrite of the gnome.yelp target to remove the
ad-hoc script, which generates multiple issues, including meson
not knowing which files were installed.

Closes #7653
Closes #9539
Closes #6916
Closes #2775
Closes #7034
Closes #1052

Related #9105
Related #1601
pull/9557/head
Pablo Correa Gómez 3 years ago committed by Eli Schwartz
parent 270843ed34
commit 26c1869a14
No known key found for this signature in database
GPG Key ID: CEB167EFB5722BD6
  1. 129
      mesonbuild/modules/gnome.py
  2. 133
      mesonbuild/scripts/yelphelper.py

@ -39,6 +39,7 @@ from ..mesonlib import (
MachineChoice, MesonException, OrderedSet, Popen_safe, join_args,
)
from ..programs import ExternalProgram, OverrideProgram, EmptyExternalProgram
from ..scripts.gettext import read_linguas
if T.TYPE_CHECKING:
from typing_extensions import Literal, TypedDict
@ -1154,47 +1155,99 @@ class GnomeModule(ExtensionModule):
raise MesonException('Yelp requires a list of sources')
elif args[1]:
mlog.warning('"gnome.yelp" ignores positional sources arguments when the "sources" keyword argument is set')
source_str = '@@'.join(sources)
sources_files = [mesonlib.File.from_source_file(state.environment.source_dir,
os.path.join(state.subdir, 'C'),
s) for s in sources]
langs = kwargs['languages']
if not langs:
langs = read_linguas(os.path.join(state.environment.source_dir, state.subdir))
media = kwargs['media']
symlinks = kwargs['symlink_media']
targets: T.List[T.Union['Target', build.Data, build.SymlinkData]] = []
potargets: T.List[build.RunTarget] = []
itstool = state.find_program('itstool')
msgmerge = state.find_program('msgmerge')
msgfmt = state.find_program('msgfmt')
install_dir = os.path.join(state.environment.get_datadir(), 'help')
c_install_dir = os.path.join(install_dir, 'C', project_id)
c_data = build.Data(sources_files, c_install_dir, c_install_dir,
mesonlib.FileMode(), state.subproject)
targets.append(c_data)
media_files: T.List[mesonlib.File] = []
for m in media:
f = mesonlib.File.from_source_file(state.environment.source_dir,
os.path.join(state.subdir, 'C'), m)
media_files.append(f)
m_install_dir = os.path.join(c_install_dir, os.path.dirname(m))
m_data = build.Data([f], m_install_dir, m_install_dir,
mesonlib.FileMode(), state.subproject)
targets.append(m_data)
pot_file = os.path.join('@SOURCE_ROOT@', state.subdir, 'C', project_id + '.pot')
pot_sources = [os.path.join('@SOURCE_ROOT@', state.subdir, 'C', s) for s in sources]
pot_args = [itstool, '-o', pot_file] + pot_sources
pottarget = build.RunTarget(f'help-{project_id}-pot', pot_args, [],
os.path.join(state.subdir, 'C'), state.subproject)
targets.append(pottarget)
for l in langs:
l_subdir = os.path.join(state.subdir, l)
l_install_dir = os.path.join(install_dir, l, project_id)
for i, m in enumerate(media):
m_dir = os.path.dirname(m)
m_install_dir = os.path.join(l_install_dir, m_dir)
if symlinks:
link_target = os.path.join(os.path.relpath(c_install_dir, start=m_install_dir), m)
l_data = build.SymlinkData(link_target, os.path.basename(m),
m_install_dir, state.subproject)
else:
try:
m_file = mesonlib.File.from_source_file(state.environment.source_dir, l_subdir, m)
except MesonException:
m_file = media_files[i]
l_data = build.Data([m_file], m_install_dir, m_install_dir,
mesonlib.FileMode(), state.subproject)
targets.append(l_data)
po_file = l + '.po'
po_args = [msgmerge, '-q', '-o',
os.path.join('@SOURCE_ROOT@', l_subdir, po_file),
os.path.join('@SOURCE_ROOT@', l_subdir, po_file), pot_file]
potarget = build.RunTarget(f'help-{project_id}-{l}-update-po',
po_args, [pottarget], l_subdir, state.subproject)
targets.append(potarget)
potargets.append(potarget)
gmo_file = project_id + '-' + l + '.gmo'
gmo_kwargs = {'command': [msgfmt, '@INPUT@', '-o', '@OUTPUT@'],
'input': po_file,
'output': gmo_file,
}
gmotarget = build.CustomTarget(f'help-{project_id}-{l}-gmo', l_subdir, state.subproject, gmo_kwargs)
targets.append(gmotarget)
merge_kwargs = {'command': [itstool, '-m', os.path.join(l_subdir, gmo_file),
'-o', '@OUTDIR@', '@INPUT@'],
'input': sources_files,
'output': sources,
'depends': gmotarget,
'install': True,
'install_dir': l_install_dir,
}
mergetarget = build.CustomTarget(f'help-{project_id}-{l}', l_subdir, state.subproject, merge_kwargs)
targets.append(mergetarget)
script = state.environment.get_build_command()
inscript_args = ['--internal',
'yelphelper',
'install',
'--subdir=' + state.subdir,
'--id=' + project_id,
'--installdir=' + os.path.join(state.environment.get_datadir(), 'help'),
'--sources=' + source_str]
if kwargs['symlink_media']:
inscript_args.append('--symlinks=true')
if kwargs['media']:
inscript_args.append('--media=' + '@@'.join(kwargs['media']))
if langs:
inscript_args.append('--langs=' + '@@'.join(langs))
inscript = state.backend.get_executable_serialisation(script + inscript_args)
potargs = state.environment.get_build_command() + [
'--internal', 'yelphelper', 'pot',
'--subdir=' + state.subdir,
'--id=' + project_id,
'--sources=' + source_str,
]
pottarget = build.RunTarget('help-' + project_id + '-pot', potargs,
[], state.subdir, state.subproject)
poargs = state.environment.get_build_command() + [
'--internal', 'yelphelper', 'update-po',
'--subdir=' + state.subdir,
'--id=' + project_id,
'--sources=' + source_str,
'--langs=' + '@@'.join(langs),
]
potarget = build.RunTarget('help-' + project_id + '-update-po', poargs,
[], state.subdir, state.subproject)
rv: T.List[T.Union[build.ExecutableSerialisation, build.RunTarget]] = [inscript, pottarget, potarget]
return ModuleReturnValue(None, rv)
allpotarget = build.AliasTarget(f'help-{project_id}-update-po', potargets,
state.subdir, state.subproject)
targets.append(allpotarget)
return ModuleReturnValue(None, targets)
@typed_pos_args('gnome.gtkdoc', str)
@typed_kwargs(

@ -1,133 +0,0 @@
# Copyright 2016 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import subprocess
import shutil
import argparse
from .. import mlog
from ..mesonlib import has_path_sep
from . import destdir_join
from .gettext import read_linguas
import typing as T
parser = argparse.ArgumentParser()
parser.add_argument('command')
parser.add_argument('--id', dest='project_id')
parser.add_argument('--subdir', dest='subdir')
parser.add_argument('--installdir', dest='install_dir')
parser.add_argument('--sources', dest='sources')
parser.add_argument('--media', dest='media', default='')
parser.add_argument('--langs', dest='langs', default='')
parser.add_argument('--symlinks', type=bool, dest='symlinks', default=False)
def build_pot(srcdir: str, project_id: str, sources: T.List[str]) -> None:
# Must be relative paths
sources = [os.path.join('C', source) for source in sources]
outfile = os.path.join(srcdir, project_id + '.pot')
subprocess.call(['itstool', '-o', outfile] + sources)
def update_po(srcdir: str, project_id: str, langs: T.List[str]) -> None:
potfile = os.path.join(srcdir, project_id + '.pot')
for lang in langs:
pofile = os.path.join(srcdir, lang, lang + '.po')
subprocess.call(['msgmerge', '-q', '-o', pofile, pofile, potfile])
def build_translations(srcdir: str, blddir: str, langs: T.List[str]) -> None:
for lang in langs:
outdir = os.path.join(blddir, lang)
os.makedirs(outdir, exist_ok=True)
subprocess.call([
'msgfmt', os.path.join(srcdir, lang, lang + '.po'),
'-o', os.path.join(outdir, lang + '.gmo')
])
def merge_translations(blddir: str, sources: T.List[str], langs: T.List[str]) -> None:
for lang in langs:
subprocess.call([
'itstool', '-m', os.path.join(blddir, lang, lang + '.gmo'),
'-o', os.path.join(blddir, lang)
] + sources)
def install_help(srcdir: str, blddir: str, sources: T.List[str], media: T.List[str], langs: T.List[str], install_dir: str, destdir: str, project_id: str, symlinks: bool) -> None:
c_install_dir = os.path.join(install_dir, 'C', project_id)
for lang in langs + ['C']:
indir = destdir_join(destdir, os.path.join(install_dir, lang, project_id))
os.makedirs(indir, exist_ok=True)
for source in sources:
infile = os.path.join(srcdir if lang == 'C' else blddir, lang, source)
outfile = os.path.join(indir, source)
mlog.log(f'Installing {infile} to {outfile}')
shutil.copy2(infile, outfile)
for m in media:
infile = os.path.join(srcdir, lang, m)
outfile = os.path.join(indir, m)
c_infile = os.path.join(srcdir, 'C', m)
if not os.path.exists(infile):
if not os.path.exists(c_infile):
mlog.warning('Media file "%s" did not exist in C directory' % m)
continue
elif symlinks:
srcfile = os.path.join(c_install_dir, m)
mlog.log(f'Symlinking {outfile} to {srcfile}.')
if has_path_sep(m):
os.makedirs(os.path.dirname(outfile), exist_ok=True)
try:
try:
os.symlink(srcfile, outfile)
except FileExistsError:
os.remove(outfile)
os.symlink(srcfile, outfile)
continue
except (NotImplementedError, OSError):
mlog.warning('Symlinking not supported, falling back to copying')
infile = c_infile
else:
# Lang doesn't have media file so copy it over 'C' one
infile = c_infile
mlog.log(f'Installing {infile} to {outfile}')
if has_path_sep(m):
os.makedirs(os.path.dirname(outfile), exist_ok=True)
shutil.copyfile(infile, outfile)
shutil.copystat(infile, outfile)
def run(args: T.List[str]) -> int:
options = parser.parse_args(args)
langs = options.langs.split('@@') if options.langs else []
media = options.media.split('@@') if options.media else []
sources = options.sources.split('@@')
destdir = os.environ.get('DESTDIR', '')
src_subdir = os.path.join(os.environ['MESON_SOURCE_ROOT'], options.subdir)
build_subdir = os.path.join(os.environ['MESON_BUILD_ROOT'], options.subdir)
abs_sources = [os.path.join(src_subdir, 'C', source) for source in sources]
if not langs:
langs = read_linguas(src_subdir)
if options.command == 'pot':
build_pot(src_subdir, options.project_id, sources)
elif options.command == 'update-po':
build_pot(src_subdir, options.project_id, sources)
update_po(src_subdir, options.project_id, langs)
elif options.command == 'build':
if langs:
build_translations(src_subdir, build_subdir, langs)
elif options.command == 'install':
install_dir = os.path.join(os.environ['MESON_INSTALL_PREFIX'], options.install_dir)
if langs:
build_translations(src_subdir, build_subdir, langs)
merge_translations(build_subdir, abs_sources, langs)
install_help(src_subdir, build_subdir, sources, media, langs, install_dir,
destdir, options.project_id, options.symlinks)
return 0
Loading…
Cancel
Save