cmMakefile.cxx 168 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
19
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
20
#include "cmCommands.h"
Stephen Kelly's avatar
Stephen Kelly committed
21
#include "cmState.h"
22
#include "cmFunctionBlocker.h"
23
#include "cmListFileCache.h"
24
#include "cmCommandArgumentParserHelper.h"
25
#include "cmGeneratorExpression.h"
26
#include "cmTest.h"
27
28
29
#ifdef CMAKE_BUILD_WITH_CMAKE
#  include "cmVariableWatch.h"
#endif
30
#include "cmInstallGenerator.h"
31
#include "cmTestGenerator.h"
32
#include "cmDefinitions.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 <stack>
42
#include <list>
43
#include <ctype.h> // for isspace
44
#include <assert.h>
45

46
47
48
class cmMakefile::Internals
{
public:
49
  std::list<cmDefinitions> VarStack;
50
51
  std::stack<std::set<std::string> > VarInitStack;
  std::stack<std::set<std::string> > VarUsageStack;
52
  bool IsSourceFileTryCompile;
53
54
55

  void PushDefinitions()
  {
56
    this->VarStack.push_back(cmDefinitions());
57
58
59
60
  }

  void InitializeDefinitions(cmMakefile* parent)
  {
61
62
63
    this->VarStack.back() =
        cmDefinitions::MakeClosure(parent->Internal->VarStack.rbegin(),
                                   parent->Internal->VarStack.rend());
64
65
66
67
  }

  const char* GetDefinition(std::string const& name)
  {
68
69
    return cmDefinitions::Get(name, this->VarStack.rbegin(),
                                    this->VarStack.rend());
70
71
72
73
  }

  void SetDefinition(std::string const& name, std::string const& value)
  {
74
    this->VarStack.back().Set(name, value.c_str());
75
76
77
78
  }

  void RemoveDefinition(std::string const& name)
  {
79
80
81
    if (this->VarStack.size() > 1)
      {
      // In lower scopes we store keys, defined or not.
82
      this->VarStack.back().Set(name, 0);
83
84
85
      }
    else
      {
86
      this->VarStack.back().Erase(name);
87
      }
88
89
  }

90
  std::vector<std::string> LocalKeys() const
91
  {
92
    return this->VarStack.back().LocalKeys();
93
94
  }

95
  std::vector<std::string> ClosureKeys() const
96
  {
97
98
    return cmDefinitions::ClosureKeys(this->VarStack.rbegin(),
                                      this->VarStack.rend());
99
100
101
102
  }

  void PopDefinitions()
  {
103
    this->VarStack.pop_back();
104
105
106
107
  }

  bool RaiseScope(std::string const& var, const char* varDef, cmMakefile* mf)
  {
108
    assert(this->VarStack.size() > 0);
109

110
111
112
    std::list<cmDefinitions>::reverse_iterator it = this->VarStack.rbegin();
    ++it;
    if(it == this->VarStack.rend())
113
      {
114
      if(cmLocalGenerator* plg = mf->GetLocalGenerator()->GetParent())
115
        {
116
117
118
119
120
121
122
123
124
125
126
127
128
        // Update the definition in the parent directory top scope.  This
        // directory's scope was initialized by the closure of the parent
        // scope, so we do not need to localize the definition first.
        cmMakefile* parent = plg->GetMakefile();
        if (varDef)
          {
          parent->AddDefinition(var, varDef);
          }
        else
          {
          parent->RemoveDefinition(var);
          }
        return true;
129
130
131
        }
      else
        {
132
        return false;
133
134
        }
      }
135
136
137
138
139
    // First localize the definition in the current scope.
    this->GetDefinition(var);

    // Now update the definition in the parent scope.
    it->Set(var, varDef);
140
141
    return true;
  }
142
143
};

144
// default is not to be building executables
145
cmMakefile::cmMakefile(cmLocalGenerator* localGenerator)
Stephen Kelly's avatar
Stephen Kelly committed
146
147
  : Internal(new Internals),
    LocalGenerator(localGenerator),
148
    StateSnapshot(localGenerator->GetStateSnapshot())
149
{
150
151
152
  this->Internal->PushDefinitions();
  this->Internal->VarInitStack.push(std::set<std::string>());
  this->Internal->VarUsageStack.push(std::set<std::string>());
153
  this->Internal->IsSourceFileTryCompile = false;
154

155
156
157
  // Initialize these first since AddDefaultDefinitions calls AddDefinition
  this->WarnUnused = false;
  this->CheckSystemVars = false;
158

159
160
161
  this->GeneratingBuildSystem = false;
  this->SuppressWatches = false;

162
  // Setup the default include file regular expression (match everything).
Ken Martin's avatar
Ken Martin committed
163
  this->IncludeFileRegularExpression = "^.*$";
164
  // Setup the default include complaint regular expression (match nothing).
Ken Martin's avatar
Ken Martin committed
165
  this->ComplainFileRegularExpression = "^$";
166
  // Source and header file extensions that we can handle
167

168
  // Set up a list of source and header extensions
Alexander Neundorf's avatar
   
Alexander Neundorf committed
169
  // these are used to find files when the extension
170
  // is not given
171
  // The "c" extension MUST precede the "C" extension.
Ken Martin's avatar
Ken Martin committed
172
173
  this->SourceFileExtensions.push_back( "c" );
  this->SourceFileExtensions.push_back( "C" );
Alexander Neundorf's avatar
   
Alexander Neundorf committed
174

Ken Martin's avatar
Ken Martin committed
175
176
177
178
179
  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
180
  this->SourceFileExtensions.push_back( "M" );
Ken Martin's avatar
Ken Martin committed
181
182
183
  this->SourceFileExtensions.push_back( "mm" );

  this->HeaderFileExtensions.push_back( "h" );
184
  this->HeaderFileExtensions.push_back( "hh" );
Ken Martin's avatar
Ken Martin committed
185
186
187
188
189
190
  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
191

Ken Martin's avatar
Ken Martin committed
192
  this->DefineFlags = " ";
193

194
  this->AddDefaultDefinitions();
195

196
197
198
  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/.+-]+@)");
199
  this->cmNamedCurly.compile("^[A-Za-z0-9/_.+-]+{");
200
201
202

  // Enter a policy level for this directory.
  this->PushPolicy();
203

Brad King's avatar
Brad King committed
204
205
206
  // Protect the directory-level policies.
  this->PushPolicyBarrier();

207
208
209
  // push empty loop block
  this->PushLoopBlockBarrier();

210
211
212
  // By default the check is not done.  It is enabled by
  // cmListFileCache in the top level if necessary.
  this->CheckCMP0000 = false;
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245

#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

  this->Properties.SetCMakeInstance(this->GetCMakeInstance());
  this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused();
  this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars();

  {
  const char* dir = this->GetCMakeInstance()->GetHomeDirectory();
  this->AddDefinition("CMAKE_SOURCE_DIR", dir);
  if ( !this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR") )
    {
    this->AddDefinition("CMAKE_CURRENT_SOURCE_DIR", dir);
    }
  }
  {
  const char* dir = this->GetCMakeInstance()->GetHomeOutputDirectory();
  this->AddDefinition("CMAKE_BINARY_DIR", dir);
  if ( !this->GetDefinition("CMAKE_CURRENT_BINARY_DIR") )
    {
    this->AddDefinition("CMAKE_CURRENT_BINARY_DIR", dir);
    }
  }
246
}
247

248
249
cmMakefile::~cmMakefile()
{
250
251
252
253
254
255
256
  cmDeleteAll(this->InstallGenerators);
  cmDeleteAll(this->TestGenerators);
  cmDeleteAll(this->SourceFiles);
  cmDeleteAll(this->Tests);
  cmDeleteAll(this->ImportedTargetsOwned);
  cmDeleteAll(this->FinalPassCommands);
  cmDeleteAll(this->FunctionBlockers);
Ken Martin's avatar
Ken Martin committed
257
  this->FunctionBlockers.clear();
258
259
260
261
262
  if (this->PolicyStack.size() != 1)
  {
    cmSystemTools::Error("Internal CMake Error, Policy Stack has not been"
      " popped properly");
  }
263
264
}

Alexander Neundorf's avatar
   
Alexander Neundorf committed
265
void cmMakefile::PrintStringVector(const char* s,
Ken Martin's avatar
Ken Martin committed
266
                                   const std::vector<std::string>& v) const
267
{
268
  std::cout << s << ": ( \n" << cmWrap('"', v, '"', " ") << ")\n";
269
270
}

Ken Martin's avatar
Ken Martin committed
271
void cmMakefile
Alexander Neundorf's avatar
   
Alexander Neundorf committed
272
::PrintStringVector(const char* s,
273
                    const std::vector<std::pair<std::string, bool> >& v) const
274
275
{
  std::cout << s << ": ( \n";
276
  for(std::vector<std::pair<std::string, bool> >::const_iterator i
Ken Martin's avatar
Ken Martin committed
277
        = v.begin(); i != v.end(); ++i)
278
    {
279
    std::cout << i->first << " " << i->second;
280
281
282
283
    }
  std::cout << " )\n";
}

284
285

// call print on all the classes in the makefile
286
void cmMakefile::Print() const
287
{
288
  // print the class lists
289
  std::cout << "classes:\n";
290

Ken Martin's avatar
Ken Martin committed
291
292
293
  std::cout << " this->Targets: ";
  for (cmTargets::iterator l = this->Targets.begin();
       l != this->Targets.end(); l++)
294
295
296
297
    {
    std::cout << l->first << std::endl;
    }

Alexander Neundorf's avatar
   
Alexander Neundorf committed
298
  std::cout << " this->StartOutputDirectory; " <<
299
    this->GetCurrentBinaryDirectory() << std::endl;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
300
  std::cout << " this->HomeOutputDirectory; " <<
301
    this->GetHomeOutputDirectory() << std::endl;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
302
  std::cout << " this->cmStartDirectory; " <<
303
    this->GetCurrentSourceDirectory() << std::endl;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
304
  std::cout << " this->cmHomeDirectory; " <<
305
    this->GetHomeDirectory() << std::endl;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
306
  std::cout << " this->ProjectName; "
307
            <<  this->ProjectName << std::endl;
Ken Martin's avatar
Ken Martin committed
308
  this->PrintStringVector("this->LinkDirectories", this->LinkDirectories);
309
#if defined(CMAKE_BUILD_WITH_CMAKE)
Alexander Neundorf's avatar
   
Alexander Neundorf committed
310
  for( std::vector<cmSourceGroup>::const_iterator i =
Ken Martin's avatar
Ken Martin committed
311
         this->SourceGroups.begin(); i != this->SourceGroups.end(); ++i)
312
    {
313
    std::cout << "Source Group: " << i->GetName() << std::endl;
314
    }
315
#endif
316
317
}

318
//----------------------------------------------------------------------------
Bill Hoffman's avatar
Bill Hoffman committed
319
320
void cmMakefile::IssueMessage(cmake::MessageType t,
                              std::string const& text) const
321
{
322
  // Collect context information.
323
324
325
326
327
328
  cmLocalGenerator* localGen = this->GetLocalGenerator();
  if(this->CallStack.empty() && this->GetCMakeInstance()->GetIsInTryCompile())
    {
    localGen = 0;
    }
  cmListFileBacktrace backtrace(localGen);
329
  if(!this->CallStack.empty())
330
    {
331
    if((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR))
332
      {
333
      this->CallStack.back().Status->SetNestedError(true);
334
      }
Ben Boeckel's avatar
Ben Boeckel committed
335
    backtrace = this->GetBacktrace();
336
    }
337
  else
338
    {
339
    cmListFileContext lfc;
340
341
342
    if(this->ListFileStack.empty())
      {
      // We are not processing the project.  Add the directory-level context.
343
      lfc.FilePath = this->GetCurrentSourceDirectory();
344
345
346
347
348
349
350
351
      lfc.FilePath += "/CMakeLists.txt";
      }
    else
      {
      // We are processing the project but are not currently executing a
      // command.  Add whatever context information we have.
      lfc.FilePath = this->ListFileStack.back();
      }
352
    lfc.Line = 0;
353
    backtrace.Append(lfc);
354
    }
355

356
357
358
  // Issue the message.
  this->GetCMakeInstance()->IssueMessage(t, text, backtrace);
}
359

360
//----------------------------------------------------------------------------
Ben Boeckel's avatar
Ben Boeckel committed
361
cmListFileBacktrace cmMakefile::GetBacktrace() const
362
{
363
  cmListFileBacktrace backtrace(this->GetLocalGenerator());
364
365
  for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin();
      i != this->CallStack.rend(); ++i)
366
    {
367
    backtrace.Append(*i->Context);
368
    }
Ben Boeckel's avatar
Ben Boeckel committed
369
  return backtrace;
370
371
}

372
373
374
375
376
377
//----------------------------------------------------------------------------
cmListFileContext cmMakefile::GetExecutionContext() const
{
  return *this->CallStack.back().Context;
}

378
//----------------------------------------------------------------------------
379
void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const
380
{
381
  std::ostringstream msg;
382
383
384
385
386
387
388
389
390
391
392
393
  msg << lff.FilePath << "(" << lff.Line << "):  ";
  msg << lff.Name << "(";
  for(std::vector<cmListFileArgument>::const_iterator i =
        lff.Arguments.begin(); i != lff.Arguments.end(); ++i)
    {
    msg << i->Value;
    msg << " ";
    }
  msg << ")";
  cmSystemTools::Message(msg.str().c_str());
}

394
//----------------------------------------------------------------------------
395
396
bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
                                cmExecutionStatus &status)
Ken Martin's avatar
Ken Martin committed
397
{
398
  bool result = true;
399

400
  // quick return if blocked
401
  if(this->IsFunctionBlocked(lff,status))
402
    {
403
404
    // No error.
    return result;
405
    }
406

Ken Martin's avatar
Ken Martin committed
407
  std::string name = lff.Name;
408

409
410
411
412
413
  // Place this call on the call stack.
  cmMakefileCall stack_manager(this, lff, status);
  static_cast<void>(stack_manager);

  // Lookup the command prototype.
414
  if(cmCommand* proto = this->GetState()->GetCommand(name))
415
416
417
418
419
420
421
    {
    // Clone the prototype.
    cmsys::auto_ptr<cmCommand> pcmd(proto->Clone());
    pcmd->SetMakefile(this);

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

425
      {
426
      // if trace is enabled, print out invoke information
Bill Hoffman's avatar
Bill Hoffman committed
427
428
      if(this->GetCMakeInstance()->GetTrace())
        {
429
        this->PrintCommandTrace(lff);
Bill Hoffman's avatar
Bill Hoffman committed
430
        }
431
432
433
      // Try invoking the command.
      if(!pcmd->InvokeInitialPass(lff.Arguments,status) ||
         status.GetNestedError())
Ken Martin's avatar
Ken Martin committed
434
        {
435
436
437
        if(!status.GetNestedError())
          {
          // The command invocation requested that we report an error.
Bill Hoffman's avatar
Bill Hoffman committed
438
          this->IssueMessage(cmake::FATAL_ERROR, pcmd->GetError());
439
          }
440
        result = false;
441
        if ( this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE)
Ken Martin's avatar
Ken Martin committed
442
          {
443
          cmSystemTools::SetFatalErrorOccured();
Ken Martin's avatar
Ken Martin committed
444
445
          }
        }
446
      else if(pcmd->HasFinalPass())
447
448
        {
        // use the command
449
        this->FinalPassCommands.push_back(pcmd.release());
450
        }
Ken Martin's avatar
Ken Martin committed
451
      }
452
    else if ( this->GetCMakeInstance()->GetWorkingMode() == cmake::SCRIPT_MODE
453
              && !pcmd->IsScriptable() )
454
      {
455
456
457
      std::string error = "Command ";
      error += pcmd->GetName();
      error += "() is not scriptable";
Bill Hoffman's avatar
Bill Hoffman committed
458
      this->IssueMessage(cmake::FATAL_ERROR, error);
459
460
461
      result = false;
      cmSystemTools::SetFatalErrorOccured();
      }
Ken Martin's avatar
Ken Martin committed
462
463
464
    }
  else
    {
465
466
    if(!cmSystemTools::GetFatalErrorOccured())
      {
467
468
469
      std::string error = "Unknown CMake command \"";
      error += lff.Name;
      error += "\".";
Bill Hoffman's avatar
Bill Hoffman committed
470
      this->IssueMessage(cmake::FATAL_ERROR, error);
471
      result = false;
472
      cmSystemTools::SetFatalErrorOccured();
473
      }
Ken Martin's avatar
Ken Martin committed
474
    }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
475

476
  return result;
Ken Martin's avatar
Ken Martin committed
477
478
}

Brad King's avatar
Brad King committed
479
480
481
482
//----------------------------------------------------------------------------
class cmMakefile::IncludeScope
{
public:
483
  IncludeScope(cmMakefile* mf, const char* fname, bool noPolicyScope);
Brad King's avatar
Brad King committed
484
485
486
487
  ~IncludeScope();
  void Quiet() { this->ReportError = false; }
private:
  cmMakefile* Makefile;
488
489
490
  const char* File;
  bool NoPolicyScope;
  bool CheckCMP0011;
Brad King's avatar
Brad King committed
491
  bool ReportError;
492
  void EnforceCMP0011();
Brad King's avatar
Brad King committed
493
494
495
};

//----------------------------------------------------------------------------
496
497
498
499
cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf, const char* fname,
                                       bool noPolicyScope):
  Makefile(mf), File(fname), NoPolicyScope(noPolicyScope),
  CheckCMP0011(false), ReportError(true)
Brad King's avatar
Brad King committed
500
{
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
  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
530
531
532
533
534
535
536
537
538
  // The included file cannot pop our policy scope.
  this->Makefile->PushPolicyBarrier();
}

//----------------------------------------------------------------------------
cmMakefile::IncludeScope::~IncludeScope()
{
  // Enforce matching policy scopes inside the included file.
  this->Makefile->PopPolicyBarrier(this->ReportError);
539
540
541
542
543
544
545

  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.
546
    if(this->CheckCMP0011 && this->Makefile->PolicyStack.back().IsEmpty())
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
      {
      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();
      }
    }
}

//----------------------------------------------------------------------------
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.
      {
573
      std::ostringstream w;
Stephen Kelly's avatar
Stephen Kelly committed
574
      w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0011) << "\n"
575
576
577
578
579
580
581
582
583
584
        << "The included script\n  " << this->File << "\n"
        << "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:
      {
585
      std::ostringstream e;
Stephen Kelly's avatar
Stephen Kelly committed
586
      e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0011) << "\n"
587
588
589
590
591
592
593
594
595
596
597
598
        << "The included script\n  " << this->File << "\n"
        << "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
599
600
}

601
602
bool cmMakefile::ProcessBuildsystemFile(const char* listfile)
{
603
  this->AddDefinition("CMAKE_PARENT_LIST_FILE", listfile);
604
  this->cmCurrentListFile = listfile;
605
  std::string curSrc = this->GetCurrentSourceDirectory();
606
  return this->ReadListFile(listfile, true,
607
                            curSrc == this->GetHomeDirectory());
608
609
}

610
611
bool cmMakefile::ReadDependentFile(const char* listfile, bool noPolicyScope)
{
612
613
  this->AddDefinition("CMAKE_PARENT_LIST_FILE",
                      this->GetDefinition("CMAKE_CURRENT_LIST_FILE"));
614
  this->cmCurrentListFile =
615
    cmSystemTools::CollapseFullPath(listfile,
616
                                    this->GetCurrentSourceDirectory());
617
  return this->ReadListFile(this->cmCurrentListFile.c_str(),
618
619
620
                            noPolicyScope);
}

Brad King's avatar
Brad King committed
621
//----------------------------------------------------------------------------
622
// Parse the given CMakeLists.txt file executing all commands
Anonymous's avatar
Anonymous committed
623
//
624
bool cmMakefile::ReadListFile(const char* listfile,
625
626
                              bool noPolicyScope,
                              bool requireProjectCommand)
627
{
628
629
  std::string filenametoread =
    cmSystemTools::CollapseFullPath(listfile,
630
                                    this->GetCurrentSourceDirectory());
631

632
633
634
635
636
  std::string currentParentFile
      = this->GetSafeDefinition("CMAKE_PARENT_LIST_FILE");
  std::string currentFile
    = this->GetSafeDefinition("CMAKE_CURRENT_LIST_FILE");

637
638
639
640
  this->AddDefinition("CMAKE_CURRENT_LIST_FILE", filenametoread.c_str());
  this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
                       cmSystemTools::GetFilenamePath(filenametoread).c_str());

641
  this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
642
643
644
645
  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");

  this->ListFileStack.push_back(filenametoread);
646

647
  bool res = this->ReadListFileInternal(filenametoread.c_str(),
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
                                        noPolicyScope, requireProjectCommand);

  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");

  this->ListFileStack.pop_back();

  if (res)
    {
    // Check for unused variables
    this->CheckForUnusedVariables();
    }

  return res;
}

bool cmMakefile::ReadListFileInternal(const char* filenametoread,
                                      bool noPolicyScope,
                                      bool requireProjectCommand)
{
673
  cmListFile cacheFile;
674
  if( !cacheFile.ParseFile(filenametoread, requireProjectCommand, this) )
675
676
677
    {
    return false;
    }
678
  // add this list file to the list of dependencies
Ken Martin's avatar
Ken Martin committed
679
  this->ListFiles.push_back( filenametoread);
680
681
682
683

  // Enforce balanced blocks (if/endif, function/endfunction, etc.).
  {
  LexicalPushPop lexScope(this);
684
  IncludeScope incScope(this, filenametoread, noPolicyScope);
685
686

  // Run the parsed commands.
Ken Martin's avatar
Ken Martin committed
687
  const size_t numberFunctions = cacheFile.Functions.size();
688
  for(size_t i =0; i < numberFunctions; ++i)
689
    {
690
691
    cmExecutionStatus status;
    this->ExecuteCommand(cacheFile.Functions[i],status);
692
    if(cmSystemTools::GetFatalErrorOccured())
693
      {
694
695
      // Exit early due to error.
      lexScope.Quiet();
Brad King's avatar
Brad King committed
696
      incScope.Quiet();
697
698
699
700
701
      break;
      }
    if(status.GetReturnInvoked())
      {
      // Exit early due to return command.
702
      break;
703
      }
704
    }
705
  }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
706

707
708
  // If this is the directory-level CMakeLists.txt file then perform
  // some extra checks.
709
710
  if(this->ListFileStack.size() == 1)
    {
711
    this->EnforceDirectoryLevelRules();
712
713
    }

714
715
  return true;
}
716

717
//----------------------------------------------------------------------------
718
void cmMakefile::EnforceDirectoryLevelRules() const
719
720
721
722
{
  // Diagnose a violation of CMP0000 if necessary.
  if(this->CheckCMP0000)
    {
723
    std::ostringstream msg;
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
    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
740
        this->IssueMessage(cmake::AUTHOR_WARNING, msg.str());
741
742
743
744
745
746
747
748
      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
749
        this->IssueMessage(cmake::FATAL_ERROR, msg.str());
750
751
752
753
754
        cmSystemTools::SetFatalErrorOccured();
        return;
      }
    }
}
755

756
757
namespace
{
758
  struct file_not_persistent
759
760
  {
    bool operator()(const std::string& path) const
761
762
763
764
      {
      return !(path.find("CMakeTmp") == path.npos &&
               cmSystemTools::FileExists(path.c_str()));
      }
765
766
767
  };
}

768
void cmMakefile::FinalPass()
769
770
{
  // do all the variable expansions here
771
  this->ExpandVariablesCMP0019();
772

773
  // give all the commands a chance to do something
774
  // after the file has been parsed before generation
775
776
  for(std::vector<cmCommand*>::iterator i = this->FinalPassCommands.begin();
      i != this->FinalPassCommands.end(); ++i)
777
778
    {
    (*i)->FinalPass();
779
    }
780

781
782
783
784
785
786
787
  //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
788
789
790
791
  std::vector<std::string>::iterator new_output_files_end = std::remove_if(
                                                     this->OutputFiles.begin(),
                                                     this->OutputFiles.end(),
                                                     file_not_persistent() );
792
  //we just have to erase all items at the back
793
794
795
796
797
798
799
800
801
  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() );
802

803
  this->ListFiles.erase(new_list_files_end, this->ListFiles.end() );
804
805
}

Bill Hoffman's avatar
Bill Hoffman committed
806
// Generate the output file
807
void cmMakefile::ConfigureFinalPass()
808
809
{
  this->FinalPass();
810
811
  const char* oldValue
    = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
812
813
  if (oldValue && cmSystemTools::VersionCompare(
        cmSystemTools::OP_LESS, oldValue, "2.4"))
814
    {
815
816
817
818
819
820
    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.");
821
    }
Ken Martin's avatar
Ken Martin committed
822
823
  for (cmTargets::iterator l = this->Targets.begin();
       l != this->Targets.end(); l++)
824
    {
825
826
827
828
    if (l->second.GetType() == cmTarget::INTERFACE_LIBRARY)
      {
      continue;
      }
829
    l->second.FinishConfigure();
830
    }
831
832
}

833
834
//----------------------------------------------------------------------------
void
835
cmMakefile::AddCustomCommandToTarget(const std::string& target,
836
                                   const std::vector<std::string>& byproducts,
837
838
839
                                     const std::vector<std::string>& depends,
                                     const cmCustomCommandLines& commandLines,
                                     cmTarget::CustomCommandType type,
840
                                     const char* comment,
841
                                     const char* workingDir,
842
                                     bool escapeOldStyle,
843
                                     bool uses_terminal)
844
{
845
  // Find the target to which to add the custom command.
Ken Martin's avatar
Ken Martin committed
846
  cmTargets::iterator ti = this->Targets.find(target);
847
848

  if(ti == this->Targets.end())
849
    {
850
851
    cmake::MessageType messageType = cmake::AUTHOR_WARNING;
    bool issueMessage = false;
852
    std::ostringstream e;
853
    switch(this->GetPolicyStatus(cmPolicies::CMP0040))
Brad King's avatar
Brad King committed
854
      {
855
      case cmPolicies::WARN:
Stephen Kelly's avatar
Stephen Kelly committed
856
        e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0040) << "\n";
857
858
859
860
861
862
863
864
        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
865
      }
866
867

    if(issueMessage)
868
      {
869
      e << "The target name \"" << target << "\" is unknown in this context.";
Stephen Kelly's avatar
Stephen Kelly committed
870
      IssueMessage(messageType, e.str());
871
      }
872
873
874
875
876
877

      return;
    }

  if(ti->second.GetType() == cmTarget::OBJECT_LIBRARY)
    {
878
    std::ostringstream e;
879
880
881
882
883
    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;
    }
884
885
  if(ti->second.GetType() == cmTarget::INTERFACE_LIBRARY)
    {
886
    std::ostringstream e;
887
888
889
890
891
    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;
    }
892
893
894
895
896
897
898
899
900
901
902

  // 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");
      }
    }

903
904
  // Add the command to the appropriate build step for the target.
  std::vector<std::string> no_output;
905
  cmCustomCommand cc(this, no_output, byproducts, depends,
906
907
908
                     commandLines, comment, workingDir);
  cc.SetEscapeOldStyle(escapeOldStyle);
  cc.SetEscapeAllowMakeVars(true);
909
  cc.SetUsesTerminal(uses_terminal);
910
911
912
913
914
915
916
917
918
919
920
  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;
921
922
923
    }
}

924
//----------------------------------------------------------------------------
925
cmSourceFile*
926
cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
927
                                  const std::vector<std::string>& byproducts,
928
                                     const std::vector<std::string>& depends,
929
                                     const std::string& main_dependency,
930
931
                                     const cmCustomCommandLines& commandLines,
                                     const char* comment,
932
                                     const char* workingDir,
933
                                     bool replace,
934
935
                                     bool escapeOldStyle,
                                     bool uses_terminal)
936
{
937
938
939
940
  // Make sure there is at least one output.
  if(outputs.empty())
    {
    cmSystemTools::Error("Attempt to add a custom rule with no output!");
941
    return 0;
942
943
    }

944
945
946
947
948
949
950
  // 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] == '"')
      {