CMake Nightly Date Stamp
[kiteware-cmake.git] / Source / cmFindPathCommand.cxx
blob74a69d80aa58f46bc1b48c0b0f786a63a53cf207
1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmFindPathCommand.h"
5 #include <utility>
7 #include "cmsys/Glob.hxx"
9 #include "cmStateTypes.h"
10 #include "cmStringAlgorithms.h"
11 #include "cmSystemTools.h"
13 class cmExecutionStatus;
15 cmFindPathCommand::cmFindPathCommand(std::string findCommandName,
16 cmExecutionStatus& status)
17 : cmFindBase(std::move(findCommandName), status)
19 this->EnvironmentPath = "INCLUDE";
20 this->IncludeFileInPath = false;
21 this->VariableDocumentation = "Path to a file.";
22 this->VariableType = cmStateEnums::PATH;
24 cmFindPathCommand::cmFindPathCommand(cmExecutionStatus& status)
25 : cmFindPathCommand("find_path", status)
29 // cmFindPathCommand
30 bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn)
32 this->CMakePathName = "INCLUDE";
34 if (!this->ParseArguments(argsIn)) {
35 return false;
38 this->DebugMode = this->ComputeIfDebugModeWanted(this->VariableName);
40 if (this->AlreadyDefined) {
41 this->NormalizeFindResult();
42 return true;
45 std::string result = this->FindHeader();
46 this->StoreFindResult(result);
47 return true;
50 std::string cmFindPathCommand::FindHeader()
52 cmFindBaseDebugState debug(this->FindCommandName, this);
53 std::string header;
54 if (this->SearchFrameworkFirst || this->SearchFrameworkOnly) {
55 header = this->FindFrameworkHeader(debug);
57 if (header.empty() && !this->SearchFrameworkOnly) {
58 header = this->FindNormalHeader(debug);
60 if (header.empty() && this->SearchFrameworkLast) {
61 header = this->FindFrameworkHeader(debug);
64 return header;
67 std::string cmFindPathCommand::FindHeaderInFramework(
68 std::string const& file, std::string const& dir,
69 cmFindBaseDebugState& debug) const
71 std::string fileName = file;
72 std::string frameWorkName;
73 std::string::size_type pos = fileName.find('/');
74 // if there is a / in the name try to find the header as a framework
75 // For example bar/foo.h would look for:
76 // bar.framework/Headers/foo.h
77 if (pos != std::string::npos) {
78 // remove the name from the slash;
79 fileName = fileName.substr(pos + 1);
80 frameWorkName = file;
81 frameWorkName =
82 frameWorkName.substr(0, frameWorkName.size() - fileName.size() - 1);
83 // if the framework has a path in it then just use the filename
84 if (frameWorkName.find('/') != std::string::npos) {
85 fileName = file;
86 frameWorkName.clear();
88 if (!frameWorkName.empty()) {
89 std::string fpath = cmStrCat(dir, frameWorkName, ".framework");
90 std::string intPath = cmStrCat(fpath, "/Headers/", fileName);
91 if (cmSystemTools::FileExists(intPath) &&
92 this->Validate(this->IncludeFileInPath ? intPath : fpath)) {
93 debug.FoundAt(intPath);
94 if (this->IncludeFileInPath) {
95 return intPath;
97 return fpath;
99 debug.FailedAt(intPath);
102 // if it is not found yet or not a framework header, then do a glob search
103 // for all frameworks in the directory: dir/*.framework/Headers/<file>
104 std::string glob = cmStrCat(dir, "*.framework/Headers/", file);
105 cmsys::Glob globIt;
106 globIt.FindFiles(glob);
107 std::vector<std::string> files = globIt.GetFiles();
108 if (!files.empty()) {
109 std::string fheader = cmSystemTools::CollapseFullPath(files[0]);
110 debug.FoundAt(fheader);
111 if (this->IncludeFileInPath) {
112 return fheader;
114 fheader.resize(fheader.size() - file.size());
115 return fheader;
118 // No frameworks matched the glob, so nothing more to add to debug.FailedAt()
119 return "";
122 std::string cmFindPathCommand::FindNormalHeader(cmFindBaseDebugState& debug)
124 std::string tryPath;
125 for (std::string const& n : this->Names) {
126 for (std::string const& sp : this->SearchPaths) {
127 tryPath = cmStrCat(sp, n);
128 if (cmSystemTools::FileExists(tryPath) &&
129 this->Validate(this->IncludeFileInPath ? tryPath : sp)) {
130 debug.FoundAt(tryPath);
131 if (this->IncludeFileInPath) {
132 return tryPath;
134 return sp;
136 debug.FailedAt(tryPath);
139 return "";
142 std::string cmFindPathCommand::FindFrameworkHeader(cmFindBaseDebugState& debug)
144 for (std::string const& n : this->Names) {
145 for (std::string const& sp : this->SearchPaths) {
146 std::string fwPath = this->FindHeaderInFramework(n, sp, debug);
147 if (!fwPath.empty()) {
148 return fwPath;
152 return "";
155 bool cmFindPath(std::vector<std::string> const& args,
156 cmExecutionStatus& status)
158 return cmFindPathCommand(status).InitialPass(args);