cmake.cxx 136 KB
Newer Older
1
2
3
/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
Ken Martin's avatar
Ken Martin committed
4

5
6
  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.
Ken Martin's avatar
Ken Martin committed
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.
============================================================================*/
Ken Martin's avatar
Ken Martin committed
12
#include "cmake.h"
Bill Hoffman's avatar
Bill Hoffman committed
13
#include "cmDocumentVariables.h"
Ken Martin's avatar
Ken Martin committed
14
#include "time.h"
Ken Martin's avatar
Ken Martin committed
15
#include "cmCacheManager.h"
Ken Martin's avatar
Ken Martin committed
16
17
#include "cmMakefile.h"
#include "cmLocalGenerator.h"
Alexander Neundorf's avatar
   
Alexander Neundorf committed
18
#include "cmExternalMakefileProjectGenerator.h"
Ken Martin's avatar
Ken Martin committed
19
20
#include "cmCommands.h"
#include "cmCommand.h"
21
#include "cmFileTimeComparison.h"
22
#include "cmGeneratedFileStream.h"
23
#include "cmQtAutomoc.h"
24
#include "cmSourceFile.h"
Bill Hoffman's avatar
Bill Hoffman committed
25
#include "cmVersion.h"
26
#include "cmTest.h"
27
#include "cmDocumentationFormatterText.h"
Ken Martin's avatar
Ken Martin committed
28

29
#if defined(CMAKE_BUILD_WITH_CMAKE)
30
# include "cmGraphVizWriter.h"
31
# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
32
# include "cmVariableWatch.h"
33
# include <cmsys/Terminal.h>
34
# include <cmsys/CommandLineArguments.hxx>
35
#endif
36

Alexander Neundorf's avatar
   
Alexander Neundorf committed
37
#include <cmsys/Directory.hxx>
38
#include <cmsys/Process.h>
Alexander Neundorf's avatar
   
Alexander Neundorf committed
39
40
#include <cmsys/Glob.hxx>
#include <cmsys/RegularExpression.hxx>
Ken Martin's avatar
Ken Martin committed
41

42
43
44
45
46
47
48
49
// only build kdevelop generator on non-windows platforms
// when not bootstrapping cmake
#if !defined(_WIN32)
# if defined(CMAKE_BUILD_WITH_CMAKE)
#   define CMAKE_USE_KDEVELOP
# endif
#endif

Alexander Neundorf's avatar
   
Alexander Neundorf committed
50
51
52
53
#if defined(CMAKE_BUILD_WITH_CMAKE)
#  define CMAKE_USE_ECLIPSE
#endif

54
55
56
57
#if defined(__MINGW32__) && !defined(CMAKE_BUILD_WITH_CMAKE)
# define CMAKE_BOOT_MINGW
#endif

Ken Martin's avatar
Ken Martin committed
58
59
// include the generator
#if defined(_WIN32) && !defined(__CYGWIN__)
60
61
#  if !defined(CMAKE_BOOT_MINGW)
#    include "cmGlobalVisualStudio6Generator.h"
62
63
64
#    include "cmGlobalVisualStudio7Generator.h"
#    include "cmGlobalVisualStudio71Generator.h"
#    include "cmGlobalVisualStudio8Generator.h"
65
#    include "cmGlobalVisualStudio9Generator.h"
66
#    include "cmGlobalVisualStudio9IA64Generator.h"
Bill Hoffman's avatar
Bill Hoffman committed
67
#    include "cmGlobalVisualStudio9Win64Generator.h"
68
#    include "cmGlobalVisualStudio10Generator.h"
69
#    include "cmGlobalVisualStudio10IA64Generator.h"
Brad King's avatar
Brad King committed
70
#    include "cmGlobalVisualStudio10Win64Generator.h"
71
72
#    include "cmGlobalVisualStudio11Generator.h"
#    include "cmGlobalVisualStudio11Win64Generator.h"
73
#    include "cmGlobalVisualStudio11ARMGenerator.h"
74
#    include "cmGlobalVisualStudio8Win64Generator.h"
75
76
#    include "cmGlobalBorlandMakefileGenerator.h"
#    include "cmGlobalNMakeMakefileGenerator.h"
77
#    include "cmGlobalJOMMakefileGenerator.h"
78
#    include "cmGlobalWatcomWMakeGenerator.h"
79
#    define CMAKE_HAVE_VS_GENERATORS
80
#  endif
81
82
#  include "cmGlobalMSYSMakefileGenerator.h"
#  include "cmGlobalMinGWMakefileGenerator.h"
83
#  include "cmWin32ProcessExecution.h"
Ken Martin's avatar
Ken Martin committed
84
#else
Ken Martin's avatar
Ken Martin committed
85
#endif
Ken Martin's avatar
Ken Martin committed
86
#include "cmGlobalUnixMakefileGenerator3.h"
87
#include "cmGlobalNinjaGenerator.h"
88

89

90
#if defined(CMAKE_HAVE_VS_GENERATORS)
91
92
93
#include "cmCallVisualStudioMacro.h"
#endif

94
#if !defined(CMAKE_BOOT_MINGW)
Alexander Neundorf's avatar
   
Alexander Neundorf committed
95
96
97
# include "cmExtraCodeBlocksGenerator.h"
#endif

98
99
100
#ifdef CMAKE_USE_KDEVELOP
# include "cmGlobalKdevelopGenerator.h"
#endif
Ken Martin's avatar
Ken Martin committed
101

Alexander Neundorf's avatar
   
Alexander Neundorf committed
102
103
104
105
#ifdef CMAKE_USE_ECLIPSE
# include "cmExtraEclipseCDT4Generator.h"
#endif

106
#include <stdlib.h> // required for atoi
107

108
109
110
111
112
#if defined( __APPLE__ )
#  if defined(CMAKE_BUILD_WITH_CMAKE)
#    include "cmGlobalXCodeGenerator.h"
#    define CMAKE_USE_XCODE 1
#  endif
113
114
115
#  include <sys/types.h>
#  include <sys/time.h>
#  include <sys/resource.h>
Ken Martin's avatar
Ken Martin committed
116
#endif
117

118
119
#include <sys/stat.h> // struct stat

Andy Cedilnik's avatar
Andy Cedilnik committed
120
#include <memory> // auto_ptr
121

122
static bool cmakeCheckStampFile(const char* stampName);
123
static bool cmakeCheckStampList(const char* stampName);
124

Andy Cedilnik's avatar
Andy Cedilnik committed
125
void cmNeedBackwardsCompatibility(const std::string& variable,
126
  int access_type, void*, const char*, const cmMakefile*)
127
{
128
#ifdef CMAKE_BUILD_WITH_CMAKE
129
130
  if (access_type == cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS)
    {
Brad King's avatar
Brad King committed
131
    std::string message = "An attempt was made to access a variable: ";
132
    message += variable;
Andy Cedilnik's avatar
Andy Cedilnik committed
133
134
135
136
    message +=
      " that has not been defined. Some variables were always defined "
      "by CMake in versions prior to 1.6. To fix this you might need to set "
      "the cache value of CMAKE_BACKWARDS_COMPATIBILITY to 1.4 or less. If "
137
      "you are writing a CMakeLists file, (or have already set "
Andy Cedilnik's avatar
Andy Cedilnik committed
138
139
140
      "CMAKE_BACKWARDS_COMPATABILITY to 1.4 or less) then you probably need "
      "to include a CMake module to test for the feature this variable "
      "defines.";
141
142
    cmSystemTools::Error(message.c_str());
    }
143
144
145
146
#else
  (void)variable;
  (void)access_type;
#endif
147
148
}

149
150
151
152
153
154
155
void cmWarnUnusedCliWarning(const std::string& variable,
  int, void* ctx, const char*, const cmMakefile*)
{
  cmake* cm = reinterpret_cast<cmake*>(ctx);
  cm->MarkCliAsUsed(variable);
}

Bill Hoffman's avatar
Bill Hoffman committed
156
157
cmake::cmake()
{
Bill Hoffman's avatar
Bill Hoffman committed
158
  this->Trace = false;
159
  this->WarnUninitialized = false;
160
  this->WarnUnused = false;
161
  this->WarnUnusedCli = true;
162
  this->CheckSystemVars = false;
163
  this->SuppressDevWarnings = false;
164
  this->DoSuppressDevWarnings = false;
165
  this->DebugOutput = false;
Ken Martin's avatar
Ken Martin committed
166
167
168
  this->DebugTryCompile = false;
  this->ClearBuildSystem = false;
  this->FileComparison = new cmFileTimeComparison;
Andy Cedilnik's avatar
Andy Cedilnik committed
169

170
  this->Policies = new cmPolicies();
171
  this->InitializeProperties();
172

173
174
175
176
#ifdef __APPLE__
  struct rlimit rlp;
  if(!getrlimit(RLIMIT_STACK, &rlp))
    {
177
    if(rlp.rlim_cur != rlp.rlim_max)
178
      {
179
        rlp.rlim_cur = rlp.rlim_max;
180
181
182
183
184
         setrlimit(RLIMIT_STACK, &rlp);
      }
    }
#endif

Ken Martin's avatar
Ken Martin committed
185
186
  this->Verbose = false;
  this->InTryCompile = false;
187
  this->CacheManager = new cmCacheManager(this);
Ken Martin's avatar
Ken Martin committed
188
189
190
  this->GlobalGenerator = 0;
  this->ProgressCallback = 0;
  this->ProgressCallbackClientData = 0;
191
  this->CurrentWorkingMode = NORMAL_MODE;
192

193
#ifdef CMAKE_BUILD_WITH_CMAKE
Ken Martin's avatar
Ken Martin committed
194
195
  this->VariableWatch = new cmVariableWatch;
  this->VariableWatch->AddWatch("CMAKE_WORDS_BIGENDIAN",
196
                            cmNeedBackwardsCompatibility);
Ken Martin's avatar
Ken Martin committed
197
  this->VariableWatch->AddWatch("CMAKE_SIZEOF_INT",
198
                            cmNeedBackwardsCompatibility);
Ken Martin's avatar
Ken Martin committed
199
  this->VariableWatch->AddWatch("CMAKE_X_LIBS",
200
                            cmNeedBackwardsCompatibility);
201
202
203
#endif

  this->AddDefaultGenerators();
Alexander Neundorf's avatar
   
Alexander Neundorf committed
204
  this->AddDefaultExtraGenerators();
205
206
  this->AddDefaultCommands();

207
208
  // Make sure we can capture the build tool output.
  cmSystemTools::EnableVSConsoleOutput();
Bill Hoffman's avatar
Bill Hoffman committed
209
210
}

211
212
cmake::~cmake()
{
Ken Martin's avatar
Ken Martin committed
213
  delete this->CacheManager;
214
  delete this->Policies;
Ken Martin's avatar
Ken Martin committed
215
  if (this->GlobalGenerator)
216
    {
Ken Martin's avatar
Ken Martin committed
217
218
    delete this->GlobalGenerator;
    this->GlobalGenerator = 0;
219
    }
Ken Martin's avatar
Ken Martin committed
220
221
  for(RegisteredCommandsMap::iterator j = this->Commands.begin();
      j != this->Commands.end(); ++j)
Ken Martin's avatar
Ken Martin committed
222
223
224
    {
    delete (*j).second;
    }
225
#ifdef CMAKE_BUILD_WITH_CMAKE
Ken Martin's avatar
Ken Martin committed
226
  delete this->VariableWatch;
227
#endif
Ken Martin's avatar
Ken Martin committed
228
  delete this->FileComparison;
Ken Martin's avatar
Ken Martin committed
229
230
}

231
232
233
234
void cmake::InitializeProperties()
{
  this->Properties.clear();
  this->Properties.SetCMakeInstance(this);
235
236
  this->AccessedProperties.clear();
  this->PropertyDefinitions.clear();
237
238

  // initialize properties
239
  cmCacheManager::DefineProperties(this);
240
241
242
243
244
245
246
  cmSourceFile::DefineProperties(this);
  cmTarget::DefineProperties(this);
  cmMakefile::DefineProperties(this);
  cmTest::DefineProperties(this);
  cmake::DefineProperties(this);
}

247
248
void cmake::CleanupCommandsAndMacros()
{
249
  this->InitializeProperties();
250
  std::vector<cmCommand*> commands;
Ken Martin's avatar
Ken Martin committed
251
252
  for(RegisteredCommandsMap::iterator j = this->Commands.begin();
      j != this->Commands.end(); ++j)
253
    {
254
    if ( !j->second->IsA("cmMacroHelperCommand") &&
255
         !j->second->IsA("cmFunctionHelperCommand"))
256
257
258
259
260
261
262
263
      {
      commands.push_back(j->second);
      }
    else
      {
      delete j->second;
      }
    }
Ken Martin's avatar
Ken Martin committed
264
  this->Commands.erase(this->Commands.begin(), this->Commands.end());
265
266
267
268
  std::vector<cmCommand*>::iterator it;
  for ( it = commands.begin(); it != commands.end();
    ++ it )
    {
Ken Martin's avatar
Ken Martin committed
269
    this->Commands[cmSystemTools::LowerCase((*it)->GetName())] = *it;
270
271
272
    }
}

Ken Martin's avatar
Ken Martin committed
273
274
bool cmake::CommandExists(const char* name) const
{
275
  std::string sName = cmSystemTools::LowerCase(name);
Ken Martin's avatar
Ken Martin committed
276
  return (this->Commands.find(sName) != this->Commands.end());
277
278
}

Andy Cedilnik's avatar
Andy Cedilnik committed
279
cmCommand *cmake::GetCommand(const char *name)
Ken Martin's avatar
Ken Martin committed
280
281
{
  cmCommand* rm = 0;
282
  std::string sName = cmSystemTools::LowerCase(name);
Ken Martin's avatar
Ken Martin committed
283
284
  RegisteredCommandsMap::iterator pos = this->Commands.find(sName);
  if (pos != this->Commands.end())
Ken Martin's avatar
Ken Martin committed
285
286
287
288
289
290
    {
    rm = (*pos).second;
    }
  return rm;
}

291
292
293
void cmake::RenameCommand(const char*oldName, const char* newName)
{
  // if the command already exists, free the old one
294
295
  std::string sOldName = cmSystemTools::LowerCase(oldName);
  std::string sNewName = cmSystemTools::LowerCase(newName);
Ken Martin's avatar
Ken Martin committed
296
297
  RegisteredCommandsMap::iterator pos = this->Commands.find(sOldName);
  if ( pos == this->Commands.end() )
298
299
300
    {
    return;
    }
301
  cmCommand* cmd = pos->second;
302

Ken Martin's avatar
Ken Martin committed
303
304
  pos = this->Commands.find(sNewName);
  if (pos != this->Commands.end())
305
306
    {
    delete pos->second;
Ken Martin's avatar
Ken Martin committed
307
    this->Commands.erase(pos);
308
    }
Ken Martin's avatar
Ken Martin committed
309
310
311
  this->Commands.insert(RegisteredCommandsMap::value_type(sNewName, cmd));
  pos = this->Commands.find(sOldName);
  this->Commands.erase(pos);
312
313
}

Alexander Neundorf's avatar
   
Alexander Neundorf committed
314
315
316
317
318
319
320
321
322
323
324
void cmake::RemoveCommand(const char* name)
{
  std::string sName = cmSystemTools::LowerCase(name);
  RegisteredCommandsMap::iterator pos = this->Commands.find(sName);
  if ( pos != this->Commands.end() )
    {
    delete pos->second;
    this->Commands.erase(pos);
    }
}

Ken Martin's avatar
Ken Martin committed
325
326
void cmake::AddCommand(cmCommand* wg)
{
327
  std::string name = cmSystemTools::LowerCase(wg->GetName());
Ken Martin's avatar
Ken Martin committed
328
  // if the command already exists, free the old one
Ken Martin's avatar
Ken Martin committed
329
330
  RegisteredCommandsMap::iterator pos = this->Commands.find(name);
  if (pos != this->Commands.end())
Ken Martin's avatar
Ken Martin committed
331
332
    {
    delete pos->second;
Ken Martin's avatar
Ken Martin committed
333
    this->Commands.erase(pos);
Ken Martin's avatar
Ken Martin committed
334
    }
Ken Martin's avatar
Ken Martin committed
335
  this->Commands.insert( RegisteredCommandsMap::value_type(name, wg));
Ken Martin's avatar
Ken Martin committed
336
}
337

Alexander Neundorf's avatar
   
Alexander Neundorf committed
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360

void cmake::RemoveUnscriptableCommands()
{
  std::vector<std::string> unscriptableCommands;
  cmake::RegisteredCommandsMap* commands = this->GetCommands();
  for (cmake::RegisteredCommandsMap::const_iterator pos = commands->begin();
       pos != commands->end();
       ++pos)
    {
    if (!pos->second->IsScriptable())
      {
      unscriptableCommands.push_back(pos->first);
      }
    }

  for(std::vector<std::string>::const_iterator it=unscriptableCommands.begin();
      it != unscriptableCommands.end();
      ++it)
    {
    this->RemoveCommand(it->c_str());
    }
}

361
// Parse the args
362
bool cmake::SetCacheArgs(const std::vector<std::string>& args)
Andy Cedilnik's avatar
Andy Cedilnik committed
363
{
364
  bool findPackageMode = false;
365
366
367
368
369
370
  for(unsigned int i=1; i < args.size(); ++i)
    {
    std::string arg = args[i];
    if(arg.find("-D",0) == 0)
      {
      std::string entry = arg.substr(2);
371
372
      if(entry.size() == 0)
        {
373
374
375
376
377
378
379
        ++i;
        if(i < args.size())
          {
          entry = args[i];
          }
        else
          {
Alexander Neundorf's avatar
   
Alexander Neundorf committed
380
          cmSystemTools::Error("-D must be followed with VAR=VALUE.");
381
382
          return false;
          }
383
        }
384
      std::string var, value;
385
      cmCacheManager::CacheEntryType type = cmCacheManager::UNINITIALIZED;
386
      if(cmCacheManager::ParseEntry(entry.c_str(), var, value, type))
387
        {
Ken Martin's avatar
Ken Martin committed
388
        this->CacheManager->AddCacheEntry(var.c_str(), value.c_str(),
Alexander Neundorf's avatar
   
Alexander Neundorf committed
389
          "No help, variable specified on the command line.", type);
390
391
        if(this->WarnUnusedCli)
          {
392
          this->WatchUnusedCli(var.c_str());
393
          }
394
395
396
397
398
        }
      else
        {
        std::cerr << "Parse error in command line argument: " << arg << "\n"
                  << "Should be: VAR:type=value\n";
Alexander Neundorf's avatar
Alexander Neundorf committed
399
        cmSystemTools::Error("No cmake script provided.");
400
        return false;
Andy Cedilnik's avatar
Andy Cedilnik committed
401
        }
402
      }
403
404
    else if(arg.find("-Wno-dev",0) == 0)
      {
405
      this->SuppressDevWarnings = true;
406
      this->DoSuppressDevWarnings = true;
407
408
      }
    else if(arg.find("-Wdev",0) == 0)
409
      {
410
      this->SuppressDevWarnings = false;
411
      this->DoSuppressDevWarnings = true;
412
      }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
    else if(arg.find("-U",0) == 0)
      {
      std::string entryPattern = arg.substr(2);
      if(entryPattern.size() == 0)
        {
        ++i;
        if(i < args.size())
          {
          entryPattern = args[i];
          }
        else
          {
          cmSystemTools::Error("-U must be followed with VAR.");
          return false;
          }
        }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
429
      cmsys::RegularExpression regex(
430
        cmsys::Glob::PatternToRegex(entryPattern.c_str(), true, true).c_str());
Alexander Neundorf's avatar
   
Alexander Neundorf committed
431
432
      //go through all cache entries and collect the vars which will be removed
      std::vector<std::string> entriesToDelete;
433
      cmCacheManager::CacheIterator it =
Alexander Neundorf's avatar
   
Alexander Neundorf committed
434
435
436
437
                                    this->CacheManager->GetCacheIterator();
      for ( it.Begin(); !it.IsAtEnd(); it.Next() )
        {
        cmCacheManager::CacheEntryType t = it.GetType();
Alexander Neundorf's avatar
   
Alexander Neundorf committed
438
        if(t != cmCacheManager::STATIC)
Alexander Neundorf's avatar
   
Alexander Neundorf committed
439
440
          {
          std::string entryName = it.GetName();
Alexander Neundorf's avatar
   
Alexander Neundorf committed
441
          if (regex.find(entryName.c_str()))
Alexander Neundorf's avatar
   
Alexander Neundorf committed
442
443
444
445
446
447
448
            {
            entriesToDelete.push_back(entryName);
            }
          }
        }

      // now remove them from the cache
449
450
      for(std::vector<std::string>::const_iterator currentEntry =
          entriesToDelete.begin();
Alexander Neundorf's avatar
   
Alexander Neundorf committed
451
452
453
454
455
456
          currentEntry != entriesToDelete.end();
          ++currentEntry)
        {
        this->CacheManager->RemoveCacheEntry(currentEntry->c_str());
        }
      }
457
458
459
    else if(arg.find("-C",0) == 0)
      {
      std::string path = arg.substr(2);
460
461
      if ( path.size() == 0 )
        {
462
463
464
465
466
467
468
469
470
471
        ++i;
        if(i < args.size())
          {
          path = args[i];
          }
        else
          {
          cmSystemTools::Error("-C must be followed by a file name.");
          return false;
          }
472
        }
473
      std::cerr << "loading initial cache file " << path.c_str() << "\n";
474
      this->ReadListFile(args, path.c_str());
Ken Martin's avatar
Ken Martin committed
475
      }
476
    else if(arg.find("-P",0) == 0)
477
      {
478
      i++;
479
480
481
482
483
      if(i >= args.size())
        {
        cmSystemTools::Error("-P must be followed by a file name.");
        return false;
        }
484
      std::string path = args[i];
485
486
      if ( path.size() == 0 )
        {
487
        cmSystemTools::Error("No cmake script provided.");
488
489
        return false;
        }
490
      this->ReadListFile(args, path.c_str());
491
      }
492
493
494
495
    else if (arg.find("--find-package",0) == 0)
      {
      findPackageMode = true;
      }
Ken Martin's avatar
Ken Martin committed
496
    }
497
498
499
500

  if (findPackageMode)
    {
    return this->FindPackage(args);
Ken Martin's avatar
Ken Martin committed
501
    }
502

503
  return true;
Ken Martin's avatar
Ken Martin committed
504
505
}

506
507
void cmake::ReadListFile(const std::vector<std::string>& args,
                         const char *path)
Ken Martin's avatar
Ken Martin committed
508
509
510
{
  // if a generator was not yet created, temporarily create one
  cmGlobalGenerator *gg = this->GetGlobalGenerator();
Ken Martin's avatar
Ken Martin committed
511
  bool created = false;
Andy Cedilnik's avatar
Andy Cedilnik committed
512

Ken Martin's avatar
Ken Martin committed
513
514
515
516
517
518
519
520
521
522
523
  // if a generator was not specified use a generic one
  if (!gg)
    {
    gg = new cmGlobalGenerator;
    gg->SetCMakeInstance(this);
    created = true;
    }

  // read in the list file to fill the cache
  if(path)
    {
Andy Cedilnik's avatar
Andy Cedilnik committed
524
    std::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator());
525
526
527
528
529
530
531
532
    lg->GetMakefile()->SetHomeOutputDirectory
      (cmSystemTools::GetCurrentWorkingDirectory().c_str());
    lg->GetMakefile()->SetStartOutputDirectory
      (cmSystemTools::GetCurrentWorkingDirectory().c_str());
    lg->GetMakefile()->SetHomeDirectory
      (cmSystemTools::GetCurrentWorkingDirectory().c_str());
    lg->GetMakefile()->SetStartDirectory
      (cmSystemTools::GetCurrentWorkingDirectory().c_str());
533
    if (this->GetWorkingMode() != NORMAL_MODE)
534
535
536
537
      {
      std::string file(cmSystemTools::CollapseFullPath(path));
      cmSystemTools::ConvertToUnixSlashes(file);
      lg->GetMakefile()->SetScriptModeFile(file.c_str());
538
539

      lg->GetMakefile()->SetArgcArgv(args);
540
      }
541
    if (!lg->GetMakefile()->ReadListFile(0, path))
Ken Martin's avatar
Ken Martin committed
542
      {
543
      cmSystemTools::Error("Error processing file:", path);
544
      }
545
    }
Andy Cedilnik's avatar
Andy Cedilnik committed
546

Ken Martin's avatar
Ken Martin committed
547
548
549
550
551
  // free generic one if generated
  if (created)
    {
    delete gg;
    }
552
553
}

554
555
556

bool cmake::FindPackage(const std::vector<std::string>& args)
{
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
  // if a generator was not yet created, temporarily create one
  cmGlobalGenerator *gg = new cmGlobalGenerator;
  gg->SetCMakeInstance(this);
  this->SetGlobalGenerator(gg);

  // read in the list file to fill the cache
  std::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator());
  cmMakefile* mf = lg->GetMakefile();
  mf->SetHomeOutputDirectory
    (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  mf->SetStartOutputDirectory
    (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  mf->SetHomeDirectory
    (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  mf->SetStartDirectory
    (cmSystemTools::GetCurrentWorkingDirectory().c_str());

  mf->SetArgcArgv(args);

  std::string systemFile = mf->GetModulesFile("CMakeFindPackageMode.cmake");
  mf->ReadListFile(0, systemFile.c_str());

  std::string language = mf->GetSafeDefinition("LANGUAGE");
  std::string mode = mf->GetSafeDefinition("MODE");
  std::string packageName = mf->GetSafeDefinition("NAME");
  bool packageFound = mf->IsOn("PACKAGE_FOUND");
  bool quiet = mf->IsOn("PACKAGE_QUIET");

  if (!packageFound)
    {
    if (!quiet)
      {
      printf("%s not found.\n", packageName.c_str());
      }
    }
  else if (mode == "EXIST")
    {
    if (!quiet)
      {
      printf("%s found.\n", packageName.c_str());
      }
    }
  else if (mode == "COMPILE")
    {
    std::string includes = mf->GetSafeDefinition("PACKAGE_INCLUDE_DIRS");
    std::vector<std::string> includeDirs;
    cmSystemTools::ExpandListArgument(includes, includeDirs);

605
    std::string includeFlags = lg->GetIncludeFlags(includeDirs,
606
607
                                                   language.c_str(), false);

608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
    std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS");
    printf("%s %s\n", includeFlags.c_str(), definitions.c_str());
    }
  else if (mode == "LINK")
    {
    const char* targetName = "dummy";
    std::vector<std::string> srcs;
    cmTarget* tgt = mf->AddExecutable(targetName, srcs, true);
    tgt->SetProperty("LINKER_LANGUAGE", language.c_str());

    std::string libs = mf->GetSafeDefinition("PACKAGE_LIBRARIES");
    std::vector<std::string> libList;
    cmSystemTools::ExpandListArgument(libs, libList);
    for(std::vector<std::string>::const_iterator libIt=libList.begin();
            libIt != libList.end();
            ++libIt)
      {
Alexander Neundorf's avatar
Alexander Neundorf committed
625
626
      mf->AddLinkLibraryForTarget(targetName, libIt->c_str(),
                                  cmTarget::GENERAL);
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
      }


    std::string linkLibs;
    std::string flags;
    std::string linkFlags;
    lg->GetTargetFlags(linkLibs, flags, linkFlags, *tgt);

    printf("%s\n", linkLibs.c_str() );

/*    if ( use_win32 )
      {
      tgt->SetProperty("WIN32_EXECUTABLE", "ON");
      }
    if ( use_macbundle)
      {
      tgt->SetProperty("MACOSX_BUNDLE", "ON");
      }*/
    }

  // free generic one if generated
//  this->SetGlobalGenerator(0); // setting 0-pointer is not possible
//  delete gg; // this crashes inside the cmake instance

  return packageFound;
652
653
654
}


Ken Martin's avatar
Ken Martin committed
655
// Parse the args
Ben Boeckel's avatar
Ben Boeckel committed
656
657
void cmake::SetArgs(const std::vector<std::string>& args,
                    bool directoriesSetBefore)
Ken Martin's avatar
Ken Martin committed
658
{
659
  bool directoriesSet = directoriesSetBefore;
Brad King's avatar
Brad King committed
660
  for(unsigned int i=1; i < args.size(); ++i)
Ken Martin's avatar
Ken Martin committed
661
    {
662
    std::string arg = args[i];
Ken Martin's avatar
Ken Martin committed
663
    if(arg.find("-H",0) == 0)
Ken Martin's avatar
Ken Martin committed
664
      {
Bill Hoffman's avatar
Bill Hoffman committed
665
      directoriesSet = true;
Ken Martin's avatar
Ken Martin committed
666
      std::string path = arg.substr(2);
667
668
      path = cmSystemTools::CollapseFullPath(path.c_str());
      cmSystemTools::ConvertToUnixSlashes(path);
Ken Martin's avatar
Ken Martin committed
669
      this->SetHomeDirectory(path.c_str());
Ken Martin's avatar
Ken Martin committed
670
      }
Bill Hoffman's avatar
Bill Hoffman committed
671
    else if(arg.find("-S",0) == 0)
Ken Martin's avatar
Ken Martin committed
672
      {
673
      // There is no local generate anymore.  Ignore -S option.
Ken Martin's avatar
Ken Martin committed
674
      }
Bill Hoffman's avatar
Bill Hoffman committed
675
    else if(arg.find("-O",0) == 0)
Ken Martin's avatar
Ken Martin committed
676
      {
677
      // There is no local generate anymore.  Ignore -O option.
Ken Martin's avatar
Ken Martin committed
678
      }
Bill Hoffman's avatar
Bill Hoffman committed
679
    else if(arg.find("-B",0) == 0)
Ken Martin's avatar
Ken Martin committed
680
      {
Bill Hoffman's avatar
Bill Hoffman committed
681
      directoriesSet = true;
Ken Martin's avatar
Ken Martin committed
682
      std::string path = arg.substr(2);
683
684
      path = cmSystemTools::CollapseFullPath(path.c_str());
      cmSystemTools::ConvertToUnixSlashes(path);
Ken Martin's avatar
Ken Martin committed
685
      this->SetHomeOutputDirectory(path.c_str());
Ken Martin's avatar
Ken Martin committed
686
      }
687
    else if((i < args.size()-1) && (arg.find("--check-build-system",0) == 0))
688
      {
Ken Martin's avatar
Ken Martin committed
689
690
      this->CheckBuildSystemArgument = args[++i];
      this->ClearBuildSystem = (atoi(args[++i].c_str()) > 0);
691
      }
692
693
694
695
    else if((i < args.size()-1) && (arg.find("--check-stamp-file",0) == 0))
      {
      this->CheckStampFile = args[++i];
      }
696
697
698
699
    else if((i < args.size()-1) && (arg.find("--check-stamp-list",0) == 0))
      {
      this->CheckStampList = args[++i];
      }
700
#if defined(CMAKE_HAVE_VS_GENERATORS)
701
702
703
704
    else if((i < args.size()-1) && (arg.find("--vs-solution-file",0) == 0))
      {
      this->VSSolutionFile = args[++i];
      }
705
#endif
Bill Hoffman's avatar
Bill Hoffman committed
706
    else if(arg.find("-V",0) == 0)
Ken Martin's avatar
Ken Martin committed
707
      {
Ken Martin's avatar
Ken Martin committed
708
        this->Verbose = true;
Ken Martin's avatar
Ken Martin committed
709
      }
710
711
712
713
    else if(arg.find("-D",0) == 0)
      {
      // skip for now
      }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
714
715
716
717
    else if(arg.find("-U",0) == 0)
      {
      // skip for now
      }
718
719
720
721
    else if(arg.find("-C",0) == 0)
      {
      // skip for now
      }
722
    else if(arg.find("-P",0) == 0)
723
724
      {
      // skip for now
725
      i++;
726
      }
727
728
729
730
731
    else if(arg.find("--find-package",0) == 0)
      {
      // skip for now
      i++;
      }
732
733
734
735
736
737
738
739
    else if(arg.find("-Wno-dev",0) == 0)
      {
      // skip for now
      }
    else if(arg.find("-Wdev",0) == 0)
      {
      // skip for now
      }
740
741
742
743
744
    else if(arg.find("--graphviz=",0) == 0)
      {
      std::string path = arg.substr(strlen("--graphviz="));
      path = cmSystemTools::CollapseFullPath(path.c_str());
      cmSystemTools::ConvertToUnixSlashes(path);
Ken Martin's avatar
Ken Martin committed
745
746
      this->GraphVizFile = path;
      if ( this->GraphVizFile.empty() )
747
748
749
750
        {
        cmSystemTools::Error("No file specified for --graphviz");
        }
      }
751
752
753
754
755
    else if(arg.find("--debug-trycompile",0) == 0)
      {
      std::cout << "debug trycompile on\n";
      this->DebugTryCompileOn();
      }
756
757
758
    else if(arg.find("--debug-output",0) == 0)
      {
      std::cout << "Running with debug output on.\n";
759
      this->SetDebugOutputOn(true);
760
      }
Bill Hoffman's avatar
Bill Hoffman committed
761
762
763
764
765
    else if(arg.find("--trace",0) == 0)
      {
      std::cout << "Running with trace output on.\n";
      this->SetTrace(true);
      }
766
    else if(arg.find("--warn-uninitialized",0) == 0)
767
      {
768
769
      std::cout << "Warn about uninitialized values.\n";
      this->SetWarnUninitialized(true);
770
      }
771
    else if(arg.find("--warn-unused-vars",0) == 0)
772
      {
773
      std::cout << "Finding unused variables.\n";
774
      this->SetWarnUnused(true);
775
      }
776
    else if(arg.find("--no-warn-unused-cli",0) == 0)
777
      {
778
779
      std::cout << "Not searching for unused variables given on the " <<
                   "command line.\n";
780
      this->SetWarnUnusedCli(false);
781
      }
782
783
    else if(arg.find("--check-system-vars",0) == 0)
      {
784
785
      std::cout << "Also check system files when warning about unused and " <<
                   "uninitialized variables.\n";
786
787
      this->SetCheckSystemVars(true);
      }
Bill Hoffman's avatar
Bill Hoffman committed
788
789
790
    else if(arg.find("-G",0) == 0)
      {
      std::string value = arg.substr(2);
791
792
      if(value.size() == 0)
        {
793
794
795
796
797
798
799
        ++i;
        if(i >= args.size())
          {
          cmSystemTools::Error("No generator specified for -G");
          return;
          }
        value = args[i];
800
        }
Andy Cedilnik's avatar
Andy Cedilnik committed
801
      cmGlobalGenerator* gen =
Ken Martin's avatar
Ken Martin committed
802
        this->CreateGlobalGenerator(value.c_str());
Bill Hoffman's avatar
Bill Hoffman committed
803
804
805
806
807
808
809
      if(!gen)
        {
        cmSystemTools::Error("Could not create named generator ",
                             value.c_str());
        }
      else
        {
Ken Martin's avatar
Ken Martin committed
810
        this->SetGlobalGenerator(gen);
Bill Hoffman's avatar
Bill Hoffman committed
811
812
        }
      }
813
    // no option assume it is the path to the source
Bill Hoffman's avatar
Bill Hoffman committed
814
815
    else
      {
816
      directoriesSet = true;
817
      this->SetDirectoriesFromFile(arg.c_str());
Bill Hoffman's avatar
Bill Hoffman committed
818
819
820
821
      }
    }
  if(!directoriesSet)
    {
Ken Martin's avatar
Ken Martin committed
822
    this->SetHomeOutputDirectory
823
      (cmSystemTools::GetCurrentWorkingDirectory().c_str());
Ken Martin's avatar
Ken Martin committed
824
    this->SetStartOutputDirectory
825
      (cmSystemTools::GetCurrentWorkingDirectory().c_str());
Ken Martin's avatar
Ken Martin committed
826
    this->SetHomeDirectory
827
      (cmSystemTools::GetCurrentWorkingDirectory().c_str());
Ken Martin's avatar
Ken Martin committed
828
    this->SetStartDirectory
829
      (cmSystemTools::GetCurrentWorkingDirectory().c_str());
Ken Martin's avatar
Ken Martin committed
830
    }
831
832
833

  this->SetStartDirectory(this->GetHomeDirectory());
  this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
Ken Martin's avatar
Ken Martin committed
834
835
}

836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
//----------------------------------------------------------------------------
void cmake::SetDirectoriesFromFile(const char* arg)
{
  // Check if the argument refers to a CMakeCache.txt or
  // CMakeLists.txt file.
  std::string listPath;
  std::string cachePath;
  bool argIsFile = false;
  if(cmSystemTools::FileIsDirectory(arg))
    {
    std::string path = cmSystemTools::CollapseFullPath(arg);
    cmSystemTools::ConvertToUnixSlashes(path);
    std::string cacheFile = path;
    cacheFile += "/CMakeCache.txt";
    std::string listFile = path;
    listFile += "/CMakeLists.txt";
    if(cmSystemTools::FileExists(cacheFile.c_str()))
      {
      cachePath = path;
      }
    if(cmSystemTools::FileExists(listFile.c_str()))
      {
      listPath = path;
      }
    }
  else if(cmSystemTools::FileExists(arg))
    {
    argIsFile = true;
    std::string fullPath = cmSystemTools::CollapseFullPath(arg);
    std::string name = cmSystemTools::GetFilenameName(fullPath.c_str());
    name = cmSystemTools::LowerCase(name);
    if(name == "cmakecache.txt")
      {
      cachePath = cmSystemTools::GetFilenamePath(fullPath.c_str());
      }
    else if(name == "cmakelists.txt")
      {
      listPath = cmSystemTools::GetFilenamePath(fullPath.c_str());
      }
    }
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
  else
    {
    // Specified file or directory does not exist.  Try to set things
    // up to produce a meaningful error message.
    std::string fullPath = cmSystemTools::CollapseFullPath(arg);
    std::string name = cmSystemTools::GetFilenameName(fullPath.c_str());
    name = cmSystemTools::LowerCase(name);
    if(name == "cmakecache.txt" || name == "cmakelists.txt")
      {
      argIsFile = true;
      listPath = cmSystemTools::GetFilenamePath(fullPath.c_str());
      }
    else
      {
      listPath = fullPath;
      }
    }

894
895
896
897
898
  // If there is a CMakeCache.txt file, use its settings.
  if(cachePath.length() > 0)
    {
    cmCacheManager* cachem = this->GetCacheManager();
    cmCacheManager::CacheIterator it = cachem->NewIterator();
Andy Cedilnik's avatar
Andy Cedilnik committed
899
900
    if(cachem->LoadCache(cachePath.c_str()) &&
      it.Find("CMAKE_HOME_DIRECTORY"))
901
      {
Andy Cedilnik's avatar
Andy Cedilnik committed
902
903
      this->SetHomeOutputDirectory(cachePath.c_str());
      this->SetStartOutputDirectory(cachePath.c_str());
904
905
906
907
908
      this->SetHomeDirectory(it.GetValue());
      this->SetStartDirectory(it.GetValue());
      return;
      }
    }
Andy Cedilnik's avatar
Andy Cedilnik committed
909

910
911
912
913
914
  // If there is a CMakeLists.txt file, use it as the source tree.
  if(listPath.length() > 0)
    {
    this->SetHomeDirectory(listPath.c_str());
    this->SetStartDirectory(listPath.c_str());
Andy Cedilnik's avatar
Andy Cedilnik committed
915

916
917
918
919
    if(argIsFile)
      {
      // Source CMakeLists.txt file given.  It was probably dropped
      // onto the executable in a GUI.  Default to an in-source build.
Andy Cedilnik's avatar
Andy Cedilnik committed
920
921
      this->SetHomeOutputDirectory(listPath.c_str());
      this->SetStartOutputDirectory(listPath.c_str());
922
923
924
925
926
927
928
      }
    else
      {
      // Source directory given on command line.  Use current working
      // directory as build tree.
      std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
      this->SetHomeOutputDirectory(cwd.c_str());
Andy Cedilnik's avatar
Andy Cedilnik committed
929
      this->SetStartOutputDirectory(cwd.c_str());
930
931
932
      }
    return;
    }
Andy Cedilnik's avatar
Andy Cedilnik committed
933

934
935
936
937
938
939
940
941
  // We didn't find a CMakeLists.txt or CMakeCache.txt file from the
  // argument.  Assume it is the path to the source tree, and use the
  // current working directory as the build tree.
  std::string full = cmSystemTools::CollapseFullPath(arg);
  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
  this->SetHomeDirectory(full.c_str());
  this->SetStartDirectory(full.c_str());
  this->SetHomeOutputDirectory(cwd.c_str());
Andy Cedilnik's avatar
Andy Cedilnik committed
942
  this->SetStartOutputDirectory(cwd.c_str());
943
944
}

Andy Cedilnik's avatar
Andy Cedilnik committed
945
946
// at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the
// cache
947
int cmake::AddCMakePaths()
Ken Martin's avatar
Ken Martin committed
948
{
Alexander Neundorf's avatar
   
Alexander Neundorf committed
949
  // Find the cmake executable
950
  std::string cMakeSelf = cmSystemTools::GetExecutableDirectory();
951
  cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str());
Ken Martin's avatar
Ken Martin committed
952
953
  cMakeSelf += "/cmake";
  cMakeSelf += cmSystemTools::GetExecutableExtension();
954
955
956
957
958
959
960
961
962
963
964
965
#if __APPLE__
  // on the apple this might be the gui bundle
  if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
    {
    cMakeSelf = cmSystemTools::GetExecutableDirectory();
    cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str());
    cMakeSelf += "../../../..";
    cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str());
    cMakeSelf = cmSystemTools::CollapseFullPath(cMakeSelf.c_str());
    cMakeSelf += "/cmake";
    std::cerr << cMakeSelf.c_str() << "\n";
    }
966
#endif
Bill Hoffman's avatar
Bill Hoffman committed
967
  if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
968
    {
969
970
    cmSystemTools::Error("CMake executable cannot be found at ",
                         cMakeSelf.c_str());
971
    return 0;
972
    }
973
  // Save the value in the cache
Ken Martin's avatar
Ken Martin committed
974
  this->CacheManager->AddCacheEntry
975
    ("CMAKE_COMMAND",cMakeSelf.c_str(), "Path to CMake executable.",
Ken Martin's avatar
Ken Martin committed
976
     cmCacheManager::INTERNAL);
977
  // if the edit command is not yet in the cache,
978
979
980
981
  // or if CMakeEditCommand has been set on this object,
  // then set the CMAKE_EDIT_COMMAND in the cache
  // This will mean that the last gui to edit the cache
  // will be the one that make edit_cache uses.
982
  if(!this->GetCacheDefinition("CMAKE_EDIT_COMMAND")
983
    || !this->CMakeEditCommand.empty())
Alexander Neundorf's avatar
   
Alexander Neundorf committed
984
    {
985
986
987
988
989
    // Find and save the command to edit the cache
    std::string editCacheCommand;
    if(!this->CMakeEditCommand.empty())
      {
      editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf)
990
991
        + std::string("/")
        + this->CMakeEditCommand
992
993
994
995
996
997
998
999
1000
1001
        + cmSystemTools::GetFilenameExtension(cMakeSelf);
      }
    if( !cmSystemTools::FileExists(editCacheCommand.c_str()))
      {
      editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
        "/ccmake" + cmSystemTools::GetFilenameExtension(cMakeSelf);
      }
    if( !cmSystemTools::FileExists(editCacheCommand.c_str()))
      {
      editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
1002
        "/cmake-gui" + cmSystemTools::GetFilenameExtension(cMakeSelf);
1003
1004
1005
1006
1007
1008
1009
      }
    if(cmSystemTools::FileExists(editCacheCommand.c_str()))
      {
      this->CacheManager->AddCacheEntry
        ("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(),
         "Path to cache edit program executable.", cmCacheManager::INTERNAL);
      }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
1010
    }
1011
1012
1013
1014
  std::string ctestCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
    "/ctest" + cmSystemTools::GetFilenameExtension(cMakeSelf);
  if(cmSystemTools::FileExists(ctestCommand.c_str()))
    {
Ken Martin's avatar
Ken Martin committed
1015
    this->CacheManager->AddCacheEntry
1016
1017
1018
      ("CMAKE_CTEST_COMMAND", ctestCommand.c_str(),
       "Path to ctest program executable.", cmCacheManager::INTERNAL);
    }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
1019
1020
  std::string cpackCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
    "/cpack" + cmSystemTools::GetFilenameExtension(cMakeSelf);
1021
  if(cmSystemTools::FileExists(cpackCommand.c_str()))
1022
    {
Ken Martin's avatar
Ken Martin committed
1023
    this->CacheManager->AddCacheEntry
Alexander Neundorf's avatar
   
Alexander Neundorf committed
1024
1025
      ("CMAKE_CPACK_COMMAND", cpackCommand.c_str(),
       "Path to cpack program executable.", cmCacheManager::INTERNAL);