cmMakefile.cxx 161 KB
Newer Older
1
2
3
/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4

5
6
  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.
7

8
9
10
11
  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
12
#include "cmMakefile.h"
13
#include "cmVersion.h"
14
#include "cmCommand.h"
15
#include "cmSourceFile.h"
16
#include "cmSourceFileLocation.h"
17
#include "cmSystemTools.h"
Ken Martin's avatar
Ken Martin committed
18
#include "cmGlobalGenerator.h"
19
#include "cmCommands.h"
Stephen Kelly's avatar
Stephen Kelly committed
20
#include "cmState.h"
21
#include "cmOutputConverter.h"
22
#include "cmFunctionBlocker.h"
23
#include "cmGeneratorExpressionEvaluationFile.h"
24
#include "cmListFileCache.h"
25
#include "cmCommandArgumentParserHelper.h"
26
#include "cmGeneratorExpression.h"
27
#include "cmTest.h"
28
29
30
#ifdef CMAKE_BUILD_WITH_CMAKE
#  include "cmVariableWatch.h"
#endif
31
#include "cmInstallGenerator.h"
32
#include "cmTestGenerator.h"
33
#include "cmAlgorithms.h"
34
#include "cmake.h"
35
#include <stdlib.h> // required for atoi
36
37

#include <cmsys/RegularExpression.hxx>
38
#include <cmsys/FStream.hxx>
39
40
#include <cmsys/auto_ptr.hxx>

41
#include <list>
42
#include <ctype.h> // for isspace
43
#include <assert.h>
44

45
// default is not to be building executables
46
47
48
49
cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator,
                       cmState::Snapshot const& snapshot)
  : GlobalGenerator(globalGenerator),
    StateSnapshot(snapshot)
50
{
51
  this->IsSourceFileTryCompile = false;
52

53
  // Initialize these first since AddDefaultDefinitions calls AddDefinition
54
55
  this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused();
  this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars();
56

57
58
  this->SuppressWatches = false;

59
  // Setup the default include file regular expression (match everything).
60
  this->SetProperty("INCLUDE_REGULAR_EXPRESSION", "^.*$");
61
  // Setup the default include complaint regular expression (match nothing).
Ken Martin's avatar
Ken Martin committed
62
  this->ComplainFileRegularExpression = "^$";
63
  // Source and header file extensions that we can handle
64

65
  // Set up a list of source and header extensions
Alexander Neundorf's avatar
   
Alexander Neundorf committed
66
  // these are used to find files when the extension
67
  // is not given
68
  // The "c" extension MUST precede the "C" extension.
Ken Martin's avatar
Ken Martin committed
69
70
  this->SourceFileExtensions.push_back( "c" );
  this->SourceFileExtensions.push_back( "C" );
Alexander Neundorf's avatar
   
Alexander Neundorf committed
71

Ken Martin's avatar
Ken Martin committed
72
73
74
75
76
  this->SourceFileExtensions.push_back( "c++" );
  this->SourceFileExtensions.push_back( "cc" );
  this->SourceFileExtensions.push_back( "cpp" );
  this->SourceFileExtensions.push_back( "cxx" );
  this->SourceFileExtensions.push_back( "m" );
Alexander Neundorf's avatar
   
Alexander Neundorf committed
77
  this->SourceFileExtensions.push_back( "M" );
Ken Martin's avatar
Ken Martin committed
78
79
80
  this->SourceFileExtensions.push_back( "mm" );

  this->HeaderFileExtensions.push_back( "h" );
81
  this->HeaderFileExtensions.push_back( "hh" );
Ken Martin's avatar
Ken Martin committed
82
83
84
85
86
87
  this->HeaderFileExtensions.push_back( "h++" );
  this->HeaderFileExtensions.push_back( "hm" );
  this->HeaderFileExtensions.push_back( "hpp" );
  this->HeaderFileExtensions.push_back( "hxx" );
  this->HeaderFileExtensions.push_back( "in" );
  this->HeaderFileExtensions.push_back( "txx" );
Alexander Neundorf's avatar
   
Alexander Neundorf committed
88

Ken Martin's avatar
Ken Martin committed
89
  this->DefineFlags = " ";
90

91
  this->AddDefaultDefinitions();
92

93
94
95
  this->cmDefineRegex.compile("#cmakedefine[ \t]+([A-Za-z_0-9]*)");
  this->cmDefine01Regex.compile("#cmakedefine01[ \t]+([A-Za-z_0-9]*)");
  this->cmAtVarRegex.compile("(@[A-Za-z_0-9/.+-]+@)");
96
  this->cmNamedCurly.compile("^[A-Za-z0-9/_.+-]+{");
97

98
99
100
  this->StateSnapshot = this->StateSnapshot.GetState()
      ->CreatePolicyScopeSnapshot(this->StateSnapshot);

101
102
  // Enter a policy level for this directory.
  this->PushPolicy();
103

104
105
106
  // push empty loop block
  this->PushLoopBlockBarrier();

107
108
109
  // By default the check is not done.  It is enabled by
  // cmListFileCache in the top level if necessary.
  this->CheckCMP0000 = false;
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

#if defined(CMAKE_BUILD_WITH_CMAKE)
  this->AddSourceGroup("", "^.*$");
  this->AddSourceGroup
    ("Source Files",
     "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|f|f90|for|fpp"
     "|ftn|m|mm|rc|def|r|odl|idl|hpj|bat)$");
  this->AddSourceGroup("Header Files", CM_HEADER_REGEX);
  this->AddSourceGroup("CMake Rules", "\\.rule$");
  this->AddSourceGroup("Resources", "\\.plist$");
  this->AddSourceGroup("Object Files", "\\.(lo|o|obj)$");
#endif

  {
  const char* dir = this->GetCMakeInstance()->GetHomeDirectory();
  this->AddDefinition("CMAKE_SOURCE_DIR", dir);
126
  this->AddDefinition("CMAKE_CURRENT_SOURCE_DIR", dir);
127
128
129
130
  }
  {
  const char* dir = this->GetCMakeInstance()->GetHomeOutputDirectory();
  this->AddDefinition("CMAKE_BINARY_DIR", dir);
131
  this->AddDefinition("CMAKE_CURRENT_BINARY_DIR", dir);
132
  }
133
}
134

135
136
cmMakefile::~cmMakefile()
{
137
138
139
140
141
142
143
  cmDeleteAll(this->InstallGenerators);
  cmDeleteAll(this->TestGenerators);
  cmDeleteAll(this->SourceFiles);
  cmDeleteAll(this->Tests);
  cmDeleteAll(this->ImportedTargetsOwned);
  cmDeleteAll(this->FinalPassCommands);
  cmDeleteAll(this->FunctionBlockers);
144
145
146
  cmDeleteAll(this->EvaluationFiles);
  this->EvaluationFiles.clear();

Ken Martin's avatar
Ken Martin committed
147
  this->FunctionBlockers.clear();
148
149
}

150
//----------------------------------------------------------------------------
Bill Hoffman's avatar
Bill Hoffman committed
151
152
void cmMakefile::IssueMessage(cmake::MessageType t,
                              std::string const& text) const
153
{
154
  // Collect context information.
155
  if(!this->ExecutionStatusStack.empty())
156
    {
157
    if((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR))
158
      {
159
      this->ExecutionStatusStack.back()->SetNestedError(true);
160
      }
161
    this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace());
162
    }
163
  else
164
    {
165
    cmListFileContext lfc;
166
167
    // We are not currently executing a command.  Add whatever context
    // information we have.
168
    lfc.FilePath = this->GetExecutionFilePath();
169

170
    if(!this->GetCMakeInstance()->GetIsInTryCompile())
171
      {
172
173
      cmOutputConverter converter(this->StateSnapshot);
      lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME);
174
      }
175
    lfc.Line = 0;
176
    this->GetCMakeInstance()->IssueMessage(t, text, lfc);
177
    }
178
}
179

180
cmStringRange cmMakefile::GetIncludeDirectoriesEntries() const
181
{
182
  return this->StateSnapshot.GetDirectory().GetIncludeDirectoriesEntries();
183
184
}

185
cmBacktraceRange cmMakefile::GetIncludeDirectoriesBacktraces() const
186
{
187
188
  return this->StateSnapshot.GetDirectory()
      .GetIncludeDirectoriesEntryBacktraces();
189
190
}

191
cmStringRange cmMakefile::GetCompileOptionsEntries() const
192
{
193
  return this->StateSnapshot.GetDirectory().GetCompileOptionsEntries();
194
195
}

196
cmBacktraceRange cmMakefile::GetCompileOptionsBacktraces() const
197
{
198
  return this->StateSnapshot.GetDirectory().GetCompileOptionsEntryBacktraces();
199
200
}

201
cmStringRange cmMakefile::GetCompileDefinitionsEntries() const
202
{
203
  return this->StateSnapshot.GetDirectory().GetCompileDefinitionsEntries();
204
205
}

206
cmBacktraceRange cmMakefile::GetCompileDefinitionsBacktraces() const
207
{
208
209
  return this->StateSnapshot.GetDirectory()
      .GetCompileDefinitionsEntryBacktraces();
210
211
}

212
//----------------------------------------------------------------------------
Ben Boeckel's avatar
Ben Boeckel committed
213
cmListFileBacktrace cmMakefile::GetBacktrace() const
214
{
215
216
  cmListFileBacktrace backtrace;
  if (!this->ContextStack.empty())
217
    {
218
219
    backtrace = cmListFileBacktrace(this->StateSnapshot,
                                    *this->ContextStack.back());
220
    }
Ben Boeckel's avatar
Ben Boeckel committed
221
  return backtrace;
222
223
}

224
225
//----------------------------------------------------------------------------
cmListFileBacktrace
226
cmMakefile::GetBacktrace(cmCommandContext const& cc) const
227
{
228
  cmState::Snapshot snp = this->StateSnapshot;
229
  return cmListFileBacktrace(snp, cc);
230
231
}

232
233
234
//----------------------------------------------------------------------------
cmListFileContext cmMakefile::GetExecutionContext() const
{
235
236
237
  return cmListFileContext::FromCommandContext(
        *this->ContextStack.back(),
        this->StateSnapshot.GetExecutionListFile());
238
239
}

240
//----------------------------------------------------------------------------
241
void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const
242
{
243
  std::ostringstream msg;
244
  msg << this->GetExecutionFilePath() << "(" << lff.Line << "):  ";
245
  msg << lff.Name << "(";
Ben Boeckel's avatar
Ben Boeckel committed
246
247
  bool expand = this->GetCMakeInstance()->GetTraceExpand();
  std::string temp;
248
249
250
  for(std::vector<cmListFileArgument>::const_iterator i =
        lff.Arguments.begin(); i != lff.Arguments.end(); ++i)
    {
Ben Boeckel's avatar
Ben Boeckel committed
251
252
253
254
255
256
257
258
259
260
    if (expand)
      {
      temp = i->Value;
      this->ExpandVariablesInString(temp);
      msg << temp;
      }
    else
      {
      msg << i->Value;
      }
261
262
263
264
265
266
    msg << " ";
    }
  msg << ")";
  cmSystemTools::Message(msg.str().c_str());
}

267
//----------------------------------------------------------------------------
268
269
bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
                                cmExecutionStatus &status)
Ken Martin's avatar
Ken Martin committed
270
{
271
  bool result = true;
272

273
  // quick return if blocked
274
  if(this->IsFunctionBlocked(lff,status))
275
    {
276
277
    // No error.
    return result;
278
    }
279

Ken Martin's avatar
Ken Martin committed
280
  std::string name = lff.Name;
281

282
283
284
285
286
  // Place this call on the call stack.
  cmMakefileCall stack_manager(this, lff, status);
  static_cast<void>(stack_manager);

  // Lookup the command prototype.
287
  if(cmCommand* proto = this->GetState()->GetCommand(name))
288
289
290
291
292
293
294
    {
    // Clone the prototype.
    cmsys::auto_ptr<cmCommand> pcmd(proto->Clone());
    pcmd->SetMakefile(this);

    // Decide whether to invoke the command.
    if(pcmd->GetEnabled() && !cmSystemTools::GetFatalErrorOccured()  &&
295
296
       (this->GetCMakeInstance()->GetWorkingMode() != cmake::SCRIPT_MODE
       || pcmd->IsScriptable()))
297

298
      {
299
      // if trace is enabled, print out invoke information
Bill Hoffman's avatar
Bill Hoffman committed
300
301
      if(this->GetCMakeInstance()->GetTrace())
        {
302
        this->PrintCommandTrace(lff);
Bill Hoffman's avatar
Bill Hoffman committed
303
        }
304
305
306
      // Try invoking the command.
      if(!pcmd->InvokeInitialPass(lff.Arguments,status) ||
         status.GetNestedError())
Ken Martin's avatar
Ken Martin committed
307
        {
308
309
310
        if(!status.GetNestedError())
          {
          // The command invocation requested that we report an error.
Bill Hoffman's avatar
Bill Hoffman committed
311
          this->IssueMessage(cmake::FATAL_ERROR, pcmd->GetError());
312
          }
313
        result = false;
314
        if ( this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE)
Ken Martin's avatar
Ken Martin committed
315
          {
316
          cmSystemTools::SetFatalErrorOccured();
Ken Martin's avatar
Ken Martin committed
317
318
          }
        }
319
      else if(pcmd->HasFinalPass())
320
321
        {
        // use the command
322
        this->FinalPassCommands.push_back(pcmd.release());
323
        }
Ken Martin's avatar
Ken Martin committed
324
      }
325
    else if ( this->GetCMakeInstance()->GetWorkingMode() == cmake::SCRIPT_MODE
326
              && !pcmd->IsScriptable() )
327
      {
328
329
330
      std::string error = "Command ";
      error += pcmd->GetName();
      error += "() is not scriptable";
Bill Hoffman's avatar
Bill Hoffman committed
331
      this->IssueMessage(cmake::FATAL_ERROR, error);
332
333
334
      result = false;
      cmSystemTools::SetFatalErrorOccured();
      }
Ken Martin's avatar
Ken Martin committed
335
336
337
    }
  else
    {
338
339
    if(!cmSystemTools::GetFatalErrorOccured())
      {
340
341
342
      std::string error = "Unknown CMake command \"";
      error += lff.Name;
      error += "\".";
Bill Hoffman's avatar
Bill Hoffman committed
343
      this->IssueMessage(cmake::FATAL_ERROR, error);
344
      result = false;
345
      cmSystemTools::SetFatalErrorOccured();
346
      }
Ken Martin's avatar
Ken Martin committed
347
    }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
348

349
  return result;
Ken Martin's avatar
Ken Martin committed
350
351
}

Brad King's avatar
Brad King committed
352
353
354
355
//----------------------------------------------------------------------------
class cmMakefile::IncludeScope
{
public:
356
357
  IncludeScope(cmMakefile* mf, std::string const& filenametoread,
               bool noPolicyScope);
Brad King's avatar
Brad King committed
358
359
360
361
  ~IncludeScope();
  void Quiet() { this->ReportError = false; }
private:
  cmMakefile* Makefile;
362
363
  bool NoPolicyScope;
  bool CheckCMP0011;
Brad King's avatar
Brad King committed
364
  bool ReportError;
365
  void EnforceCMP0011();
Brad King's avatar
Brad King committed
366
367
368
};

//----------------------------------------------------------------------------
369
cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf,
370
                                       std::string const& filenametoread,
371
                                       bool noPolicyScope):
372
  Makefile(mf), NoPolicyScope(noPolicyScope),
373
  CheckCMP0011(false), ReportError(true)
Brad King's avatar
Brad King committed
374
{
375
376
377
378
379
380
381
382
  this->Makefile->PushFunctionBlockerBarrier();

  this->Makefile->StateSnapshot =
      this->Makefile->GetState()->CreateCallStackSnapshot(
        this->Makefile->StateSnapshot,
        this->Makefile->ContextStack.back()->Name,
        this->Makefile->ContextStack.back()->Line,
        filenametoread);
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
  if(!this->NoPolicyScope)
    {
    // Check CMP0011 to determine the policy scope type.
    switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0011))
      {
      case cmPolicies::WARN:
        // We need to push a scope to detect whether the script sets
        // any policies that would affect the includer and therefore
        // requires a warning.  We use a weak scope to simulate OLD
        // behavior by allowing policy changes to affect the includer.
        this->Makefile->PushPolicy(true);
        this->CheckCMP0011 = true;
        break;
      case cmPolicies::OLD:
        // OLD behavior is to not push a scope at all.
        this->NoPolicyScope = true;
        break;
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::REQUIRED_ALWAYS:
        // We should never make this policy required, but we handle it
        // here just in case.
        this->CheckCMP0011 = true;
      case cmPolicies::NEW:
        // NEW behavior is to push a (strong) scope.
        this->Makefile->PushPolicy();
        break;
      }
    }
Brad King's avatar
Brad King committed
411
412
413
414
415
}

//----------------------------------------------------------------------------
cmMakefile::IncludeScope::~IncludeScope()
{
416
417
418
419
420
421
  if(!this->NoPolicyScope)
    {
    // If we need to enforce policy CMP0011 then the top entry is the
    // one we pushed above.  If the entry is empty, then the included
    // script did not set any policies that might affect the includer so
    // we do not need to enforce the policy.
422
423
    if(this->CheckCMP0011
       && !this->Makefile->StateSnapshot.HasDefinedPolicyCMP0011())
424
425
426
427
428
429
430
431
432
433
434
435
436
437
      {
      this->CheckCMP0011 = false;
      }

    // Pop the scope we pushed for the script.
    this->Makefile->PopPolicy();

    // We enforce the policy after the script's policy stack entry has
    // been removed.
    if(this->CheckCMP0011)
      {
      this->EnforceCMP0011();
      }
    }
438
  this->Makefile->PopPolicyBarrier(this->ReportError);
439
440

  this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
441
442
443
444
445
446
447
448
449
450
451
452
}

//----------------------------------------------------------------------------
void cmMakefile::IncludeScope::EnforceCMP0011()
{
  // We check the setting of this policy again because the included
  // script might actually set this policy for its includer.
  switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0011))
    {
    case cmPolicies::WARN:
      // Warn because the user did not set this policy.
      {
453
      std::ostringstream w;
Stephen Kelly's avatar
Stephen Kelly committed
454
      w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0011) << "\n"
455
        << "The included script\n  "
456
        << this->Makefile->GetExecutionFilePath() << "\n"
457
458
459
460
461
462
463
464
465
        << "affects policy settings.  "
        << "CMake is implying the NO_POLICY_SCOPE option for compatibility, "
        << "so the effects are applied to the including context.";
      this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
      }
      break;
    case cmPolicies::REQUIRED_IF_USED:
    case cmPolicies::REQUIRED_ALWAYS:
      {
466
      std::ostringstream e;
Stephen Kelly's avatar
Stephen Kelly committed
467
      e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0011) << "\n"
468
        << "The included script\n  "
469
        << this->Makefile->GetExecutionFilePath() << "\n"
470
471
472
473
474
475
476
477
478
479
480
        << "affects policy settings, so it requires this policy to be set.";
      this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
      }
      break;
    case cmPolicies::OLD:
    case cmPolicies::NEW:
      // The script set this policy.  We assume the purpose of the
      // script is to initialize policies for its includer, and since
      // the policy is now set for later scripts, we do not warn.
      break;
    }
Brad King's avatar
Brad King committed
481
482
}

483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
class cmParseFileScope
{
public:
  cmParseFileScope(cmMakefile* mf)
    : Makefile(mf)
  {
    this->Makefile->ContextStack.push_back(&this->Context);
  }

  ~cmParseFileScope()
  {
    this->Makefile->ContextStack.pop_back();
  }

private:
  cmMakefile* Makefile;
499
  cmCommandContext Context;
500
501
};

Stephen Kelly's avatar
Stephen Kelly committed
502
bool cmMakefile::ReadDependentFile(const char* filename, bool noPolicyScope)
503
{
504
505
  this->AddDefinition("CMAKE_PARENT_LIST_FILE",
                      this->GetDefinition("CMAKE_CURRENT_LIST_FILE"));
506
507
508
509
  std::string filenametoread =
    cmSystemTools::CollapseFullPath(filename,
                                    this->GetCurrentSourceDirectory());

510
  IncludeScope incScope(this, filenametoread, noPolicyScope);
511
512

  cmListFile listFile;
513
514
  {
  cmParseFileScope pfs(this);
515
516
517
518
  if (!listFile.ParseFile(filenametoread.c_str(), false, this))
    {
    return false;
    }
519
520
  }

521
  this->ReadListFile(listFile, filenametoread);
522
523
524
525
  if(cmSystemTools::GetFatalErrorOccured())
    {
    incScope.Quiet();
    }
526
  return true;
527
528
}

529
530
531
class cmMakefile::ListFileScope
{
public:
532
  ListFileScope(cmMakefile* mf, std::string const& filenametoread)
533
534
    : Makefile(mf), ReportError(true)
  {
535
536
537
538
539
540
541
    long line = 0;
    std::string name;
    if (!this->Makefile->ContextStack.empty())
      {
      line = this->Makefile->ContextStack.back()->Line;
      name = this->Makefile->ContextStack.back()->Name;
      }
542
543
    this->Makefile->StateSnapshot =
        this->Makefile->GetState()->CreateInlineListFileSnapshot(
544
          this->Makefile->StateSnapshot, name, line, filenametoread);
545
    assert(this->Makefile->StateSnapshot.IsValid());
546

547
    this->Makefile->PushFunctionBlockerBarrier();
548
549
550
551
552
  }

  ~ListFileScope()
  {
    this->Makefile->PopPolicyBarrier(this->ReportError);
553
    this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
554
555
556
557
558
559
560
561
  }

  void Quiet() { this->ReportError = false; }
private:
  cmMakefile* Makefile;
  bool ReportError;
};

Stephen Kelly's avatar
Stephen Kelly committed
562
bool cmMakefile::ReadListFile(const char* filename)
563
{
564
  std::string filenametoread =
Stephen Kelly's avatar
Stephen Kelly committed
565
    cmSystemTools::CollapseFullPath(filename,
566
                                    this->GetCurrentSourceDirectory());
567

568
  ListFileScope scope(this, filenametoread);
569
570

  cmListFile listFile;
571
572
  {
  cmParseFileScope pfs(this);
573
  if (!listFile.ParseFile(filenametoread.c_str(), false, this))
574
    {
575
    return false;
576
    }
577
  }
578

579
  this->ReadListFile(listFile, filenametoread);
580
581
582
583
  if(cmSystemTools::GetFatalErrorOccured())
    {
    scope.Quiet();
    }
584
  return true;
585
586
}

587
588
void cmMakefile::ReadListFile(cmListFile const& listFile,
                              std::string const& filenametoread)
589
{
590
591
  // add this list file to the list of dependencies
  this->ListFiles.push_back(filenametoread);
592

593
594
595
596
597
  std::string currentParentFile
      = this->GetSafeDefinition("CMAKE_PARENT_LIST_FILE");
  std::string currentFile
    = this->GetSafeDefinition("CMAKE_CURRENT_LIST_FILE");

598
599
600
601
  this->AddDefinition("CMAKE_CURRENT_LIST_FILE", filenametoread.c_str());
  this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
                       cmSystemTools::GetFilenamePath(filenametoread).c_str());

602
  this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
603
604
605
  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");

606
  // Run the parsed commands.
Stephen Kelly's avatar
Stephen Kelly committed
607
  const size_t numberFunctions = listFile.Functions.size();
608
  for(size_t i =0; i < numberFunctions; ++i)
609
    {
610
    cmExecutionStatus status;
Stephen Kelly's avatar
Stephen Kelly committed
611
    this->ExecuteCommand(listFile.Functions[i],status);
612
    if(cmSystemTools::GetFatalErrorOccured())
613
      {
614
615
616
617
618
      break;
      }
    if(status.GetReturnInvoked())
      {
      // Exit early due to return command.
619
      break;
620
      }
621
    }
622
  this->CheckForUnusedVariables();
Alexander Neundorf's avatar
   
Alexander Neundorf committed
623

624
625
626
627
628
629
630
  this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str());
  this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str());
  this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
                      cmSystemTools::GetFilenamePath(currentFile).c_str());
  this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
631
}
632

633
//----------------------------------------------------------------------------
634
void cmMakefile::EnforceDirectoryLevelRules() const
635
636
637
638
{
  // Diagnose a violation of CMP0000 if necessary.
  if(this->CheckCMP0000)
    {
639
    std::ostringstream msg;
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
    msg << "No cmake_minimum_required command is present.  "
        << "A line of code such as\n"
        << "  cmake_minimum_required(VERSION "
        << cmVersion::GetMajorVersion() << "."
        << cmVersion::GetMinorVersion()
        << ")\n"
        << "should be added at the top of the file.  "
        << "The version specified may be lower if you wish to "
        << "support older CMake versions for this project.  "
        << "For more information run "
        << "\"cmake --help-policy CMP0000\".";
    switch (this->GetPolicyStatus(cmPolicies::CMP0000))
      {
      case cmPolicies::WARN:
        // Warn because the user did not provide a mimimum required
        // version.
Stephen Kelly's avatar
Stephen Kelly committed
656
        this->IssueMessage(cmake::AUTHOR_WARNING, msg.str());
657
658
659
660
661
662
663
664
      case cmPolicies::OLD:
        // OLD behavior is to use policy version 2.4 set in
        // cmListFileCache.
        break;
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::REQUIRED_ALWAYS:
      case cmPolicies::NEW:
        // NEW behavior is to issue an error.
Stephen Kelly's avatar
Stephen Kelly committed
665
        this->IssueMessage(cmake::FATAL_ERROR, msg.str());
666
667
668
669
670
        cmSystemTools::SetFatalErrorOccured();
        return;
      }
    }
}
671

672
673
674
675
676
677
678
void cmMakefile::AddEvaluationFile(const std::string& inputFile,
                     cmsys::auto_ptr<cmCompiledGeneratorExpression> outputName,
                     cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
                     bool inputIsContent)
{
  this->EvaluationFiles.push_back(
              new cmGeneratorExpressionEvaluationFile(inputFile, outputName,
679
                                                      condition,
680
681
682
683
684
685
686
687
688
                                                      inputIsContent));
}

std::vector<cmGeneratorExpressionEvaluationFile*>
cmMakefile::GetEvaluationFiles() const
{
  return this->EvaluationFiles;
}

689
690
namespace
{
691
  struct file_not_persistent
692
693
  {
    bool operator()(const std::string& path) const
694
695
696
697
      {
      return !(path.find("CMakeTmp") == path.npos &&
               cmSystemTools::FileExists(path.c_str()));
      }
698
699
700
  };
}

701
void cmMakefile::FinalPass()
702
703
{
  // do all the variable expansions here
704
  this->ExpandVariablesCMP0019();
705

706
  // give all the commands a chance to do something
707
  // after the file has been parsed before generation
708
709
  for(std::vector<cmCommand*>::iterator i = this->FinalPassCommands.begin();
      i != this->FinalPassCommands.end(); ++i)
710
711
    {
    (*i)->FinalPass();
712
    }
713

714
715
716
717
718
719
720
  //go through all configured files and see which ones still exist.
  //we don't want cmake to re-run if a configured file is created and deleted
  //during processing as that would make it a transient file that can't
  //influence the build process

  //remove_if will move all items that don't have a valid file name to the
  //back of the vector
721
722
723
724
  std::vector<std::string>::iterator new_output_files_end = std::remove_if(
                                                     this->OutputFiles.begin(),
                                                     this->OutputFiles.end(),
                                                     file_not_persistent() );
725
  //we just have to erase all items at the back
726
727
728
729
730
731
732
733
734
  this->OutputFiles.erase(new_output_files_end, this->OutputFiles.end() );

  //if a configured file is used as input for another configured file,
  //and then deleted it will show up in the input list files so we
  //need to scan those too
  std::vector<std::string>::iterator new_list_files_end = std::remove_if(
                                                   this->ListFiles.begin(),
                                                   this->ListFiles.end(),
                                                   file_not_persistent() );
735

736
  this->ListFiles.erase(new_list_files_end, this->ListFiles.end() );
737
738
}

Bill Hoffman's avatar
Bill Hoffman committed
739
// Generate the output file
740
void cmMakefile::ConfigureFinalPass()
741
742
{
  this->FinalPass();
743
744
  const char* oldValue
    = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
745
746
  if (oldValue && cmSystemTools::VersionCompare(
        cmSystemTools::OP_LESS, oldValue, "2.4"))
747
    {
748
749
750
751
752
753
    this->IssueMessage(
      cmake::FATAL_ERROR,
      "You have set CMAKE_BACKWARDS_COMPATIBILITY to a CMake version less "
      "than 2.4. This version of CMake only supports backwards compatibility "
      "with CMake 2.4 or later. For compatibility with older versions please "
      "use any CMake 2.8.x release or lower.");
754
    }
Ken Martin's avatar
Ken Martin committed
755
756
  for (cmTargets::iterator l = this->Targets.begin();
       l != this->Targets.end(); l++)
757
    {
758
759
760
761
    if (l->second.GetType() == cmTarget::INTERFACE_LIBRARY)
      {
      continue;
      }
762
    l->second.FinishConfigure();
763
    }
764
765
}

766
767
//----------------------------------------------------------------------------
void
768
cmMakefile::AddCustomCommandToTarget(const std::string& target,
769
                                   const std::vector<std::string>& byproducts,
770
771
772
                                     const std::vector<std::string>& depends,
                                     const cmCustomCommandLines& commandLines,
                                     cmTarget::CustomCommandType type,
773
                                     const char* comment,
774
                                     const char* workingDir,
775
                                     bool escapeOldStyle,
776
                                     bool uses_terminal)
777
{
778
  // Find the target to which to add the custom command.
Ken Martin's avatar
Ken Martin committed
779
  cmTargets::iterator ti = this->Targets.find(target);
780
781

  if(ti == this->Targets.end())
782
    {
783
784
    cmake::MessageType messageType = cmake::AUTHOR_WARNING;
    bool issueMessage = false;
785
    std::ostringstream e;
786
    switch(this->GetPolicyStatus(cmPolicies::CMP0040))
Brad King's avatar
Brad King committed
787
      {
788
      case cmPolicies::WARN:
Stephen Kelly's avatar
Stephen Kelly committed
789
        e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0040) << "\n";
790
791
792
793
794
795
796
797
        issueMessage = true;
      case cmPolicies::OLD:
        break;
      case cmPolicies::NEW:
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::REQUIRED_ALWAYS:
        issueMessage = true;
        messageType = cmake::FATAL_ERROR;
Brad King's avatar
Brad King committed
798
      }
799
800

    if(issueMessage)
801
      {
802
      e << "The target name \"" << target << "\" is unknown in this context.";
Stephen Kelly's avatar
Stephen Kelly committed
803
      IssueMessage(messageType, e.str());
804
      }
805
806
807
808
809
810

      return;
    }

  if(ti->second.GetType() == cmTarget::OBJECT_LIBRARY)
    {
811
    std::ostringstream e;
812
813
814
815
816
    e << "Target \"" << target << "\" is an OBJECT library "
      "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands.";
    this->IssueMessage(cmake::FATAL_ERROR, e.str());
    return;
    }
817
818
  if(ti->second.GetType() == cmTarget::INTERFACE_LIBRARY)
    {
819
    std::ostringstream e;
820
821
822
823
824
    e << "Target \"" << target << "\" is an INTERFACE library "
      "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands.";
    this->IssueMessage(cmake::FATAL_ERROR, e.str());
    return;
    }
825
826
827
828
829
830
831
832
833
834
835

  // Always create the byproduct sources and mark them generated.
  for(std::vector<std::string>::const_iterator o = byproducts.begin();
      o != byproducts.end(); ++o)
    {
    if(cmSourceFile* out = this->GetOrCreateSource(*o, true))
      {
      out->SetProperty("GENERATED", "1");
      }
    }

836
837
  // Add the command to the appropriate build step for the target.
  std::vector<std::string> no_output;
838
  cmCustomCommand cc(this, no_output, byproducts, depends,
839
840
841
                     commandLines, comment, workingDir);
  cc.SetEscapeOldStyle(escapeOldStyle);
  cc.SetEscapeAllowMakeVars(true);
842
  cc.SetUsesTerminal(uses_terminal);
843
844
845
846
847
848
849
850
851
852
853
  switch(type)
    {
    case cmTarget::PRE_BUILD:
      ti->second.AddPreBuildCommand(cc);
      break;
    case cmTarget::PRE_LINK:
      ti->second.AddPreLinkCommand(cc);
      break;
    case cmTarget::POST_BUILD:
      ti->second.AddPostBuildCommand(cc);
      break;
854
855
856
    }
}

857
//----------------------------------------------------------------------------
858
cmSourceFile*
859
cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
860
                                  const std::vector<std::string>& byproducts,
861
                                     const std::vector<std::string>& depends,
862
                                     const std::string& main_dependency,
863
864
                                     const cmCustomCommandLines& commandLines,
                                     const char* comment,
865
                                     const char* workingDir,
866
                                     bool replace,
867
868
                                     bool escapeOldStyle,
                                     bool uses_terminal)
869
{
870
871
872
873
  // Make sure there is at least one output.
  if(outputs.empty())
    {
    cmSystemTools::Error("Attempt to add a custom rule with no output!");
874
    return 0;
875
876
    }

877
878
879
880
881
882
883
  // Validate custom commands.  TODO: More strict?
  for(cmCustomCommandLines::const_iterator i=commandLines.begin();
      i != commandLines.end(); ++i)
    {
    cmCustomCommandLine const& cl = *i;
    if(!cl.empty() && !cl[0].empty() && cl[0][0] == '"')
      {
884
      std::ostringstream e;
885
886
      e << "COMMAND may not contain literal quotes:\n  " << cl[0] << "\n";
      this->IssueMessage(cmake::FATAL_ERROR, e.str());
887
      return 0;
888
889
890
      }
    }

891
892
  // Choose a source file on which to store the custom command.
  cmSourceFile* file = 0;
893
  if(!commandLines.empty() && !main_dependency.empty())
894
895
896
897
898
    {
    // The main dependency was specified.  Use it unless a different
    // custom command already used it.
    file = this->GetSource(main_dependency);
    if(file && file->GetCustomCommand() && !replace)
899
      {
900
901
      // The main dependency already has a custom command.
      if(commandLines == file->GetCustomCommand()->GetCommandLines())
902
        {
903
904
        // The existing custom command is identical.  Silently ignore
        // the duplicate.
905
        return file;
906
907
908
        }
      else
        {
909
910
911
        // The existing custom command is different.  We need to
        // generate a rule file for this new command.
        file = 0;
912
        }
913
      }
914
    else if (!file)
915
      {