From 28a92bde8027737304706513881cc90ff2984a98 Mon Sep 17 00:00:00 2001 From: Vito Gamberini Date: Tue, 25 Feb 2025 12:10:37 -0500 Subject: [PATCH] PkgC: Implement cmake_pkg_config IMPORT / POPULATE Issue: #26067 --- Help/command/cmake_pkg_config.rst | 111 +++- Help/release/dev/cmake-pkg-config-import.rst | 6 + Source/cmCMakePkgConfigCommand.cxx | 519 ++++++++++++++---- Source/cmMakefile.cxx | 10 +- Source/cmPkgConfigResolver.cxx | 66 ++- Source/cmPkgConfigResolver.h | 5 +- ...stEnv-stderr.txt => ExtractEnv-stderr.txt} | 0 .../{TestEnv.cmake => ExtractEnv.cmake} | 0 ...ct-stderr.txt => ExtractFields-stderr.txt} | 0 ...{TestExtract.cmake => ExtractFields.cmake} | 0 ...le-stderr.txt => ExtractMangle-stderr.txt} | 0 .../{TestMangle.cmake => ExtractMangle.cmake} | 0 .../{TestQuiet.cmake => ExtractQuiet.cmake} | 0 ...-result.txt => ExtractRequired-result.txt} | 0 .../ExtractRequired-stderr.txt | 4 + ...stRequired.cmake => ExtractRequired.cmake} | 0 ...ot-stderr.txt => ExtractReroot-stderr.txt} | 0 .../{TestReroot.cmake => ExtractReroot.cmake} | 0 ... ExtractStrictness-BEST_EFFORT-stderr.txt} | 0 ...> ExtractStrictness-PERMISSIVE-stderr.txt} | 8 +- ...xt => ExtractStrictness-STRICT-stderr.txt} | 10 +- ...rictness.cmake => ExtractStrictness.cmake} | 0 ...derr.txt => ExtractUninstalled-stderr.txt} | 0 ...stalled.cmake => ExtractUninstalled.cmake} | 0 ...n-stderr.txt => ExtractVersion-stderr.txt} | 34 +- ...TestVersion.cmake => ExtractVersion.cmake} | 0 .../ImportRequires-check.cmake | 14 + .../cmake_pkg_config/ImportRequires.cmake | 18 + .../cmake_pkg_config/ImportSimple-check.cmake | 15 + .../cmake_pkg_config/ImportSimple.cmake | 15 + .../ImportTransitiveFail-result.txt | 1 + .../ImportTransitiveFail-stderr.txt | 11 + .../ImportTransitiveFail.cmake | 5 + .../ImportTransitiveVersion.cmake | 3 + .../ImportTransitiveVersionFail-stderr.txt | 5 + .../ImportTransitiveVersionFail.cmake | 4 + .../PackageRoot/RequiresPackages/alpha.pc | 5 + .../PackageRoot/RequiresPackages/bravo.pc | 6 + .../PackageRoot/RequiresPackages/charlie.pc | 6 + .../PackageRoot/RequiresPackages/delta.pc | 5 + .../PackageRoot/RequiresPackages/echo.pc | 6 + .../PackageRoot/RequiresPackages/golf.pc | 6 + .../PackageRoot/RequiresPackages/hotel.pc | 6 + .../PackageRoot/RequiresPackages/india.pc | 6 + .../PackageRoot/RequiresPackages/juliet.pc | 6 + .../PackageRoot/import-simple.pc | 6 + .../PopulateFoundVar-stderr.txt | 8 + .../cmake_pkg_config/PopulateFoundVar.cmake | 7 + .../PopulateMissing-check.cmake | 10 + .../cmake_pkg_config/PopulateMissing.cmake | 19 + .../cmake_pkg_config/RunCMakeTest.cmake | 27 +- .../TestDirectories/Include/dummy-header.h | 0 .../TestDirectories/Library/libdummy | 0 .../cmake_pkg_config/TestRequired-stderr.txt | 4 - 54 files changed, 813 insertions(+), 184 deletions(-) create mode 100644 Help/release/dev/cmake-pkg-config-import.rst rename Tests/RunCMake/cmake_pkg_config/{TestEnv-stderr.txt => ExtractEnv-stderr.txt} (100%) rename Tests/RunCMake/cmake_pkg_config/{TestEnv.cmake => ExtractEnv.cmake} (100%) rename Tests/RunCMake/cmake_pkg_config/{TestExtract-stderr.txt => ExtractFields-stderr.txt} (100%) rename Tests/RunCMake/cmake_pkg_config/{TestExtract.cmake => ExtractFields.cmake} (100%) rename Tests/RunCMake/cmake_pkg_config/{TestMangle-stderr.txt => ExtractMangle-stderr.txt} (100%) rename Tests/RunCMake/cmake_pkg_config/{TestMangle.cmake => ExtractMangle.cmake} (100%) rename Tests/RunCMake/cmake_pkg_config/{TestQuiet.cmake => ExtractQuiet.cmake} (100%) rename Tests/RunCMake/cmake_pkg_config/{TestRequired-result.txt => ExtractRequired-result.txt} (100%) create mode 100644 Tests/RunCMake/cmake_pkg_config/ExtractRequired-stderr.txt rename Tests/RunCMake/cmake_pkg_config/{TestRequired.cmake => ExtractRequired.cmake} (100%) rename Tests/RunCMake/cmake_pkg_config/{TestReroot-stderr.txt => ExtractReroot-stderr.txt} (100%) rename Tests/RunCMake/cmake_pkg_config/{TestReroot.cmake => ExtractReroot.cmake} (100%) rename Tests/RunCMake/cmake_pkg_config/{TestStrictness-BEST_EFFORT-stderr.txt => ExtractStrictness-BEST_EFFORT-stderr.txt} (100%) rename Tests/RunCMake/cmake_pkg_config/{TestStrictness-PERMISSIVE-stderr.txt => ExtractStrictness-PERMISSIVE-stderr.txt} (69%) rename Tests/RunCMake/cmake_pkg_config/{TestStrictness-STRICT-stderr.txt => ExtractStrictness-STRICT-stderr.txt} (68%) rename Tests/RunCMake/cmake_pkg_config/{TestStrictness.cmake => ExtractStrictness.cmake} (100%) rename Tests/RunCMake/cmake_pkg_config/{TestUninstalled-stderr.txt => ExtractUninstalled-stderr.txt} (100%) rename Tests/RunCMake/cmake_pkg_config/{TestUninstalled.cmake => ExtractUninstalled.cmake} (100%) rename Tests/RunCMake/cmake_pkg_config/{TestVersion-stderr.txt => ExtractVersion-stderr.txt} (69%) rename Tests/RunCMake/cmake_pkg_config/{TestVersion.cmake => ExtractVersion.cmake} (100%) create mode 100644 Tests/RunCMake/cmake_pkg_config/ImportRequires-check.cmake create mode 100644 Tests/RunCMake/cmake_pkg_config/ImportRequires.cmake create mode 100644 Tests/RunCMake/cmake_pkg_config/ImportSimple-check.cmake create mode 100644 Tests/RunCMake/cmake_pkg_config/ImportSimple.cmake create mode 100644 Tests/RunCMake/cmake_pkg_config/ImportTransitiveFail-result.txt create mode 100644 Tests/RunCMake/cmake_pkg_config/ImportTransitiveFail-stderr.txt create mode 100644 Tests/RunCMake/cmake_pkg_config/ImportTransitiveFail.cmake create mode 100644 Tests/RunCMake/cmake_pkg_config/ImportTransitiveVersion.cmake create mode 100644 Tests/RunCMake/cmake_pkg_config/ImportTransitiveVersionFail-stderr.txt create mode 100644 Tests/RunCMake/cmake_pkg_config/ImportTransitiveVersionFail.cmake create mode 100644 Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/alpha.pc create mode 100644 Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/bravo.pc create mode 100644 Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/charlie.pc create mode 100644 Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/delta.pc create mode 100644 Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/echo.pc create mode 100644 Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/golf.pc create mode 100644 Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/hotel.pc create mode 100644 Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/india.pc create mode 100644 Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/juliet.pc create mode 100644 Tests/RunCMake/cmake_pkg_config/PackageRoot/import-simple.pc create mode 100644 Tests/RunCMake/cmake_pkg_config/PopulateFoundVar-stderr.txt create mode 100644 Tests/RunCMake/cmake_pkg_config/PopulateFoundVar.cmake create mode 100644 Tests/RunCMake/cmake_pkg_config/PopulateMissing-check.cmake create mode 100644 Tests/RunCMake/cmake_pkg_config/PopulateMissing.cmake create mode 100644 Tests/RunCMake/cmake_pkg_config/TestDirectories/Include/dummy-header.h create mode 100644 Tests/RunCMake/cmake_pkg_config/TestDirectories/Library/libdummy delete mode 100644 Tests/RunCMake/cmake_pkg_config/TestRequired-stderr.txt diff --git a/Help/command/cmake_pkg_config.rst b/Help/command/cmake_pkg_config.rst index 3744d93b8f..a794e2345b 100644 --- a/Help/command/cmake_pkg_config.rst +++ b/Help/command/cmake_pkg_config.rst @@ -12,9 +12,11 @@ Process pkg-config format package files. Synopsis ^^^^^^^^ -.. code-block:: cmake +.. parsed-literal:: - cmake_pkg_config(EXTRACT [] [...]) + cmake_pkg_config(`EXTRACT`_ [] [...]) + cmake_pkg_config(`POPULATE`_ [] [...]) + cmake_pkg_config(`IMPORT`_ [] [...]) Introduction ^^^^^^^^^^^^ @@ -27,7 +29,31 @@ search patterns. The optional ```` string has the same format and semantics as a pkg-config style version specifier, with the exception that if no comparison operator is specified ``=`` is assumed. -.. _`common options`: +PkgConfig Targets +^^^^^^^^^^^^^^^^^ + +``cmake_pkg_config`` may recursively generate target-like names in the global +scope in order to resolve a package ``IMPORT`` or ``POPULATE`` command. These +names take the form of ``@foreign_pkgcfg::`` and are exposed via the +:prop_tgt:`INTERFACE_LINK_LIBRARIES` target property of an ``IMPORT``-generated +target. + +It is not possible to modify or address these pkg-config native targets via +normal target-based commands. Limited control over their generation is possible +via the ``POPULATE`` command, but modification should generally be performed +inside the corresponding package file, not downstream in CMake. + +Pkg-config targets are reused across commands. Once a given package name has +been resolved via ``POPULATE`` or ``IMPORT`` (but not ``EXTRACT``), all future +requests for the corresponding package name by those commands will resolve to +the previously generated pkg-config target. + +``EXTRACT`` always performs the complete package name lookup in order to allow +searches for multiple installations of the same package in custom dependency +management schemes. + +Common Options +^^^^^^^^^^^^^^ There are multiple signatures for this command, and some of the options are common between them. They are: @@ -143,7 +169,7 @@ common between them. They are: library directory paths and ``pc_sysrootdir`` will be set to ``/`` ``TOP_BUILD_DIR `` - Overrides the top build directory path used to derived the ``pc_top_builddir`` + Overrides the top build directory path used to derive the ``pc_top_builddir`` package variable. When this option is not provided, the default top build directory path is @@ -154,29 +180,41 @@ common between them. They are: #. If no top build directory path is available, the ``pc_top_builddir`` package variable is not set +``BIND_PC_REQUIRES`` + A list of ``=`` pairs, the ``Name`` is a package name as it + appears in the ``Requires`` list of a pkg-config file and the ``Target`` is a + CMake-native target name (not a pkg-config target). + + When a given package name appears in the ``Requires`` list of a package, it + will be fulfilled with the associated CMake target. This behavior applies to + all dependencies in the pkg-config graph that have not been previously + populated. + Signatures ^^^^^^^^^^ .. signature:: cmake_pkg_config(EXTRACT [] [...]) + .. versionadded:: 3.31 + Extract the contents of the package into variables. .. code-block:: cmake cmake_pkg_config(EXTRACT [] [REQUIRED] [EXACT] [QUIET] + [SYSTEM_INCLUDE_DIRS ...] + [SYSTEM_LIBRARY_DIRS ...] + [ALLOW_SYSTEM_INCLUDES ] + [ALLOW_SYSTEM_LIBS ] [STRICTNESS ] [ENV_MODE ] [PC_LIBDIR ...] [PC_PATH ...] [DISABLE_UNINSTALLED ] [PC_SYSROOT_DIR ] - [TOP_BUILD_DIR ] - [SYSTEM_INCLUDE_DIRS ...] - [SYSTEM_LIBRARY_DIRS ...] - [ALLOW_SYSTEM_INCLUDES ] - [ALLOW_SYSTEM_LIBS ]) + [TOP_BUILD_DIR ]) The following variables will be populated from the contents of package file: @@ -261,3 +299,58 @@ The following variables will be populated from the contents of package file: #. ``CMAKE_PKG_CONFIG_ALLOW_SYS_LIBS`` #. If the ``PKG_CONFIG_ALLOW_SYSTEM_LIBS`` environment variable is defined the flags are preserved, otherwise they are filtered during flag mangling. + +.. signature:: + cmake_pkg_config(POPULATE [] [...]) + + .. versionadded:: 4.1 + + Populate a package in the pkg-config target namespace + + .. code-block:: cmake + + cmake_pkg_config(POPULATE [] + [REQUIRED] [EXACT] [QUIET] + [BIND_PC_REQUIRES <=>...] + [STRICTNESS ] + [ENV_MODE ] + [PC_LIBDIR ...] + [PC_PATH ...] + [DISABLE_UNINSTALLED ] + [PC_SYSROOT_DIR ] + [TOP_BUILD_DIR ]) + +``POPULATE`` enables manual control of resolution of a given package's +``Requires`` list without importing onto a native CMake target. Once populated, +a package and its dependencies will be used for resolution of all future +``POPULATE`` and ``IMPORT`` commands. + +A ``PKGCONFIG__FOUND`` variable will be set to indicate whether the +package was found. + +.. signature:: + cmake_pkg_config(IMPORT [] [...]) + + .. versionadded:: 4.1 + + Import a pkg-config target as a CMake :prop_tgt:`IMPORTED` target + + .. code-block:: cmake + + cmake_pkg_config(IMPORT [] + [REQUIRED] [EXACT] [QUIET] + [BIND_PC_REQUIRES <=>...] + [STRICTNESS ] + [ENV_MODE ] + [PC_LIBDIR ...] + [PC_PATH ...] + [DISABLE_UNINSTALLED ] + [PC_SYSROOT_DIR ] + [TOP_BUILD_DIR ]) + +Creates a native CMake ``IMPORTED`` target that can be linked to via +:command:`target_link_libraries`. This new target is named +``PkgConfig::``. + +A ``PKGCONFIG__FOUND`` variable will be set to indicate whether the +package was found. diff --git a/Help/release/dev/cmake-pkg-config-import.rst b/Help/release/dev/cmake-pkg-config-import.rst new file mode 100644 index 0000000000..5a9d086030 --- /dev/null +++ b/Help/release/dev/cmake-pkg-config-import.rst @@ -0,0 +1,6 @@ +cmake-pkg-config-import +----------------------- + +* The :command:`cmake_pkg_config` command now supports the ``IMPORT`` and + ``POPULATE`` subcommands for interfacing CMake targets with pkg-config based + dependencies. diff --git a/Source/cmCMakePkgConfigCommand.cxx b/Source/cmCMakePkgConfigCommand.cxx index 61ddf9c520..51b1145386 100644 --- a/Source/cmCMakePkgConfigCommand.cxx +++ b/Source/cmCMakePkgConfigCommand.cxx @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -28,12 +29,14 @@ #include "cmStringAlgorithms.h" #include "cmSubcommandTable.h" #include "cmSystemTools.h" +#include "cmTarget.h" #include "cmValue.h" #include // IWYU wants this namespace { struct ExtractArguments; +struct PopulateArguments; } namespace { @@ -441,89 +444,59 @@ void CollectEnv(cmMakefile& mf, cmPkgConfigEnv& env, *env.SysLibs += GetPkgConfSysLibs(mf); } -cm::optional HandleCommon(CommonArguments& args, - cmExecutionStatus& status) +struct ImportEnv { + bool required; + bool quiet; + bool exact; + bool err; + CommonArguments::StrictnessType strictness; + cmExecutionStatus& status; +}; - auto& mf = status.GetMakefile(); - - if (!args.CheckArgs(status)) { - return {}; +void warn_or_error(std::string const& err, ImportEnv& imEnv) +{ + if (imEnv.required) { + imEnv.status.SetError(err); + cmSystemTools::SetFatalErrorOccurred(); + } else if (!imEnv.quiet) { + imEnv.status.GetMakefile().IssueMessage(MessageType::WARNING, err); } + imEnv.err = true; +} - auto warn_or_error = [&](std::string const& err) { - if (args.Required) { - status.SetError(err); - cmSystemTools::SetFatalErrorOccurred(); - } else if (!args.Quiet) { - mf.IssueMessage(MessageType::WARNING, err); - } - }; - - cm::filesystem::path path{ *args.Package }; - - cmPkgConfigEnv env; - - if (args.PcLibdir) { - env.LibDirs = std::move(*args.PcLibdir); - } - - if (args.PcPath) { - env.Path = std::move(*args.PcPath); - } - - if (args.DisableUninstalled) { - env.DisableUninstalled = args.DisableUninstalled; - } - - if (args.SysrootDir) { - env.SysrootDir = std::move(*args.SysrootDir); - } - - if (args.TopBuildDir) { - env.TopBuildDir = std::move(*args.TopBuildDir); - } - - CollectEnv(mf, env, args.EnvMode); +cm::optional ReadPackage(std::string const& package, + ImportEnv& imEnv, + cmPkgConfigEnv& pcEnv) +{ + cm::optional result; + cm::filesystem::path path{ package }; if (path.extension() == ".pc") { if (!cmSystemTools::FileExists(path.string())) { - warn_or_error(cmStrCat("Could not find '", *args.Package, "'")); - return {}; + return result; } } else { - std::vector search; - if (env.Path) { - search = *env.Path; - if (env.LibDirs) { - search += *env.LibDirs; - } - } else if (env.LibDirs) { - search = *env.LibDirs; - } - - if (env.DisableUninstalled && !*env.DisableUninstalled) { + if (pcEnv.DisableUninstalled && !*pcEnv.DisableUninstalled) { auto uninstalled = path; uninstalled.concat("-uninstalled.pc"); uninstalled = - cmSystemTools::FindFile(uninstalled.string(), search, true); + cmSystemTools::FindFile(uninstalled.string(), pcEnv.search, true); if (uninstalled.empty()) { - path = - cmSystemTools::FindFile(path.concat(".pc").string(), search, true); + path = cmSystemTools::FindFile(path.concat(".pc").string(), + pcEnv.search, true); if (path.empty()) { - warn_or_error(cmStrCat("Could not find '", *args.Package, "'")); - return {}; + return result; } } else { path = uninstalled; } } else { - path = - cmSystemTools::FindFile(path.concat(".pc").string(), search, true); + path = cmSystemTools::FindFile(path.concat(".pc").string(), pcEnv.search, + true); if (path.empty()) { - warn_or_error(cmStrCat("Could not find '", *args.Package, "'")); - return {}; + return result; } } } @@ -534,8 +507,9 @@ cm::optional HandleCommon(CommonArguments& args, cmsys::ifstream ifs(path.string().c_str(), std::ios::binary); if (!ifs) { - warn_or_error(cmStrCat("Could not open file '", path.string(), "'")); - return {}; + warn_or_error(cmStrCat("Could not open file '", path.string(), "'"), + imEnv); + return result; } std::unique_ptr buf(new char[len]); @@ -543,8 +517,9 @@ cm::optional HandleCommon(CommonArguments& args, // Shouldn't have hit eof on previous read, should hit eof now if (ifs.fail() || ifs.eof() || ifs.get() != EOF) { - warn_or_error(cmStrCat("Error while reading file '", path.string(), "'")); - return {}; + warn_or_error(cmStrCat("Error while reading file '", path.string(), "'"), + imEnv); + return result; } using StrictnessType = CommonArguments::StrictnessType; @@ -552,53 +527,161 @@ cm::optional HandleCommon(CommonArguments& args, cmPkgConfigParser parser; auto err = parser.Finish(buf.get(), len); - if (args.Strictness != StrictnessType::STRICTNESS_BEST_EFFORT && + if (imEnv.strictness != StrictnessType::STRICTNESS_BEST_EFFORT && err != PCE_OK) { - warn_or_error(cmStrCat("Parsing failed for file '", path.string(), "'")); - return {}; + warn_or_error(cmStrCat("Parsing failed for file '", path.string(), "'"), + imEnv); + return result; } - cm::optional result; - if (args.Strictness == StrictnessType::STRICTNESS_STRICT) { - result = cmPkgConfigResolver::ResolveStrict(parser.Data(), std::move(env)); - } else if (args.Strictness == StrictnessType::STRICTNESS_PERMISSIVE) { - result = - cmPkgConfigResolver::ResolvePermissive(parser.Data(), std::move(env)); + if (imEnv.strictness == StrictnessType::STRICTNESS_STRICT) { + result = cmPkgConfigResolver::ResolveStrict(parser.Data(), pcEnv); + } else if (imEnv.strictness == StrictnessType::STRICTNESS_PERMISSIVE) { + result = cmPkgConfigResolver::ResolvePermissive(parser.Data(), pcEnv); } else { - result = - cmPkgConfigResolver::ResolveBestEffort(parser.Data(), std::move(env)); + result = cmPkgConfigResolver::ResolveBestEffort(parser.Data(), pcEnv); } if (!result) { - warn_or_error( - cmStrCat("Resolution failed for file '", path.string(), "'")); - } else if (args.Exact) { + warn_or_error(cmStrCat("Resolution failed for file '", path.string(), "'"), + imEnv); + } + + return result; +} + +cm::optional ImportPackage( + std::string const& package, cm::optional version, + ImportEnv& imEnv, cmPkgConfigEnv& pcEnv) +{ + auto result = ReadPackage(package, imEnv, pcEnv); + + if (!result) { + if (!imEnv.err) { + warn_or_error(cmStrCat("Could not find pkg-config: '", package, "'"), + imEnv); + } + return result; + } + + if (imEnv.exact) { std::string ver; - if (args.Version) { - ver = cmPkgConfigResolver::ParseVersion(*args.Version).Version; + if (version) { + ver = cmPkgConfigResolver::ParseVersion(*version).Version; } if (ver != result->Version()) { warn_or_error( - cmStrCat("Package '", *args.Package, "' version '", result->Version(), - "' does not meet exact version requirement '", ver, "'")); + cmStrCat("Package '", package, "' version '", result->Version(), + "' does not meet exact version requirement '", ver, "'"), + imEnv); return {}; } - } else if (args.Version) { - auto rv = cmPkgConfigResolver::ParseVersion(*args.Version); + } else if (version) { + auto rv = cmPkgConfigResolver::ParseVersion(*version); if (!cmPkgConfigResolver::CheckVersion(rv, result->Version())) { warn_or_error( - cmStrCat("Package '", *args.Package, "' version '", result->Version(), - "' does not meet version requirement '", *args.Version, "'")); + cmStrCat("Package '", package, "' version '", result->Version(), + "' does not meet version requirement '", *version, "'"), + imEnv); return {}; } } + result->env = &pcEnv; return result; } +struct pkgStackEntry +{ + cmPkgConfigVersionReq ver; + std::string parent; +}; + +cm::optional ImportPackage( + std::string const& package, std::vector const& reqs, + ImportEnv& imEnv, cmPkgConfigEnv& pcEnv) +{ + auto result = ReadPackage(package, imEnv, pcEnv); + + if (!result) { + if (!imEnv.err) { + std::string req_str = cmStrCat("'", reqs.begin()->parent, "'"); + for (auto it = reqs.begin() + 1; it != reqs.end(); ++it) { + req_str = cmStrCat(req_str, ", '", it->parent, "'"); + } + warn_or_error(cmStrCat("Could not find pkg-config: '", package, + "' required by: ", req_str), + imEnv); + } + return result; + } + + auto ver = result->Version(); + for (auto const& req : reqs) { + + if (!cmPkgConfigResolver::CheckVersion(req.ver, ver)) { + warn_or_error(cmStrCat("Package '", package, "' version '", ver, + "' does not meet version requirement '", + req.ver.string(), "' ", "of '", req.parent, "'"), + imEnv); + return {}; + } + } + + result->env = &pcEnv; + return result; +} + +cm::optional> HandleCommon( + CommonArguments& args, cmExecutionStatus& status) +{ + + auto& mf = status.GetMakefile(); + + if (!args.CheckArgs(status)) { + return {}; + } + + cmPkgConfigEnv pcEnv; + + if (args.PcLibdir) { + pcEnv.LibDirs = std::move(*args.PcLibdir); + } + + if (args.PcPath) { + pcEnv.Path = std::move(*args.PcPath); + } + + pcEnv.DisableUninstalled = args.DisableUninstalled; + + if (args.SysrootDir) { + pcEnv.SysrootDir = std::move(*args.SysrootDir); + } + + if (args.TopBuildDir) { + pcEnv.TopBuildDir = std::move(*args.TopBuildDir); + } + + CollectEnv(mf, pcEnv, args.EnvMode); + + if (pcEnv.Path) { + pcEnv.search = *pcEnv.Path; + if (pcEnv.LibDirs) { + pcEnv.search += *pcEnv.LibDirs; + } + } else if (pcEnv.LibDirs) { + pcEnv.search = *pcEnv.LibDirs; + } + + return std::pair{ + pcEnv, + { args.Required, args.Quiet, args.Exact, false, args.Strictness, status } + }; +} + struct ExtractArguments : CommonArguments { cm::optional AllowSystemIncludes; @@ -623,35 +706,41 @@ bool HandleExtractCommand(std::vector const& args, std::vector unparsed; auto parsedArgs = ExtractParser.Parse(args, &unparsed); - auto maybeResolved = HandleCommon(parsedArgs, status); + auto maybeEnv = HandleCommon(parsedArgs, status); - if (!maybeResolved) { + if (!maybeEnv) { return !parsedArgs.Required; } + auto& pcEnv = maybeEnv->first; + auto& imEnv = maybeEnv->second; - auto& resolved = *maybeResolved; - auto version = resolved.Version(); + auto maybePackage = + ImportPackage(*parsedArgs.Package, parsedArgs.Version, imEnv, pcEnv); + if (!maybePackage) { + return !parsedArgs.Required; + } + auto& package = *maybePackage; if (parsedArgs.AllowSystemIncludes) { - resolved.env.AllowSysCflags = *parsedArgs.AllowSystemIncludes; + pcEnv.AllowSysCflags = *parsedArgs.AllowSystemIncludes; } if (parsedArgs.AllowSystemLibs) { - resolved.env.AllowSysLibs = *parsedArgs.AllowSystemLibs; + pcEnv.AllowSysLibs = *parsedArgs.AllowSystemLibs; } if (parsedArgs.SystemIncludeDirs) { - resolved.env.SysCflags = *parsedArgs.SystemIncludeDirs; + pcEnv.SysCflags = *parsedArgs.SystemIncludeDirs; } if (parsedArgs.SystemLibraryDirs) { - resolved.env.SysLibs = *parsedArgs.SystemLibraryDirs; + pcEnv.SysLibs = *parsedArgs.SystemLibraryDirs; } auto& mf = status.GetMakefile(); - mf.AddDefinition("CMAKE_PKG_CONFIG_NAME", resolved.Name()); - mf.AddDefinition("CMAKE_PKG_CONFIG_DESCRIPTION", resolved.Description()); - mf.AddDefinition("CMAKE_PKG_CONFIG_VERSION", version); + mf.AddDefinition("CMAKE_PKG_CONFIG_NAME", package.Name()); + mf.AddDefinition("CMAKE_PKG_CONFIG_DESCRIPTION", package.Description()); + mf.AddDefinition("CMAKE_PKG_CONFIG_VERSION", package.Version()); auto make_list = [&](char const* def, std::vector const& deps) { @@ -665,26 +754,26 @@ bool HandleExtractCommand(std::vector const& args, mf.AddDefinition(def, cmList::to_string(vec)); }; - make_list("CMAKE_PKG_CONFIG_CONFLICTS", resolved.Conflicts()); - make_list("CMAKE_PKG_CONFIG_PROVIDES", resolved.Provides()); - make_list("CMAKE_PKG_CONFIG_REQUIRES", resolved.Requires()); - make_list("CMAKE_PKG_CONFIG_REQUIRES_PRIVATE", resolved.Requires(true)); + make_list("CMAKE_PKG_CONFIG_CONFLICTS", package.Conflicts()); + make_list("CMAKE_PKG_CONFIG_PROVIDES", package.Provides()); + make_list("CMAKE_PKG_CONFIG_REQUIRES", package.Requires()); + make_list("CMAKE_PKG_CONFIG_REQUIRES_PRIVATE", package.Requires(true)); - auto cflags = resolved.Cflags(); + auto cflags = package.Cflags(); mf.AddDefinition("CMAKE_PKG_CONFIG_CFLAGS", cflags.Flagline); mf.AddDefinition("CMAKE_PKG_CONFIG_INCLUDES", cmList::to_string(cflags.Includes)); mf.AddDefinition("CMAKE_PKG_CONFIG_COMPILE_OPTIONS", cmList::to_string(cflags.CompileOptions)); - cflags = resolved.Cflags(true); + cflags = package.Cflags(true); mf.AddDefinition("CMAKE_PKG_CONFIG_CFLAGS_PRIVATE", cflags.Flagline); mf.AddDefinition("CMAKE_PKG_CONFIG_INCLUDES_PRIVATE", cmList::to_string(cflags.Includes)); mf.AddDefinition("CMAKE_PKG_CONFIG_COMPILE_OPTIONS_PRIVATE", cmList::to_string(cflags.CompileOptions)); - auto libs = resolved.Libs(); + auto libs = package.Libs(); mf.AddDefinition("CMAKE_PKG_CONFIG_LIBS", libs.Flagline); mf.AddDefinition("CMAKE_PKG_CONFIG_LIBDIRS", cmList::to_string(libs.LibDirs)); @@ -693,7 +782,7 @@ bool HandleExtractCommand(std::vector const& args, mf.AddDefinition("CMAKE_PKG_CONFIG_LINK_OPTIONS", cmList::to_string(libs.LinkOptions)); - libs = resolved.Libs(true); + libs = package.Libs(true); mf.AddDefinition("CMAKE_PKG_CONFIG_LIBS_PRIVATE", libs.Flagline); mf.AddDefinition("CMAKE_PKG_CONFIG_LIBDIRS_PRIVATE", cmList::to_string(libs.LibDirs)); @@ -704,6 +793,220 @@ bool HandleExtractCommand(std::vector const& args, return true; } + +using pkgStack = std::unordered_map>; +using pkgProviders = std::unordered_map; + +cmTarget* CreateCMakeTarget(std::string const& name, cmPkgConfigResult& pkg, + pkgProviders& providers, cmMakefile& mf) +{ + auto* tgt = mf.AddForeignTarget("pkgcfg", name); + + tgt->AppendProperty("VERSION", pkg.Version()); + + auto libs = pkg.Libs(); + for (auto const& flag : libs.LibNames) { + tgt->AppendProperty("INTERFACE_LINK_LIBRARIES", flag.substr(2)); + } + for (auto const& flag : libs.LibDirs) { + tgt->AppendProperty("INTERFACE_LINK_DIRECTORIES", flag.substr(2)); + } + tgt->AppendProperty("INTERFACE_LINK_OPTIONS", + cmList::to_string(libs.LinkOptions)); + + auto cflags = pkg.Cflags(); + for (auto const& flag : cflags.Includes) { + tgt->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES", flag.substr(2)); + } + tgt->AppendProperty("INTERFACE_COMPILE_OPTIONS", + cmList::to_string(cflags.CompileOptions)); + + for (auto& dep : pkg.Requires()) { + auto it = providers.find(dep.Name); + if (it != providers.end()) { + tgt->AppendProperty("INTERFACE_LINK_LIBRARIES", it->second); + continue; + } + + tgt->AppendProperty("INTERFACE_LINK_LIBRARIES", + cmStrCat("@foreign_pkgcfg::", dep.Name)); + } + return tgt; +} + +bool CheckPackageDependencies( + std::string const& name, cmPkgConfigResult& pkg, pkgStack& inStack, + std::unordered_map& outStack, + pkgProviders& providers, ImportEnv& imEnv) +{ + for (auto& dep : pkg.Requires()) { + auto prov_it = providers.find(dep.Name); + if (prov_it != providers.end()) { + continue; + } + + auto* tgt = imEnv.status.GetMakefile().FindTargetToUse( + cmStrCat("@foreign_pkgcfg::", dep.Name), + cmStateEnums::TargetDomain::FOREIGN); + if (tgt) { + auto ver = tgt->GetProperty("VERSION"); + if (!cmPkgConfigResolver::CheckVersion(dep.VerReq, *ver)) { + warn_or_error(cmStrCat("Package '", dep.Name, "' version '", *ver, + "' does not meet version requirement '", + dep.VerReq.string(), "' ", "of '", name, "'"), + imEnv); + return false; + } + continue; + } + + auto it = outStack.find(dep.Name); + if (it != outStack.end()) { + auto ver = it->second.Version(); + if (!cmPkgConfigResolver::CheckVersion(dep.VerReq, ver)) { + warn_or_error(cmStrCat("Package '", dep.Name, "' version '", ver, + "' does not meet version requirement '", + dep.VerReq.string(), "' ", "of '", name, "'"), + imEnv); + return false; + } + continue; + } + + inStack[dep.Name].emplace_back( + pkgStackEntry{ std::move(dep.VerReq), name }); + } + + return true; +} + +struct PopulateArguments : CommonArguments +{ + cm::optional>> providers; +}; + +auto const PopulateParser = + BIND_COMMON(PopulateArguments) + .Bind("BIND_PC_REQUIRES"_s, &PopulateArguments::providers); + +std::pair PopulatePCTarget(PopulateArguments& args, + cmExecutionStatus& status) +{ + + auto& mf = status.GetMakefile(); + auto maybeEnv = HandleCommon(args, status); + + if (!maybeEnv) { + return { !args.Required, false }; + } + auto& pcEnv = maybeEnv->first; + auto& imEnv = maybeEnv->second; + + pkgProviders providers; + if (args.providers) { + for (auto const& provider_str : *args.providers) { + auto assignment = provider_str.find('='); + if (assignment != std::string::npos) { + providers.emplace(provider_str.substr(0, assignment), + provider_str.substr(assignment + 1)); + } else { + imEnv.status.SetError(cmStrCat( + "No '=' found in BIND_PC_REQUIRES argument '", provider_str, "'")); + cmSystemTools::SetFatalErrorOccurred(); + return { false, false }; + } + } + } + + pkgStack inStack; + std::unordered_map outStack; + + auto maybePackage = ImportPackage(*args.Package, args.Version, imEnv, pcEnv); + if (!maybePackage) { + return { !args.Required, false }; + } + imEnv.exact = false; + + if (!CheckPackageDependencies(*args.Package, *maybePackage, inStack, + outStack, providers, imEnv)) { + return { !args.Required, false }; + } + outStack[*args.Package] = std::move(*maybePackage); + + while (!inStack.empty()) { + auto name = inStack.begin()->first; + auto reqs = inStack.begin()->second; + maybePackage = ImportPackage(name, reqs, imEnv, pcEnv); + if (!maybePackage) { + return { !args.Required, false }; + } + if (!CheckPackageDependencies(name, *maybePackage, inStack, outStack, + providers, imEnv)) { + return { !args.Required, false }; + } + inStack.erase(name); + outStack[std::move(name)] = std::move(*maybePackage); + } + + for (auto& entry : outStack) { + CreateCMakeTarget(entry.first, entry.second, providers, mf); + } + + return { true, true }; +} + +bool HandlePopulateCommand(std::vector const& args, + cmExecutionStatus& status) +{ + std::vector unparsed; + auto parsedArgs = PopulateParser.Parse(args, &unparsed); + + auto foreign_name = cmStrCat("@foreign_pkgcfg::", *parsedArgs.Package); + auto found_var = cmStrCat("PKGCONFIG_", *parsedArgs.Package, "_FOUND"); + + auto& mf = status.GetMakefile(); + + if (mf.FindTargetToUse(foreign_name, cmStateEnums::TargetDomain::FOREIGN)) { + mf.AddDefinition(found_var, "TRUE"); + return true; + } + + auto result = PopulatePCTarget(parsedArgs, status); + mf.AddDefinition(found_var, result.second ? "TRUE" : "FALSE"); + return result.first; +} + +bool HandleImportCommand(std::vector const& args, + cmExecutionStatus& status) +{ + std::vector unparsed; + auto parsedArgs = PopulateParser.Parse(args, &unparsed); + auto foreign_name = cmStrCat("@foreign_pkgcfg::", *parsedArgs.Package); + auto local_name = cmStrCat("PkgConfig::", *parsedArgs.Package); + auto found_var = cmStrCat("PKGCONFIG_", *parsedArgs.Package, "_FOUND"); + + auto& mf = status.GetMakefile(); + + if (mf.FindTargetToUse(local_name)) { + mf.AddDefinition(found_var, "TRUE"); + return true; + } + + if (!mf.FindTargetToUse(foreign_name, cmStateEnums::TargetDomain::FOREIGN)) { + auto result = PopulatePCTarget(parsedArgs, status); + if (!result.second) { + mf.AddDefinition(found_var, "FALSE"); + return result.first; + } + } + + mf.AddDefinition(found_var, "TRUE"); + auto* tgt = mf.AddImportedTarget( + local_name, cmStateEnums::TargetType::INTERFACE_LIBRARY, false); + tgt->AppendProperty("INTERFACE_LINK_LIBRARIES", foreign_name); + return true; +} + } // namespace bool cmCMakePkgConfigCommand(std::vector const& args, @@ -716,6 +1019,8 @@ bool cmCMakePkgConfigCommand(std::vector const& args, static cmSubcommandTable const subcommand{ { "EXTRACT"_s, HandleExtractCommand }, + { "POPULATE"_s, HandlePopulateCommand }, + { "IMPORT"_s, HandleImportCommand }, }; return subcommand(args[0], args, status); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index dd1d7cdbf1..ff56ac2be5 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3796,14 +3796,14 @@ cmTarget* cmMakefile::AddImportedTarget(std::string const& name, cmTarget* cmMakefile::AddForeignTarget(std::string const& origin, std::string const& name) { + auto foreign_name = cmStrCat("@foreign_", origin, "::", name); std::unique_ptr target(new cmTarget( - cmStrCat("@foreign_", origin, "::", name), - cmStateEnums::TargetType::INTERFACE_LIBRARY, cmTarget::Visibility::Foreign, - this, cmTarget::PerConfig::Yes)); + foreign_name, cmStateEnums::TargetType::INTERFACE_LIBRARY, + cmTarget::Visibility::Foreign, this, cmTarget::PerConfig::Yes)); - this->ImportedTargets[name] = target.get(); + this->ImportedTargets[foreign_name] = target.get(); this->GetGlobalGenerator()->IndexTarget(target.get()); - this->GetStateSnapshot().GetDirectory().AddImportedTargetName(name); + this->GetStateSnapshot().GetDirectory().AddImportedTargetName(foreign_name); this->ImportedTargetsOwned.push_back(std::move(target)); return this->ImportedTargetsOwned.back().get(); diff --git a/Source/cmPkgConfigResolver.cxx b/Source/cmPkgConfigResolver.cxx index 2386e33978..f40657a083 100644 --- a/Source/cmPkgConfigResolver.cxx +++ b/Source/cmPkgConfigResolver.cxx @@ -16,6 +16,7 @@ #include #include "cmPkgConfigParser.h" +#include "cmStringAlgorithms.h" namespace { @@ -57,6 +58,27 @@ std::string AppendAndTrim(std::string& str, cm::string_view sv) } // namespace +std::string cmPkgConfigVersionReq::string() const +{ + switch (Operation) { + case ANY: + return ""; + case LT: + return cmStrCat("<", Version); + case LT_EQ: + return cmStrCat("<=", Version); + case EQ: + return cmStrCat("=", Version); + case NEQ: + return cmStrCat("!=", Version); + case GT_EQ: + return cmStrCat(">=", Version); + case GT: + return cmStrCat(">", Version); + } + return ""; +} + std::string cmPkgConfigResult::StrOrDefault(std::string const& key, cm::string_view def) { @@ -127,24 +149,24 @@ cmPkgConfigCflagsResult cmPkgConfigResult::Cflags(bool priv) auto tokens = cmPkgConfigResolver::TokenizeFlags(cflags); - if (env.AllowSysCflags) { - if (env.SysrootDir) { - return cmPkgConfigResolver::MangleCflags(tokens, *env.SysrootDir); + if (env->AllowSysCflags) { + if (env->SysrootDir) { + return cmPkgConfigResolver::MangleCflags(tokens, *env->SysrootDir); } return cmPkgConfigResolver::MangleCflags(tokens); } - if (env.SysCflags) { - if (env.SysrootDir) { - return cmPkgConfigResolver::MangleCflags(tokens, *env.SysrootDir, - *env.SysCflags); + if (env->SysCflags) { + if (env->SysrootDir) { + return cmPkgConfigResolver::MangleCflags(tokens, *env->SysrootDir, + *env->SysCflags); } - return cmPkgConfigResolver::MangleCflags(tokens, *env.SysCflags); + return cmPkgConfigResolver::MangleCflags(tokens, *env->SysCflags); } - if (env.SysrootDir) { + if (env->SysrootDir) { return cmPkgConfigResolver::MangleCflags( - tokens, *env.SysrootDir, std::vector{ "/usr/include" }); + tokens, *env->SysrootDir, std::vector{ "/usr/include" }); } return cmPkgConfigResolver::MangleCflags( @@ -160,24 +182,24 @@ cmPkgConfigLibsResult cmPkgConfigResult::Libs(bool priv) auto tokens = cmPkgConfigResolver::TokenizeFlags(it->second); - if (env.AllowSysLibs) { - if (env.SysrootDir) { - return cmPkgConfigResolver::MangleLibs(tokens, *env.SysrootDir); + if (env->AllowSysLibs) { + if (env->SysrootDir) { + return cmPkgConfigResolver::MangleLibs(tokens, *env->SysrootDir); } return cmPkgConfigResolver::MangleLibs(tokens); } - if (env.SysLibs) { - if (env.SysrootDir) { - return cmPkgConfigResolver::MangleLibs(tokens, *env.SysrootDir, - *env.SysLibs); + if (env->SysLibs) { + if (env->SysrootDir) { + return cmPkgConfigResolver::MangleLibs(tokens, *env->SysrootDir, + *env->SysLibs); } - return cmPkgConfigResolver::MangleLibs(tokens, *env.SysLibs); + return cmPkgConfigResolver::MangleLibs(tokens, *env->SysLibs); } - if (env.SysrootDir) { + if (env->SysrootDir) { return cmPkgConfigResolver::MangleLibs( - tokens, *env.SysrootDir, std::vector{ "/usr/lib" }); + tokens, *env->SysrootDir, std::vector{ "/usr/lib" }); } return cmPkgConfigResolver::MangleLibs( @@ -210,7 +232,7 @@ cm::optional cmPkgConfigResolver::ResolveStrict( config.Variables["pc_top_builddir"] = *env.TopBuildDir; } - config.env = std::move(env); + config.env = &env; for (auto const& entry : entries) { std::string key(entry.Key); @@ -288,7 +310,7 @@ cmPkgConfigResult cmPkgConfigResolver::ResolveBestEffort( result.Variables["pc_top_builddir"] = *env.TopBuildDir; } - result.env = std::move(env); + result.env = &env; for (auto const& entry : entries) { std::string key(entry.Key); diff --git a/Source/cmPkgConfigResolver.h b/Source/cmPkgConfigResolver.h index 99bfe87264..703fbd8f2f 100644 --- a/Source/cmPkgConfigResolver.h +++ b/Source/cmPkgConfigResolver.h @@ -43,6 +43,8 @@ struct cmPkgConfigVersionReq GT, } Operation = ANY; std::string Version; + + std::string string() const; }; struct cmPkgConfigDependency @@ -60,6 +62,7 @@ struct cmPkgConfigEnv cm::optional SysrootDir; cm::optional TopBuildDir; + std::vector search; cm::optional DisableUninstalled; @@ -84,7 +87,7 @@ public: cmPkgConfigCflagsResult Cflags(bool priv = false); cmPkgConfigLibsResult Libs(bool priv = false); - cmPkgConfigEnv env; + cmPkgConfigEnv* env; private: std::string StrOrDefault(std::string const& key, cm::string_view def = ""); diff --git a/Tests/RunCMake/cmake_pkg_config/TestEnv-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ExtractEnv-stderr.txt similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestEnv-stderr.txt rename to Tests/RunCMake/cmake_pkg_config/ExtractEnv-stderr.txt diff --git a/Tests/RunCMake/cmake_pkg_config/TestEnv.cmake b/Tests/RunCMake/cmake_pkg_config/ExtractEnv.cmake similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestEnv.cmake rename to Tests/RunCMake/cmake_pkg_config/ExtractEnv.cmake diff --git a/Tests/RunCMake/cmake_pkg_config/TestExtract-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ExtractFields-stderr.txt similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestExtract-stderr.txt rename to Tests/RunCMake/cmake_pkg_config/ExtractFields-stderr.txt diff --git a/Tests/RunCMake/cmake_pkg_config/TestExtract.cmake b/Tests/RunCMake/cmake_pkg_config/ExtractFields.cmake similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestExtract.cmake rename to Tests/RunCMake/cmake_pkg_config/ExtractFields.cmake diff --git a/Tests/RunCMake/cmake_pkg_config/TestMangle-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ExtractMangle-stderr.txt similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestMangle-stderr.txt rename to Tests/RunCMake/cmake_pkg_config/ExtractMangle-stderr.txt diff --git a/Tests/RunCMake/cmake_pkg_config/TestMangle.cmake b/Tests/RunCMake/cmake_pkg_config/ExtractMangle.cmake similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestMangle.cmake rename to Tests/RunCMake/cmake_pkg_config/ExtractMangle.cmake diff --git a/Tests/RunCMake/cmake_pkg_config/TestQuiet.cmake b/Tests/RunCMake/cmake_pkg_config/ExtractQuiet.cmake similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestQuiet.cmake rename to Tests/RunCMake/cmake_pkg_config/ExtractQuiet.cmake diff --git a/Tests/RunCMake/cmake_pkg_config/TestRequired-result.txt b/Tests/RunCMake/cmake_pkg_config/ExtractRequired-result.txt similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestRequired-result.txt rename to Tests/RunCMake/cmake_pkg_config/ExtractRequired-result.txt diff --git a/Tests/RunCMake/cmake_pkg_config/ExtractRequired-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ExtractRequired-stderr.txt new file mode 100644 index 0000000000..735b14207b --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/ExtractRequired-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at ExtractRequired.cmake:[0-9]+ \(cmake_pkg_config\): + cmake_pkg_config Could not find pkg-config: 'does-not-exist' +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_pkg_config/TestRequired.cmake b/Tests/RunCMake/cmake_pkg_config/ExtractRequired.cmake similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestRequired.cmake rename to Tests/RunCMake/cmake_pkg_config/ExtractRequired.cmake diff --git a/Tests/RunCMake/cmake_pkg_config/TestReroot-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ExtractReroot-stderr.txt similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestReroot-stderr.txt rename to Tests/RunCMake/cmake_pkg_config/ExtractReroot-stderr.txt diff --git a/Tests/RunCMake/cmake_pkg_config/TestReroot.cmake b/Tests/RunCMake/cmake_pkg_config/ExtractReroot.cmake similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestReroot.cmake rename to Tests/RunCMake/cmake_pkg_config/ExtractReroot.cmake diff --git a/Tests/RunCMake/cmake_pkg_config/TestStrictness-BEST_EFFORT-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ExtractStrictness-BEST_EFFORT-stderr.txt similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestStrictness-BEST_EFFORT-stderr.txt rename to Tests/RunCMake/cmake_pkg_config/ExtractStrictness-BEST_EFFORT-stderr.txt diff --git a/Tests/RunCMake/cmake_pkg_config/TestStrictness-PERMISSIVE-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ExtractStrictness-PERMISSIVE-stderr.txt similarity index 69% rename from Tests/RunCMake/cmake_pkg_config/TestStrictness-PERMISSIVE-stderr.txt rename to Tests/RunCMake/cmake_pkg_config/ExtractStrictness-PERMISSIVE-stderr.txt index 2f4a69cae1..b07571f6b7 100644 --- a/Tests/RunCMake/cmake_pkg_config/TestStrictness-PERMISSIVE-stderr.txt +++ b/Tests/RunCMake/cmake_pkg_config/ExtractStrictness-PERMISSIVE-stderr.txt @@ -1,25 +1,25 @@ -CMake Warning at TestStrictness.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractStrictness.cmake:[0-9]+ \(cmake_pkg_config\): Resolution failed for file[^ ]*(.)*/PackageRoot/no-name.pc' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestStrictness.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractStrictness.cmake:[0-9]+ \(cmake_pkg_config\): Resolution failed for file[^ ]*(.)*/PackageRoot/no-description.pc' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestStrictness.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractStrictness.cmake:[0-9]+ \(cmake_pkg_config\): Resolution failed for file[^ ]*(.)*/PackageRoot/no-version.pc' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestStrictness.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractStrictness.cmake:[0-9]+ \(cmake_pkg_config\): Parsing failed for file[^ ]*(.)*/PackageRoot/invalid.pc' Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/cmake_pkg_config/TestStrictness-STRICT-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ExtractStrictness-STRICT-stderr.txt similarity index 68% rename from Tests/RunCMake/cmake_pkg_config/TestStrictness-STRICT-stderr.txt rename to Tests/RunCMake/cmake_pkg_config/ExtractStrictness-STRICT-stderr.txt index 7329e8d150..1ddc841091 100644 --- a/Tests/RunCMake/cmake_pkg_config/TestStrictness-STRICT-stderr.txt +++ b/Tests/RunCMake/cmake_pkg_config/ExtractStrictness-STRICT-stderr.txt @@ -1,25 +1,25 @@ -CMake Warning at TestStrictness.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractStrictness.cmake:[0-9]+ \(cmake_pkg_config\): Resolution failed for file[^ ]*(.)*/PackageRoot/no-name.pc' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestStrictness.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractStrictness.cmake:[0-9]+ \(cmake_pkg_config\): Resolution failed for file[^ ]*(.)*/PackageRoot/no-description.pc' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestStrictness.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractStrictness.cmake:[0-9]+ \(cmake_pkg_config\): Resolution failed for file[^ ]*(.)*/PackageRoot/no-version.pc' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestStrictness.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractStrictness.cmake:[0-9]+ \(cmake_pkg_config\): Parsing failed for file[^ ]*(.)*/PackageRoot/invalid.pc' Call Stack \(most recent call first\): @@ -28,7 +28,7 @@ Call Stack \(most recent call first\): Cflags: lowercase CFlags: uppercase -CMake Warning at TestStrictness.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractStrictness.cmake:[0-9]+ \(cmake_pkg_config\): Resolution failed for file[^ ]*(.)*/PackageRoot/cflags-bothcase-f.pc' Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/cmake_pkg_config/TestStrictness.cmake b/Tests/RunCMake/cmake_pkg_config/ExtractStrictness.cmake similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestStrictness.cmake rename to Tests/RunCMake/cmake_pkg_config/ExtractStrictness.cmake diff --git a/Tests/RunCMake/cmake_pkg_config/TestUninstalled-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ExtractUninstalled-stderr.txt similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestUninstalled-stderr.txt rename to Tests/RunCMake/cmake_pkg_config/ExtractUninstalled-stderr.txt diff --git a/Tests/RunCMake/cmake_pkg_config/TestUninstalled.cmake b/Tests/RunCMake/cmake_pkg_config/ExtractUninstalled.cmake similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestUninstalled.cmake rename to Tests/RunCMake/cmake_pkg_config/ExtractUninstalled.cmake diff --git a/Tests/RunCMake/cmake_pkg_config/TestVersion-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ExtractVersion-stderr.txt similarity index 69% rename from Tests/RunCMake/cmake_pkg_config/TestVersion-stderr.txt rename to Tests/RunCMake/cmake_pkg_config/ExtractVersion-stderr.txt index 4b710d8f23..551efb2642 100644 --- a/Tests/RunCMake/cmake_pkg_config/TestVersion-stderr.txt +++ b/Tests/RunCMake/cmake_pkg_config/ExtractVersion-stderr.txt @@ -1,103 +1,103 @@ -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'a' version 'aa' does not meet version requirement 'aaa' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'a' version 'aa' does not meet version requirement '>bb' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'a' version 'aa' does not meet version requirement '>1' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'empty-key' version '' does not meet version requirement '!=' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'empty-key' version '' does not meet version requirement '=0' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'one' version '11' does not meet version requirement '<1' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'one' version '11' does not meet version requirement '>111' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'one' version '11' does not meet version requirement '>22' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'one' version '11' does not meet version requirement '1.2.1' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'onedot' version '1.1.1' does not meet version requirement '> 1.2.1' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'onedot' version '1.1.1' does not meet exact version requirement '01.01.01' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'pseudo-empty' version '~0' does not meet version requirement '=~' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'pseudo-empty' version '~0' does not meet version requirement '!=~0' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'tilde' version '~~1' does not meet version requirement '>~1' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -CMake Warning at TestVersion.cmake:[0-9]+ \(cmake_pkg_config\): +CMake Warning at ExtractVersion.cmake:[0-9]+ \(cmake_pkg_config\): Package 'tilde' version '~~1' does not meet version requirement '<~~~1' Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_pkg_config/TestVersion.cmake b/Tests/RunCMake/cmake_pkg_config/ExtractVersion.cmake similarity index 100% rename from Tests/RunCMake/cmake_pkg_config/TestVersion.cmake rename to Tests/RunCMake/cmake_pkg_config/ExtractVersion.cmake diff --git a/Tests/RunCMake/cmake_pkg_config/ImportRequires-check.cmake b/Tests/RunCMake/cmake_pkg_config/ImportRequires-check.cmake new file mode 100644 index 0000000000..e098e6c61f --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/ImportRequires-check.cmake @@ -0,0 +1,14 @@ +set(expected + "alpha: Alpha +bravo: Bravo;Alpha +charlie: Charlie;Bravo;Alpha +delta: Delta +echo: Echo;Bravo;Alpha;Delta +" +) + +file(READ "${RunCMake_TEST_BINARY_DIR}/import-requires.txt" actual) + +if(NOT(expected STREQUAL actual)) + set(RunCMake_TEST_FAILED "cmake_pkg_config import-requires.txt does not match expected:\n${actual}") +endif() diff --git a/Tests/RunCMake/cmake_pkg_config/ImportRequires.cmake b/Tests/RunCMake/cmake_pkg_config/ImportRequires.cmake new file mode 100644 index 0000000000..48e0b90e58 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/ImportRequires.cmake @@ -0,0 +1,18 @@ +set(CMAKE_PKG_CONFIG_PC_PATH ${CMAKE_CURRENT_LIST_DIR}/PackageRoot/RequiresPackages) + +cmake_pkg_config(IMPORT echo REQUIRED) +cmake_pkg_config(IMPORT delta REQUIRED) +cmake_pkg_config(IMPORT charlie REQUIRED) +cmake_pkg_config(IMPORT bravo REQUIRED) +cmake_pkg_config(IMPORT alpha REQUIRED) + +file(GENERATE + OUTPUT import-requires.txt + CONTENT + "alpha: $ +bravo: $ +charlie: $ +delta: $ +echo: $ +" +) diff --git a/Tests/RunCMake/cmake_pkg_config/ImportSimple-check.cmake b/Tests/RunCMake/cmake_pkg_config/ImportSimple-check.cmake new file mode 100644 index 0000000000..906cf104b1 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/ImportSimple-check.cmake @@ -0,0 +1,15 @@ +set(expected +"Import Simple Found: TRUE +Include Directories: ${RunCMake_SOURCE_DIR}/TestDirectories/Include +Compile Options: TestCflag +Link Directories: ${RunCMake_SOURCE_DIR}/TestDirectories/Library +Link Libraries: @foreign_pkgcfg::import-simple +Link Options: TestLinkOption +" +) + +file(READ "${RunCMake_TEST_BINARY_DIR}/import-simple.txt" actual) + +if(NOT(expected STREQUAL actual)) + set(RunCMake_TEST_FAILED "cmake_pkg_config import-simple.txt does not match expected:\n${actual}") +endif() diff --git a/Tests/RunCMake/cmake_pkg_config/ImportSimple.cmake b/Tests/RunCMake/cmake_pkg_config/ImportSimple.cmake new file mode 100644 index 0000000000..fb1d97345a --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/ImportSimple.cmake @@ -0,0 +1,15 @@ +set(CMAKE_PKG_CONFIG_SYSROOT_DIR ${CMAKE_CURRENT_LIST_DIR}) + +cmake_pkg_config(IMPORT import-simple REQUIRED) + +file(GENERATE + OUTPUT import-simple.txt + CONTENT +"Import Simple Found: ${PKGCONFIG_import-simple_FOUND} +Include Directories: $ +Compile Options: $ +Link Directories: $ +Link Libraries: $ +Link Options: $ +" +) diff --git a/Tests/RunCMake/cmake_pkg_config/ImportTransitiveFail-result.txt b/Tests/RunCMake/cmake_pkg_config/ImportTransitiveFail-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/ImportTransitiveFail-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_pkg_config/ImportTransitiveFail-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ImportTransitiveFail-stderr.txt new file mode 100644 index 0000000000..c80c2274b6 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/ImportTransitiveFail-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning at ImportTransitiveFail.cmake:[0-9]+ \(cmake_pkg_config\): + Could not find pkg-config: 'foxtrot' required by: 'golf' +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) + + +Import Golf Found: FALSE +CMake Error at ImportTransitiveFail.cmake:[0-9]+ \(cmake_pkg_config\): + cmake_pkg_config Could not find pkg-config: 'foxtrot' required by: 'golf' +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_pkg_config/ImportTransitiveFail.cmake b/Tests/RunCMake/cmake_pkg_config/ImportTransitiveFail.cmake new file mode 100644 index 0000000000..76292447a9 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/ImportTransitiveFail.cmake @@ -0,0 +1,5 @@ +set(CMAKE_PKG_CONFIG_PC_PATH ${CMAKE_CURRENT_LIST_DIR}/PackageRoot/RequiresPackages) + +cmake_pkg_config(IMPORT golf) +message("Import Golf Found: ${PKGCONFIG_golf_FOUND}") +cmake_pkg_config(IMPORT golf REQUIRED) diff --git a/Tests/RunCMake/cmake_pkg_config/ImportTransitiveVersion.cmake b/Tests/RunCMake/cmake_pkg_config/ImportTransitiveVersion.cmake new file mode 100644 index 0000000000..e5e641aed6 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/ImportTransitiveVersion.cmake @@ -0,0 +1,3 @@ +set(CMAKE_PKG_CONFIG_PC_PATH ${CMAKE_CURRENT_LIST_DIR}/PackageRoot/RequiresPackages) + +cmake_pkg_config(IMPORT india) diff --git a/Tests/RunCMake/cmake_pkg_config/ImportTransitiveVersionFail-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ImportTransitiveVersionFail-stderr.txt new file mode 100644 index 0000000000..a658b987c5 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/ImportTransitiveVersionFail-stderr.txt @@ -0,0 +1,5 @@ +CMake Warning at ImportTransitiveVersionFail.cmake:[0-9]+ \(cmake_pkg_config\): + Package 'alpha' version '1.0.0' does not meet version requirement '>=2.0.0' + of 'hotel' +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_pkg_config/ImportTransitiveVersionFail.cmake b/Tests/RunCMake/cmake_pkg_config/ImportTransitiveVersionFail.cmake new file mode 100644 index 0000000000..283c47aa1f --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/ImportTransitiveVersionFail.cmake @@ -0,0 +1,4 @@ +set(CMAKE_PKG_CONFIG_PC_PATH ${CMAKE_CURRENT_LIST_DIR}/PackageRoot/RequiresPackages) + +cmake_pkg_config(POPULATE bravo) +cmake_pkg_config(IMPORT hotel) diff --git a/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/alpha.pc b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/alpha.pc new file mode 100644 index 0000000000..f6b4610911 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/alpha.pc @@ -0,0 +1,5 @@ +Name: Alpha +Description: Alpha +Version: 1.0.0 + +Cflags: Alpha diff --git a/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/bravo.pc b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/bravo.pc new file mode 100644 index 0000000000..075e887e46 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/bravo.pc @@ -0,0 +1,6 @@ +Name: Bravo +Description: Bravo +Version: 1.0.0 + +Cflags: Bravo +Requires: alpha diff --git a/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/charlie.pc b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/charlie.pc new file mode 100644 index 0000000000..6a16d3ef55 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/charlie.pc @@ -0,0 +1,6 @@ +Name: Charlie +Description: Charlie +Version: 1.0.0 + +Cflags: Charlie +Requires: bravo diff --git a/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/delta.pc b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/delta.pc new file mode 100644 index 0000000000..bb1486c818 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/delta.pc @@ -0,0 +1,5 @@ +Name: Delta +Description: Delta +Version: 1.0.0 + +Cflags: Delta diff --git a/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/echo.pc b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/echo.pc new file mode 100644 index 0000000000..7b05d000b5 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/echo.pc @@ -0,0 +1,6 @@ +Name: Echo +Description: Echo +Version: 1.0.0 + +Cflags: Echo +Requires: bravo delta diff --git a/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/golf.pc b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/golf.pc new file mode 100644 index 0000000000..c457194320 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/golf.pc @@ -0,0 +1,6 @@ +Name: Golf +Description: Golf +Version: 1.0.0 + +Cflags: Golf +Requires: foxtrot diff --git a/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/hotel.pc b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/hotel.pc new file mode 100644 index 0000000000..396491f69e --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/hotel.pc @@ -0,0 +1,6 @@ +Name: Hotel +Description: Hotel +Version: 1.0.0 + +Cflags: Hotel +Requires: alpha >= 2.0.0 diff --git a/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/india.pc b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/india.pc new file mode 100644 index 0000000000..7b5a5c52eb --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/india.pc @@ -0,0 +1,6 @@ +Name: India +Description: India +Version: 1.0.0 + +Cflags: India +Requires: alpha = 1.0.0 bravo > 0.5.0 diff --git a/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/juliet.pc b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/juliet.pc new file mode 100644 index 0000000000..b5ce5f1c6d --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/PackageRoot/RequiresPackages/juliet.pc @@ -0,0 +1,6 @@ +Name: Juliet +Description: Juliet +Version: 1.0.0 + +Cflags: Juliet +Requires: golf diff --git a/Tests/RunCMake/cmake_pkg_config/PackageRoot/import-simple.pc b/Tests/RunCMake/cmake_pkg_config/PackageRoot/import-simple.pc new file mode 100644 index 0000000000..fb13815ad1 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/PackageRoot/import-simple.pc @@ -0,0 +1,6 @@ +Name: Import Simple +Description: A simple import with no dependencies +Version: 1.0.0 + +Cflags: -I/TestDirectories/Include TestCflag +Libs: -L/TestDirectories/Library -ldummy TestLinkOption diff --git a/Tests/RunCMake/cmake_pkg_config/PopulateFoundVar-stderr.txt b/Tests/RunCMake/cmake_pkg_config/PopulateFoundVar-stderr.txt new file mode 100644 index 0000000000..bff56925e2 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/PopulateFoundVar-stderr.txt @@ -0,0 +1,8 @@ +Found Alpha: TRUE +CMake Warning at PopulateFoundVar.cmake:[0-9]+ \(cmake_pkg_config\): + Could not find pkg-config: 'foxtrot' +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) + + +Found Foxtrot: FALSE diff --git a/Tests/RunCMake/cmake_pkg_config/PopulateFoundVar.cmake b/Tests/RunCMake/cmake_pkg_config/PopulateFoundVar.cmake new file mode 100644 index 0000000000..7ff1ed8a79 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/PopulateFoundVar.cmake @@ -0,0 +1,7 @@ +set(CMAKE_PKG_CONFIG_PC_PATH ${CMAKE_CURRENT_LIST_DIR}/PackageRoot/RequiresPackages) + +cmake_pkg_config(POPULATE alpha) +message("Found Alpha: ${PKGCONFIG_alpha_FOUND}") + +cmake_pkg_config(POPULATE foxtrot) +message("Found Foxtrot: ${PKGCONFIG_foxtrot_FOUND}") diff --git a/Tests/RunCMake/cmake_pkg_config/PopulateMissing-check.cmake b/Tests/RunCMake/cmake_pkg_config/PopulateMissing-check.cmake new file mode 100644 index 0000000000..9481a8f182 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/PopulateMissing-check.cmake @@ -0,0 +1,10 @@ +set(expected + "juliet: Juliet;Golf;Foxtrot +" +) + +file(READ "${RunCMake_TEST_BINARY_DIR}/populate-missing.txt" actual) + +if(NOT(expected STREQUAL actual)) + set(RunCMake_TEST_FAILED "cmake_pkg_config populate-missing.txt does not match expected:\n${actual}") +endif() diff --git a/Tests/RunCMake/cmake_pkg_config/PopulateMissing.cmake b/Tests/RunCMake/cmake_pkg_config/PopulateMissing.cmake new file mode 100644 index 0000000000..d7e035b645 --- /dev/null +++ b/Tests/RunCMake/cmake_pkg_config/PopulateMissing.cmake @@ -0,0 +1,19 @@ +set(CMAKE_PKG_CONFIG_PC_PATH ${CMAKE_CURRENT_LIST_DIR}/PackageRoot/RequiresPackages) + +add_library(native-foxtrot INTERFACE) +target_compile_options(native-foxtrot INTERFACE Foxtrot) + +cmake_pkg_config( + POPULATE golf + BIND_PC_REQUIRES + foxtrot=native-foxtrot +) + +cmake_pkg_config(IMPORT juliet) + +file(GENERATE + OUTPUT populate-missing.txt + CONTENT + "juliet: $ +" +) diff --git a/Tests/RunCMake/cmake_pkg_config/RunCMakeTest.cmake b/Tests/RunCMake/cmake_pkg_config/RunCMakeTest.cmake index 4f9200b123..32e0866128 100644 --- a/Tests/RunCMake/cmake_pkg_config/RunCMakeTest.cmake +++ b/Tests/RunCMake/cmake_pkg_config/RunCMakeTest.cmake @@ -3,16 +3,23 @@ include(RunCMake) set(cmd ${CMAKE_COMMAND} ${CMAKE_CURRENT_LIST_DIR} -G ${RunCMake_GENERATOR}) foreach(strictness IN ITEMS STRICT PERMISSIVE BEST_EFFORT) - run_cmake_command(TestStrictness-${strictness} ${cmd} - -DRunCMake_TEST=TestStrictness -DSTRICTNESS=${strictness} + run_cmake_command(ExtractStrictness-${strictness} ${cmd} + -DRunCMake_TEST=ExtractStrictness -DSTRICTNESS=${strictness} ) endforeach() -run_cmake(TestEnv) -run_cmake(TestExtract) -run_cmake(TestMangle) -run_cmake(TestQuiet) -run_cmake(TestRequired) -run_cmake(TestReroot) -run_cmake(TestUninstalled) -run_cmake(TestVersion) +run_cmake(ExtractEnv) +run_cmake(ExtractFields) +run_cmake(ExtractMangle) +run_cmake(ExtractQuiet) +run_cmake(ExtractRequired) +run_cmake(ExtractReroot) +run_cmake(ExtractUninstalled) +run_cmake(ExtractVersion) +run_cmake(ImportSimple) +run_cmake(ImportRequires) +run_cmake(ImportTransitiveFail) +run_cmake(ImportTransitiveVersion) +run_cmake(ImportTransitiveVersionFail) +run_cmake(PopulateFoundVar) +run_cmake(PopulateMissing) diff --git a/Tests/RunCMake/cmake_pkg_config/TestDirectories/Include/dummy-header.h b/Tests/RunCMake/cmake_pkg_config/TestDirectories/Include/dummy-header.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Tests/RunCMake/cmake_pkg_config/TestDirectories/Library/libdummy b/Tests/RunCMake/cmake_pkg_config/TestDirectories/Library/libdummy new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Tests/RunCMake/cmake_pkg_config/TestRequired-stderr.txt b/Tests/RunCMake/cmake_pkg_config/TestRequired-stderr.txt deleted file mode 100644 index d7f5158f56..0000000000 --- a/Tests/RunCMake/cmake_pkg_config/TestRequired-stderr.txt +++ /dev/null @@ -1,4 +0,0 @@ -CMake Error at TestRequired.cmake:[0-9]+ \(cmake_pkg_config\): - cmake_pkg_config Could not find 'does-not-exist' -Call Stack \(most recent call first\): - CMakeLists.txt:[0-9]+ \(include\)