3849c6fa428747369862c80d832c3e594319452f
[platform/upstream/cmake.git] / Source / cmMakefileExecutableTargetGenerator.cxx
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 "cmMakefileExecutableTargetGenerator.h"
4
5 #include <set>
6 #include <sstream>
7 #include <string>
8 #include <utility>
9 #include <vector>
10
11 #include <cm/memory>
12 #include <cmext/algorithm>
13
14 #include "cmGeneratedFileStream.h"
15 #include "cmGeneratorTarget.h"
16 #include "cmGlobalUnixMakefileGenerator3.h"
17 #include "cmLinkLineComputer.h"
18 #include "cmLinkLineDeviceComputer.h"
19 #include "cmLocalGenerator.h"
20 #include "cmLocalUnixMakefileGenerator3.h"
21 #include "cmMakefile.h"
22 #include "cmOSXBundleGenerator.h"
23 #include "cmOutputConverter.h"
24 #include "cmRulePlaceholderExpander.h"
25 #include "cmState.h"
26 #include "cmStateDirectory.h"
27 #include "cmStateSnapshot.h"
28 #include "cmStateTypes.h"
29 #include "cmStringAlgorithms.h"
30 #include "cmSystemTools.h"
31 #include "cmValue.h"
32
33 cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator(
34   cmGeneratorTarget* target)
35   : cmMakefileTargetGenerator(target)
36 {
37   this->CustomCommandDriver = OnDepends;
38   this->TargetNames =
39     this->GeneratorTarget->GetExecutableNames(this->GetConfigName());
40
41   this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target);
42   this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
43 }
44
45 cmMakefileExecutableTargetGenerator::~cmMakefileExecutableTargetGenerator() =
46   default;
47
48 void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
49 {
50   // create the build.make file and directory, put in the common blocks
51   this->CreateRuleFile();
52
53   // write rules used to help build object files
54   this->WriteCommonCodeRules();
55
56   // write the per-target per-language flags
57   this->WriteTargetLanguageFlags();
58
59   // write in rules for object files and custom commands
60   this->WriteTargetBuildRules();
61
62   // write the device link rules
63   this->WriteDeviceExecutableRule(false);
64
65   // write the link rules
66   this->WriteExecutableRule(false);
67   if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->GetConfigName())) {
68     // Write rules to link an installable version of the target.
69     this->WriteExecutableRule(true);
70   }
71
72   // Write clean target
73   this->WriteTargetCleanRules();
74
75   // Write the dependency generation rule.  This must be done last so
76   // that multiple output pair information is available.
77   this->WriteTargetDependRules();
78
79   // close the streams
80   this->CloseFileStreams();
81 }
82
83 void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
84   bool relink)
85 {
86 #ifndef CMAKE_BOOTSTRAP
87   const bool requiresDeviceLinking = requireDeviceLinking(
88     *this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName());
89   if (!requiresDeviceLinking) {
90     return;
91   }
92
93   std::vector<std::string> commands;
94
95   // Get the name of the device object to generate.
96   std::string const& objExt =
97     this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION");
98   std::string const targetOutput =
99     this->GeneratorTarget->ObjectDirectory + "cmake_device_link" + objExt;
100   this->DeviceLinkObject = targetOutput;
101
102   this->NumberOfProgressActions++;
103   if (!this->NoRuleMessages) {
104     cmLocalUnixMakefileGenerator3::EchoProgress progress;
105     this->MakeEchoProgress(progress);
106     // Add the link message.
107     std::string buildEcho = cmStrCat(
108       "Linking CUDA device code ",
109       this->LocalGenerator->ConvertToOutputFormat(
110         this->LocalGenerator->MaybeRelativeToCurBinDir(this->DeviceLinkObject),
111         cmOutputConverter::SHELL));
112     this->LocalGenerator->AppendEcho(
113       commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
114   }
115
116   if (this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID") == "Clang") {
117     this->WriteDeviceLinkRule(commands, targetOutput);
118   } else {
119     this->WriteNvidiaDeviceExecutableRule(relink, commands, targetOutput);
120   }
121
122   // Write the main driver rule to build everything in this target.
123   this->WriteTargetDriverRule(targetOutput, relink);
124 #else
125   static_cast<void>(relink);
126 #endif
127 }
128
129 void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
130   bool relink, std::vector<std::string>& commands,
131   const std::string& targetOutput)
132 {
133   const std::string linkLanguage = "CUDA";
134
135   // Build list of dependencies.
136   std::vector<std::string> depends;
137   this->AppendLinkDepends(depends, linkLanguage);
138
139   // Build a list of compiler flags and linker flags.
140   std::string langFlags;
141   std::string linkFlags;
142
143   // Add language feature flags.
144   this->LocalGenerator->AddLanguageFlagsForLinking(
145     langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName());
146
147   // Add device-specific linker flags.
148   this->GetDeviceLinkFlags(linkFlags, linkLanguage);
149
150   // Construct a list of files associated with this executable that
151   // may need to be cleaned.
152   std::vector<std::string> exeCleanFiles;
153   exeCleanFiles.push_back(
154     this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput));
155
156   // Determine whether a link script will be used.
157   bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
158
159   // Construct the main link rule.
160   std::vector<std::string> real_link_commands;
161   const std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_EXECUTABLE";
162   const std::string linkRule = this->GetLinkRule(linkRuleVar);
163   std::vector<std::string> commands1;
164   cmExpandList(linkRule, real_link_commands);
165
166   bool useResponseFileForObjects =
167     this->CheckUseResponseFileForObjects(linkLanguage);
168   bool const useResponseFileForLibs =
169     this->CheckUseResponseFileForLibraries(linkLanguage);
170
171   // Expand the rule variables.
172   {
173     // Set path conversion for link script shells.
174     this->LocalGenerator->SetLinkScriptShell(useLinkScript);
175
176     std::unique_ptr<cmLinkLineComputer> linkLineComputer(
177       new cmLinkLineDeviceComputer(
178         this->LocalGenerator,
179         this->LocalGenerator->GetStateSnapshot().GetDirectory()));
180     linkLineComputer->SetForResponse(useResponseFileForLibs);
181     linkLineComputer->SetRelink(relink);
182
183     // Collect up flags to link in needed libraries.
184     std::string linkLibs;
185     this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
186                          useResponseFileForLibs, depends);
187
188     // Construct object file lists that may be needed to expand the
189     // rule.
190     std::string buildObjs;
191     this->CreateObjectLists(useLinkScript, false, useResponseFileForObjects,
192                             buildObjs, depends, false);
193
194     cmRulePlaceholderExpander::RuleVariables vars;
195     std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
196
197     objectDir = this->LocalGenerator->ConvertToOutputFormat(
198       this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir),
199       cmOutputConverter::SHELL);
200
201     std::string target = this->LocalGenerator->ConvertToOutputFormat(
202       this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput),
203       cmOutputConverter::SHELL);
204
205     std::string targetFullPathCompilePDB =
206       this->ComputeTargetCompilePDB(this->GetConfigName());
207     std::string targetOutPathCompilePDB =
208       this->LocalGenerator->ConvertToOutputFormat(targetFullPathCompilePDB,
209                                                   cmOutputConverter::SHELL);
210
211     vars.Language = linkLanguage.c_str();
212     vars.Objects = buildObjs.c_str();
213     vars.ObjectDir = objectDir.c_str();
214     vars.Target = target.c_str();
215     vars.LinkLibraries = linkLibs.c_str();
216     vars.LanguageCompileFlags = langFlags.c_str();
217     vars.LinkFlags = linkFlags.c_str();
218     vars.TargetCompilePDB = targetOutPathCompilePDB.c_str();
219
220     std::string launcher;
221
222     cmValue val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
223                                                         "RULE_LAUNCH_LINK");
224     if (cmNonempty(val)) {
225       launcher = cmStrCat(*val, ' ');
226     }
227
228     std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
229       this->LocalGenerator->CreateRulePlaceholderExpander());
230
231     // Expand placeholders in the commands.
232     rulePlaceholderExpander->SetTargetImpLib(targetOutput);
233     for (std::string& real_link_command : real_link_commands) {
234       real_link_command = cmStrCat(launcher, real_link_command);
235       rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
236                                                    real_link_command, vars);
237     }
238
239     // Restore path conversion to normal shells.
240     this->LocalGenerator->SetLinkScriptShell(false);
241   }
242
243   // Optionally convert the build rule to use a script to avoid long
244   // command lines in the make shell.
245   if (useLinkScript) {
246     // Use a link script.
247     const char* name = (relink ? "drelink.txt" : "dlink.txt");
248     this->CreateLinkScript(name, real_link_commands, commands1, depends);
249   } else {
250     // No link script.  Just use the link rule directly.
251     commands1 = real_link_commands;
252   }
253   this->LocalGenerator->CreateCDCommand(
254     commands1, this->Makefile->GetCurrentBinaryDirectory(),
255     this->LocalGenerator->GetBinaryDirectory());
256   cm::append(commands, commands1);
257   commands1.clear();
258
259   // Write the build rule.
260   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
261                                       targetOutput, depends, commands, false);
262
263   // Clean all the possible executable names and symlinks.
264   this->CleanFiles.insert(exeCleanFiles.begin(), exeCleanFiles.end());
265 }
266
267 void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
268 {
269   std::vector<std::string> commands;
270
271   // Get the name of the executable to generate.
272   cmGeneratorTarget::Names targetNames =
273     this->GeneratorTarget->GetExecutableNames(this->GetConfigName());
274
275   // Construct the full path version of the names.
276   std::string outpath =
277     this->GeneratorTarget->GetDirectory(this->GetConfigName());
278   if (this->GeneratorTarget->IsAppBundleOnApple()) {
279     this->OSXBundleGenerator->CreateAppBundle(targetNames.Output, outpath,
280                                               this->GetConfigName());
281   }
282   outpath += '/';
283   std::string outpathImp;
284   if (relink) {
285     outpath = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(),
286                        "/CMakeFiles/CMakeRelink.dir");
287     cmSystemTools::MakeDirectory(outpath);
288     outpath += '/';
289     if (!targetNames.ImportLibrary.empty()) {
290       outpathImp = outpath;
291     }
292   } else {
293     cmSystemTools::MakeDirectory(outpath);
294     if (!targetNames.ImportLibrary.empty()) {
295       outpathImp = this->GeneratorTarget->GetDirectory(
296         this->GetConfigName(), cmStateEnums::ImportLibraryArtifact);
297       cmSystemTools::MakeDirectory(outpathImp);
298       outpathImp += '/';
299     }
300   }
301
302   std::string compilePdbOutputPath =
303     this->GeneratorTarget->GetCompilePDBDirectory(this->GetConfigName());
304   cmSystemTools::MakeDirectory(compilePdbOutputPath);
305
306   std::string pdbOutputPath =
307     this->GeneratorTarget->GetPDBDirectory(this->GetConfigName());
308   cmSystemTools::MakeDirectory(pdbOutputPath);
309   pdbOutputPath += '/';
310
311   std::string targetFullPath = outpath + targetNames.Output;
312   std::string targetFullPathReal = outpath + targetNames.Real;
313   std::string targetFullPathPDB = pdbOutputPath + targetNames.PDB;
314   std::string targetFullPathImport = outpathImp + targetNames.ImportLibrary;
315   std::string targetOutPathPDB = this->LocalGenerator->ConvertToOutputFormat(
316     targetFullPathPDB, cmOutputConverter::SHELL);
317   // Convert to the output path to use in constructing commands.
318   std::string targetOutPath = this->LocalGenerator->ConvertToOutputFormat(
319     this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPath),
320     cmOutputConverter::SHELL);
321   std::string targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
322     this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal),
323     cmOutputConverter::SHELL);
324   std::string targetOutPathImport =
325     this->LocalGenerator->ConvertToOutputFormat(
326       this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathImport),
327       cmOutputConverter::SHELL);
328
329   // Get the language to use for linking this executable.
330   std::string linkLanguage =
331     this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName());
332
333   // Make sure we have a link language.
334   if (linkLanguage.empty()) {
335     cmSystemTools::Error("Cannot determine link language for target \"" +
336                          this->GeneratorTarget->GetName() + "\".");
337     return;
338   }
339
340   // Build list of dependencies.
341   std::vector<std::string> depends;
342   this->AppendLinkDepends(depends, linkLanguage);
343   if (!this->DeviceLinkObject.empty()) {
344     depends.push_back(this->DeviceLinkObject);
345   }
346
347   this->NumberOfProgressActions++;
348   if (!this->NoRuleMessages) {
349     cmLocalUnixMakefileGenerator3::EchoProgress progress;
350     this->MakeEchoProgress(progress);
351     // Add the link message.
352     std::string buildEcho =
353       cmStrCat("Linking ", linkLanguage, " executable ", targetOutPath);
354     this->LocalGenerator->AppendEcho(
355       commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
356   }
357
358   // Build a list of compiler flags and linker flags.
359   std::string flags;
360   std::string linkFlags;
361
362   // Add flags to create an executable.
363   this->LocalGenerator->AddConfigVariableFlags(
364     linkFlags, "CMAKE_EXE_LINKER_FLAGS", this->GetConfigName());
365
366   if (this->GeneratorTarget->IsWin32Executable(
367         this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"))) {
368     this->LocalGenerator->AppendFlags(
369       linkFlags,
370       this->Makefile->GetSafeDefinition(
371         cmStrCat("CMAKE_", linkLanguage, "_CREATE_WIN32_EXE")));
372   } else {
373     this->LocalGenerator->AppendFlags(
374       linkFlags,
375       this->Makefile->GetSafeDefinition(
376         cmStrCat("CMAKE_", linkLanguage, "_CREATE_CONSOLE_EXE")));
377   }
378
379   // Add symbol export flags if necessary.
380   if (this->GeneratorTarget->IsExecutableWithExports()) {
381     std::string export_flag_var =
382       cmStrCat("CMAKE_EXE_EXPORTS_", linkLanguage, "_FLAG");
383     this->LocalGenerator->AppendFlags(
384       linkFlags, this->Makefile->GetSafeDefinition(export_flag_var));
385   }
386
387   this->LocalGenerator->AppendFlags(linkFlags,
388                                     this->LocalGenerator->GetLinkLibsCMP0065(
389                                       linkLanguage, *this->GeneratorTarget));
390
391   this->UseLWYU = this->LocalGenerator->AppendLWYUFlags(
392     linkFlags, this->GeneratorTarget, linkLanguage);
393
394   // Add language feature flags.
395   this->LocalGenerator->AddLanguageFlagsForLinking(
396     flags, this->GeneratorTarget, linkLanguage, this->GetConfigName());
397
398   this->LocalGenerator->AddArchitectureFlags(
399     flags, this->GeneratorTarget, linkLanguage, this->GetConfigName());
400
401   // Add target-specific linker flags.
402   this->GetTargetLinkFlags(linkFlags, linkLanguage);
403
404   {
405     std::unique_ptr<cmLinkLineComputer> linkLineComputer =
406       this->CreateLinkLineComputer(
407         this->LocalGenerator,
408         this->LocalGenerator->GetStateSnapshot().GetDirectory());
409
410     this->LocalGenerator->AppendModuleDefinitionFlag(
411       linkFlags, this->GeneratorTarget, linkLineComputer.get(),
412       this->GetConfigName());
413   }
414
415   this->LocalGenerator->AppendIPOLinkerFlags(
416     linkFlags, this->GeneratorTarget, this->GetConfigName(), linkLanguage);
417
418   // Construct a list of files associated with this executable that
419   // may need to be cleaned.
420   std::vector<std::string> exeCleanFiles;
421   exeCleanFiles.push_back(
422     this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPath));
423 #ifdef _WIN32
424   // There may be a manifest file for this target.  Add it to the
425   // clean set just in case.
426   exeCleanFiles.push_back(this->LocalGenerator->MaybeRelativeToCurBinDir(
427     targetFullPath + ".manifest"));
428 #endif
429   if (this->TargetNames.Real != this->TargetNames.Output) {
430     exeCleanFiles.push_back(
431       this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal));
432   }
433   if (!this->TargetNames.ImportLibrary.empty()) {
434     exeCleanFiles.push_back(
435       this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathImport));
436     std::string implib;
437     if (this->GeneratorTarget->GetImplibGNUtoMS(
438           this->GetConfigName(), targetFullPathImport, implib)) {
439       exeCleanFiles.push_back(
440         this->LocalGenerator->MaybeRelativeToCurBinDir(implib));
441     }
442   }
443
444   // List the PDB for cleaning only when the whole target is
445   // cleaned.  We do not want to delete the .pdb file just before
446   // linking the target.
447   this->CleanFiles.insert(
448     this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathPDB));
449
450   // Add the pre-build and pre-link rules building but not when relinking.
451   if (!relink) {
452     this->LocalGenerator->AppendCustomCommands(
453       commands, this->GeneratorTarget->GetPreBuildCommands(),
454       this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());
455     this->LocalGenerator->AppendCustomCommands(
456       commands, this->GeneratorTarget->GetPreLinkCommands(),
457       this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());
458   }
459
460   // Determine whether a link script will be used.
461   bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
462
463   // Construct the main link rule.
464   std::vector<std::string> real_link_commands;
465   std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable(
466     linkLanguage, this->GetConfigName());
467   std::string linkRule = this->GetLinkRule(linkRuleVar);
468   std::vector<std::string> commands1;
469   cmExpandList(linkRule, real_link_commands);
470   if (this->GeneratorTarget->IsExecutableWithExports()) {
471     // If a separate rule for creating an import library is specified
472     // add it now.
473     std::string implibRuleVar =
474       cmStrCat("CMAKE_", linkLanguage, "_CREATE_IMPORT_LIBRARY");
475     this->Makefile->GetDefExpandList(implibRuleVar, real_link_commands);
476   }
477
478   bool useResponseFileForObjects =
479     this->CheckUseResponseFileForObjects(linkLanguage);
480   bool const useResponseFileForLibs =
481     this->CheckUseResponseFileForLibraries(linkLanguage);
482
483   // Expand the rule variables.
484   {
485     bool useWatcomQuote =
486       this->Makefile->IsOn(linkRuleVar + "_USE_WATCOM_QUOTE");
487
488     // Set path conversion for link script shells.
489     this->LocalGenerator->SetLinkScriptShell(useLinkScript);
490
491     std::unique_ptr<cmLinkLineComputer> linkLineComputer =
492       this->CreateLinkLineComputer(
493         this->LocalGenerator,
494         this->LocalGenerator->GetStateSnapshot().GetDirectory());
495     linkLineComputer->SetForResponse(useResponseFileForLibs);
496     linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
497     linkLineComputer->SetRelink(relink);
498
499     // Collect up flags to link in needed libraries.
500     std::string linkLibs;
501     this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
502                          useResponseFileForLibs, depends);
503
504     // Construct object file lists that may be needed to expand the
505     // rule.
506     std::string buildObjs;
507     this->CreateObjectLists(useLinkScript, false, useResponseFileForObjects,
508                             buildObjs, depends, useWatcomQuote);
509     if (!this->DeviceLinkObject.empty()) {
510       buildObjs += " " +
511         this->LocalGenerator->ConvertToOutputFormat(
512           this->LocalGenerator->MaybeRelativeToCurBinDir(
513             this->DeviceLinkObject),
514           cmOutputConverter::SHELL);
515     }
516
517     // maybe create .def file from list of objects
518     this->GenDefFile(real_link_commands);
519
520     std::string manifests = this->GetManifests(this->GetConfigName());
521
522     std::string const& aixExports = this->GetAIXExports(this->GetConfigName());
523
524     cmRulePlaceholderExpander::RuleVariables vars;
525     vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
526     vars.CMTargetType =
527       cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str();
528     vars.Language = linkLanguage.c_str();
529     vars.AIXExports = aixExports.c_str();
530     vars.Objects = buildObjs.c_str();
531     std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
532
533     objectDir = this->LocalGenerator->ConvertToOutputFormat(
534       this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir),
535       cmOutputConverter::SHELL);
536     vars.ObjectDir = objectDir.c_str();
537     cmOutputConverter::OutputFormat output = (useWatcomQuote)
538       ? cmOutputConverter::WATCOMQUOTE
539       : cmOutputConverter::SHELL;
540     std::string target = this->LocalGenerator->ConvertToOutputFormat(
541       this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal),
542       output);
543     vars.Target = target.c_str();
544     vars.TargetPDB = targetOutPathPDB.c_str();
545
546     // Setup the target version.
547     std::string targetVersionMajor;
548     std::string targetVersionMinor;
549     {
550       std::ostringstream majorStream;
551       std::ostringstream minorStream;
552       int major;
553       int minor;
554       this->GeneratorTarget->GetTargetVersion(major, minor);
555       majorStream << major;
556       minorStream << minor;
557       targetVersionMajor = majorStream.str();
558       targetVersionMinor = minorStream.str();
559     }
560     vars.TargetVersionMajor = targetVersionMajor.c_str();
561     vars.TargetVersionMinor = targetVersionMinor.c_str();
562
563     vars.LinkLibraries = linkLibs.c_str();
564     vars.Flags = flags.c_str();
565     vars.LinkFlags = linkFlags.c_str();
566     vars.Manifests = manifests.c_str();
567
568     std::string linkerLauncher =
569       this->GetLinkerLauncher(this->GetConfigName());
570     if (cmNonempty(linkerLauncher)) {
571       vars.Launcher = linkerLauncher.c_str();
572     }
573
574     if (this->UseLWYU) {
575       cmValue lwyuCheck =
576         this->Makefile->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK");
577       if (lwyuCheck) {
578         std::string cmakeCommand = cmStrCat(
579           this->LocalGenerator->ConvertToOutputFormat(
580             cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
581           " -E __run_co_compile --lwyu=");
582         cmakeCommand += this->LocalGenerator->EscapeForShell(*lwyuCheck);
583         cmakeCommand += cmStrCat(" --source=", targetOutPathReal);
584         real_link_commands.push_back(std::move(cmakeCommand));
585       }
586     }
587
588     std::string launcher;
589
590     cmValue val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
591                                                         "RULE_LAUNCH_LINK");
592     if (cmNonempty(val)) {
593       launcher = cmStrCat(*val, ' ');
594     }
595
596     std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
597       this->LocalGenerator->CreateRulePlaceholderExpander());
598
599     // Expand placeholders in the commands.
600     rulePlaceholderExpander->SetTargetImpLib(targetOutPathImport);
601     for (std::string& real_link_command : real_link_commands) {
602       real_link_command = cmStrCat(launcher, real_link_command);
603       rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
604                                                    real_link_command, vars);
605     }
606
607     // Restore path conversion to normal shells.
608     this->LocalGenerator->SetLinkScriptShell(false);
609   }
610
611   // Optionally convert the build rule to use a script to avoid long
612   // command lines in the make shell.
613   if (useLinkScript) {
614     // Use a link script.
615     const char* name = (relink ? "relink.txt" : "link.txt");
616     this->CreateLinkScript(name, real_link_commands, commands1, depends);
617   } else {
618     // No link script.  Just use the link rule directly.
619     commands1 = real_link_commands;
620   }
621   this->LocalGenerator->CreateCDCommand(
622     commands1, this->Makefile->GetCurrentBinaryDirectory(),
623     this->LocalGenerator->GetBinaryDirectory());
624   cm::append(commands, commands1);
625   commands1.clear();
626
627   // Add a rule to create necessary symlinks for the library.
628   if (targetOutPath != targetOutPathReal) {
629     std::string symlink =
630       cmStrCat("$(CMAKE_COMMAND) -E cmake_symlink_executable ",
631                targetOutPathReal, ' ', targetOutPath);
632     commands1.push_back(std::move(symlink));
633     this->LocalGenerator->CreateCDCommand(
634       commands1, this->Makefile->GetCurrentBinaryDirectory(),
635       this->LocalGenerator->GetBinaryDirectory());
636     cm::append(commands, commands1);
637     commands1.clear();
638   }
639
640   // Add the post-build rules when building but not when relinking.
641   if (!relink) {
642     this->LocalGenerator->AppendCustomCommands(
643       commands, this->GeneratorTarget->GetPostBuildCommands(),
644       this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());
645   }
646
647   // Write the build rule.
648   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
649                                       targetFullPathReal, depends, commands,
650                                       false);
651
652   // The symlink name for the target should depend on the real target
653   // so if the target version changes it rebuilds and recreates the
654   // symlink.
655   if (targetFullPath != targetFullPathReal) {
656     depends.clear();
657     commands.clear();
658     depends.push_back(targetFullPathReal);
659     this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
660                                         targetFullPath, depends, commands,
661                                         false);
662   }
663
664   // Write the main driver rule to build everything in this target.
665   this->WriteTargetDriverRule(targetFullPath, relink);
666
667   // Clean all the possible executable names and symlinks.
668   this->CleanFiles.insert(exeCleanFiles.begin(), exeCleanFiles.end());
669 }