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
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
  this->LocalGenerator = localGenerator;
202

203
  this->AddDefaultDefinitions();
204

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

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

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

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

219
220
221
  // By default the check is not done.  It is enabled by
  // cmListFileCache in the top level if necessary.
  this->CheckCMP0000 = false;
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
254

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

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

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

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

293
294

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  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.
549
    if(this->CheckCMP0011 && this->Makefile->PolicyStack.back().IsEmpty())
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
575
      {
      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.
      {
576
      std::ostringstream w;
Stephen Kelly's avatar
Stephen Kelly committed
577
      w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0011) << "\n"
578
579
580
581
582
583
584
585
586
587
        << "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:
      {
588
      std::ostringstream e;
Stephen Kelly's avatar
Stephen Kelly committed
589
      e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0011) << "\n"
590
591
592
593
594
595
596
597
598
599
600
601
        << "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
602
603
}

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

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

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

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

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

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

  this->ListFileStack.push_back(filenametoread);
648

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

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

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

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

716
717
  return true;
}
718

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

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

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

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

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

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

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

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

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

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

      return;
    }

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

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

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

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

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