~ubuntu-branches/ubuntu/jaunty/cmake/jaunty-security

« back to all changes in this revision

Viewing changes to Source/cmMakefileExecutableTargetGenerator.cxx

  • Committer: Bazaar Package Importer
  • Author(s): A. Maitland Bottoms
  • Date: 2006-06-18 16:34:11 UTC
  • mfrom: (1.4.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060618163411-pi234s3v6jwlcmof
Tags: 2.4.2-1
* New upstream release (Closes: #338324)
* Put cmake .vim files into /usr/share/vim/addons/plugin/
  where they can be used. (Closes: #366663)
* Install cmake-mode.el so it can be used. (Closes: #366664)
* Ensure cmake FindKDE locates KDE libraries on Debian
  based distributions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*=========================================================================
 
2
 
 
3
  Program:   CMake - Cross-Platform Makefile Generator
 
4
  Module:    $RCSfile: cmMakefileExecutableTargetGenerator.cxx,v $
 
5
  Language:  C++
 
6
  Date:      $Date: 2006/05/16 18:04:08 $
 
7
  Version:   $Revision: 1.12.2.3 $
 
8
 
 
9
  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
 
10
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
 
11
 
 
12
     This software is distributed WITHOUT ANY WARRANTY; without even
 
13
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 
14
     PURPOSE.  See the above copyright notices for more information.
 
15
 
 
16
=========================================================================*/
 
17
#include "cmMakefileExecutableTargetGenerator.h"
 
18
 
 
19
#include "cmGeneratedFileStream.h"
 
20
#include "cmGlobalGenerator.h"
 
21
#include "cmLocalUnixMakefileGenerator3.h"
 
22
#include "cmMakefile.h"
 
23
#include "cmSourceFile.h"
 
24
#include "cmTarget.h"
 
25
 
 
26
//----------------------------------------------------------------------------
 
27
void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
 
28
{
 
29
  // create the build.make file and directory, put in the common blocks
 
30
  this->CreateRuleFile();
 
31
 
 
32
  // Add in any rules for custom commands
 
33
  this->WriteCustomCommandsForTarget();
 
34
 
 
35
  // write in rules for object files
 
36
  this->WriteCommonCodeRules();
 
37
 
 
38
  // Write the dependency generation rule.
 
39
  this->WriteTargetDependRules();
 
40
 
 
41
  // write the link rules
 
42
  this->WriteExecutableRule(false);
 
43
  if(this->Target->NeedRelinkBeforeInstall())
 
44
    {
 
45
    // Write rules to link an installable version of the target.
 
46
    this->WriteExecutableRule(true);
 
47
    }
 
48
 
 
49
  // Write the requires target.
 
50
  this->WriteTargetRequiresRules();
 
51
 
 
52
  // Write clean target
 
53
  this->WriteTargetCleanRules();
 
54
 
 
55
  // close the streams
 
56
  this->CloseFileStreams();
 
57
}
 
58
 
 
59
 
 
60
 
 
61
//----------------------------------------------------------------------------
 
62
void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
 
63
{
 
64
  std::vector<std::string> commands;
 
65
 
 
66
  std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
 
67
  std::string objTarget;
 
68
 
 
69
  // Build list of dependencies.
 
70
  std::vector<std::string> depends;
 
71
  for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
 
72
      obj != this->Objects.end(); ++obj)
 
73
    {
 
74
    objTarget = relPath;
 
75
    objTarget += *obj;
 
76
    depends.push_back(objTarget);
 
77
    }
 
78
 
 
79
  // Add dependencies on targets that must be built first.
 
80
  this->AppendTargetDepends(depends);
 
81
 
 
82
  // Add a dependency on the rule file itself.
 
83
  this->LocalGenerator->AppendRuleDepend(depends,
 
84
                                         this->BuildFileNameFull.c_str());
 
85
 
 
86
  for(std::vector<std::string>::const_iterator obj =
 
87
        this->ExternalObjects.begin();
 
88
      obj != this->ExternalObjects.end(); ++obj)
 
89
    {
 
90
    depends.push_back(*obj);
 
91
    }
 
92
 
 
93
  // from here up is the same for exe or lib
 
94
 
 
95
  // Get the name of the executable to generate.
 
96
  std::string targetName;
 
97
  std::string targetNameReal;
 
98
  this->Target->GetExecutableNames
 
99
    (targetName, targetNameReal,
 
100
                                   this->LocalGenerator->ConfigurationName.c_str());
 
101
 
 
102
  // Construct the full path version of the names.
 
103
  std::string outpath = this->LocalGenerator->ExecutableOutputPath;
 
104
  if(outpath.length() == 0)
 
105
    {
 
106
    outpath = this->Makefile->GetStartOutputDirectory();
 
107
    outpath += "/";
 
108
    }
 
109
#ifdef __APPLE__
 
110
  if(this->Target->GetPropertyAsBool("MACOSX_BUNDLE"))
 
111
    {
 
112
    // Make bundle directories
 
113
    outpath += targetName;
 
114
    outpath += ".app/Contents/MacOS/";
 
115
    std::string f1 =
 
116
      this->Makefile->GetModulesFile("MacOSXBundleInfo.plist.in");
 
117
    if ( f1.size() == 0 )
 
118
      {
 
119
      cmSystemTools::Error("could not find Mac OSX bundle template file.");
 
120
      }
 
121
    std::string macdir =
 
122
      this->Makefile->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
 
123
    if ( macdir.size() == 0 )
 
124
      {
 
125
      macdir = this->Makefile->GetCurrentOutputDirectory();
 
126
      }
 
127
    if(macdir.size() && macdir[macdir.size()-1] != '/')
 
128
      {
 
129
      macdir += "/";
 
130
      }
 
131
    macdir += targetName;
 
132
    macdir += ".app/Contents/";
 
133
 
 
134
    std::vector<cmSourceFile*>::iterator sourceIt;
 
135
    for ( sourceIt = this->Target->GetSourceFiles().begin();
 
136
      sourceIt != this->Target->GetSourceFiles().end();
 
137
      ++ sourceIt )
 
138
      {
 
139
      const char* subDir = 
 
140
        (*sourceIt)->GetProperty("MACOSX_PACKAGE_LOCATION");
 
141
      if ( subDir )
 
142
        {
 
143
        std::string newDir = macdir;
 
144
        newDir += subDir;
 
145
        if ( !cmSystemTools::MakeDirectory(newDir.c_str()) )
 
146
          {
 
147
          cmSystemTools::Error("Cannot create a subdirectory for \"",
 
148
            newDir.c_str(), "\".");
 
149
          return;
 
150
          }
 
151
        }
 
152
      }
 
153
 
 
154
    // Configure the Info.plist file.  Note that it needs the executable name
 
155
    // to be set.
 
156
    std::string f2 = macdir + "Info.plist";
 
157
    macdir += "MacOS";
 
158
    cmSystemTools::MakeDirectory(macdir.c_str());
 
159
    this->Makefile->AddDefinition("MACOSX_BUNDLE_EXECUTABLE_NAME",
 
160
                                  targetName.c_str());
 
161
    this->Makefile->ConfigureFile(f1.c_str(), f2.c_str(), 
 
162
                                  false, false, false);
 
163
    }
 
164
#endif
 
165
  if(relink)
 
166
    {
 
167
    outpath = this->Makefile->GetStartOutputDirectory();
 
168
    outpath += "/CMakeFiles/CMakeRelink.dir";
 
169
    cmSystemTools::MakeDirectory(outpath.c_str());
 
170
    outpath += "/";
 
171
    }
 
172
  std::string targetFullPath = outpath + targetName;
 
173
  std::string targetFullPathReal = outpath + targetNameReal;
 
174
  std::string targetFullPathPDB = outpath + this->Target->GetName();
 
175
  targetFullPathPDB += ".pdb";
 
176
  std::string targetOutPathPDB = 
 
177
    this->Convert(targetFullPathPDB.c_str(),
 
178
                  cmLocalGenerator::FULL,
 
179
                  cmLocalGenerator::MAKEFILE); 
 
180
  // Convert to the output path to use in constructing commands.
 
181
  std::string targetOutPath =
 
182
    this->Convert(targetFullPath.c_str(),
 
183
                                  cmLocalGenerator::START_OUTPUT,
 
184
                                  cmLocalGenerator::MAKEFILE);
 
185
  std::string targetOutPathReal =
 
186
    this->Convert(targetFullPathReal.c_str(),
 
187
                                  cmLocalGenerator::START_OUTPUT,
 
188
                                  cmLocalGenerator::MAKEFILE);
 
189
 
 
190
  // Get the language to use for linking this executable.
 
191
  const char* linkLanguage =
 
192
    this->Target->GetLinkerLanguage(this->GlobalGenerator);
 
193
 
 
194
  // Make sure we have a link language.
 
195
  if(!linkLanguage)
 
196
    {
 
197
    cmSystemTools::Error("Cannot determine link language for target \"",
 
198
                         this->Target->GetName(), "\".");
 
199
    return;
 
200
    }
 
201
 
 
202
  // Add the link message.
 
203
  std::string buildEcho = "Linking ";
 
204
  buildEcho += linkLanguage;
 
205
  buildEcho += " executable ";
 
206
  buildEcho += targetOutPath;
 
207
  this->LocalGenerator->AppendEcho(commands, buildEcho.c_str(),
 
208
                                   cmLocalUnixMakefileGenerator3::EchoLink);
 
209
 
 
210
  // Build a list of compiler flags and linker flags.
 
211
  std::string flags;
 
212
  std::string linkFlags;
 
213
 
 
214
  // Add flags to deal with shared libraries.  Any library being
 
215
  // linked in might be shared, so always use shared flags for an
 
216
  // executable.
 
217
  this->LocalGenerator->AddSharedFlags(linkFlags, linkLanguage, true);
 
218
 
 
219
  // Add flags to create an executable.
 
220
  this->LocalGenerator->
 
221
    AddConfigVariableFlags(linkFlags, "CMAKE_EXE_LINKER_FLAGS",
 
222
                           this->LocalGenerator->ConfigurationName.c_str());
 
223
 
 
224
 
 
225
  if(this->Target->GetPropertyAsBool("WIN32_EXECUTABLE"))
 
226
    {
 
227
    this->LocalGenerator->AppendFlags
 
228
      (linkFlags, this->Makefile->GetDefinition("CMAKE_CREATE_WIN32_EXE"));
 
229
    }
 
230
  else
 
231
    {
 
232
    this->LocalGenerator->AppendFlags
 
233
      (linkFlags, this->Makefile->GetDefinition("CMAKE_CREATE_CONSOLE_EXE"));
 
234
    }
 
235
 
 
236
  // Add language-specific flags.
 
237
  this->LocalGenerator
 
238
    ->AddLanguageFlags(flags, linkLanguage,
 
239
                       this->LocalGenerator->ConfigurationName.c_str());
 
240
 
 
241
  // Add target-specific linker flags.
 
242
  this->LocalGenerator->AppendFlags
 
243
    (linkFlags, this->Target->GetProperty("LINK_FLAGS"));
 
244
  std::string linkFlagsConfig = "LINK_FLAGS_";
 
245
  linkFlagsConfig += 
 
246
    cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName.c_str());
 
247
  this->LocalGenerator->AppendFlags
 
248
    (linkFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
 
249
 
 
250
  // Construct a list of files associated with this executable that
 
251
  // may need to be cleaned.
 
252
  std::vector<std::string> exeCleanFiles;
 
253
  {
 
254
  std::string cleanName;
 
255
  std::string cleanRealName;
 
256
  this->Target->GetExecutableCleanNames
 
257
    (cleanName, cleanRealName,
 
258
                                        this->LocalGenerator->ConfigurationName.c_str());
 
259
 
 
260
  std::string cleanFullName = outpath + cleanName;
 
261
  std::string cleanFullRealName = outpath + cleanRealName;
 
262
  exeCleanFiles.push_back(this->Convert(cleanFullName.c_str(),
 
263
                                        cmLocalGenerator::START_OUTPUT,
 
264
                                        cmLocalGenerator::UNCHANGED));
 
265
  if(cleanRealName != cleanName)
 
266
    {
 
267
    exeCleanFiles.push_back(this->Convert(cleanFullRealName.c_str(),
 
268
                                          cmLocalGenerator::START_OUTPUT,
 
269
                                          cmLocalGenerator::UNCHANGED));
 
270
    }
 
271
  }
 
272
 
 
273
  // Add a command to remove any existing files for this executable.
 
274
  std::vector<std::string> commands1;
 
275
  this->LocalGenerator->AppendCleanCommand(commands1, exeCleanFiles,
 
276
                                           *this->Target, "target");
 
277
  this->LocalGenerator->CreateCDCommand
 
278
    (commands1,
 
279
                                        this->Makefile->GetStartOutputDirectory(),
 
280
                                        this->Makefile->GetHomeOutputDirectory());
 
281
 
 
282
  commands.insert(commands.end(), commands1.begin(), commands1.end());
 
283
  commands1.clear();
 
284
 
 
285
  // Add the pre-build and pre-link rules building but not when relinking.
 
286
  if(!relink)
 
287
    {
 
288
    this->LocalGenerator
 
289
      ->AppendCustomCommands(commands, this->Target->GetPreBuildCommands());
 
290
    this->LocalGenerator
 
291
      ->AppendCustomCommands(commands, this->Target->GetPreLinkCommands());
 
292
    }
 
293
 
 
294
  // Construct the main link rule.
 
295
  std::string linkRuleVar = "CMAKE_";
 
296
  linkRuleVar += linkLanguage;
 
297
  linkRuleVar += "_LINK_EXECUTABLE";
 
298
  std::string linkRule =
 
299
    this->Makefile->GetRequiredDefinition(linkRuleVar.c_str());
 
300
  cmSystemTools::ExpandListArgument(linkRule, commands1);
 
301
  this->LocalGenerator->CreateCDCommand
 
302
    (commands1,
 
303
     this->Makefile->GetStartOutputDirectory(),
 
304
     this->Makefile->GetHomeOutputDirectory());
 
305
  commands.insert(commands.end(), commands1.begin(), commands1.end());
 
306
 
 
307
  // Add a rule to create necessary symlinks for the library.
 
308
  if(targetOutPath != targetOutPathReal)
 
309
    {
 
310
    std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_executable ";
 
311
    symlink += targetOutPathReal;
 
312
    symlink += " ";
 
313
    symlink += targetOutPath;
 
314
    commands.push_back(symlink);
 
315
    commands1.clear();
 
316
    commands1.push_back(symlink);
 
317
    this->LocalGenerator->CreateCDCommand(commands1,
 
318
                                  this->Makefile->GetStartOutputDirectory(),
 
319
                                  this->Makefile->GetHomeOutputDirectory());
 
320
    commands.insert(commands.end(), commands1.begin(), commands1.end());
 
321
    }
 
322
 
 
323
  // Add the post-build rules when building but not when relinking.
 
324
  if(!relink)
 
325
    {
 
326
    this->LocalGenerator->
 
327
      AppendCustomCommands(commands, this->Target->GetPostBuildCommands());
 
328
    }
 
329
 
 
330
  // Collect up flags to link in needed libraries.
 
331
  cmOStringStream linklibs;
 
332
  this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target, relink);
 
333
 
 
334
  // Construct object file lists that may be needed to expand the
 
335
  // rule.
 
336
  std::string variableName;
 
337
  std::string variableNameExternal;
 
338
  this->WriteObjectsVariable(variableName, variableNameExternal);
 
339
  std::string buildObjs = "$(";
 
340
  buildObjs += variableName;
 
341
  buildObjs += ") $(";
 
342
  buildObjs += variableNameExternal;
 
343
  buildObjs += ")";
 
344
  std::string cleanObjs = "$(";
 
345
  cleanObjs += variableName;
 
346
  cleanObjs += ")";
 
347
 
 
348
  cmLocalGenerator::RuleVariables vars;
 
349
  vars.Language = linkLanguage;
 
350
  vars.Objects = buildObjs.c_str();
 
351
  vars.Target = targetOutPathReal.c_str();
 
352
  vars.TargetPDB = targetOutPathPDB.c_str();
 
353
  std::string linkString = linklibs.str();
 
354
  vars.LinkLibraries = linkString.c_str();
 
355
  vars.Flags = flags.c_str();
 
356
  vars.LinkFlags = linkFlags.c_str();
 
357
  // Expand placeholders in the commands.
 
358
  for(std::vector<std::string>::iterator i = commands.begin();
 
359
      i != commands.end(); ++i)
 
360
    {
 
361
    this->LocalGenerator->ExpandRuleVariables(*i, vars);
 
362
    }
 
363
 
 
364
  // Write the build rule.
 
365
  this->LocalGenerator->WriteMakeRule(*this->BuildFileStream,
 
366
                                      0,
 
367
                                      targetFullPathReal.c_str(),
 
368
                                      depends, commands, false);
 
369
 
 
370
  // The symlink name for the target should depend on the real target
 
371
  // so if the target version changes it rebuilds and recreates the
 
372
  // symlink.
 
373
  if(targetFullPath != targetFullPathReal)
 
374
    {
 
375
    depends.clear();
 
376
    commands.clear();
 
377
    depends.push_back(targetFullPathReal.c_str());
 
378
    this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
 
379
                                        targetFullPath.c_str(),
 
380
                                        depends, commands, false);
 
381
    }
 
382
 
 
383
  // Write convenience targets.
 
384
  std::string dir = this->Makefile->GetStartOutputDirectory();
 
385
  dir += "/";
 
386
  dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
 
387
  std::string buildTargetRuleName = dir;
 
388
  buildTargetRuleName += relink?"/preinstall":"/build";
 
389
  buildTargetRuleName =
 
390
    this->Convert(buildTargetRuleName.c_str(),
 
391
                  cmLocalGenerator::HOME_OUTPUT,
 
392
                  cmLocalGenerator::MAKEFILE);
 
393
  this->LocalGenerator->WriteConvenienceRule(*this->BuildFileStream,
 
394
                                             targetFullPath.c_str(),
 
395
                                             buildTargetRuleName.c_str());
 
396
 
 
397
  // Clean all the possible executable names and symlinks and object files.
 
398
  this->CleanFiles.insert(this->CleanFiles.end(),
 
399
                          exeCleanFiles.begin(),
 
400
                          exeCleanFiles.end());
 
401
  this->CleanFiles.insert(this->CleanFiles.end(),
 
402
                          this->Objects.begin(),
 
403
                          this->Objects.end());
 
404
}
 
405