cmMakefile.cxx 169 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
99
100
101
102
103
104
105
106
    std::vector<std::string> closureKeys;
    std::set<std::string> bound;
    for (std::list<cmDefinitions>::const_reverse_iterator it =
         this->VarStack.rbegin(); it != this->VarStack.rend(); ++it)
      {
      std::vector<std::string> const& localKeys = it->ClosureKeys(bound);
      closureKeys.insert(closureKeys.end(),
                         localKeys.begin(), localKeys.end());
      }
    return closureKeys;
107
108
109
110
  }

  void PopDefinitions()
  {
111
    this->VarStack.pop_back();
112
113
114
115
  }

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

118
119
120
    std::list<cmDefinitions>::reverse_iterator it = this->VarStack.rbegin();
    ++it;
    if(it == this->VarStack.rend())
121
      {
122
      if(cmLocalGenerator* plg = mf->GetLocalGenerator()->GetParent())
123
        {
124
125
126
127
128
129
130
131
132
133
134
135
136
        // 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;
137
138
139
        }
      else
        {
140
        return false;
141
142
        }
      }
143
144
145
146
147
    // First localize the definition in the current scope.
    this->GetDefinition(var);

    // Now update the definition in the parent scope.
    it->Set(var, varDef);
148
149
    return true;
  }
150
151
};

152
// default is not to be building executables
153
cmMakefile::cmMakefile(cmLocalGenerator* localGenerator)
Stephen Kelly's avatar
Stephen Kelly committed
154
155
  : Internal(new Internals),
    LocalGenerator(localGenerator),
156
    StateSnapshot(localGenerator->GetStateSnapshot())
157
{
158
159
160
  this->Internal->PushDefinitions();
  this->Internal->VarInitStack.push(std::set<std::string>());
  this->Internal->VarUsageStack.push(std::set<std::string>());
161
  this->Internal->IsSourceFileTryCompile = false;
162

163
164
165
  // Initialize these first since AddDefaultDefinitions calls AddDefinition
  this->WarnUnused = false;
  this->CheckSystemVars = false;
166

167
168
169
  this->GeneratingBuildSystem = false;
  this->SuppressWatches = false;

170
  // Setup the default include file regular expression (match everything).
Ken Martin's avatar
Ken Martin committed
171
  this->IncludeFileRegularExpression = "^.*$";
172
  // Setup the default include complaint regular expression (match nothing).
Ken Martin's avatar
Ken Martin committed
173
  this->ComplainFileRegularExpression = "^$";
174
  // Source and header file extensions that we can handle
175

176
  // Set up a list of source and header extensions
Alexander Neundorf's avatar
   
Alexander Neundorf committed
177
  // these are used to find files when the extension
178
  // is not given
179
  // The "c" extension MUST precede the "C" extension.
Ken Martin's avatar
Ken Martin committed
180
181
  this->SourceFileExtensions.push_back( "c" );
  this->SourceFileExtensions.push_back( "C" );
Alexander Neundorf's avatar
   
Alexander Neundorf committed
182

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

  this->HeaderFileExtensions.push_back( "h" );
192
  this->HeaderFileExtensions.push_back( "hh" );
Ken Martin's avatar
Ken Martin committed
193
194
195
196
197
198
  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
199

Ken Martin's avatar
Ken Martin committed
200
  this->DefineFlags = " ";
201

202
  this->AddDefaultDefinitions();
203

204
205
206
  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/.+-]+@)");
207
  this->cmNamedCurly.compile("^[A-Za-z0-9/_.+-]+{");
208
209
210

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

Brad King's avatar
Brad King committed
212
213
214
  // Protect the directory-level policies.
  this->PushPolicyBarrier();

215
216
217
  // push empty loop block
  this->PushLoopBlockBarrier();

218
219
220
  // By default the check is not done.  It is enabled by
  // cmListFileCache in the top level if necessary.
  this->CheckCMP0000 = false;
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
246
247
248
249
250
251
252
253

#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);
    }
  }
254
}
255

256
257
cmMakefile::~cmMakefile()
{
258
259
260
261
262
263
264
  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
265
  this->FunctionBlockers.clear();
266
267
268
269
270
  if (this->PolicyStack.size() != 1)
  {
    cmSystemTools::Error("Internal CMake Error, Policy Stack has not been"
      " popped properly");
  }
271
272
}

Alexander Neundorf's avatar
   
Alexander Neundorf committed
273
void cmMakefile::PrintStringVector(const char* s,
Ken Martin's avatar
Ken Martin committed
274
                                   const std::vector<std::string>& v) const
275
{
276
  std::cout << s << ": ( \n" << cmWrap('"', v, '"', " ") << ")\n";
277
278
}

Ken Martin's avatar
Ken Martin committed
279
void cmMakefile
Alexander Neundorf's avatar
   
Alexander Neundorf committed
280
::PrintStringVector(const char* s,
281
                    const std::vector<std::pair<std::string, bool> >& v) const
282
283
{
  std::cout << s << ": ( \n";
284
  for(std::vector<std::pair<std::string, bool> >::const_iterator i
Ken Martin's avatar
Ken Martin committed
285
        = v.begin(); i != v.end(); ++i)
286
    {
287
    std::cout << i->first << " " << i->second;
288
289
290
291
    }
  std::cout << " )\n";
}

292
293

// call print on all the classes in the makefile
294
void cmMakefile::Print() const
295
{
296
  // print the class lists
297
  std::cout << "classes:\n";
298

Ken Martin's avatar
Ken Martin committed
299
300
301
  std::cout << " this->Targets: ";
  for (cmTargets::iterator l = this->Targets.begin();
       l != this->Targets.end(); l++)
302
303
304
305
    {
    std::cout << l->first << std::endl;
    }

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

326
//----------------------------------------------------------------------------
Bill Hoffman's avatar
Bill Hoffman committed
327
328
void cmMakefile::IssueMessage(cmake::MessageType t,
                              std::string const& text) const
329
{
330
  // Collect context information.
331
332
333
334
335
336
  cmLocalGenerator* localGen = this->GetLocalGenerator();
  if(this->CallStack.empty() && this->GetCMakeInstance()->GetIsInTryCompile())
    {
    localGen = 0;
    }
  cmListFileBacktrace backtrace(localGen);
337
  if(!this->CallStack.empty())
338
    {
339
    if((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR))
340
      {
341
      this->CallStack.back().Status->SetNestedError(true);
342
      }
Ben Boeckel's avatar
Ben Boeckel committed
343
    backtrace = this->GetBacktrace();
344
    }
345
  else
346
    {
347
    cmListFileContext lfc;
348
349
350
    if(this->ListFileStack.empty())
      {
      // We are not processing the project.  Add the directory-level context.
351
      lfc.FilePath = this->GetCurrentSourceDirectory();
352
353
354
355
356
357
358
359
      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();
      }
360
361
    lfc.Line = 0;
    backtrace.push_back(lfc);
362
    }
363

364
365
366
  // Issue the message.
  this->GetCMakeInstance()->IssueMessage(t, text, backtrace);
}
367

368
//----------------------------------------------------------------------------
Ben Boeckel's avatar
Ben Boeckel committed
369
cmListFileBacktrace cmMakefile::GetBacktrace() const
370
{
371
  cmListFileBacktrace backtrace(this->GetLocalGenerator());
372
373
  for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin();
      i != this->CallStack.rend(); ++i)
374
    {
375
    backtrace.push_back(*i->Context);
376
    }
Ben Boeckel's avatar
Ben Boeckel committed
377
  return backtrace;
378
379
}

380
//----------------------------------------------------------------------------
381
void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const
382
{
383
  std::ostringstream msg;
384
385
386
387
388
389
390
391
392
393
394
395
  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());
}

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

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

Ken Martin's avatar
Ken Martin committed
409
  std::string name = lff.Name;
410

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

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

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

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

478
  return result;
Ken Martin's avatar
Ken Martin committed
479
480
}

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

//----------------------------------------------------------------------------
498
499
500
501
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
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
530
531
  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
532
533
534
535
536
537
538
539
540
  // 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);
541
542
543
544
545
546
547

  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.
548
    if(this->CheckCMP0011 && this->Makefile->PolicyStack.back().IsEmpty())
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
      {
      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.
      {
575
      std::ostringstream w;
Stephen Kelly's avatar
Stephen Kelly committed
576
      w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0011) << "\n"
577
578
579
580
581
582
583
584
585
586
        << "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:
      {
587
      std::ostringstream e;
Stephen Kelly's avatar
Stephen Kelly committed
588
      e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0011) << "\n"
589
590
591
592
593
594
595
596
597
598
599
600
        << "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
601
602
}

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

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

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

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

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

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

  this->ListFileStack.push_back(filenametoread);
647

648
  bool res = this->ReadListFileInternal(filenametoread.c_str(),
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
                                        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)
{
674
  cmListFile cacheFile;
675
  if( !cacheFile.ParseFile(filenametoread, requireProjectCommand, this) )
676
677
678
    {
    return false;
    }
679
  // add this list file to the list of dependencies
Ken Martin's avatar
Ken Martin committed
680
  this->ListFiles.push_back( filenametoread);
681
682
683
684

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

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

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

715
716
  return true;
}
717

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

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

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

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

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

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

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

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

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

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

      return;
    }

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

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

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

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

945
946
947
948
949
950
951
  // 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] == '"')
      {
952
      std::ostringstream e;
Brad King's avatar