Skip to content

Commit

Permalink
pkgconfig: add support to override pkg-config
Browse files Browse the repository at this point in the history
  • Loading branch information
ylatuya committed Oct 9, 2024
1 parent 7396839 commit 05fb320
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 10 deletions.
52 changes: 43 additions & 9 deletions mesonbuild/dependencies/pkgconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@
from pathlib import Path

from .base import ExternalDependency, DependencyException, sort_libpaths, DependencyTypeName
from ..mesonlib import EnvironmentVariables, OrderedSet, PerMachine, Popen_safe, Popen_safe_logged, MachineChoice, join_args
from ..mesonlib import (
EnvironmentVariables,
OrderedSet,
PerMachine,
Popen_safe,
Popen_safe_logged,
MachineChoice,
join_args,
MesonException,
)
from ..options import OptionKey
from ..programs import find_external_program, ExternalProgram
from .. import mlog
Expand All @@ -30,14 +39,24 @@ class PkgConfigInterface:

class_impl: PerMachine[T.Union[Literal[False], T.Optional[PkgConfigInterface]]] = PerMachine(False, False)
class_cli_impl: PerMachine[T.Union[Literal[False], T.Optional[PkgConfigCLI]]] = PerMachine(False, False)
pkg_bin_per_machine: PerMachine[T.Union[Literal[False], T.Optional[ExternalProgram]]] = PerMachine(False, False)

@staticmethod
def set_program_override(pkg_bin: ExternalProgram, for_machine: MachineChoice) -> None:
if PkgConfigInterface.class_impl[for_machine]:
raise MesonException(
f"Tried to override pkg-config for machine {for_machine} but it was already initialized.\n"
"pkg-config must be overridden before it's used."
)
PkgConfigInterface.pkg_bin_per_machine[for_machine] = pkg_bin

@staticmethod
def instance(env: Environment, for_machine: MachineChoice, silent: bool) -> T.Optional[PkgConfigInterface]:
'''Return a pkg-config implementation singleton'''
for_machine = for_machine if env.is_cross_build() else MachineChoice.HOST
impl = PkgConfigInterface.class_impl[for_machine]
if impl is False:
impl = PkgConfigCLI(env, for_machine, silent)
impl = PkgConfigCLI(env, for_machine, silent, PkgConfigInterface.pkg_bin_per_machine[for_machine])
if not impl.found():
impl = None
if not impl and not silent:
Expand All @@ -57,7 +76,7 @@ def _cli(env: Environment, for_machine: MachineChoice, silent: bool = False) ->
if impl and not isinstance(impl, PkgConfigCLI):
impl = PkgConfigInterface.class_cli_impl[for_machine]
if impl is False:
impl = PkgConfigCLI(env, for_machine, silent)
impl = PkgConfigCLI(env, for_machine, silent, PkgConfigInterface.pkg_bin_per_machine[for_machine])
if not impl.found():
impl = None
PkgConfigInterface.class_cli_impl[for_machine] = impl
Expand Down Expand Up @@ -113,9 +132,11 @@ def list_all(self) -> ImmutableListProtocol[str]:
class PkgConfigCLI(PkgConfigInterface):
'''pkg-config CLI implementation'''

def __init__(self, env: Environment, for_machine: MachineChoice, silent: bool) -> None:
def __init__(
self, env: Environment, for_machine: MachineChoice, silent: bool, pkgbin: T.Optional[ExternalProgram] = None
) -> None:
super().__init__(env, for_machine)
self._detect_pkgbin()
self._detect_pkgbin(pkgbin)
if self.pkgbin and not silent:
mlog.log('Found pkg-config:', mlog.green('YES'), mlog.bold(f'({self.pkgbin.get_path()})'), mlog.blue(self.pkgbin_version))

Expand Down Expand Up @@ -200,14 +221,27 @@ def _split_args(cmd: str) -> T.List[str]:
# output using shlex.split rather than mesonlib.split_args
return shlex.split(cmd)

def _detect_pkgbin(self) -> None:
for potential_pkgbin in find_external_program(
self.env, self.for_machine, 'pkg-config', 'Pkg-config',
self.env.default_pkgconfig, allow_default_for_cross=False):
def _detect_pkgbin(self, pkgbin: T.Optional[ExternalProgram] = None) -> None:
def validate(potential_pkgbin: ExternalProgram) -> bool:
version_if_ok = self._check_pkgconfig(potential_pkgbin)
if version_if_ok:
self.pkgbin = potential_pkgbin
self.pkgbin_version = version_if_ok
return True
return False

if pkgbin and validate(pkgbin):
return

for potential_pkgbin in find_external_program(
self.env,
self.for_machine,
"pkg-config",
"Pkg-config",
self.env.default_pkgconfig,
allow_default_for_cross=False,
):
if validate(potential_pkgbin):
return
self.pkgbin = None

Expand Down
4 changes: 3 additions & 1 deletion mesonbuild/interpreter/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
extract_as_list, has_path_sep, path_is_in_root, PerMachine)
from ..options import OptionKey
from ..programs import ExternalProgram, NonExistingExternalProgram
from ..dependencies import Dependency
from ..dependencies import Dependency, pkgconfig
from ..depfile import DepFile
from ..interpreterbase import ContainerTypeInfo, InterpreterBase, KwargInfo, typed_kwargs, typed_pos_args
from ..interpreterbase import noPosargs, noKwargs, permittedKwargs, noArgsFlattening, noSecondLevelHolderResolving, unholder_return
Expand Down Expand Up @@ -1638,6 +1638,8 @@ def add_find_program_override(self, name: str, exe: T.Union[build.Executable, Ex
if name in self.build.find_overrides:
raise InterpreterException(f'Tried to override executable "{name}" which has already been overridden.')
self.build.find_overrides[name] = exe
if name == "pkg-config" and exe is ExternalProgram:
pkgconfig.PkgConfigInterface.set_program_override(exe, MachineChoice.HOST)

def notfound_program(self, args: T.List[mesonlib.FileOrString]) -> ExternalProgram:
return NonExistingExternalProgram(' '.join(
Expand Down
8 changes: 8 additions & 0 deletions test cases/common/279 pkgconfig override/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
project('override pkg-config', 'c')

subproject('pkg-config')

pkgconfig = find_program('pkg-config')

# This dependency can only be found if pkg-config is overridden with our custom pkg-config.py
gobj = dependency('test-package-0.0', version : '= 0.0.0')
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[wrap-file]
directory = pkg-config

[provide]
program_names = pkg-config
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env python3

import sys

if len(sys.argv) > 1:
if sys.argv[1] == "--modversion":
if sys.argv[2] == "test-package-0.0":
print("0.0.0")
else:
exit(-1)
elif sys.argv[1] == "--version":
print("0.0.0")
exit(0)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
project('pkg-config')

pkgconfig = find_program(meson.project_source_root() / 'bin' / 'pkg-config.py')
meson.override_find_program('pkg-config', pkgconfig)
1 change: 1 addition & 0 deletions test cases/unit/116 empty project/expected_mods.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
"mesonbuild.dependencies",
"mesonbuild.dependencies.base",
"mesonbuild.dependencies.detect",
"mesonbuild.dependencies.pkgconfig",
"mesonbuild.depfile",
"mesonbuild.envconfig",
"mesonbuild.environment",
Expand Down

0 comments on commit 05fb320

Please sign in to comment.