| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file LICENSE.rst or https://cmake.org/licensing for details. */ |
| |
| #include "cmCMakePkgConfigCommand.h" |
| |
| #include <cstdio> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include <cm/filesystem> |
| #include <cm/optional> |
| #include <cm/string_view> |
| #include <cmext/string_view> |
| |
| #include "cmsys/FStream.hxx" |
| |
| #include "cmArgumentParser.h" |
| #include "cmArgumentParserTypes.h" |
| #include "cmExecutionStatus.h" |
| #include "cmList.h" |
| #include "cmMakefile.h" |
| #include "cmMessageType.h" |
| #include "cmPkgConfigParser.h" |
| #include "cmPkgConfigResolver.h" |
| #include "cmStateTypes.h" |
| #include "cmStringAlgorithms.h" |
| #include "cmSubcommandTable.h" |
| #include "cmSystemTools.h" |
| #include "cmValue.h" |
| #include <cmllpkgc/llpkgc.h> |
| |
| // IWYU wants this |
| namespace { |
| struct ExtractArguments; |
| } |
| |
| namespace { |
| |
| cm::optional<std::string> GetPkgConfigBin(cmMakefile& mf) |
| { |
| cm::optional<std::string> result; |
| |
| auto pkgcfg = mf.GetDefinition("CMAKE_PKG_CONFIG_BIN"); |
| if (pkgcfg.IsNOTFOUND()) { |
| return result; |
| } |
| |
| if (pkgcfg) { |
| result = *pkgcfg; |
| return result; |
| } |
| |
| std::string path = cmSystemTools::FindProgram("pkgconf"); |
| if (path.empty()) { |
| path = cmSystemTools::FindProgram("pkg-config"); |
| if (path.empty()) { |
| mf.AddCacheDefinition("CMAKE_PKG_CONFIG_BIN", "pkg-config-NOTFOUND", |
| "Location of pkg-config or pkgconf binary", |
| cmStateEnums::FILEPATH); |
| return result; |
| } |
| } |
| |
| mf.AddCacheDefinition("CMAKE_PKG_CONFIG_BIN", path, |
| "Location of pkg-config or pkgconf binary", |
| cmStateEnums::FILEPATH); |
| |
| result = std::move(path); |
| return result; |
| } |
| |
| std::vector<std::string> GetLocations(cmMakefile& mf, char const* cachevar, |
| char const* envvar, char const* desc, |
| char const* pcvar, bool need_pkgconf, |
| std::vector<std::string> default_locs) |
| { |
| auto def = mf.GetDefinition(cachevar); |
| if (def) { |
| return cmList(def); |
| } |
| |
| std::string paths; |
| if (cmSystemTools::GetEnv(envvar, paths)) { |
| cmPkgConfigResolver::ReplaceSep(paths); |
| mf.AddCacheDefinition(cachevar, paths, desc, cmStateEnums::STRING); |
| return cmList(paths); |
| } |
| |
| auto pkgcfg = GetPkgConfigBin(mf); |
| if (!pkgcfg || (need_pkgconf && (pkgcfg->find("pkgconf") == pkgcfg->npos))) { |
| mf.AddCacheDefinition(cachevar, cmList::to_string(default_locs), desc, |
| cmStateEnums::STRING); |
| return default_locs; |
| } |
| |
| std::string out; |
| cmSystemTools::RunSingleCommand({ *pkgcfg, pcvar, "pkg-config" }, &out, |
| nullptr, nullptr, nullptr, |
| cmSystemTools::OUTPUT_NONE); |
| |
| cmPkgConfigResolver::ReplaceSep(out); |
| out = cmTrimWhitespace(out); |
| mf.AddCacheDefinition(cachevar, out, desc, cmStateEnums::STRING); |
| return cmList(out); |
| } |
| |
| std::vector<std::string> GetPcLibDirs(cmMakefile& mf) |
| { |
| std::vector<std::string> default_locs = { |
| #ifndef _WIN32 |
| "/usr/lib/pkgconfig", "/usr/share/pkgconfig" |
| #endif |
| }; |
| return GetLocations(mf, "CMAKE_PKG_CONFIG_PC_LIB_DIRS", "PKG_CONFIG_LIBDIR", |
| "Default search locations for package files", |
| "--variable=pc_path", false, std::move(default_locs)); |
| } |
| |
| std::vector<std::string> GetSysLibDirs(cmMakefile& mf) |
| { |
| std::vector<std::string> default_locs = { |
| #ifndef _WIN32 |
| "/lib", "/usr/lib" |
| #endif |
| }; |
| return GetLocations( |
| mf, "CMAKE_PKG_CONFIG_SYS_LIB_DIRS", "PKG_CONFIG_SYSTEM_LIBRARY_PATH", |
| "System library directories filtered by flag mangling", |
| "--variable=pc_system_libdirs", true, std::move(default_locs)); |
| } |
| |
| std::vector<std::string> GetSysCflags(cmMakefile& mf) |
| { |
| std::vector<std::string> default_locs = { |
| #ifndef _WIN32 |
| "/usr/include" |
| #endif |
| }; |
| return GetLocations( |
| mf, "CMAKE_PKG_CONFIG_SYS_INCLUDE_DIRS", "PKG_CONFIG_SYSTEM_INCLUDE_PATH", |
| "System include directories filtered by flag mangling", |
| "--variable=pc_system_includedirs", true, std::move(default_locs)); |
| } |
| |
| std::vector<std::string> GetPkgConfSysLibs(cmMakefile& mf) |
| { |
| auto def = mf.GetDefinition("CMAKE_PKG_CONFIG_PKGCONF_LIB_DIRS"); |
| if (def) { |
| return cmList(def); |
| } |
| |
| std::string paths; |
| if (!cmSystemTools::GetEnv("LIBRARY_PATH", paths)) { |
| return {}; |
| } |
| |
| cmPkgConfigResolver::ReplaceSep(paths); |
| mf.AddCacheDefinition("CMAKE_PKG_CONFIG_PKGCONF_LIB_DIRS", paths, |
| "Additional system library directories filtered by " |
| "flag mangling in PKGCONF mode", |
| cmStateEnums::STRING); |
| return cmList(paths); |
| } |
| |
| std::vector<std::string> GetPkgConfSysCflags(cmMakefile& mf) |
| { |
| auto def = mf.GetDefinition("CMAKE_PKG_CONFIG_PKGCONF_INCLUDES"); |
| if (def) { |
| return cmList(def); |
| } |
| |
| std::string paths; |
| auto get_and_append = [&](char const* var) { |
| if (paths.empty()) { |
| cmSystemTools::GetEnv(var, paths); |
| } else { |
| std::string tmp; |
| cmSystemTools::GetEnv(var, tmp); |
| if (!tmp.empty()) { |
| paths += ";" + tmp; |
| } |
| } |
| }; |
| |
| get_and_append("CPATH"); |
| get_and_append("C_INCLUDE_PATH"); |
| get_and_append("CPLUS_INCLUDE_PATH"); |
| get_and_append("OBJC_INCLUDE_PATH"); |
| |
| #ifdef _WIN32 |
| get_and_append("INCLUDE"); |
| #endif |
| |
| cmPkgConfigResolver::ReplaceSep(paths); |
| mf.AddCacheDefinition("CMAKE_PKG_CONFIG_PKGCONF_INCLUDES", paths, |
| "Additional system include directories filtered by " |
| "flag mangling in PKGCONF mode", |
| cmStateEnums::STRING); |
| return cmList(paths); |
| } |
| |
| std::vector<std::string> GetPcPath(cmMakefile& mf) |
| { |
| auto def = mf.GetDefinition("CMAKE_PKG_CONFIG_PC_PATH"); |
| if (def) { |
| return cmList(def); |
| } |
| |
| std::string pcpath; |
| if (cmSystemTools::GetEnv("PKG_CONFIG_PATH", pcpath)) { |
| auto result = cmSystemTools::SplitString(pcpath, cmPkgConfigResolver::Sep); |
| mf.AddCacheDefinition( |
| "CMAKE_PKG_CONFIG_PC_PATH", cmList::to_string(result), |
| "Additional search locations for package files", cmStateEnums::STRING); |
| return result; |
| } |
| |
| mf.AddCacheDefinition("CMAKE_PKG_CONFIG_PC_PATH", "", |
| "Additional search locations for package files", |
| cmStateEnums::STRING); |
| return {}; |
| } |
| |
| cm::optional<std::string> GetPath(cmMakefile& mf, char const* cachevar, |
| char const* envvar, char const* desc) |
| { |
| cm::optional<std::string> result; |
| |
| auto def = mf.GetDefinition(cachevar); |
| if (def) { |
| result = *def; |
| return result; |
| } |
| |
| std::string path; |
| if (cmSystemTools::GetEnv(envvar, path)) { |
| mf.AddCacheDefinition(cachevar, path, desc, cmStateEnums::FILEPATH); |
| result = std::move(path); |
| return result; |
| } |
| |
| return result; |
| } |
| |
| cm::optional<std::string> GetSysrootDir(cmMakefile& mf) |
| { |
| return GetPath(mf, "CMAKE_PKG_CONFIG_SYSROOT_DIR", "PKG_CONFIG_SYSROOT_DIR", |
| "System root used for re-rooting package includes and " |
| "library directories"); |
| } |
| |
| cm::optional<std::string> GetTopBuildDir(cmMakefile& mf) |
| { |
| return GetPath(mf, "CMAKE_PKG_CONFIG_TOP_BUILD_DIR", |
| "PKG_CONFIG_TOP_BUILD_DIR", |
| "Package file top_build_dir variable default value"); |
| } |
| |
| bool GetBool(cmMakefile& mf, char const* cachevar, char const* envvar, |
| char const* desc) |
| { |
| auto def = mf.GetDefinition(cachevar); |
| if (def) { |
| return def.IsOn(); |
| } |
| |
| if (cmSystemTools::HasEnv(envvar)) { |
| mf.AddCacheDefinition(cachevar, "ON", desc, cmStateEnums::BOOL); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| bool GetDisableUninstalled(cmMakefile& mf) |
| { |
| return GetBool(mf, "CMAKE_PKG_CONFIG_DISABLE_UNINSTALLED", |
| "PKG_CONFIG_DISABLE_UNINSTALLED", |
| "Disable search for `-uninstalled` (build tree) packages"); |
| } |
| |
| bool GetAllowSysLibs(cmMakefile& mf) |
| { |
| return GetBool(mf, "CMAKE_PKG_CONFIG_ALLOW_SYS_LIBS", |
| "PKG_CONFIG_ALLOW_SYSTEM_LIBS", |
| "Allow system library directories during flag mangling"); |
| } |
| |
| bool GetAllowSysInclude(cmMakefile& mf) |
| { |
| return GetBool(mf, "CMAKE_PKG_CONFIG_ALLOW_SYS_INCLUDES", |
| "PKG_CONFIG_ALLOW_SYSTEM_CFLAGS", |
| "Allow system include paths during flag manglging"); |
| } |
| |
| struct CommonArguments : ArgumentParser::ParseResult |
| { |
| bool Required = false; |
| bool Exact = false; |
| bool Quiet = false; |
| |
| enum StrictnessType |
| { |
| STRICTNESS_STRICT, |
| STRICTNESS_PERMISSIVE, |
| STRICTNESS_BEST_EFFORT, |
| }; |
| |
| StrictnessType Strictness = STRICTNESS_PERMISSIVE; |
| std::string StrictnessError; |
| |
| ArgumentParser::Continue SetStrictness(cm::string_view strictness) |
| { |
| if (strictness == "STRICT"_s) { |
| Strictness = STRICTNESS_STRICT; |
| } else if (strictness == "PERMISSIVE"_s) { |
| Strictness = STRICTNESS_PERMISSIVE; |
| } else if (strictness == "BEST_EFFORT"_s) { |
| Strictness = STRICTNESS_BEST_EFFORT; |
| } else { |
| StrictnessError = |
| cmStrCat("Invalid 'STRICTNESS' '", strictness, |
| "'; must be one of 'STRICT', 'PERMISSIVE', or 'BEST_EFFORT'"); |
| } |
| return ArgumentParser::Continue::Yes; |
| } |
| |
| enum EnvModeType |
| { |
| ENVMODE_FDO, |
| ENVMODE_PKGCONF, |
| ENVMODE_IGNORE, |
| }; |
| |
| EnvModeType EnvMode = ENVMODE_PKGCONF; |
| std::string EnvModeError; |
| |
| ArgumentParser::Continue SetEnvMode(cm::string_view envMode) |
| { |
| if (envMode == "FDO"_s) { |
| EnvMode = ENVMODE_FDO; |
| } else if (envMode == "PKGCONF"_s) { |
| EnvMode = ENVMODE_PKGCONF; |
| } else if (envMode == "IGNORE"_s) { |
| EnvMode = ENVMODE_IGNORE; |
| } else { |
| EnvModeError = |
| cmStrCat("Invalid 'ENV_MODE' '", envMode, |
| "'; must be one of 'FDO', 'PKGCONF', or 'IGNORE'"); |
| } |
| return ArgumentParser::Continue::Yes; |
| } |
| |
| cm::optional<std::string> Package; |
| cm::optional<std::string> Version; |
| cm::optional<std::string> SysrootDir; |
| cm::optional<std::string> TopBuildDir; |
| |
| cm::optional<bool> DisableUninstalled; |
| |
| cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> PcPath; |
| cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> PcLibdir; |
| |
| bool CheckArgs(cmExecutionStatus& status) const |
| { |
| |
| if (!Package) { |
| status.SetError("A package name or absolute path must be specified"); |
| return false; |
| } |
| |
| if (!StrictnessError.empty()) { |
| status.SetError(StrictnessError); |
| return false; |
| } |
| |
| if (!EnvModeError.empty()) { |
| status.SetError(EnvModeError); |
| return false; |
| } |
| |
| return true; |
| } |
| }; |
| |
| #define BIND_COMMON(argtype) \ |
| (cmArgumentParser<argtype>{}) \ |
| .Bind(1, &argtype::Package) \ |
| .Bind(2, &argtype::Version) \ |
| .Bind("REQUIRED"_s, &argtype::Required) \ |
| .Bind("EXACT"_s, &argtype::Exact) \ |
| .Bind("QUIET"_s, &argtype::Quiet) \ |
| .Bind("STRICTNESS"_s, &argtype::SetStrictness) \ |
| .Bind("ENV_MODE"_s, &argtype::SetEnvMode) \ |
| .Bind("PC_SYSROOT_DIR"_s, &argtype::SysrootDir) \ |
| .Bind("TOP_BUILD_DIR"_s, &argtype::TopBuildDir) \ |
| .Bind("DISABLE_UNINSTALLED"_s, &argtype::DisableUninstalled) \ |
| .Bind("PC_LIBDIR"_s, &argtype::PcLibdir) \ |
| .Bind("PC_PATH"_s, &argtype::PcPath) |
| |
| void CollectEnv(cmMakefile& mf, cmPkgConfigEnv& env, |
| CommonArguments::EnvModeType mode) |
| { |
| if (mode == CommonArguments::EnvModeType::ENVMODE_IGNORE) { |
| return; |
| } |
| |
| if (!env.Path) { |
| env.Path = GetPcPath(mf); |
| } |
| |
| if (!env.LibDirs) { |
| env.LibDirs = GetPcLibDirs(mf); |
| } |
| |
| if (!env.DisableUninstalled) { |
| env.DisableUninstalled = GetDisableUninstalled(mf); |
| } |
| |
| if (!env.SysrootDir) { |
| env.SysrootDir = GetSysrootDir(mf); |
| } |
| |
| if (!env.TopBuildDir) { |
| env.TopBuildDir = GetTopBuildDir(mf); |
| } |
| |
| env.AllowSysCflags = GetAllowSysInclude(mf); |
| env.SysCflags = GetSysCflags(mf); |
| |
| env.AllowSysLibs = GetAllowSysLibs(mf); |
| env.SysLibs = GetSysLibDirs(mf); |
| |
| if (mode == CommonArguments::EnvModeType::ENVMODE_FDO) { |
| return; |
| } |
| |
| *env.SysCflags += GetPkgConfSysCflags(mf); |
| *env.SysLibs += GetPkgConfSysLibs(mf); |
| } |
| |
| cm::optional<cmPkgConfigResult> HandleCommon(CommonArguments& args, |
| cmExecutionStatus& status) |
| { |
| |
| auto& mf = status.GetMakefile(); |
| |
| if (!args.CheckArgs(status)) { |
| return {}; |
| } |
| |
| 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); |
| |
| if (path.extension() == ".pc") { |
| if (!cmSystemTools::FileExists(path.string())) { |
| warn_or_error(cmStrCat("Could not find '", *args.Package, "'")); |
| return {}; |
| } |
| } else { |
| |
| std::vector<std::string> 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) { |
| auto uninstalled = path; |
| uninstalled.concat("-uninstalled.pc"); |
| uninstalled = |
| cmSystemTools::FindFile(uninstalled.string(), search, true); |
| if (uninstalled.empty()) { |
| path = |
| cmSystemTools::FindFile(path.concat(".pc").string(), search, true); |
| if (path.empty()) { |
| warn_or_error(cmStrCat("Could not find '", *args.Package, "'")); |
| return {}; |
| } |
| } else { |
| path = uninstalled; |
| } |
| } else { |
| path = |
| cmSystemTools::FindFile(path.concat(".pc").string(), search, true); |
| if (path.empty()) { |
| warn_or_error(cmStrCat("Could not find '", *args.Package, "'")); |
| return {}; |
| } |
| } |
| } |
| |
| auto len = cmSystemTools::FileLength(path.string()); |
| |
| // Windows requires this weird string -> c_str dance |
| cmsys::ifstream ifs(path.string().c_str(), std::ios::binary); |
| |
| if (!ifs) { |
| warn_or_error(cmStrCat("Could not open file '", path.string(), "'")); |
| return {}; |
| } |
| |
| std::unique_ptr<char[]> buf(new char[len]); |
| ifs.read(buf.get(), len); |
| |
| // 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 {}; |
| } |
| |
| using StrictnessType = CommonArguments::StrictnessType; |
| |
| cmPkgConfigParser parser; |
| auto err = parser.Finish(buf.get(), len); |
| |
| if (args.Strictness != StrictnessType::STRICTNESS_BEST_EFFORT && |
| err != PCE_OK) { |
| warn_or_error(cmStrCat("Parsing failed for file '", path.string(), "'")); |
| return {}; |
| } |
| |
| cm::optional<cmPkgConfigResult> 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)); |
| } else { |
| result = |
| cmPkgConfigResolver::ResolveBestEffort(parser.Data(), std::move(env)); |
| } |
| |
| if (!result) { |
| warn_or_error( |
| cmStrCat("Resolution failed for file '", path.string(), "'")); |
| } else if (args.Exact) { |
| std::string ver; |
| |
| if (args.Version) { |
| ver = cmPkgConfigResolver::ParseVersion(*args.Version).Version; |
| } |
| |
| if (ver != result->Version()) { |
| warn_or_error( |
| cmStrCat("Package '", *args.Package, "' version '", result->Version(), |
| "' does not meet exact version requirement '", ver, "'")); |
| return {}; |
| } |
| |
| } else if (args.Version) { |
| auto rv = cmPkgConfigResolver::ParseVersion(*args.Version); |
| if (!cmPkgConfigResolver::CheckVersion(rv, result->Version())) { |
| warn_or_error( |
| cmStrCat("Package '", *args.Package, "' version '", result->Version(), |
| "' does not meet version requirement '", *args.Version, "'")); |
| return {}; |
| } |
| } |
| |
| return result; |
| } |
| |
| struct ExtractArguments : CommonArguments |
| { |
| cm::optional<bool> AllowSystemIncludes; |
| cm::optional<bool> AllowSystemLibs; |
| |
| cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> |
| SystemIncludeDirs; |
| cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> |
| SystemLibraryDirs; |
| }; |
| |
| auto const ExtractParser = |
| BIND_COMMON(ExtractArguments) |
| .Bind("ALLOW_SYSTEM_INCLUDES"_s, &ExtractArguments::AllowSystemIncludes) |
| .Bind("ALLOW_SYSTEM_LIBS"_s, &ExtractArguments::AllowSystemLibs) |
| .Bind("SYSTEM_INCLUDE_DIRS"_s, &ExtractArguments::SystemIncludeDirs) |
| .Bind("SYSTEM_LIBRARY_DIRS"_s, &ExtractArguments::SystemLibraryDirs); |
| |
| bool HandleExtractCommand(std::vector<std::string> const& args, |
| cmExecutionStatus& status) |
| { |
| |
| std::vector<std::string> unparsed; |
| auto parsedArgs = ExtractParser.Parse(args, &unparsed); |
| auto maybeResolved = HandleCommon(parsedArgs, status); |
| |
| if (!maybeResolved) { |
| return !parsedArgs.Required; |
| } |
| |
| auto& resolved = *maybeResolved; |
| auto version = resolved.Version(); |
| |
| if (parsedArgs.AllowSystemIncludes) { |
| resolved.env.AllowSysCflags = *parsedArgs.AllowSystemIncludes; |
| } |
| |
| if (parsedArgs.AllowSystemLibs) { |
| resolved.env.AllowSysLibs = *parsedArgs.AllowSystemLibs; |
| } |
| |
| if (parsedArgs.SystemIncludeDirs) { |
| resolved.env.SysCflags = *parsedArgs.SystemIncludeDirs; |
| } |
| |
| if (parsedArgs.SystemLibraryDirs) { |
| resolved.env.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); |
| |
| auto make_list = [&](char const* def, |
| std::vector<cmPkgConfigDependency> const& deps) { |
| std::vector<cm::string_view> vec; |
| vec.reserve(deps.size()); |
| |
| for (auto const& dep : deps) { |
| vec.emplace_back(dep.Name); |
| } |
| |
| 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)); |
| |
| auto cflags = resolved.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); |
| 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(); |
| mf.AddDefinition("CMAKE_PKG_CONFIG_LIBS", libs.Flagline); |
| mf.AddDefinition("CMAKE_PKG_CONFIG_LIBDIRS", |
| cmList::to_string(libs.LibDirs)); |
| mf.AddDefinition("CMAKE_PKG_CONFIG_LIBNAMES", |
| cmList::to_string(libs.LibNames)); |
| mf.AddDefinition("CMAKE_PKG_CONFIG_LINK_OPTIONS", |
| cmList::to_string(libs.LinkOptions)); |
| |
| libs = resolved.Libs(true); |
| mf.AddDefinition("CMAKE_PKG_CONFIG_LIBS_PRIVATE", libs.Flagline); |
| mf.AddDefinition("CMAKE_PKG_CONFIG_LIBDIRS_PRIVATE", |
| cmList::to_string(libs.LibDirs)); |
| mf.AddDefinition("CMAKE_PKG_CONFIG_LIBNAMES_PRIVATE", |
| cmList::to_string(libs.LibNames)); |
| mf.AddDefinition("CMAKE_PKG_CONFIG_LINK_OPTIONS_PRIVATE", |
| cmList::to_string(libs.LinkOptions)); |
| |
| return true; |
| } |
| } // namespace |
| |
| bool cmCMakePkgConfigCommand(std::vector<std::string> const& args, |
| cmExecutionStatus& status) |
| { |
| if (args.size() < 2) { |
| status.SetError("must be called with at least two arguments."); |
| return false; |
| } |
| |
| static cmSubcommandTable const subcommand{ |
| { "EXTRACT"_s, HandleExtractCommand }, |
| }; |
| |
| return subcommand(args[0], args, status); |
| } |