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 this->Validate(this->IncludeFileInPath
? intPath
: fpath
)) {
93 debug
.FoundAt(intPath
);
94 if (this->IncludeFileInPath
) {
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
);
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
) {
114 fheader
.resize(fheader
.size() - file
.size());
118 // No frameworks matched the glob, so nothing more to add to debug.FailedAt()
122 std::string
cmFindPathCommand::FindNormalHeader(cmFindBaseDebugState
& debug
)
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
) {
136 debug
.FailedAt(tryPath
);
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()) {
155 bool cmFindPath(std::vector
<std::string
> const& args
,
156 cmExecutionStatus
& status
)
158 return cmFindPathCommand(status
).InitialPass(args
);