cmMakefile.cxx 171 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"
21
#include "cmCacheManager.h"
Stephen Kelly's avatar
Stephen Kelly committed
22
#include "cmState.h"
23
#include "cmFunctionBlocker.h"
24
#include "cmListFileCache.h"
25
#include "cmCommandArgumentParserHelper.h"
26
#include "cmGeneratorExpression.h"
27
#include "cmTest.h"
28
29
30
#ifdef CMAKE_BUILD_WITH_CMAKE
#  include "cmVariableWatch.h"
#endif
31
#include "cmInstallGenerator.h"
32
#include "cmTestGenerator.h"
33
#include "cmDefinitions.h"
34
#include "cmAlgorithms.h"
35
#include "cmake.h"
36
#include <stdlib.h> // required for atoi
37
38

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

42
#include <stack>
43
#include <list>
44
#include <ctype.h> // for isspace
45
#include <assert.h>
46

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

56
// default is not to be building executables
57
cmMakefile::cmMakefile(): Internal(new Internals)
58
{
59
  const cmDefinitions& defs = cmDefinitions();
60
  const std::set<std::string> globalKeys = defs.LocalKeys();
61
62
  this->Internal->VarStack.push(defs);
  this->Internal->VarInitStack.push(globalKeys);
63
  this->Internal->VarUsageStack.push(globalKeys);
64
  this->Internal->IsSourceFileTryCompile = false;
65

66
67
68
  // Initialize these first since AddDefaultDefinitions calls AddDefinition
  this->WarnUnused = false;
  this->CheckSystemVars = false;
69

70
  // Setup the default include file regular expression (match everything).
Ken Martin's avatar
Ken Martin committed
71
  this->IncludeFileRegularExpression = "^.*$";
72
  // Setup the default include complaint regular expression (match nothing).
Ken Martin's avatar
Ken Martin committed
73
  this->ComplainFileRegularExpression = "^$";
74
  // Source and header file extensions that we can handle
75

76
  // Set up a list of source and header extensions
Alexander Neundorf's avatar
   
Alexander Neundorf committed
77
  // these are used to find files when the extension
78
  // is not given
79
  // The "c" extension MUST precede the "C" extension.
Ken Martin's avatar
Ken Martin committed
80
81
  this->SourceFileExtensions.push_back( "c" );
  this->SourceFileExtensions.push_back( "C" );
Alexander Neundorf's avatar
   
Alexander Neundorf committed
82

Ken Martin's avatar
Ken Martin committed
83
84
85
86
87
  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
88
  this->SourceFileExtensions.push_back( "M" );
Ken Martin's avatar
Ken Martin committed
89
90
91
  this->SourceFileExtensions.push_back( "mm" );

  this->HeaderFileExtensions.push_back( "h" );
92
  this->HeaderFileExtensions.push_back( "hh" );
Ken Martin's avatar
Ken Martin committed
93
94
95
96
97
98
  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
99

Ken Martin's avatar
Ken Martin committed
100
101
  this->DefineFlags = " ";
  this->LocalGenerator = 0;
102

103
  this->AddDefaultDefinitions();
104
  this->Initialize();
105
  this->GeneratingBuildSystem = false;
106

107
  this->SuppressWatches = false;
108
}
109

110
cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals)
111
{
112
  this->Internal->VarStack.push(mf.Internal->VarStack.top().Closure());
113
114
  this->Internal->VarInitStack.push(mf.Internal->VarInitStack.top());
  this->Internal->VarUsageStack.push(mf.Internal->VarUsageStack.top());
115

Alexander Neundorf's avatar
   
Alexander Neundorf committed
116
117
118
  this->cmStartDirectory = mf.cmStartDirectory;
  this->StartOutputDirectory = mf.StartOutputDirectory;
  this->cmHomeDirectory = mf.cmHomeDirectory;
119
120
121
122
123
124
125
  this->HomeOutputDirectory = mf.HomeOutputDirectory;
  this->cmCurrentListFile = mf.cmCurrentListFile;
  this->ProjectName = mf.ProjectName;
  this->Targets = mf.Targets;
  this->SourceFiles = mf.SourceFiles;
  this->Tests = mf.Tests;
  this->LinkDirectories = mf.LinkDirectories;
126
  this->SystemIncludeDirectories = mf.SystemIncludeDirectories;
127
128
129
130
  this->ListFiles = mf.ListFiles;
  this->OutputFiles = mf.OutputFiles;
  this->LinkLibraries = mf.LinkLibraries;
  this->InstallGenerators = mf.InstallGenerators;
131
  this->TestGenerators = mf.TestGenerators;
132
133
134
135
136
  this->IncludeFileRegularExpression = mf.IncludeFileRegularExpression;
  this->ComplainFileRegularExpression = mf.ComplainFileRegularExpression;
  this->SourceFileExtensions = mf.SourceFileExtensions;
  this->HeaderFileExtensions = mf.HeaderFileExtensions;
  this->DefineFlags = mf.DefineFlags;
137
  this->DefineFlagsOrig = mf.DefineFlagsOrig;
138
139
140
141
142
143
144

#if defined(CMAKE_BUILD_WITH_CMAKE)
  this->SourceGroups = mf.SourceGroups;
#endif

  this->LocalGenerator = mf.LocalGenerator;
  this->FunctionBlockers = mf.FunctionBlockers;
145
  this->MacrosList = mf.MacrosList;
146
  this->Properties = mf.Properties;
147
  this->WarnUnused = mf.WarnUnused;
148
  this->Initialize();
149
  this->CheckSystemVars = mf.CheckSystemVars;
150
  this->ListFileStack = mf.ListFileStack;
151
  this->OutputToSource = mf.OutputToSource;
152

153
  this->SuppressWatches = mf.SuppressWatches;
154
155
}

156
157
158
159
160
161
//----------------------------------------------------------------------------
void cmMakefile::Initialize()
{
  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/.+-]+@)");
162
  this->cmNamedCurly.compile("^[A-Za-z0-9/_.+-]+{");
163
164
165

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

Brad King's avatar
Brad King committed
167
168
169
  // Protect the directory-level policies.
  this->PushPolicyBarrier();

170
171
172
  // push empty loop block
  this->PushLoopBlockBarrier();

173
174
175
  // By default the check is not done.  It is enabled by
  // cmListFileCache in the top level if necessary.
  this->CheckCMP0000 = false;
176
}
177

178
179
cmMakefile::~cmMakefile()
{
180
181
182
183
184
185
186
  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
187
  this->FunctionBlockers.clear();
188
189
190
191
192
  if (this->PolicyStack.size() != 1)
  {
    cmSystemTools::Error("Internal CMake Error, Policy Stack has not been"
      " popped properly");
  }
193
194
}

Alexander Neundorf's avatar
   
Alexander Neundorf committed
195
void cmMakefile::PrintStringVector(const char* s,
Ken Martin's avatar
Ken Martin committed
196
                                   const std::vector<std::string>& v) const
197
{
198
  std::cout << s << ": ( \n" << cmWrap('"', v, '"', " ") << ")\n";
199
200
}

Ken Martin's avatar
Ken Martin committed
201
void cmMakefile
Alexander Neundorf's avatar
   
Alexander Neundorf committed
202
::PrintStringVector(const char* s,
203
                    const std::vector<std::pair<std::string, bool> >& v) const
204
205
{
  std::cout << s << ": ( \n";
206
  for(std::vector<std::pair<std::string, bool> >::const_iterator i
Ken Martin's avatar
Ken Martin committed
207
        = v.begin(); i != v.end(); ++i)
208
    {
209
    std::cout << i->first << " " << i->second;
210
211
212
213
    }
  std::cout << " )\n";
}

214
215

// call print on all the classes in the makefile
216
void cmMakefile::Print() const
217
{
218
  // print the class lists
219
  std::cout << "classes:\n";
220

Ken Martin's avatar
Ken Martin committed
221
222
223
  std::cout << " this->Targets: ";
  for (cmTargets::iterator l = this->Targets.begin();
       l != this->Targets.end(); l++)
224
225
226
227
    {
    std::cout << l->first << std::endl;
    }

Alexander Neundorf's avatar
   
Alexander Neundorf committed
228
  std::cout << " this->StartOutputDirectory; " <<
229
    this->StartOutputDirectory << std::endl;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
230
  std::cout << " this->HomeOutputDirectory; " <<
231
    this->HomeOutputDirectory << std::endl;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
232
  std::cout << " this->cmStartDirectory; " <<
233
    this->cmStartDirectory << std::endl;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
234
  std::cout << " this->cmHomeDirectory; " <<
235
    this->cmHomeDirectory << std::endl;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
236
  std::cout << " this->ProjectName; "
237
            <<  this->ProjectName << std::endl;
Ken Martin's avatar
Ken Martin committed
238
  this->PrintStringVector("this->LinkDirectories", this->LinkDirectories);
239
#if defined(CMAKE_BUILD_WITH_CMAKE)
Alexander Neundorf's avatar
   
Alexander Neundorf committed
240
  for( std::vector<cmSourceGroup>::const_iterator i =
Ken Martin's avatar
Ken Martin committed
241
         this->SourceGroups.begin(); i != this->SourceGroups.end(); ++i)
242
    {
243
    std::cout << "Source Group: " << i->GetName() << std::endl;
244
    }
245
#endif
246
247
}

248
249
bool cmMakefile::CommandExists(const char* name) const
{
250
  return this->GetCMakeInstance()->CommandExists(name);
251
}
252

253
254

//----------------------------------------------------------------------------
Bill Hoffman's avatar
Bill Hoffman committed
255
256
void cmMakefile::IssueMessage(cmake::MessageType t,
                              std::string const& text) const
257
{
258
  // Collect context information.
259
260
261
262
263
264
  cmLocalGenerator* localGen = this->GetLocalGenerator();
  if(this->CallStack.empty() && this->GetCMakeInstance()->GetIsInTryCompile())
    {
    localGen = 0;
    }
  cmListFileBacktrace backtrace(localGen);
265
  if(!this->CallStack.empty())
266
    {
267
    if((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR))
268
      {
269
      this->CallStack.back().Status->SetNestedError(true);
270
      }
Ben Boeckel's avatar
Ben Boeckel committed
271
    backtrace = this->GetBacktrace();
272
    }
273
  else
274
    {
275
    cmListFileContext lfc;
276
277
278
279
280
281
282
283
284
285
286
287
    if(this->ListFileStack.empty())
      {
      // We are not processing the project.  Add the directory-level context.
      lfc.FilePath = this->GetCurrentDirectory();
      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();
      }
288
289
    lfc.Line = 0;
    backtrace.push_back(lfc);
290
    }
291

292
293
294
  // Issue the message.
  this->GetCMakeInstance()->IssueMessage(t, text, backtrace);
}
295

296
//----------------------------------------------------------------------------
Ben Boeckel's avatar
Ben Boeckel committed
297
cmListFileBacktrace cmMakefile::GetBacktrace() const
298
{
299
  cmListFileBacktrace backtrace(this->GetLocalGenerator());
300
301
  for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin();
      i != this->CallStack.rend(); ++i)
302
    {
303
    backtrace.push_back(*i->Context);
304
    }
Ben Boeckel's avatar
Ben Boeckel committed
305
  return backtrace;
306
307
}

308
//----------------------------------------------------------------------------
309
void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const
310
{
311
  std::ostringstream msg;
312
313
314
315
316
317
318
319
320
321
322
323
  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());
}

324
//----------------------------------------------------------------------------
325
326
bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
                                cmExecutionStatus &status)
Ken Martin's avatar
Ken Martin committed
327
{
328
  bool result = true;
329

330
  // quick return if blocked
331
  if(this->IsFunctionBlocked(lff,status))
332
    {
333
334
    // No error.
    return result;
335
    }
336

Ken Martin's avatar
Ken Martin committed
337
  std::string name = lff.Name;
338

339
340
341
342
343
  // Place this call on the call stack.
  cmMakefileCall stack_manager(this, lff, status);
  static_cast<void>(stack_manager);

  // Lookup the command prototype.
Stephen Kelly's avatar
Stephen Kelly committed
344
  if(cmCommand* proto = this->GetCMakeInstance()->GetCommand(name))
345
346
347
348
349
350
351
    {
    // Clone the prototype.
    cmsys::auto_ptr<cmCommand> pcmd(proto->Clone());
    pcmd->SetMakefile(this);

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

355
      {
356
      // if trace is enabled, print out invoke information
Bill Hoffman's avatar
Bill Hoffman committed
357
358
      if(this->GetCMakeInstance()->GetTrace())
        {
359
        this->PrintCommandTrace(lff);
Bill Hoffman's avatar
Bill Hoffman committed
360
        }
361
362
363
      // Try invoking the command.
      if(!pcmd->InvokeInitialPass(lff.Arguments,status) ||
         status.GetNestedError())
Ken Martin's avatar
Ken Martin committed
364
        {
365
366
367
        if(!status.GetNestedError())
          {
          // The command invocation requested that we report an error.
Bill Hoffman's avatar
Bill Hoffman committed
368
          this->IssueMessage(cmake::FATAL_ERROR, pcmd->GetError());
369
          }
370
        result = false;
371
        if ( this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE)
Ken Martin's avatar
Ken Martin committed
372
          {
373
          cmSystemTools::SetFatalErrorOccured();
Ken Martin's avatar
Ken Martin committed
374
375
          }
        }
376
      else if(pcmd->HasFinalPass())
377
378
        {
        // use the command
379
        this->FinalPassCommands.push_back(pcmd.release());
380
        }
Ken Martin's avatar
Ken Martin committed
381
      }
382
    else if ( this->GetCMakeInstance()->GetWorkingMode() == cmake::SCRIPT_MODE
383
              && !pcmd->IsScriptable() )
384
      {
385
386
387
      std::string error = "Command ";
      error += pcmd->GetName();
      error += "() is not scriptable";
Bill Hoffman's avatar
Bill Hoffman committed
388
      this->IssueMessage(cmake::FATAL_ERROR, error);
389
390
391
      result = false;
      cmSystemTools::SetFatalErrorOccured();
      }
Ken Martin's avatar
Ken Martin committed
392
393
394
    }
  else
    {
395
396
    if(!cmSystemTools::GetFatalErrorOccured())
      {
397
398
399
      std::string error = "Unknown CMake command \"";
      error += lff.Name;
      error += "\".";
Bill Hoffman's avatar
Bill Hoffman committed
400
      this->IssueMessage(cmake::FATAL_ERROR, error);
401
      result = false;
402
      cmSystemTools::SetFatalErrorOccured();
403
      }
Ken Martin's avatar
Ken Martin committed
404
    }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
405

406
  return result;
Ken Martin's avatar
Ken Martin committed
407
408
}

Brad King's avatar
Brad King committed
409
410
411
412
//----------------------------------------------------------------------------
class cmMakefile::IncludeScope
{
public:
413
  IncludeScope(cmMakefile* mf, const char* fname, bool noPolicyScope);
Brad King's avatar
Brad King committed
414
415
416
417
  ~IncludeScope();
  void Quiet() { this->ReportError = false; }
private:
  cmMakefile* Makefile;
418
419
420
  const char* File;
  bool NoPolicyScope;
  bool CheckCMP0011;
Brad King's avatar
Brad King committed
421
  bool ReportError;
422
  void EnforceCMP0011();
Brad King's avatar
Brad King committed
423
424
425
};

//----------------------------------------------------------------------------
426
427
428
429
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
430
{
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
  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
460
461
462
463
464
465
466
467
468
  // 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);
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503

  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.
    if(this->CheckCMP0011 && this->Makefile->PolicyStack.back().empty())
      {
      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.
  cmPolicies* policies = this->Makefile->GetPolicies();
  switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0011))
    {
    case cmPolicies::WARN:
      // Warn because the user did not set this policy.
      {
504
      std::ostringstream w;
505
506
507
508
509
510
511
512
513
514
515
      w << policies->GetPolicyWarning(cmPolicies::CMP0011) << "\n"
        << "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:
      {
516
      std::ostringstream e;
517
518
519
520
521
522
523
524
525
526
527
528
529
      e << policies->GetRequiredPolicyError(cmPolicies::CMP0011) << "\n"
        << "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
530
531
532
}

//----------------------------------------------------------------------------
533
// Parse the given CMakeLists.txt file executing all commands
Anonymous's avatar
Anonymous committed
534
//
Alexander Neundorf's avatar
   
Alexander Neundorf committed
535
bool cmMakefile::ReadListFile(const char* filename_in,
Alexander Neundorf's avatar
   
Alexander Neundorf committed
536
                              const char *external_in,
537
538
                              std::string* fullPath,
                              bool noPolicyScope)
539
{
540
541
542
543
  std::string currentParentFile
    = this->GetSafeDefinition("CMAKE_PARENT_LIST_FILE");
  std::string currentFile
    = this->GetSafeDefinition("CMAKE_CURRENT_LIST_FILE");
544
  this->AddDefinition("CMAKE_PARENT_LIST_FILE", filename_in);
545
  this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
546

Brad King's avatar
Brad King committed
547
548
549
550
551
552
553
554
555
556
  const char* external = 0;
  std::string external_abs;

  const char* filename = filename_in;
  std::string filename_abs;

  if (external_in)
    {
    external_abs =
      cmSystemTools::CollapseFullPath(external_in,
Ken Martin's avatar
Ken Martin committed
557
                                      this->cmStartDirectory.c_str());
Brad King's avatar
Brad King committed
558
559
560
561
562
    external = external_abs.c_str();
    if (filename_in)
      {
      filename_abs =
        cmSystemTools::CollapseFullPath(filename_in,
Ken Martin's avatar
Ken Martin committed
563
                                        this->cmStartDirectory.c_str());
Brad King's avatar
Brad King committed
564
565
566
      filename = filename_abs.c_str();
      }
    }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
567

568
  // keep track of the current file being read
569
570
  if (filename)
    {
Ken Martin's avatar
Ken Martin committed
571
    if(this->cmCurrentListFile != filename)
Bill Hoffman's avatar
Bill Hoffman committed
572
      {
Ken Martin's avatar
Ken Martin committed
573
      this->cmCurrentListFile = filename;
Bill Hoffman's avatar
Bill Hoffman committed
574
      }
575
576
    }

577
  // Now read the input file
Anonymous's avatar
Anonymous committed
578
579
580
  const char *filenametoread= filename;

  if( external)
581
    {
Anonymous's avatar
Anonymous committed
582
    filenametoread= external;
583
    }
584
585

  this->AddDefinition("CMAKE_CURRENT_LIST_FILE", filenametoread);
586
  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
587
588
  this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
                       cmSystemTools::GetFilenamePath(filenametoread).c_str());
589
  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
590

591
592
593
  // try to see if the list file is the top most
  // list file for a project, and if it is, then it
  // must have a project command.   If there is not
Alexander Neundorf's avatar
   
Alexander Neundorf committed
594
  // one, then cmake will provide one via the
595
596
  // cmListFileCache class.
  bool requireProjectCommand = false;
Ken Martin's avatar
Ken Martin committed
597
  if(!external && this->cmStartDirectory == this->cmHomeDirectory)
598
599
    {
    if(cmSystemTools::LowerCase(
Bill Hoffman's avatar
Bill Hoffman committed
600
      cmSystemTools::GetFilenameName(filename)) == "cmakelists.txt")
601
602
603
604
      {
      requireProjectCommand = true;
      }
    }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
605

Ken Martin's avatar
Ken Martin committed
606
607
  // push the listfile onto the stack
  this->ListFileStack.push_back(filenametoread);
Alexander Neundorf's avatar
   
Alexander Neundorf committed
608
609
610
611
  if(fullPath!=0)
    {
    *fullPath=filenametoread;
    }
612
  cmListFile cacheFile;
613
  if( !cacheFile.ParseFile(filenametoread, requireProjectCommand, this) )
614
    {
Alexander Neundorf's avatar
   
Alexander Neundorf committed
615
616
    // pop the listfile off the stack
    this->ListFileStack.pop_back();
Alexander Neundorf's avatar
   
Alexander Neundorf committed
617
618
    if(fullPath!=0)
      {
619
      *fullPath = "";
Alexander Neundorf's avatar
   
Alexander Neundorf committed
620
      }
621
    this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str());
622
    this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
623
    this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str());
624
    this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
625
626
    this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
                        cmSystemTools::GetFilenamePath(currentFile).c_str());
627
    this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
628
629
    return false;
    }
630
  // add this list file to the list of dependencies
Ken Martin's avatar
Ken Martin committed
631
  this->ListFiles.push_back( filenametoread);
632
633
634
635

  // Enforce balanced blocks (if/endif, function/endfunction, etc.).
  {
  LexicalPushPop lexScope(this);
636
  IncludeScope incScope(this, filenametoread, noPolicyScope);
637
638

  // Run the parsed commands.
Ken Martin's avatar
Ken Martin committed
639
  const size_t numberFunctions = cacheFile.Functions.size();
640
  for(size_t i =0; i < numberFunctions; ++i)
641
    {
642
643
    cmExecutionStatus status;
    this->ExecuteCommand(cacheFile.Functions[i],status);
644
    if(cmSystemTools::GetFatalErrorOccured())
645
      {
646
647
      // Exit early due to error.
      lexScope.Quiet();
Brad King's avatar
Brad King committed
648
      incScope.Quiet();
649
650
651
652
653
      break;
      }
    if(status.GetReturnInvoked())
      {
      // Exit early due to return command.
654
      break;
655
      }
656
    }
657
  }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
658

659
660
  // If this is the directory-level CMakeLists.txt file then perform
  // some extra checks.
661
662
  if(this->ListFileStack.size() == 1)
    {
663
    this->EnforceDirectoryLevelRules();
664
665
    }

666
  this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str());
667
  this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
668
  this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str());
669
  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
670
671
  this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
                      cmSystemTools::GetFilenamePath(currentFile).c_str());
672
  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
Ken Martin's avatar
Ken Martin committed
673
674
675
676

  // pop the listfile off the stack
  this->ListFileStack.pop_back();

677
678
679
  // Check for unused variables
  this->CheckForUnusedVariables();

680
681
  return true;
}
682

683
//----------------------------------------------------------------------------
684
void cmMakefile::EnforceDirectoryLevelRules() const
685
686
687
688
{
  // Diagnose a violation of CMP0000 if necessary.
  if(this->CheckCMP0000)
    {
689
    std::ostringstream msg;
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
    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
706
        this->IssueMessage(cmake::AUTHOR_WARNING, msg.str());
707
708
709
710
711
712
713
714
      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
715
        this->IssueMessage(cmake::FATAL_ERROR, msg.str());
716
717
718
719
720
        cmSystemTools::SetFatalErrorOccured();
        return;
      }
    }
}
721

722
void cmMakefile::AddCommand(cmCommand* wg)
723
{
724
  this->GetCMakeInstance()->AddCommand(wg);
725
726
}

Alexander Neundorf's avatar
   
Alexander Neundorf committed
727
// Set the make file
Ken Martin's avatar
Ken Martin committed
728
void cmMakefile::SetLocalGenerator(cmLocalGenerator* lg)
729
{
Ken Martin's avatar
Ken Martin committed
730
  this->LocalGenerator = lg;
731
732
733
734
735
736
737
738
  // the source groups need to access the global generator
  // so don't create them until the lg is set
#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)$");
739
  this->AddSourceGroup("Header Files", CM_HEADER_REGEX);
740
741
  this->AddSourceGroup("CMake Rules", "\\.rule$");
  this->AddSourceGroup("Resources", "\\.plist$");
742
  this->AddSourceGroup("Object Files", "\\.(lo|o|obj)$");
743
744
#endif

745
  this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused();
746
  this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars();
747
748
}

749
750
namespace
{
751
  struct file_not_persistent
752
753
  {
    bool operator()(const std::string& path) const
754
755
756
757
      {
      return !(path.find("CMakeTmp") == path.npos &&
               cmSystemTools::FileExists(path.c_str()));
      }
758
759
760
  };
}

761
void cmMakefile::FinalPass()
762
763
{
  // do all the variable expansions here
764
  this->ExpandVariablesCMP0019();
765

766
  // give all the commands a chance to do something
767
  // after the file has been parsed before generation
768
769
  for(std::vector<cmCommand*>::iterator i = this->FinalPassCommands.begin();
      i != this->FinalPassCommands.end(); ++i)
770
771
    {
    (*i)->FinalPass();
772
    }
773

774
775
776
777
778
779
780
  //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
781
782
783
784
  std::vector<std::string>::iterator new_output_files_end = std::remove_if(
                                                     this->OutputFiles.begin(),
                                                     this->OutputFiles.end(),
                                                     file_not_persistent() );
785
  //we just have to erase all items at the back
786
787
788
789
790
791
792
793
794
  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() );
795

796
  this->ListFiles.erase(new_list_files_end, this->ListFiles.end() );
797
798
}

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

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

  if(ti == this->Targets.end())
842
    {
843
844
    cmake::MessageType messageType = cmake::AUTHOR_WARNING;
    bool issueMessage = false;
845
    std::ostringstream e;
846
    switch(this->GetPolicyStatus(cmPolicies::CMP0040))
Brad King's avatar
Brad King committed
847
      {
848
      case cmPolicies::WARN:
849
850
        e << (this->GetPolicies()
          ->GetPolicyWarning(cmPolicies::CMP0040)) << "\n";
851
852
853
854
855
856
857
858
        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
859
      }
860
861

    if(issueMessage)
862
      {
863
      e << "The target name \"" << target << "\" is unknown in this context.";
Stephen Kelly's avatar
Stephen Kelly committed
864
      IssueMessage(messageType, e.str());
865
      }
866
867
868
869
870
871

      return;
    }

  if(ti->second.GetType() == cmTarget::OBJECT_LIBRARY)
    {
872
    std::ostringstream e;
873
874
875
876
877
    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;
    }
878
879
  if(ti->second.GetType() == cmTarget::INTERFACE_LIBRARY)
    {
880
    std::ostringstream e;
881
882
883
884
885
    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;
    }
886
887
888
889
890
891
892
893
894
895
896

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

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

918
//----------------------------------------------------------------------------
919
cmSourceFile*
920
cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
921
                                  const std::vector<std::string>& byproducts,
922
                                     const std::vector<std::string>& depends,
923
                                     const std::string& main_dependency,
924
925
                                     const cmCustomCommandLines& commandLines,
                                     const char* comment,
926
                                     const char* workingDir,