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"
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 "cmGlobalVisualStudio10Generator.h"
67
#    include "cmGlobalVisualStudio11Generator.h"
68 69
#    include "cmGlobalBorlandMakefileGenerator.h"
#    include "cmGlobalNMakeMakefileGenerator.h"
70
#    include "cmGlobalJOMMakefileGenerator.h"
71
#    include "cmGlobalWatcomWMakeGenerator.h"
72
#    define CMAKE_HAVE_VS_GENERATORS
73
#  endif
74 75
#  include "cmGlobalMSYSMakefileGenerator.h"
#  include "cmGlobalMinGWMakefileGenerator.h"
76
#  include "cmWin32ProcessExecution.h"
Ken Martin's avatar
Ken Martin committed
77
#else
Ken Martin's avatar
Ken Martin committed
78
#endif
Ken Martin's avatar
Ken Martin committed
79
#include "cmGlobalUnixMakefileGenerator3.h"
80
#include "cmGlobalNinjaGenerator.h"
81

82

83
#if defined(CMAKE_HAVE_VS_GENERATORS)
84
#include "cmCallVisualStudioMacro.h"
85
#include "cmVisualStudioWCEPlatformParser.h"
86 87
#endif

88
#if !defined(CMAKE_BOOT_MINGW)
Alexander Neundorf's avatar
 
Alexander Neundorf committed
89 90 91
# include "cmExtraCodeBlocksGenerator.h"
#endif

92 93 94
#ifdef CMAKE_USE_KDEVELOP
# include "cmGlobalKdevelopGenerator.h"
#endif
Ken Martin's avatar
Ken Martin committed
95

Alexander Neundorf's avatar
 
Alexander Neundorf committed
96 97 98 99
#ifdef CMAKE_USE_ECLIPSE
# include "cmExtraEclipseCDT4Generator.h"
#endif

100
#include <stdlib.h> // required for atoi
101

102 103 104 105 106
#if defined( __APPLE__ )
#  if defined(CMAKE_BUILD_WITH_CMAKE)
#    include "cmGlobalXCodeGenerator.h"
#    define CMAKE_USE_XCODE 1
#  endif
107 108 109
#  include <sys/types.h>
#  include <sys/time.h>
#  include <sys/resource.h>
Ken Martin's avatar
Ken Martin committed
110
#endif
111

112 113
#include <sys/stat.h> // struct stat

114
static bool cmakeCheckStampFile(const char* stampName);
115
static bool cmakeCheckStampList(const char* stampName);
116

Andy Cedilnik's avatar
Andy Cedilnik committed
117
void cmNeedBackwardsCompatibility(const std::string& variable,
118
  int access_type, void*, const char*, const cmMakefile*)
119
{
120
#ifdef CMAKE_BUILD_WITH_CMAKE
121 122
  if (access_type == cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS)
    {
123
    std::string message = "An attempt was made to access a variable: ";
124
    message += variable;
Andy Cedilnik's avatar
Andy Cedilnik committed
125 126 127 128
    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 "
129
      "you are writing a CMakeLists file, (or have already set "
Andy Cedilnik's avatar
Andy Cedilnik committed
130 131 132
      "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.";
133 134
    cmSystemTools::Error(message.c_str());
    }
135 136 137 138
#else
  (void)variable;
  (void)access_type;
#endif
139 140
}

141 142 143 144 145 146 147
void cmWarnUnusedCliWarning(const std::string& variable,
  int, void* ctx, const char*, const cmMakefile*)
{
  cmake* cm = reinterpret_cast<cmake*>(ctx);
  cm->MarkCliAsUsed(variable);
}

148 149
cmake::cmake()
{
Bill Hoffman's avatar
Bill Hoffman committed
150
  this->Trace = false;
151
  this->WarnUninitialized = false;
152
  this->WarnUnused = false;
153
  this->WarnUnusedCli = true;
154
  this->CheckSystemVars = false;
155
  this->SuppressDevWarnings = false;
156
  this->DoSuppressDevWarnings = false;
157
  this->DebugOutput = false;
158 159 160
  this->DebugTryCompile = false;
  this->ClearBuildSystem = false;
  this->FileComparison = new cmFileTimeComparison;
Andy Cedilnik's avatar
Andy Cedilnik committed
161

162
  this->Policies = new cmPolicies();
163
  this->InitializeProperties();
164

165 166 167 168
#ifdef __APPLE__
  struct rlimit rlp;
  if(!getrlimit(RLIMIT_STACK, &rlp))
    {
169
    if(rlp.rlim_cur != rlp.rlim_max)
170
      {
171
        rlp.rlim_cur = rlp.rlim_max;
172 173 174 175 176
         setrlimit(RLIMIT_STACK, &rlp);
      }
    }
#endif

177 178
  this->Verbose = false;
  this->InTryCompile = false;
179
  this->CacheManager = new cmCacheManager(this);
180 181 182
  this->GlobalGenerator = 0;
  this->ProgressCallback = 0;
  this->ProgressCallbackClientData = 0;
183
  this->CurrentWorkingMode = NORMAL_MODE;
184

185
#ifdef CMAKE_BUILD_WITH_CMAKE
186 187
  this->VariableWatch = new cmVariableWatch;
  this->VariableWatch->AddWatch("CMAKE_WORDS_BIGENDIAN",
188
                            cmNeedBackwardsCompatibility);
189
  this->VariableWatch->AddWatch("CMAKE_SIZEOF_INT",
190
                            cmNeedBackwardsCompatibility);
191
  this->VariableWatch->AddWatch("CMAKE_X_LIBS",
192
                            cmNeedBackwardsCompatibility);
193 194 195
#endif

  this->AddDefaultGenerators();
Alexander Neundorf's avatar
 
Alexander Neundorf committed
196
  this->AddDefaultExtraGenerators();
197 198
  this->AddDefaultCommands();

199 200
  // Make sure we can capture the build tool output.
  cmSystemTools::EnableVSConsoleOutput();
201 202
}

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

228 229 230 231
void cmake::InitializeProperties()
{
  this->Properties.clear();
  this->Properties.SetCMakeInstance(this);
232 233
  this->AccessedProperties.clear();
  this->PropertyDefinitions.clear();
234 235

  // initialize properties
236
  cmCacheManager::DefineProperties(this);
237 238 239 240 241 242 243
  cmSourceFile::DefineProperties(this);
  cmTarget::DefineProperties(this);
  cmMakefile::DefineProperties(this);
  cmTest::DefineProperties(this);
  cmake::DefineProperties(this);
}

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

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

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

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

300 301
  pos = this->Commands.find(sNewName);
  if (pos != this->Commands.end())
302 303
    {
    delete pos->second;
304
    this->Commands.erase(pos);
305
    }
306 307 308
  this->Commands.insert(RegisteredCommandsMap::value_type(sNewName, cmd));
  pos = this->Commands.find(sOldName);
  this->Commands.erase(pos);
309 310
}

Alexander Neundorf's avatar
 
Alexander Neundorf committed
311 312 313 314 315 316 317 318 319 320 321
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
322 323
void cmake::AddCommand(cmCommand* wg)
{
324
  std::string name = cmSystemTools::LowerCase(wg->GetName());
Ken Martin's avatar
Ken Martin committed
325
  // if the command already exists, free the old one
326 327
  RegisteredCommandsMap::iterator pos = this->Commands.find(name);
  if (pos != this->Commands.end())
Ken Martin's avatar
Ken Martin committed
328 329
    {
    delete pos->second;
330
    this->Commands.erase(pos);
Ken Martin's avatar
Ken Martin committed
331
    }
332
  this->Commands.insert( RegisteredCommandsMap::value_type(name, wg));
Ken Martin's avatar
Ken Martin committed
333
}
334

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

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());
    }
}

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

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

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

500
  return true;
Ken Martin's avatar
Ken Martin committed
501 502
}

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

Ken Martin's avatar
Ken Martin committed
510 511 512 513 514 515 516 517 518 519 520
  // 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)
    {
521
    cmsys::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator());
522 523 524 525 526 527 528 529
    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());
530
    if (this->GetWorkingMode() != NORMAL_MODE)
531 532 533 534
      {
      std::string file(cmSystemTools::CollapseFullPath(path));
      cmSystemTools::ConvertToUnixSlashes(file);
      lg->GetMakefile()->SetScriptModeFile(file.c_str());
535 536

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

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

551 552 553

bool cmake::FindPackage(const std::vector<std::string>& args)
{
554 555 556 557 558 559
  // 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
560
  cmsys::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator());
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
  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);

602
    std::string includeFlags = lg->GetIncludeFlags(includeDirs,
603 604
                                                   language.c_str(), false);

605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
    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
622 623
      mf->AddLinkLibraryForTarget(targetName, libIt->c_str(),
                                  cmTarget::GENERAL);
624 625 626 627
      }


    std::string linkLibs;
628 629
    std::string frameworkPath;
    std::string linkPath;
630 631
    std::string flags;
    std::string linkFlags;
632
    cmGeneratorTarget gtgt(tgt);
633 634 635
    lg->GetTargetFlags(linkLibs, frameworkPath, linkPath, flags, linkFlags,
                       &gtgt);
    linkLibs = frameworkPath + linkPath + linkLibs;
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653

    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;
654 655 656
}


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

  this->SetStartDirectory(this->GetHomeDirectory());
  this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
Ken Martin's avatar
Ken Martin committed
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 876 877
//----------------------------------------------------------------------------
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());
      }
    }
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895
  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;
      }
    }

896 897 898 899 900
  // 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
901 902
    if(cachem->LoadCache(cachePath.c_str()) &&
      it.Find("CMAKE_HOME_DIRECTORY"))
903
      {
Andy Cedilnik's avatar
Andy Cedilnik committed
904 905
      this->SetHomeOutputDirectory(cachePath.c_str());
      this->SetStartOutputDirectory(cachePath.c_str());
906 907 908 909 910
      this->SetHomeDirectory(it.GetValue());
      this->SetStartDirectory(it.GetValue());
      return;
      }
    }
Andy Cedilnik's avatar
Andy Cedilnik committed
911

912 913 914 915 916
  // 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
917

918 919 920 921
    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
922 923
      this->SetHomeOutputDirectory(listPath.c_str());
      this->SetStartOutputDirectory(listPath.c_str());
924 925 926 927 928 929 930
      }
    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
931
      this->SetStartOutputDirectory(cwd.c_str());
932 933 934
      }
    return;
    }
Andy Cedilnik's avatar
Andy Cedilnik committed
935

936 937 938 939 940 941 942 943
  // 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
944
  this->SetStartOutputDirectory(cwd.c_str());
945 946
}

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

Ken Martin's avatar
Ken Martin committed
1030 1031
  // do CMAKE_ROOT, look for the environment variable first
  std::string cMakeRoot;
1032
  std::string modules;
Ken Martin's avatar
Ken Martin committed
1033 1034 1035
  if (getenv("CMAKE_ROOT"))
    {
    cMakeRoot = getenv("CMAKE_ROOT");
1036
    modules = cMakeRoot + "/Modules/CMake.cmake";
Ken Martin's avatar
Ken Martin committed
1037
    }
1038
  if(!cmSystemTools::FileExists(modules.c_str()))
Ken Martin's avatar
Ken Martin committed
1039 1040
    {
    // next try exe/..
1041 1042
    cMakeRoot = cmSystemTools::GetRealPath(cMakeSelf.c_str());
    cMakeRoot = cmSystemTools::GetProgramPath(cMakeRoot.c_str());
Ken Martin's avatar
Ken Martin committed
1043
    std::string::size_type slashPos = cMakeRoot.rfind("/");
Andy Cedilnik's avatar
Andy Cedilnik committed
1044
    if(slashPos != std::string::npos)
Ken Martin's avatar
Ken Martin committed
1045 1046 1047
      {
      cMakeRoot = cMakeRoot.substr(0, slashPos);
      }
1048
    // is there no Modules directory there?
Andy Cedilnik's avatar
Andy Cedilnik committed
1049
    modules = cMakeRoot + "/Modules/CMake.cmake";