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
382
383
384
385
//----------------------------------------------------------------------------
cmListFileContext cmMakefile::GetExecutionContext() const
{
  return *this->CallStack.back().Context;
}

386
//----------------------------------------------------------------------------
387
void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const
388
{
389
  std::ostringstream msg;
390
391
392
393
394
395
396
397
398
399
400
401
  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());
}

402
//----------------------------------------------------------------------------
403
404
bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
                                cmExecutionStatus &status)
Ken Martin's avatar
Ken Martin committed
405
{
406
  bool result = true;
407

408
  // quick return if blocked
409
  if(this->IsFunctionBlocked(lff,status))
410
    {
411
412
    // No error.
    return result;
413
    }
414

Ken Martin's avatar
Ken Martin committed
415
  std::string name = lff.Name;
416

417
418
419
420
421
  // Place this call on the call stack.
  cmMakefileCall stack_manager(this, lff, status);
  static_cast<void>(stack_manager);

  // Lookup the command prototype.
422
  if(cmCommand* proto = this->GetState()->GetCommand(name))
423
424
425
426
427
428
429
    {
    // Clone the prototype.
    cmsys::auto_ptr<cmCommand> pcmd(proto->Clone());
    pcmd->SetMakefile(this);

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

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

484
  return result;
Ken Martin's avatar
Ken Martin committed
485
486
}

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

//----------------------------------------------------------------------------
504
505
506
507
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
508
{
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
  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
538
539
540
541
542
543
544
545
546
  // 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);
547
548
549
550
551
552
553

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

609
610
bool cmMakefile::ProcessBuildsystemFile(const char* listfile)
{
611
  this->AddDefinition("CMAKE_PARENT_LIST_FILE", listfile);
612
  this->cmCurrentListFile = listfile;
613
  std::string curSrc = this->GetCurrentSourceDirectory();
614
  return this->ReadListFile(listfile, true,
615
                            curSrc == this->GetHomeDirectory());
616
617
}

618
619
bool cmMakefile::ReadDependentFile(const char* listfile, bool noPolicyScope)
{
620
  this->AddDefinition("CMAKE_PARENT_LIST_FILE", this->GetCurrentListFile());
621
  this->cmCurrentListFile =
622
    cmSystemTools::CollapseFullPath(listfile,
623
                                    this->GetCurrentSourceDirectory());
624
  return this->ReadListFile(this->cmCurrentListFile.c_str(),
625
626
627
                            noPolicyScope);
}

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

639
640
641
642
643
  std::string currentParentFile
      = this->GetSafeDefinition("CMAKE_PARENT_LIST_FILE");
  std::string currentFile
    = this->GetSafeDefinition("CMAKE_CURRENT_LIST_FILE");

644
645
646
647
  this->AddDefinition("CMAKE_CURRENT_LIST_FILE", filenametoread.c_str());
  this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
                       cmSystemTools::GetFilenamePath(filenametoread).c_str());

648
  this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
649
650
651
652
  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");

  this->ListFileStack.push_back(filenametoread);
653

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

  // Enforce balanced blocks (if/endif, function/endfunction, etc.).
  {
  LexicalPushPop lexScope(this);
691
  IncludeScope incScope(this, filenametoread, noPolicyScope);
692
693

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

714
715
  // If this is the directory-level CMakeLists.txt file then perform
  // some extra checks.
716
717
  if(this->ListFileStack.size() == 1)
    {
718
    this->EnforceDirectoryLevelRules();
719
720
    }

721
722
  return true;
}
723

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

763
764
namespace
{
765
  struct file_not_persistent
766
767
  {
    bool operator()(const std::string& path) const
768
769
770
771
      {
      return !(path.find("CMakeTmp") == path.npos &&
               cmSystemTools::FileExists(path.c_str()));
      }
772
773
774
  };
}

775
void cmMakefile::FinalPass()
776
777
{
  // do all the variable expansions here
778
  this->ExpandVariablesCMP0019();
779

780
  // give all the commands a chance to do something
781
  // after the file has been parsed before generation
782
783
  for(std::vector<cmCommand*>::iterator i = this->FinalPassCommands.begin();
      i != this->FinalPassCommands.end(); ++i)
784
785
    {
    (*i)->FinalPass();
786
    }
787

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

810
  this->ListFiles.erase(new_list_files_end, this->ListFiles.end() );
811
812
}

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

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

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

    if(issueMessage)
875
      {
876
      e << "The target name \"" << target << "\" is unknown in this context.";
Stephen Kelly's avatar
Stephen Kelly committed
877
      IssueMessage(messageType, e.str());
878
      }
879
880
881
882
883
884

      return;
    }

  if(ti->second.GetType() == cmTarget::OBJECT_LIBRARY)
    {
885
    std::ostringstream e;
886
887
888
889
890
    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;
    }
891
892
  if(ti->second.GetType() == cmTarget::INTERFACE_LIBRARY)
    {
893
    std::ostringstream e;
894
895
896
897
898
    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;
    }
899
900
901
902
903
904
905
906
907
908
909

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

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

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

951
952
953
954
955
956
957
  // Validate custom commands.  TODO: More strict?
  for(cmCustomCommandLines::const_iterator i=commandLines.begin();
      i != commandLines.end(); ++i)
    {