cmRulePlaceholderExpander.cxx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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 "cmRulePlaceholderExpander.h"
  4. #include <utility>
  5. #include "cmOutputConverter.h"
  6. #include "cmStringAlgorithms.h"
  7. #include "cmSystemTools.h"
  8. cmRulePlaceholderExpander::cmRulePlaceholderExpander(
  9. cmBuildStep buildStep, std::map<std::string, std::string> compilers,
  10. std::map<std::string, std::string> variableMappings,
  11. std::string compilerSysroot, std::string linkerSysroot)
  12. : BuildStep(buildStep)
  13. , Compilers(std::move(compilers))
  14. , VariableMappings(std::move(variableMappings))
  15. , CompilerSysroot(std::move(compilerSysroot))
  16. , LinkerSysroot(std::move(linkerSysroot))
  17. {
  18. }
  19. std::string cmRulePlaceholderExpander::ExpandVariable(
  20. std::string const& variable)
  21. {
  22. if (this->ReplaceValues->LinkFlags) {
  23. if (variable == "LINK_FLAGS") {
  24. return this->ReplaceValues->LinkFlags;
  25. }
  26. }
  27. if (this->ReplaceValues->Linker) {
  28. if (variable == "CMAKE_LINKER") {
  29. auto result = this->OutputConverter->ConvertToOutputForExisting(
  30. this->ReplaceValues->Linker);
  31. if (this->ReplaceValues->Launcher) {
  32. // Add launcher as part of expansion so that it always appears
  33. // immediately before the command itself, regardless of whether the
  34. // overall rule template contains other content at the front.
  35. result = cmStrCat(this->ReplaceValues->Launcher, " ", result);
  36. }
  37. return result;
  38. }
  39. }
  40. if (this->ReplaceValues->Manifests) {
  41. if (variable == "MANIFESTS") {
  42. return this->ReplaceValues->Manifests;
  43. }
  44. }
  45. if (this->ReplaceValues->Flags) {
  46. if (variable == "FLAGS") {
  47. return this->ReplaceValues->Flags;
  48. }
  49. }
  50. if (this->ReplaceValues->Source) {
  51. if (variable == "SOURCE") {
  52. return this->ReplaceValues->Source;
  53. }
  54. }
  55. if (this->ReplaceValues->DynDepFile) {
  56. if (variable == "DYNDEP_FILE") {
  57. return this->ReplaceValues->DynDepFile;
  58. }
  59. }
  60. if (this->ReplaceValues->PreprocessedSource) {
  61. if (variable == "PREPROCESSED_SOURCE") {
  62. return this->ReplaceValues->PreprocessedSource;
  63. }
  64. }
  65. if (this->ReplaceValues->AssemblySource) {
  66. if (variable == "ASSEMBLY_SOURCE") {
  67. return this->ReplaceValues->AssemblySource;
  68. }
  69. }
  70. if (this->ReplaceValues->Object) {
  71. if (variable == "OBJECT") {
  72. return this->ReplaceValues->Object;
  73. }
  74. }
  75. if (this->ReplaceValues->ObjectDir) {
  76. if (variable == "OBJECT_DIR") {
  77. return this->ReplaceValues->ObjectDir;
  78. }
  79. }
  80. if (this->ReplaceValues->ObjectFileDir) {
  81. if (variable == "OBJECT_FILE_DIR") {
  82. return this->ReplaceValues->ObjectFileDir;
  83. }
  84. }
  85. if (this->ReplaceValues->Objects) {
  86. if (variable == "OBJECTS") {
  87. return this->ReplaceValues->Objects;
  88. }
  89. }
  90. if (this->ReplaceValues->ObjectsQuoted) {
  91. if (variable == "OBJECTS_QUOTED") {
  92. return this->ReplaceValues->ObjectsQuoted;
  93. }
  94. }
  95. if (this->ReplaceValues->CudaCompileMode) {
  96. if (variable == "CUDA_COMPILE_MODE") {
  97. return this->ReplaceValues->CudaCompileMode;
  98. }
  99. }
  100. if (this->ReplaceValues->AIXExports) {
  101. if (variable == "AIX_EXPORTS") {
  102. return this->ReplaceValues->AIXExports;
  103. }
  104. }
  105. if (this->ReplaceValues->ISPCHeader) {
  106. if (variable == "ISPC_HEADER") {
  107. return this->ReplaceValues->ISPCHeader;
  108. }
  109. }
  110. if (this->ReplaceValues->Defines && variable == "DEFINES") {
  111. return this->ReplaceValues->Defines;
  112. }
  113. if (this->ReplaceValues->Includes && variable == "INCLUDES") {
  114. return this->ReplaceValues->Includes;
  115. }
  116. if (this->ReplaceValues->SwiftLibraryName) {
  117. if (variable == "SWIFT_LIBRARY_NAME") {
  118. return this->ReplaceValues->SwiftLibraryName;
  119. }
  120. }
  121. if (this->ReplaceValues->SwiftModule) {
  122. if (variable == "SWIFT_MODULE") {
  123. return this->ReplaceValues->SwiftModule;
  124. }
  125. }
  126. if (this->ReplaceValues->SwiftModuleName) {
  127. if (variable == "SWIFT_MODULE_NAME") {
  128. return this->ReplaceValues->SwiftModuleName;
  129. }
  130. }
  131. if (this->ReplaceValues->SwiftSources) {
  132. if (variable == "SWIFT_SOURCES") {
  133. return this->ReplaceValues->SwiftSources;
  134. }
  135. }
  136. if (this->ReplaceValues->TargetPDB) {
  137. if (variable == "TARGET_PDB") {
  138. return this->ReplaceValues->TargetPDB;
  139. }
  140. }
  141. if (this->ReplaceValues->TargetCompilePDB) {
  142. if (variable == "TARGET_COMPILE_PDB") {
  143. return this->ReplaceValues->TargetCompilePDB;
  144. }
  145. }
  146. if (this->ReplaceValues->DependencyFile) {
  147. if (variable == "DEP_FILE") {
  148. return this->ReplaceValues->DependencyFile;
  149. }
  150. }
  151. if (this->ReplaceValues->DependencyTarget) {
  152. if (variable == "DEP_TARGET") {
  153. return this->ReplaceValues->DependencyTarget;
  154. }
  155. }
  156. if (this->ReplaceValues->Fatbinary) {
  157. if (variable == "FATBINARY") {
  158. return this->ReplaceValues->Fatbinary;
  159. }
  160. }
  161. if (this->ReplaceValues->RegisterFile) {
  162. if (variable == "REGISTER_FILE") {
  163. return this->ReplaceValues->RegisterFile;
  164. }
  165. }
  166. if (this->ReplaceValues->Target) {
  167. if (variable == "TARGET_QUOTED") {
  168. std::string targetQuoted = this->ReplaceValues->Target;
  169. if (!targetQuoted.empty() && targetQuoted.front() != '\"') {
  170. targetQuoted = '\"';
  171. targetQuoted += this->ReplaceValues->Target;
  172. targetQuoted += '\"';
  173. }
  174. return targetQuoted;
  175. }
  176. if (variable == "TARGET_UNQUOTED") {
  177. std::string unquoted = this->ReplaceValues->Target;
  178. std::string::size_type sz = unquoted.size();
  179. if (sz > 2 && unquoted.front() == '\"' && unquoted.back() == '\"') {
  180. unquoted = unquoted.substr(1, sz - 2);
  181. }
  182. return unquoted;
  183. }
  184. if (this->ReplaceValues->LanguageCompileFlags) {
  185. if (variable == "LANGUAGE_COMPILE_FLAGS") {
  186. return this->ReplaceValues->LanguageCompileFlags;
  187. }
  188. }
  189. if (this->ReplaceValues->Target) {
  190. if (variable == "TARGET") {
  191. return this->ReplaceValues->Target;
  192. }
  193. }
  194. if (variable == "TARGET_IMPLIB") {
  195. return this->TargetImpLib;
  196. }
  197. if (variable == "TARGET_VERSION_MAJOR") {
  198. if (this->ReplaceValues->TargetVersionMajor) {
  199. return this->ReplaceValues->TargetVersionMajor;
  200. }
  201. return "0";
  202. }
  203. if (variable == "TARGET_VERSION_MINOR") {
  204. if (this->ReplaceValues->TargetVersionMinor) {
  205. return this->ReplaceValues->TargetVersionMinor;
  206. }
  207. return "0";
  208. }
  209. if (this->ReplaceValues->Target) {
  210. if (variable == "TARGET_BASE") {
  211. // Strip the last extension off the target name.
  212. std::string targetBase = this->ReplaceValues->Target;
  213. std::string::size_type pos = targetBase.rfind('.');
  214. if (pos != std::string::npos) {
  215. return targetBase.substr(0, pos);
  216. }
  217. return targetBase;
  218. }
  219. }
  220. }
  221. if (variable == "TARGET_SONAME" || variable == "SONAME_FLAG" ||
  222. variable == "TARGET_INSTALLNAME_DIR") {
  223. // All these variables depend on TargetSOName
  224. if (this->ReplaceValues->TargetSOName) {
  225. if (variable == "TARGET_SONAME") {
  226. return this->ReplaceValues->TargetSOName;
  227. }
  228. if (variable == "SONAME_FLAG" && this->ReplaceValues->SONameFlag) {
  229. return this->ReplaceValues->SONameFlag;
  230. }
  231. if (this->ReplaceValues->TargetInstallNameDir &&
  232. variable == "TARGET_INSTALLNAME_DIR") {
  233. return this->ReplaceValues->TargetInstallNameDir;
  234. }
  235. }
  236. return "";
  237. }
  238. if (this->ReplaceValues->LinkLibraries) {
  239. if (variable == "LINK_LIBRARIES") {
  240. return this->ReplaceValues->LinkLibraries;
  241. }
  242. }
  243. if (this->ReplaceValues->Language) {
  244. if (variable == "LANGUAGE") {
  245. return this->ReplaceValues->Language;
  246. }
  247. }
  248. if (this->ReplaceValues->CMTargetName) {
  249. if (variable == "TARGET_NAME") {
  250. return this->ReplaceValues->CMTargetName;
  251. }
  252. }
  253. if (this->ReplaceValues->CMTargetType) {
  254. if (variable == "TARGET_TYPE") {
  255. return this->ReplaceValues->CMTargetType;
  256. }
  257. }
  258. if (this->ReplaceValues->Output) {
  259. if (variable == "OUTPUT") {
  260. return this->ReplaceValues->Output;
  261. }
  262. }
  263. if (variable == "CMAKE_COMMAND") {
  264. return this->OutputConverter->ConvertToOutputFormat(
  265. cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
  266. }
  267. auto compIt = this->Compilers.find(variable);
  268. if (compIt != this->Compilers.end()) {
  269. std::string ret = this->OutputConverter->ConvertToOutputForExisting(
  270. this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER"]);
  271. std::string const& compilerArg1 =
  272. this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER_ARG1"];
  273. std::string const& compilerTarget =
  274. this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER_TARGET"];
  275. std::string const& compilerOptionTarget =
  276. this->VariableMappings["CMAKE_" + compIt->second +
  277. "_COMPILE_OPTIONS_TARGET"];
  278. std::string const& compilerExternalToolchain =
  279. this->VariableMappings["CMAKE_" + compIt->second +
  280. "_COMPILER_EXTERNAL_TOOLCHAIN"];
  281. std::string const& compilerOptionExternalToolchain =
  282. this->VariableMappings["CMAKE_" + compIt->second +
  283. "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN"];
  284. std::string const& compilerOptionSysroot =
  285. this->VariableMappings["CMAKE_" + compIt->second +
  286. "_COMPILE_OPTIONS_SYSROOT"];
  287. if (compIt->second == this->ReplaceValues->Language &&
  288. this->ReplaceValues->Launcher) {
  289. // Add launcher as part of expansion so that it always appears
  290. // immediately before the command itself, regardless of whether the
  291. // overall rule template contains other content at the front.
  292. ret = cmStrCat(this->ReplaceValues->Launcher, " ", ret);
  293. }
  294. // if there are required arguments to the compiler add it
  295. // to the compiler string
  296. if (!compilerArg1.empty()) {
  297. ret += " ";
  298. ret += compilerArg1;
  299. }
  300. if (!compilerTarget.empty() && !compilerOptionTarget.empty()) {
  301. ret += " ";
  302. ret += compilerOptionTarget;
  303. ret += compilerTarget;
  304. }
  305. if (!compilerExternalToolchain.empty() &&
  306. !compilerOptionExternalToolchain.empty()) {
  307. ret += " ";
  308. ret += compilerOptionExternalToolchain;
  309. ret +=
  310. this->OutputConverter->EscapeForShell(compilerExternalToolchain, true);
  311. }
  312. std::string sysroot;
  313. // Some platforms may use separate sysroots for compiling and linking.
  314. // When the build step is link, pass the link sysroot instead.
  315. if (this->BuildStep == cmBuildStep::Link) {
  316. sysroot = this->LinkerSysroot;
  317. } else {
  318. sysroot = this->CompilerSysroot;
  319. }
  320. if (!sysroot.empty() && !compilerOptionSysroot.empty()) {
  321. ret += " ";
  322. ret += compilerOptionSysroot;
  323. ret += this->OutputConverter->EscapeForShell(sysroot, true);
  324. }
  325. return ret;
  326. }
  327. auto mapIt = this->VariableMappings.find(variable);
  328. if (mapIt != this->VariableMappings.end()) {
  329. if (variable.find("_FLAG") == std::string::npos) {
  330. return this->OutputConverter->ConvertToOutputForExisting(mapIt->second);
  331. }
  332. return mapIt->second;
  333. }
  334. return variable;
  335. }
  336. void cmRulePlaceholderExpander::ExpandRuleVariables(
  337. cmOutputConverter* outputConverter, std::string& s,
  338. const RuleVariables& replaceValues)
  339. {
  340. this->OutputConverter = outputConverter;
  341. this->ReplaceValues = &replaceValues;
  342. this->ExpandVariables(s);
  343. }