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 "cmGetFilenameComponentCommand.h"
5 #include "cmExecutionStatus.h"
6 #include "cmMakefile.h"
7 #include "cmStateTypes.h"
8 #include "cmStringAlgorithms.h"
9 #include "cmSystemTools.h"
12 // cmGetFilenameComponentCommand
13 bool cmGetFilenameComponentCommand(std::vector
<std::string
> const& args
,
14 cmExecutionStatus
& status
)
16 if (args
.size() < 3) {
17 status
.SetError("called with incorrect number of arguments");
18 cmSystemTools::SetFatalErrorOccurred();
22 // Check and see if the value has been stored in the cache
23 // already, if so use that value
24 if (args
.size() >= 4 && args
.back() == "CACHE") {
25 cmValue cacheValue
= status
.GetMakefile().GetDefinition(args
.front());
26 if (cacheValue
&& !cmIsNOTFOUND(*cacheValue
)) {
32 std::string filename
= args
[1];
33 if (filename
.find("[HKEY") != std::string::npos
) {
34 // Check the registry as the target application would view it.
35 cmSystemTools::KeyWOW64 view
= cmSystemTools::KeyWOW64_32
;
36 cmSystemTools::KeyWOW64 other_view
= cmSystemTools::KeyWOW64_64
;
37 if (status
.GetMakefile().PlatformIs64Bit()) {
38 view
= cmSystemTools::KeyWOW64_64
;
39 other_view
= cmSystemTools::KeyWOW64_32
;
41 cmSystemTools::ExpandRegistryValues(filename
, view
);
42 if (filename
.find("/registry") != std::string::npos
) {
43 std::string other
= args
[1];
44 cmSystemTools::ExpandRegistryValues(other
, other_view
);
45 if (other
.find("/registry") == std::string::npos
) {
50 std::string storeArgs
;
51 std::string programArgs
;
52 if (args
[2] == "DIRECTORY" || args
[2] == "PATH") {
53 result
= cmSystemTools::GetFilenamePath(filename
);
54 } else if (args
[2] == "NAME") {
55 result
= cmSystemTools::GetFilenameName(filename
);
56 } else if (args
[2] == "PROGRAM") {
57 for (unsigned int i
= 2; i
< args
.size(); ++i
) {
58 if (args
[i
] == "PROGRAM_ARGS") {
60 if (i
< args
.size()) {
66 // First assume the path to the program was specified with no
67 // arguments and with no quoting or escaping for spaces.
68 // Only bother doing this if there is non-whitespace.
69 if (!cmTrimWhitespace(filename
).empty()) {
70 result
= cmSystemTools::FindProgram(filename
);
73 // If that failed then assume a command-line string was given
74 // and split the program part from the rest of the arguments.
77 if (cmSystemTools::SplitProgramFromArgs(filename
, program
,
79 if (cmSystemTools::FileExists(program
)) {
82 result
= cmSystemTools::FindProgram(program
);
89 } else if (args
[2] == "EXT") {
90 result
= cmSystemTools::GetFilenameExtension(filename
);
91 } else if (args
[2] == "NAME_WE") {
92 result
= cmSystemTools::GetFilenameWithoutExtension(filename
);
93 } else if (args
[2] == "LAST_EXT") {
94 result
= cmSystemTools::GetFilenameLastExtension(filename
);
95 } else if (args
[2] == "NAME_WLE") {
96 result
= cmSystemTools::GetFilenameWithoutLastExtension(filename
);
97 } else if (args
[2] == "ABSOLUTE" || args
[2] == "REALPATH") {
98 // If the path given is relative, evaluate it relative to the
99 // current source directory unless the user passes a different
101 std::string baseDir
= status
.GetMakefile().GetCurrentSourceDirectory();
102 for (unsigned int i
= 3; i
< args
.size(); ++i
) {
103 if (args
[i
] == "BASE_DIR") {
105 if (i
< args
.size()) {
110 // Collapse the path to its simplest form.
111 result
= cmSystemTools::CollapseFullPath(filename
, baseDir
);
112 if (args
[2] == "REALPATH") {
113 // Resolve symlinks if possible
114 result
= cmSystemTools::GetRealPath(result
);
117 std::string err
= "unknown component " + args
[2];
118 status
.SetError(err
);
119 cmSystemTools::SetFatalErrorOccurred();
123 if (args
.size() >= 4 && args
.back() == "CACHE") {
124 if (!programArgs
.empty() && !storeArgs
.empty()) {
125 status
.GetMakefile().AddCacheDefinition(
126 storeArgs
, programArgs
, "",
127 args
[2] == "PATH" ? cmStateEnums::FILEPATH
: cmStateEnums::STRING
);
129 status
.GetMakefile().AddCacheDefinition(
130 args
.front(), result
, "",
131 args
[2] == "PATH" ? cmStateEnums::FILEPATH
: cmStateEnums::STRING
);
133 if (!programArgs
.empty() && !storeArgs
.empty()) {
134 status
.GetMakefile().AddDefinition(storeArgs
, programArgs
);
136 status
.GetMakefile().AddDefinition(args
.front(), result
);