Merge branch 'release-3.29'
[kiteware-cmake.git] / Source / cmGetFilenameComponentCommand.cxx
blob1815c4d1c41f42e913a502514aad9ad3ee3bf1a5
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"
10 #include "cmValue.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();
19 return false;
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)) {
27 return true;
31 std::string result;
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) {
46 filename = other;
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") {
59 i++;
60 if (i < args.size()) {
61 storeArgs = args[i];
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.
75 if (result.empty()) {
76 std::string program;
77 if (cmSystemTools::SplitProgramFromArgs(filename, program,
78 programArgs)) {
79 if (cmSystemTools::FileExists(program)) {
80 result = program;
81 } else {
82 result = cmSystemTools::FindProgram(program);
85 if (result.empty()) {
86 programArgs.clear();
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
100 // base directory.
101 std::string baseDir = status.GetMakefile().GetCurrentSourceDirectory();
102 for (unsigned int i = 3; i < args.size(); ++i) {
103 if (args[i] == "BASE_DIR") {
104 ++i;
105 if (i < args.size()) {
106 baseDir = args[i];
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);
116 } else {
117 std::string err = "unknown component " + args[2];
118 status.SetError(err);
119 cmSystemTools::SetFatalErrorOccurred();
120 return false;
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);
132 } else {
133 if (!programArgs.empty() && !storeArgs.empty()) {
134 status.GetMakefile().AddDefinition(storeArgs, programArgs);
136 status.GetMakefile().AddDefinition(args.front(), result);
139 return true;