gnome: Fix gtkdoc generation

install_scripts used to replace @BUILD_ROOT@ and @SOURCE_ROOT@ but it
was not documented and got removed in Meson 0.58.0. gnome.gtkdoc() was
relying on that behaviour, but it has always been broken in the case the
source or build directory contains spaces.

Fix this by changing get_include_args() to substitue paths directly
which will then get escaped correctly.

Add a unit test that builds GObject documentation which is where this
issue has been spotted.

Fixes: #8744
pull/8761/head
Xavier Claessens 4 years ago committed by Xavier Claessens
parent 44acefd836
commit 4e312c19e6
  1. 54
      mesonbuild/modules/__init__.py
  2. 15
      mesonbuild/modules/gnome.py
  3. 3
      mesonbuild/modules/hotdoc.py
  4. 4
      mesonbuild/modules/qt.py
  5. 5
      mesonbuild/modules/windows.py
  6. 2
      test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-docs.sgml
  7. 16
      test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-sections.txt
  8. 4
      test cases/frameworks/10 gtk-doc/doc/foobar1/foobar.types
  9. 6
      test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build
  10. 30
      test cases/frameworks/10 gtk-doc/foo.c
  11. 18
      test cases/frameworks/10 gtk-doc/include/foo.h
  12. 12
      test cases/frameworks/10 gtk-doc/meson.build
  13. 4
      test cases/frameworks/10 gtk-doc/test.json

@ -56,6 +56,33 @@ class ModuleState:
self.target_machine = interpreter.builtin['target_machine'].held_object
self.current_node = interpreter.current_node
def get_include_args(self, include_dirs, prefix='-I'):
if not include_dirs:
return []
srcdir = self.environment.get_source_dir()
builddir = self.environment.get_build_dir()
dirs_str = []
for dirs in unholder(include_dirs):
if isinstance(dirs, str):
dirs_str += [f'{prefix}{dirs}']
continue
# Should be build.IncludeDirs object.
basedir = dirs.get_curdir()
for d in dirs.get_incdirs():
expdir = os.path.join(basedir, d)
srctreedir = os.path.join(srcdir, expdir)
buildtreedir = os.path.join(builddir, expdir)
dirs_str += [f'{prefix}{buildtreedir}',
f'{prefix}{srctreedir}']
for d in dirs.get_extra_build_dirs():
dirs_str += [f'{prefix}{d}']
return dirs_str
class ModuleObject:
"""Base class for all objects returned by modules
"""
@ -71,33 +98,6 @@ class ModuleObject:
class ExtensionModule(ModuleObject):
pass
def get_include_args(include_dirs, prefix='-I'):
'''
Expand include arguments to refer to the source and build dirs
by using @SOURCE_ROOT@ and @BUILD_ROOT@ for later substitution
'''
if not include_dirs:
return []
dirs_str = []
for dirs in unholder(include_dirs):
if isinstance(dirs, str):
dirs_str += [f'{prefix}{dirs}']
continue
# Should be build.IncludeDirs object.
basedir = dirs.get_curdir()
for d in dirs.get_incdirs():
expdir = os.path.join(basedir, d)
srctreedir = os.path.join('@SOURCE_ROOT@', expdir)
buildtreedir = os.path.join('@BUILD_ROOT@', expdir)
dirs_str += [f'{prefix}{buildtreedir}',
f'{prefix}{srctreedir}']
for d in dirs.get_extra_build_dirs():
dirs_str += [f'{prefix}{d}']
return dirs_str
def is_module_library(fname):
'''
Check if the file is a library-like file generated by a module-specific

@ -26,7 +26,6 @@ from .. import mlog
from .. import mesonlib
from .. import interpreter
from . import GResourceTarget, GResourceHeaderTarget, GirTarget, TypelibTarget, VapiTarget
from . import get_include_args
from . import ExtensionModule
from . import ModuleReturnValue
from ..mesonlib import (
@ -394,7 +393,7 @@ class GnomeModule(ExtensionModule):
gi_includes.update([girdir])
if isinstance(dep, InternalDependency):
cflags.update(dep.get_compile_args())
cflags.update(get_include_args(dep.include_directories))
cflags.update(state.get_include_args(dep.include_directories))
for lib in unholder(dep.libraries):
if isinstance(lib, build.SharedLibrary):
internal_ldflags.update(self._get_link_args(state, lib, depends, include_rpath))
@ -443,7 +442,7 @@ class GnomeModule(ExtensionModule):
else:
external_ldflags.update([lib])
elif isinstance(dep, (build.StaticLibrary, build.SharedLibrary)):
cflags.update(get_include_args(dep.get_include_dirs()))
cflags.update(state.get_include_args(dep.get_include_dirs()))
depends.append(dep)
else:
mlog.log(f'dependency {dep!r} not handled to build gir files')
@ -853,7 +852,7 @@ class GnomeModule(ExtensionModule):
scan_command += self._scan_header(kwargs)
scan_command += self._scan_extra_args(kwargs)
scan_command += ['-I' + srcdir, '-I' + builddir]
scan_command += get_include_args(girtargets_inc_dirs)
scan_command += state.get_include_args(girtargets_inc_dirs)
scan_command += ['--filelist=' + self._make_gir_filelist(state, srcdir, ns, nsversion, girtargets, libsources)]
scan_command += self._scan_link_withs(state, depends, kwargs)
scan_command += self._scan_include(state, depends, gir_inc_dirs, kwargs)
@ -863,8 +862,8 @@ class GnomeModule(ExtensionModule):
scan_command += ['--cflags-begin']
scan_command += cflags
scan_command += ['--cflags-end']
scan_command += get_include_args(inc_dirs)
scan_command += get_include_args(list(gi_includes) + gir_inc_dirs + inc_dirs, prefix='--add-include-path=')
scan_command += state.get_include_args(inc_dirs)
scan_command += state.get_include_args(list(gi_includes) + gir_inc_dirs + inc_dirs, prefix='--add-include-path=')
scan_command += list(internal_ldflags)
scan_command += self._scan_gir_targets(state, girtargets)
scan_command += self._scan_langs(state, [lc[0] for lc in langs_compilers])
@ -886,7 +885,7 @@ class GnomeModule(ExtensionModule):
typelib_output = f'{ns}-{nsversion}.typelib'
typelib_cmd = [gicompiler, scan_target, '--output', '@OUTPUT@']
typelib_cmd += get_include_args(gir_inc_dirs, prefix='--includedir=')
typelib_cmd += state.get_include_args(gir_inc_dirs, prefix='--includedir=')
for incdir in typelib_includes:
typelib_cmd += ["--includedir=" + incdir]
@ -1127,7 +1126,7 @@ class GnomeModule(ExtensionModule):
'Gir include dirs should be include_directories().')
cflags.extend(deps_cflags)
cflags.extend(get_include_args(inc_dirs))
cflags.extend(state.get_include_args(inc_dirs))
ldflags = []
ldflags.extend(internal_ldflags)
ldflags.extend(external_ldflags)

@ -22,7 +22,6 @@ from mesonbuild import mlog, build
from mesonbuild.coredata import MesonException
from . import ModuleReturnValue
from . import ExtensionModule
from . import get_include_args
from ..dependencies import Dependency, InternalDependency
from ..interpreterbase import FeatureNew, InvalidArguments, noPosargs, noKwargs
from ..interpreter import CustomTargetHolder
@ -191,7 +190,7 @@ class HotdocTargetBuilder:
for dep in mesonlib.listify(ensure_list(deps)):
dep = getattr(dep, "held_object", dep)
if isinstance(dep, InternalDependency):
inc_args = get_include_args(dep.include_directories)
inc_args = self.state.get_include_args(dep.include_directories)
cflags.update([self.replace_dirs_in_string(x)
for x in inc_args])
cflags.update(self.process_dependencies(dep.libraries))

@ -23,7 +23,7 @@ from .. import mesonlib
from ..mesonlib import MesonException, extract_as_list, File, unholder, version_compare
from ..dependencies import Dependency
import xml.etree.ElementTree as ET
from . import ModuleReturnValue, get_include_args, ExtensionModule
from . import ModuleReturnValue, ExtensionModule
from ..interpreterbase import noPosargs, permittedKwargs, FeatureNew, FeatureNewKwargs
from ..interpreter import extract_required_kwarg
from ..programs import NonExistingExternalProgram
@ -239,7 +239,7 @@ class QtBaseModule(ExtensionModule):
ui_gen = build.Generator([self.uic], ui_kwargs)
ui_output = ui_gen.process_files(f'Qt{self.qt_version} ui', ui_files, state)
sources.append(ui_output)
inc = get_include_args(include_dirs=include_directories)
inc = state.get_include_args(include_dirs=include_directories)
compile_args = []
for dep in unholder(dependencies):
if isinstance(dep, Dependency):

@ -19,7 +19,6 @@ import re
from .. import mlog
from .. import mesonlib, build
from ..mesonlib import MachineChoice, MesonException, extract_as_list, unholder
from . import get_include_args
from . import ModuleReturnValue
from . import ExtensionModule
from ..interpreter import CustomTargetHolder
@ -83,12 +82,12 @@ class WindowsModule(ExtensionModule):
wrc_depends = extract_as_list(kwargs, 'depends', pop = True)
for d in wrc_depends:
if isinstance(d, CustomTargetHolder):
extra_args += get_include_args([d.outdir_include()])
extra_args += state.get_include_args([d.outdir_include()])
inc_dirs = extract_as_list(kwargs, 'include_directories', pop = True)
for incd in inc_dirs:
if not isinstance(incd.held_object, (str, build.IncludeDirs)):
raise MesonException('Resource include dirs should be include_directories().')
extra_args += get_include_args(inc_dirs)
extra_args += state.get_include_args(inc_dirs)
rescomp, rescomp_type = self._find_resource_compiler(state)
if rescomp_type == ResourceCompilerType.rc:

@ -35,7 +35,7 @@
</partintro>
<xi:include href="xml/foo.xml"/>
<xi:include href="../../include/bar.xml"/>
<xi:include href="xml/foo-version.xml"/>
<xi:include href="xml/version.xml"/>
</reference>
</book>

@ -0,0 +1,16 @@
<SECTION>
<FILE>foo</FILE>
<TITLE>FooObj</TITLE>
FooObj
FooObjClass
foo_do_something
</SECTION>
<SECTION>
<FILE>version</FILE>
<TITLE>version</TITLE>
FOO_MAJOR_VERSION
FOO_MINOR_VERSION
FOO_MICRO_VERSION
</SECTION>

@ -0,0 +1,4 @@
% This include is useless it's a regression test for https://github.com/mesonbuild/meson/issues/8744
#include <foo.h>
foo_obj_get_type

@ -1,5 +1,9 @@
gnome.gtkdoc('foobar',
src_dir : inc,
src_dir : [inc, '.'],
main_sgml : 'foobar-docs.sgml',
content_files : [docbook, version_xml],
dependencies: foo_dep,
# Manually written types file for regression test:
# https://github.com/mesonbuild/meson/issues/8744
gobject_typesfile: 'foobar.types',
install : true)

@ -0,0 +1,30 @@
#include <foo.h>
struct _FooObj {
GObject parent;
int dummy;
};
G_DEFINE_TYPE(FooObj, foo_obj, G_TYPE_OBJECT)
static void foo_obj_init (FooObj *self)
{
}
static void foo_obj_class_init (FooObjClass *klass)
{
}
/**
* foo_do_something:
* @self: self
*
* Useless function.
*
* Returns: 0.
*/
int foo_do_something(FooObj *self)
{
return 0;
}

@ -1,5 +1,7 @@
#pragma once
#include <glib-object.h>
/**
* FooIndecision:
* @FOO_MAYBE: Something maybe
@ -13,3 +15,19 @@ typedef enum {
FOO_POSSIBLY,
} FooIndecision;
/**
* FooObjClass:
*
* The class
*/
/**
* FooObj:
*
* The instance
*/
#define FOO_TYPE_OBJ foo_obj_get_type()
G_DECLARE_FINAL_TYPE(FooObj, foo_obj, FOO, OBJ, GObject)
int foo_do_something(FooObj *self);

@ -24,4 +24,16 @@ if gtkdoc_ver.version_compare('<1.26')
error('MESON_SKIP_TEST gtk-doc test requires gtkdoc >= 1.26.')
endif
gobject = dependency('gobject-2.0')
libfoo = library('foo', 'foo.c',
include_directories: inc,
dependencies: gobject,
)
foo_dep = declare_dependency(
link_with: libfoo,
include_directories: inc,
)
subdir('doc')

@ -4,8 +4,8 @@
{"type": "file", "file": "usr/share/gtk-doc/html/foobar/BAR.html"},
{"type": "file", "file": "usr/share/gtk-doc/html/foobar/foobar.devhelp2"},
{"type": "file", "file": "usr/share/gtk-doc/html/foobar/foobar.html"},
{"type": "file", "file": "usr/share/gtk-doc/html/foobar/foobar-foo.html"},
{"type": "file", "file": "usr/share/gtk-doc/html/foobar/foobar-foo-version.html"},
{"type": "file", "file": "usr/share/gtk-doc/html/foobar/FooObj.html"},
{"type": "file", "file": "usr/share/gtk-doc/html/foobar/foo-version.html"},
{"type": "file", "file": "usr/share/gtk-doc/html/foobar/home.png"},
{"type": "file", "file": "usr/share/gtk-doc/html/foobar/index.html"},
{"type": "file", "file": "usr/share/gtk-doc/html/foobar/left.png"},

Loading…
Cancel
Save