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"
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)
30 bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn)
32 this->CMakePathName = "INCLUDE";
34 if (!this->ParseArguments(argsIn)) {
38 this->DebugMode = this->ComputeIfDebugModeWanted(this->VariableName);
40 if (this->AlreadyDefined) {
41 this->NormalizeFindResult();
45 std::string result = this->FindHeader();
46 this->StoreFindResult(result);
50 std::string cmFindPathCommand::FindHeader()
52 cmFindBaseDebugState debug(this->FindCommandName, this);
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);
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);
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) {
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 debug.FoundAt(intPath);
93 if (this->IncludeFileInPath) {
98 debug.FailedAt(intPath);
101 // if it is not found yet or not a framework header, then do a glob search
102 // for all frameworks in the directory: dir/*.framework/Headers/<file>
103 std::string glob = cmStrCat(dir, "*.framework/Headers/", file);
105 globIt.FindFiles(glob);
106 std::vector<std::string> files = globIt.GetFiles();
107 if (!files.empty()) {
108 std::string fheader = cmSystemTools::CollapseFullPath(files[0]);
109 debug.FoundAt(fheader);
110 if (this->IncludeFileInPath) {
113 fheader.resize(fheader.size() - file.size());
117 // No frameworks matched the glob, so nothing more to add to debug.FailedAt()
121 std::string cmFindPathCommand::FindNormalHeader(cmFindBaseDebugState& debug)
124 for (std::string const& n : this->Names) {
125 for (std::string const& sp : this->SearchPaths) {
126 tryPath = cmStrCat(sp, n);
127 if (cmSystemTools::FileExists(tryPath)) {
128 debug.FoundAt(tryPath);
129 if (this->IncludeFileInPath) {
134 debug.FailedAt(tryPath);
140 std::string cmFindPathCommand::FindFrameworkHeader(cmFindBaseDebugState& debug)
142 for (std::string const& n : this->Names) {
143 for (std::string const& sp : this->SearchPaths) {
144 std::string fwPath = this->FindHeaderInFramework(n, sp, debug);
145 if (!fwPath.empty()) {
153 bool cmFindPath(std::vector<std::string> const& args,
154 cmExecutionStatus& status)
156 return cmFindPathCommand(status).InitialPass(args);