| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file Copyright.txt or https://cmake.org/licensing for details. */ |
| #include "cmFindPathCommand.h" |
| |
| #include <utility> |
| |
| #include "cmsys/Glob.hxx" |
| |
| #include "cmStateTypes.h" |
| #include "cmStringAlgorithms.h" |
| #include "cmSystemTools.h" |
| |
| class cmExecutionStatus; |
| |
| cmFindPathCommand::cmFindPathCommand(std::string findCommandName, |
| cmExecutionStatus& status) |
| : cmFindBase(std::move(findCommandName), status) |
| { |
| this->EnvironmentPath = "INCLUDE"; |
| this->IncludeFileInPath = false; |
| this->VariableDocumentation = "Path to a file."; |
| this->VariableType = cmStateEnums::PATH; |
| } |
| cmFindPathCommand::cmFindPathCommand(cmExecutionStatus& status) |
| : cmFindPathCommand("find_path", status) |
| { |
| } |
| |
| // cmFindPathCommand |
| bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn) |
| { |
| this->DebugMode = this->ComputeIfDebugModeWanted(); |
| this->CMakePathName = "INCLUDE"; |
| |
| if (!this->ParseArguments(argsIn)) { |
| return false; |
| } |
| |
| if (this->AlreadyDefined) { |
| this->NormalizeFindResult(); |
| return true; |
| } |
| |
| std::string result = this->FindHeader(); |
| this->StoreFindResult(result); |
| return true; |
| } |
| |
| std::string cmFindPathCommand::FindHeader() |
| { |
| cmFindBaseDebugState debug(this->FindCommandName, this); |
| std::string header; |
| if (this->SearchFrameworkFirst || this->SearchFrameworkOnly) { |
| header = this->FindFrameworkHeader(debug); |
| } |
| if (header.empty() && !this->SearchFrameworkOnly) { |
| header = this->FindNormalHeader(debug); |
| } |
| if (header.empty() && this->SearchFrameworkLast) { |
| header = this->FindFrameworkHeader(debug); |
| } |
| |
| return header; |
| } |
| |
| std::string cmFindPathCommand::FindHeaderInFramework( |
| std::string const& file, std::string const& dir) const |
| { |
| std::string fileName = file; |
| std::string frameWorkName; |
| std::string::size_type pos = fileName.find('/'); |
| // if there is a / in the name try to find the header as a framework |
| // For example bar/foo.h would look for: |
| // bar.framework/Headers/foo.h |
| if (pos != std::string::npos) { |
| // remove the name from the slash; |
| fileName = fileName.substr(pos + 1); |
| frameWorkName = file; |
| frameWorkName = |
| frameWorkName.substr(0, frameWorkName.size() - fileName.size() - 1); |
| // if the framework has a path in it then just use the filename |
| if (frameWorkName.find('/') != std::string::npos) { |
| fileName = file; |
| frameWorkName.clear(); |
| } |
| if (!frameWorkName.empty()) { |
| std::string fpath = cmStrCat(dir, frameWorkName, ".framework"); |
| std::string intPath = cmStrCat(fpath, "/Headers/", fileName); |
| if (cmSystemTools::FileExists(intPath)) { |
| if (this->IncludeFileInPath) { |
| return intPath; |
| } |
| return fpath; |
| } |
| } |
| } |
| // if it is not found yet or not a framework header, then do a glob search |
| // for all frameworks in the directory: dir/*.framework/Headers/<file> |
| std::string glob = cmStrCat(dir, "*.framework/Headers/", file); |
| cmsys::Glob globIt; |
| globIt.FindFiles(glob); |
| std::vector<std::string> files = globIt.GetFiles(); |
| if (!files.empty()) { |
| std::string fheader = cmSystemTools::CollapseFullPath(files[0]); |
| if (this->IncludeFileInPath) { |
| return fheader; |
| } |
| fheader.resize(fheader.size() - file.size()); |
| return fheader; |
| } |
| return ""; |
| } |
| |
| std::string cmFindPathCommand::FindNormalHeader(cmFindBaseDebugState& debug) |
| { |
| std::string tryPath; |
| for (std::string const& n : this->Names) { |
| for (std::string const& sp : this->SearchPaths) { |
| tryPath = cmStrCat(sp, n); |
| if (cmSystemTools::FileExists(tryPath)) { |
| debug.FoundAt(tryPath); |
| if (this->IncludeFileInPath) { |
| return tryPath; |
| } |
| return sp; |
| } |
| debug.FailedAt(tryPath); |
| } |
| } |
| return ""; |
| } |
| |
| std::string cmFindPathCommand::FindFrameworkHeader(cmFindBaseDebugState& debug) |
| { |
| for (std::string const& n : this->Names) { |
| for (std::string const& sp : this->SearchPaths) { |
| std::string fwPath = this->FindHeaderInFramework(n, sp); |
| fwPath.empty() ? debug.FailedAt(fwPath) : debug.FoundAt(fwPath); |
| if (!fwPath.empty()) { |
| return fwPath; |
| } |
| } |
| } |
| return ""; |
| } |
| |
| bool cmFindPath(std::vector<std::string> const& args, |
| cmExecutionStatus& status) |
| { |
| return cmFindPathCommand(status).InitialPass(args); |
| } |