cmGlobalGenerator.cxx 97.7 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.
============================================================================*/
Alexander Neundorf's avatar
   
Alexander Neundorf committed
12
13
#if defined(_WIN32) && !defined(__CYGWIN__)
#include "windows.h" // this must be first to define GetCurrentDirectory
14
15
16
#if defined(_MSC_VER) && _MSC_VER >= 1800
# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
#endif
Alexander Neundorf's avatar
   
Alexander Neundorf committed
17
18
#endif

Ken Martin's avatar
Ken Martin committed
19
20
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
Alexander Neundorf's avatar
   
Alexander Neundorf committed
21
#include "cmExternalMakefileProjectGenerator.h"
Ken Martin's avatar
Ken Martin committed
22
#include "cmake.h"
Stephen Kelly's avatar
Stephen Kelly committed
23
#include "cmState.h"
Ken Martin's avatar
Ken Martin committed
24
#include "cmMakefile.h"
25
#include "cmQtAutoGenerators.h"
26
#include "cmSourceFile.h"
27
#include "cmVersion.h"
28
#include "cmTargetExport.h"
29
#include "cmComputeTargetDepends.h"
30
#include "cmGeneratedFileStream.h"
31
#include "cmGeneratorTarget.h"
32
#include "cmGeneratorExpression.h"
33
#include "cmGeneratorExpressionEvaluationFile.h"
34
#include "cmExportBuildFileGenerator.h"
35
#include "cmCPackPropertiesGenerator.h"
36
#include "cmAlgorithms.h"
37

38
#include <cmsys/Directory.hxx>
39
#include <cmsys/FStream.hxx>
40

41
42
#if defined(CMAKE_BUILD_WITH_CMAKE)
# include <cmsys/MD5.h>
43
44
# include "cm_jsoncpp_value.h"
# include "cm_jsoncpp_writer.h"
45
46
#endif

47
#include <stdlib.h> // required for atof
Ken Martin's avatar
Ken Martin committed
48

49
50
#include <assert.h>

51
52
cmGlobalGenerator::cmGlobalGenerator(cmake* cm)
  : CMakeInstance(cm)
Ken Martin's avatar
updates    
Ken Martin committed
53
{
54
55
56
  // By default the .SYMBOLIC dependency is not needed on symbolic rules.
  this->NeedSymbolicMark = false;

57
  // by default use the native paths
Ken Martin's avatar
Ken Martin committed
58
  this->ForceUnixPaths = false;
59
60

  // By default do not try to support color.
61
  this->ToolSupportsColor = false;
62
63
64

  // By default do not use link scripts.
  this->UseLinkScript = false;
65

66
67
  // Whether an install target is needed.
  this->InstallTargetEnabled = false;
68
69
70

  // how long to let try compiles run
  this->TryCompileTimeout = 0;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
71
72

  this->ExtraGenerator = 0;
73
  this->CurrentMakefile = 0;
74
  this->TryCompileOuterMakefile = 0;
Ken Martin's avatar
updates    
Ken Martin committed
75
76
}

Ken Martin's avatar
Ken Martin committed
77
cmGlobalGenerator::~cmGlobalGenerator()
Alexander Neundorf's avatar
   
Alexander Neundorf committed
78
{
79
  this->ClearGeneratorMembers();
80
  delete this->ExtraGenerator;
Ken Martin's avatar
Ken Martin committed
81
82
}

83
84
85
86
87
88
89
bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p,
                                             cmMakefile* mf)
{
  if(p.empty())
    {
    return true;
    }
90
91
92
93
94
95
96
97
98
99

  std::ostringstream e;
  e <<
    "Generator\n"
    "  " << this->GetName() << "\n"
    "does not support platform specification, but platform\n"
    "  " << p << "\n"
    "was specified.";
  mf->IssueMessage(cmake::FATAL_ERROR, e.str());
  return false;
100
101
}

102
103
bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts,
                                            cmMakefile* mf)
104
{
105
106
107
108
  if(ts.empty())
    {
    return true;
    }
109
110
111
112
113
114
115
116
117
  std::ostringstream e;
  e <<
    "Generator\n"
    "  " << this->GetName() << "\n"
    "does not support toolset specification, but toolset\n"
    "  " << ts << "\n"
    "was specified.";
  mf->IssueMessage(cmake::FATAL_ERROR, e.str());
  return false;
118
119
}

120
121
122
std::string cmGlobalGenerator::SelectMakeProgram(
                                          const std::string& inMakeProgram,
                                          const std::string& makeDefault) const
123
{
124
125
  std::string makeProgram = inMakeProgram;
  if(cmSystemTools::IsOff(makeProgram.c_str()))
126
    {
127
    const char* makeProgramCSTR =
128
      this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
129
    if(cmSystemTools::IsOff(makeProgramCSTR))
130
      {
131
      makeProgram = makeDefault;
132
      }
133
134
135
136
137
138
    else
      {
      makeProgram = makeProgramCSTR;
      }
    if(cmSystemTools::IsOff(makeProgram.c_str()) &&
       !makeProgram.empty())
139
140
141
142
143
144
145
      {
      makeProgram = "CMAKE_MAKE_PROGRAM-NOTFOUND";
      }
    }
  return makeProgram;
}

146
147
void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang,
                                                cmMakefile *mf,
148
                                                bool optional) const
149
{
150
151
152
153
  std::string langComp = "CMAKE_";
  langComp += lang;
  langComp += "_COMPILER";

Stephen Kelly's avatar
Stephen Kelly committed
154
  if(!mf->GetDefinition(langComp))
155
156
157
158
159
160
161
162
    {
    if(!optional)
      {
      cmSystemTools::Error(langComp.c_str(),
                           " not set, after EnableLanguage");
      }
    return;
    }
Stephen Kelly's avatar
Stephen Kelly committed
163
  const char* name = mf->GetRequiredDefinition(langComp);
164
165
166
167
168
169
170
171
172
  std::string path;
  if(!cmSystemTools::FileIsFullPath(name))
    {
    path = cmSystemTools::FindProgram(name);
    }
  else
    {
    path = name;
    }
173
  if((path.empty() || !cmSystemTools::FileExists(path.c_str()))
174
175
      && (optional==false))
    {
176
    return;
177
178
    }
  const char* cname = this->GetCMakeInstance()->
Stephen Kelly's avatar
Stephen Kelly committed
179
    GetState()->GetInitializedCacheValue(langComp);
180
  std::string changeVars;
181
  if(cname && !optional)
182
    {
183
184
185
186
187
188
189
190
191
    std::string cnameString;
    if(!cmSystemTools::FileIsFullPath(cname))
      {
      cnameString = cmSystemTools::FindProgram(cname);
      }
    else
      {
      cnameString = cname;
      }
192
193
194
195
196
197
198
    std::string pathString = path;
    // get rid of potentially multiple slashes:
    cmSystemTools::ConvertToUnixSlashes(cnameString);
    cmSystemTools::ConvertToUnixSlashes(pathString);
    if (cnameString != pathString)
      {
      const char* cvars =
199
        this->GetCMakeInstance()->GetState()->GetGlobalProperty(
200
201
202
203
204
205
206
207
208
          "__CMAKE_DELETE_CACHE_CHANGE_VARS_");
      if(cvars)
        {
        changeVars += cvars;
        changeVars += ";";
        }
      changeVars += langComp;
      changeVars += ";";
      changeVars += cname;
209
      this->GetCMakeInstance()->GetState()->SetGlobalProperty(
210
211
212
213
214
215
        "__CMAKE_DELETE_CACHE_CHANGE_VARS_",
        changeVars.c_str());
      }
    }
}

216
217
218
219
220
void cmGlobalGenerator::AddBuildExportSet(cmExportBuildFileGenerator* gen)
{
  this->BuildExportSets[gen->GetMainExportFileName()] = gen;
}

221
222
223
224
225
226
227
void
cmGlobalGenerator::AddBuildExportExportSet(cmExportBuildFileGenerator* gen)
{
  this->BuildExportSets[gen->GetMainExportFileName()] = gen;
  this->BuildExportExportSets[gen->GetMainExportFileName()] = gen;
}

228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
bool cmGlobalGenerator::GenerateImportFile(const std::string &file)
{
  std::map<std::string, cmExportBuildFileGenerator*>::iterator it
                                          = this->BuildExportSets.find(file);
  if (it != this->BuildExportSets.end())
    {
    bool result = it->second->GenerateImportFile();
    delete it->second;
    it->second = 0;
    this->BuildExportSets.erase(it);
    return result;
    }
  return false;
}

243
244
245
246
247
void cmGlobalGenerator::ForceLinkerLanguages()
{

}

248
249
250
251
252
bool
cmGlobalGenerator::IsExportedTargetsFile(const std::string &filename) const
{
  const std::map<std::string, cmExportBuildFileGenerator*>::const_iterator it
                                      = this->BuildExportSets.find(filename);
253
254
255
256
257
258
  if (it == this->BuildExportSets.end())
    {
    return false;
    }
  return this->BuildExportExportSets.find(filename)
                                        == this->BuildExportExportSets.end();
259
260
}

261
262
// Find the make program for the generator, required for try compiles
void cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
263
{
264
  if(this->FindMakeProgramFile.empty())
265
266
267
    {
    cmSystemTools::Error(
      "Generator implementation error, "
Ken Martin's avatar
Ken Martin committed
268
      "all generators must specify this->FindMakeProgramFile");
269
270
271
272
    }
  if(!mf->GetDefinition("CMAKE_MAKE_PROGRAM")
     || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
    {
Alexander Neundorf's avatar
   
Alexander Neundorf committed
273
    std::string setMakeProgram =
Ken Martin's avatar
Ken Martin committed
274
      mf->GetModulesFile(this->FindMakeProgramFile.c_str());
275
    if(!setMakeProgram.empty())
276
      {
277
      mf->ReadListFile(setMakeProgram.c_str());
278
      }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
279
    }
280
281
282
  if(!mf->GetDefinition("CMAKE_MAKE_PROGRAM")
     || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
    {
283
    std::ostringstream err;
284
285
286
287
    err << "CMake was unable to find a build program corresponding to \""
        << this->GetName() << "\".  CMAKE_MAKE_PROGRAM is not set.  You "
        << "probably need to select a different build tool.";
    cmSystemTools::Error(err.str().c_str());
288
    cmSystemTools::SetFatalErrorOccured();
289
290
    return;
    }
291
  std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
292
293
294
  // if there are spaces in the make program use short path
  // but do not short path the actual program name, as
  // this can cause trouble with VSExpress
295
296
  if(makeProgram.find(' ') != makeProgram.npos)
    {
297
298
    std::string dir;
    std::string file;
299
    cmSystemTools::SplitProgramPath(makeProgram,
300
301
                                    dir, file);
    std::string saveFile = file;
302
    cmSystemTools::GetShortPath(makeProgram, makeProgram);
303
    cmSystemTools::SplitProgramPath(makeProgram,
304
305
306
307
                                    dir, file);
    makeProgram = dir;
    makeProgram += "/";
    makeProgram += saveFile;
308
309
    mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram.c_str(),
                           "make program",
310
                           cmState::FILEPATH);
311
    }
312
313
314
}

// enable the given language
315
316
//
// The following files are loaded in this order:
Alexander Neundorf's avatar
   
Alexander Neundorf committed
317
//
318
// First figure out what OS we are running on:
Alexander Neundorf's avatar
   
Alexander Neundorf committed
319
//
Ken Martin's avatar
Ken Martin committed
320
// CMakeSystem.cmake - configured file created by CMakeDetermineSystem.cmake
Alexander Neundorf's avatar
   
Alexander Neundorf committed
321
//   CMakeDetermineSystem.cmake - figure out os info and create
Alexander Neundorf's avatar
   
Alexander Neundorf committed
322
//                                CMakeSystem.cmake IF CMAKE_SYSTEM
Ken Martin's avatar
Ken Martin committed
323
//                                not set
Alexander Neundorf's avatar
   
Alexander Neundorf committed
324
//   CMakeSystem.cmake - configured file created by
Alexander Neundorf's avatar
   
Alexander Neundorf committed
325
//                       CMakeDetermineSystem.cmake IF CMAKE_SYSTEM_LOADED
326

327
328
329
// CMakeSystemSpecificInitialize.cmake
//   - includes Platform/${CMAKE_SYSTEM_NAME}-Initialize.cmake

330
// Next try and enable all languages found in the languages vector
Alexander Neundorf's avatar
   
Alexander Neundorf committed
331
//
332
// FOREACH LANG in languages
Alexander Neundorf's avatar
   
Alexander Neundorf committed
333
//   CMake(LANG)Compiler.cmake - configured file create by
Ken Martin's avatar
Ken Martin committed
334
//                               CMakeDetermine(LANG)Compiler.cmake
Alexander Neundorf's avatar
   
Alexander Neundorf committed
335
//     CMakeDetermine(LANG)Compiler.cmake - Finds compiler for LANG and
Ken Martin's avatar
Ken Martin committed
336
//                                          creates CMake(LANG)Compiler.cmake
Alexander Neundorf's avatar
   
Alexander Neundorf committed
337
338
//     CMake(LANG)Compiler.cmake - configured file created by
//                                 CMakeDetermine(LANG)Compiler.cmake
339
//
Alexander Neundorf's avatar
   
Alexander Neundorf committed
340
// CMakeSystemSpecificInformation.cmake
Ken Martin's avatar
Ken Martin committed
341
342
//   - includes Platform/${CMAKE_SYSTEM_NAME}.cmake
//     may use compiler stuff
343
344

// FOREACH LANG in languages
Alexander Neundorf's avatar
   
Alexander Neundorf committed
345
//   CMake(LANG)Information.cmake
Ken Martin's avatar
Ken Martin committed
346
347
//     - loads Platform/${CMAKE_SYSTEM_NAME}-${COMPILER}.cmake
//   CMakeTest(LANG)Compiler.cmake
Alexander Neundorf's avatar
   
Alexander Neundorf committed
348
//     - Make sure the compiler works with a try compile if
Ken Martin's avatar
Ken Martin committed
349
//       CMakeDetermine(LANG) was loaded
Alexander Neundorf's avatar
   
Alexander Neundorf committed
350
//
351
// Now load a few files that can override values set in any of the above
Alexander Neundorf's avatar
   
Alexander Neundorf committed
352
// (PROJECTNAME)Compatibility.cmake
Ken Martin's avatar
Ken Martin committed
353
354
//   - load any backwards compatibility stuff for current project
// ${CMAKE_USER_MAKE_RULES_OVERRIDE}
Alexander Neundorf's avatar
   
Alexander Neundorf committed
355
//   - allow users a chance to override system variables
356
357
358
//
//

Alexander Neundorf's avatar
   
Alexander Neundorf committed
359
void
360
cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
361
                                  cmMakefile *mf, bool optional)
Alexander Neundorf's avatar
   
Alexander Neundorf committed
362
{
363
  if(languages.empty())
364
365
366
367
368
    {
    cmSystemTools::Error("EnableLanguage must have a lang specified!");
    cmSystemTools::SetFatalErrorOccured();
    return;
    }
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384

  if(this->TryCompileOuterMakefile)
    {
    // In a try-compile we can only enable languages provided by caller.
    for(std::vector<std::string>::const_iterator li = languages.begin();
        li != languages.end(); ++li)
      {
      if(*li == "NONE")
        {
        this->SetLanguageEnabled("NONE", mf);
        }
      else
        {
        const char* lang = li->c_str();
        if(this->LanguagesReady.find(lang) == this->LanguagesReady.end())
          {
385
          std::ostringstream e;
386
387
388
389
390
391
392
393
394
395
396
          e << "The test project needs language "
            << lang << " which is not enabled.";
          this->TryCompileOuterMakefile
            ->IssueMessage(cmake::FATAL_ERROR, e.str());
          cmSystemTools::SetFatalErrorOccured();
          return;
          }
        }
      }
    }

397
398
  bool fatalError = false;

399
  mf->AddDefinition("RUN_CONFIGURE", true);
400
  std::string rootBin = mf->GetHomeOutputDirectory();
401
  rootBin += cmake::GetCMakeFilesDirectory();
Alexander Neundorf's avatar
   
Alexander Neundorf committed
402

403
404
  // If the configuration files path has been set,
  // then we are in a try compile and need to copy the enable language
405
  // files from the parent cmake bin dir, into the try compile bin dir
406
  if(!this->ConfiguredFilesPath.empty())
407
    {
Ken Martin's avatar
Ken Martin committed
408
    rootBin = this->ConfiguredFilesPath;
409
    }
410
411
  rootBin += "/";
  rootBin += cmVersion::GetCMakeVersion();
412

413
  // set the dir for parent files so they can be used by modules
414
  mf->AddDefinition("CMAKE_PLATFORM_INFO_DIR",rootBin.c_str());
Alexander Neundorf's avatar
   
Alexander Neundorf committed
415

416
  // find and make sure CMAKE_MAKE_PROGRAM is defined
417
418
  this->FindMakeProgram(mf);

419
420
  // try and load the CMakeSystem.cmake if it is there
  std::string fpath = rootBin;
421
422
  bool const readCMakeSystem = !mf->GetDefinition("CMAKE_SYSTEM_LOADED");
  if(readCMakeSystem)
423
424
425
426
    {
    fpath += "/CMakeSystem.cmake";
    if(cmSystemTools::FileExists(fpath.c_str()))
      {
427
      mf->ReadListFile(fpath.c_str());
428
429
      }
    }
430
  //  Load the CMakeDetermineSystem.cmake file and find out
431
  // what platform we are running on
Alexander Neundorf's avatar
   
Alexander Neundorf committed
432
  if (!mf->GetDefinition("CMAKE_SYSTEM"))
Andy Cedilnik's avatar
Andy Cedilnik committed
433
    {
Alexander Neundorf's avatar
   
Alexander Neundorf committed
434
#if defined(_WIN32) && !defined(__CYGWIN__)
435
436
437
438
    /* Windows version number data.  */
    OSVERSIONINFO osvi;
    ZeroMemory(&osvi, sizeof(osvi));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
439
440
441
442
#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
# pragma warning (push)
# pragma warning (disable:4996)
#endif
443
    GetVersionEx (&osvi);
444
445
446
#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
# pragma warning (pop)
#endif
447
    std::ostringstream windowsVersionString;
448
449
    windowsVersionString << osvi.dwMajorVersion << "." << osvi.dwMinorVersion;
    windowsVersionString.str();
450
    mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION",
Ken Martin's avatar
Ken Martin committed
451
                      windowsVersionString.str().c_str());
452
#endif
Andy Cedilnik's avatar
Andy Cedilnik committed
453
    // Read the DetermineSystem file
454
    std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake");
455
    mf->ReadListFile(systemFile.c_str());
456
457
458
    // load the CMakeSystem.cmake from the binary directory
    // this file is configured by the CMakeDetermineSystem.cmake file
    fpath = rootBin;
459
    fpath += "/CMakeSystem.cmake";
460
    mf->ReadListFile(fpath.c_str());
461
    }
462

463
  if(readCMakeSystem)
464
    {
465
466
467
468
469
470
471
    // Tell the generator about the target system.
    std::string system = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
    if(!this->SetSystemName(system, mf))
      {
      cmSystemTools::SetFatalErrorOccured();
      return;
      }
472

473
474
475
476
477
478
479
    // Tell the generator about the platform, if any.
    std::string platform = mf->GetSafeDefinition("CMAKE_GENERATOR_PLATFORM");
    if(!this->SetGeneratorPlatform(platform, mf))
      {
      cmSystemTools::SetFatalErrorOccured();
      return;
      }
480

481
482
483
484
485
486
487
    // Tell the generator about the toolset, if any.
    std::string toolset = mf->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET");
    if(!this->SetGeneratorToolset(toolset, mf))
      {
      cmSystemTools::SetFatalErrorOccured();
      return;
      }
488
489
    }

490
491
492
493
  // **** Load the system specific initialization if not yet loaded
  if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INITIALIZE_LOADED"))
    {
    fpath = mf->GetModulesFile("CMakeSystemSpecificInitialize.cmake");
494
    if(!mf->ReadListFile(fpath.c_str()))
495
      {
496
497
      cmSystemTools::Error("Could not find cmake module file: "
                           "CMakeSystemSpecificInitialize.cmake");
498
499
500
      }
    }

501
502
  std::map<std::string, bool> needTestLanguage;
  std::map<std::string, bool> needSetLanguageEnabledMaps;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
503
  // foreach language
504
  // load the CMakeDetermine(LANG)Compiler.cmake file to find
Alexander Neundorf's avatar
   
Alexander Neundorf committed
505
  // the compiler
506

507
508
509
510
  for(std::vector<std::string>::const_iterator l = languages.begin();
      l != languages.end(); ++l)
    {
    const char* lang = l->c_str();
Alexander Neundorf's avatar
   
Alexander Neundorf committed
511
    needSetLanguageEnabledMaps[lang] = false;
Bill Hoffman's avatar
Bill Hoffman committed
512
513
514
515
516
    if(*l == "NONE")
      {
      this->SetLanguageEnabled("NONE", mf);
      continue;
      }
517
518
519
    std::string loadedLang = "CMAKE_";
    loadedLang +=  lang;
    loadedLang += "_COMPILER_LOADED";
Stephen Kelly's avatar
Stephen Kelly committed
520
    if(!mf->GetDefinition(loadedLang))
521
522
523
524
525
      {
      fpath = rootBin;
      fpath += "/CMake";
      fpath += lang;
      fpath += "Compiler.cmake";
526
527
528
529

      // If the existing build tree was already configured with this
      // version of CMake then try to load the configured file first
      // to avoid duplicate compiler tests.
530
      if(cmSystemTools::FileExists(fpath.c_str()))
531
        {
532
        if(!mf->ReadListFile(fpath.c_str()))
533
          {
534
          cmSystemTools::Error("Could not find cmake module file: ",
Ken Martin's avatar
Ken Martin committed
535
                               fpath.c_str());
536
          }
Ken Martin's avatar
Ken Martin committed
537
538
        // if this file was found then the language was already determined
        // to be working
539
        needTestLanguage[lang] = false;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
540
541
        this->SetLanguageEnabledFlag(lang, mf);
        needSetLanguageEnabledMaps[lang] = true;
Ken Martin's avatar
Ken Martin committed
542
        // this can only be called after loading CMake(LANG)Compiler.cmake
543
544
        }
      }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
545

546
    if(!this->GetLanguageEnabled(lang) )
Alexander Neundorf's avatar
   
Alexander Neundorf committed
547
      {
Ken Martin's avatar
Ken Martin committed
548
      if (this->CMakeInstance->GetIsInTryCompile())
549
        {
550
        cmSystemTools::Error("This should not have happened. "
Ken Martin's avatar
Ken Martin committed
551
552
553
                             "If you see this message, you are probably "
                             "using a broken CMakeLists.txt file or a "
                             "problematic release of CMake");
554
        }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
555
      // if the CMake(LANG)Compiler.cmake file was not found then
556
      // load CMakeDetermine(LANG)Compiler.cmake
557
558
559
      std::string determineCompiler = "CMakeDetermine";
      determineCompiler += lang;
      determineCompiler += "Compiler.cmake";
Alexander Neundorf's avatar
   
Alexander Neundorf committed
560
      std::string determineFile =
561
        mf->GetModulesFile(determineCompiler.c_str());
562
      if(!mf->ReadListFile(determineFile.c_str()))
563
        {
564
        cmSystemTools::Error("Could not find cmake module file: ",
565
                             determineCompiler.c_str());
Alexander Neundorf's avatar
   
Alexander Neundorf committed
566
        }
567
      needTestLanguage[lang] = true;
568
569
570
571
      // Some generators like visual studio should not use the env variables
      // So the global generator can specify that in this variable
      if(!mf->GetDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV"))
        {
Ken Martin's avatar
Ken Martin committed
572
573
574
        // put ${CMake_(LANG)_COMPILER_ENV_VAR}=${CMAKE_(LANG)_COMPILER
        // into the environment, in case user scripts want to run
        // configure, or sub cmakes
575
576
577
578
579
580
        std::string compilerName = "CMAKE_";
        compilerName += lang;
        compilerName += "_COMPILER";
        std::string compilerEnv = "CMAKE_";
        compilerEnv += lang;
        compilerEnv += "_COMPILER_ENV_VAR";
Stephen Kelly's avatar
Stephen Kelly committed
581
        std::string envVar = mf->GetRequiredDefinition(compilerEnv);
Alexander Neundorf's avatar
   
Alexander Neundorf committed
582
        std::string envVarValue =
Stephen Kelly's avatar
Stephen Kelly committed
583
          mf->GetRequiredDefinition(compilerName);
584
585
586
        std::string env = envVar;
        env += "=";
        env += envVarValue;
587
        cmSystemTools::PutEnv(env);
588
        }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
589
590
591

      // if determineLanguage was called then load the file it
      // configures CMake(LANG)Compiler.cmake
592
593
594
595
      fpath = rootBin;
      fpath += "/CMake";
      fpath += lang;
      fpath += "Compiler.cmake";
596
      if(!mf->ReadListFile(fpath.c_str()))
597
        {
598
        cmSystemTools::Error("Could not find cmake module file: ",
Ken Martin's avatar
Ken Martin committed
599
                             fpath.c_str());
600
        }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
601
602
      this->SetLanguageEnabledFlag(lang, mf);
      needSetLanguageEnabledMaps[lang] = true;
Ken Martin's avatar
Ken Martin committed
603
604
605
606
      // this can only be called after loading CMake(LANG)Compiler.cmake
      // the language must be enabled for try compile to work, but we do
      // not know if it is a working compiler yet so set the test language
      // flag
607
      needTestLanguage[lang] = true;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
608
      } // end if(!this->GetLanguageEnabled(lang) )
609
    }  // end loop over languages
Alexander Neundorf's avatar
   
Alexander Neundorf committed
610

611
  // **** Load the system specific information if not yet loaded
612
  if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED"))
Bill Hoffman's avatar
Bill Hoffman committed
613
    {
614
    fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake");
615
    if(!mf->ReadListFile(fpath.c_str()))
616
      {
617
618
      cmSystemTools::Error("Could not find cmake module file: "
                           "CMakeSystemSpecificInformation.cmake");
619
      }
Bill Hoffman's avatar
Bill Hoffman committed
620
    }
621
622
  // loop over languages again loading CMake(LANG)Information.cmake
  //
623
624
625
626
  for(std::vector<std::string>::const_iterator l = languages.begin();
      l != languages.end(); ++l)
    {
    const char* lang = l->c_str();
Bill Hoffman's avatar
Bill Hoffman committed
627
628
629
630
631
    if(*l == "NONE")
      {
      this->SetLanguageEnabled("NONE", mf);
      continue;
      }
632
633
634
635
636
637
638
639

    // Check that the compiler was found.
    std::string compilerName = "CMAKE_";
    compilerName += lang;
    compilerName += "_COMPILER";
    std::string compilerEnv = "CMAKE_";
    compilerEnv += lang;
    compilerEnv += "_COMPILER_ENV_VAR";
640
    std::ostringstream noCompiler;
Stephen Kelly's avatar
Stephen Kelly committed
641
    const char* compilerFile = mf->GetDefinition(compilerName);
642
643
644
645
646
647
648
    if(!compilerFile || !*compilerFile ||
       cmSystemTools::IsNOTFOUND(compilerFile))
      {
      noCompiler <<
        "No " << compilerName << " could be found.\n"
        ;
      }
649
650
    else if(strcmp(lang, "RC") != 0 &&
            strcmp(lang, "ASM_MASM") != 0)
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
      {
      if(!cmSystemTools::FileIsFullPath(compilerFile))
        {
        noCompiler <<
          "The " << compilerName << ":\n"
          "  " << compilerFile << "\n"
          "is not a full path and was not found in the PATH.\n"
          ;
        }
      else if(!cmSystemTools::FileExists(compilerFile))
        {
        noCompiler <<
          "The " << compilerName << ":\n"
          "  " << compilerFile << "\n"
          "is not a full path to an existing compiler tool.\n"
          ;
        }
      }
    if(!noCompiler.str().empty())
      {
      // Skip testing this language since the compiler is not found.
      needTestLanguage[lang] = false;
      if(!optional)
        {
        // The compiler was not found and it is not optional.  Remove
        // CMake(LANG)Compiler.cmake so we try again next time CMake runs.
        std::string compilerLangFile = rootBin;
        compilerLangFile += "/CMake";
        compilerLangFile += lang;
        compilerLangFile += "Compiler.cmake";
681
        cmSystemTools::RemoveFile(compilerLangFile);
682
683
684
        if(!this->CMakeInstance->GetIsInTryCompile())
          {
          this->PrintCompilerAdvice(noCompiler, lang,
Stephen Kelly's avatar
Stephen Kelly committed
685
                                    mf->GetDefinition(compilerEnv));
686
687
688
689
690
691
          mf->IssueMessage(cmake::FATAL_ERROR, noCompiler.str());
          fatalError = true;
          }
        }
      }

692
693
694
    std::string langLoadedVar = "CMAKE_";
    langLoadedVar += lang;
    langLoadedVar += "_INFORMATION_LOADED";
Stephen Kelly's avatar
Stephen Kelly committed
695
    if (!mf->GetDefinition(langLoadedVar))
Alexander Neundorf's avatar
   
Alexander Neundorf committed
696
      {
697
698
699
      fpath = "CMake";
      fpath +=  lang;
      fpath += "Information.cmake";
700
701
      std::string informationFile = mf->GetModulesFile(fpath.c_str());
      if (informationFile.empty())
702
        {
703
        cmSystemTools::Error("Could not find cmake module file: ",
Ken Martin's avatar
Ken Martin committed
704
                             fpath.c_str());
705
        }
706
      else if(!mf->ReadListFile(informationFile.c_str()))
707
        {
708
        cmSystemTools::Error("Could not process cmake module file: ",
709
710
                             informationFile.c_str());
        }
711
      }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
712
713
714
715
    if (needSetLanguageEnabledMaps[lang])
      {
      this->SetLanguageEnabledMaps(lang, mf);
      }
716
    this->LanguagesReady.insert(lang);
Alexander Neundorf's avatar
   
Alexander Neundorf committed
717

718
    // Test the compiler for the language just setup
719
    // (but only if a compiler has been actually found)
720
721
    // At this point we should have enough info for a try compile
    // which is used in the backward stuff
722
    // If the language is untested then test it now with a try compile.
723
    if(needTestLanguage[lang])
724
      {
Ken Martin's avatar
Ken Martin committed
725
      if (!this->CMakeInstance->GetIsInTryCompile())
726
        {
727
728
729
730
        std::string testLang = "CMakeTest";
        testLang += lang;
        testLang += "Compiler.cmake";
        std::string ifpath = mf->GetModulesFile(testLang.c_str());
731
        if(!mf->ReadListFile(ifpath.c_str()))
732
          {
733
          cmSystemTools::Error("Could not find cmake module file: ",
734
                               testLang.c_str());
735
          }
736
737
738
        std::string compilerWorks = "CMAKE_";
        compilerWorks += lang;
        compilerWorks += "_COMPILER_WORKS";
Ken Martin's avatar
Ken Martin committed
739
740
741
        // if the compiler did not work, then remove the
        // CMake(LANG)Compiler.cmake file so that it will get tested the
        // next time cmake is run
Stephen Kelly's avatar
Stephen Kelly committed
742
        if(!mf->IsOn(compilerWorks))
Alexander Neundorf's avatar
   
Alexander Neundorf committed
743
          {
744
745
746
747
          std::string compilerLangFile = rootBin;
          compilerLangFile += "/CMake";
          compilerLangFile += lang;
          compilerLangFile += "Compiler.cmake";
748
          cmSystemTools::RemoveFile(compilerLangFile);
749
750
751
          }
        } // end if in try compile
      } // end need test language
752
753
754
755
756
    // Store the shared library flags so that we can satisfy CMP0018
    std::string sharedLibFlagsVar = "CMAKE_SHARED_LIBRARY_";
    sharedLibFlagsVar += lang;
    sharedLibFlagsVar += "_FLAGS";
    const char* sharedLibFlags =
Stephen Kelly's avatar
Stephen Kelly committed
757
      mf->GetSafeDefinition(sharedLibFlagsVar);
758
759
760
761
    if (sharedLibFlags)
      {
      this->LanguageToOriginalSharedLibFlags[lang] = sharedLibFlags;
      }
762
763
764

    // Translate compiler ids for compatibility.
    this->CheckCompilerIdCompatibility(mf, lang);
765
    } // end for each language
Alexander Neundorf's avatar
   
Alexander Neundorf committed
766

Ken Martin's avatar
Ken Martin committed
767
768
769
  // Now load files that can override any settings on the platform or for
  // the project First load the project compatibility file if it is in
  // cmake
770
771
  std::string projectCompatibility = mf->GetDefinition("CMAKE_ROOT");
  projectCompatibility += "/Modules/";
772
  projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME");
773
774
775
  projectCompatibility += "Compatibility.cmake";
  if(cmSystemTools::FileExists(projectCompatibility.c_str()))
    {
776
    mf->ReadListFile(projectCompatibility.c_str());
777
    }
778
779
780
781
782
  // Inform any extra generator of the new language.
  if (this->ExtraGenerator)
    {
    this->ExtraGenerator->EnableLanguage(languages, mf, false);
    }
783
784
785
786
787
788
789
790
791

  if(fatalError)
    {
    cmSystemTools::SetFatalErrorOccured();
    }
}

//----------------------------------------------------------------------------
void cmGlobalGenerator::PrintCompilerAdvice(std::ostream& os,
792
                                            std::string const& lang,
793
                                            const char* envVar) const
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
{
  // Subclasses override this method if they do not support this advice.
  os <<
    "Tell CMake where to find the compiler by setting "
    ;
  if(envVar)
    {
    os <<
      "either the environment variable \"" << envVar << "\" or "
      ;
    }
  os <<
    "the CMake cache entry CMAKE_" << lang << "_COMPILER "
    "to the full path to the compiler, or to the compiler name "
    "if it is in the PATH."
    ;
810
811
}

812
//----------------------------------------------------------------------------
813
void cmGlobalGenerator::CheckCompilerIdCompatibility(cmMakefile* mf,
814
                                                std::string const& lang) const
815
816
{
  std::string compilerIdVar = "CMAKE_" + lang + "_COMPILER_ID";
Stephen Kelly's avatar
Stephen Kelly committed
817
  const char* compilerId = mf->GetDefinition(compilerIdVar);
818
819
820
821
822
823
  if(!compilerId)
    {
    return;
    }

  if(strcmp(compilerId, "AppleClang") == 0)
824
825
826
827
    {
    switch(mf->GetPolicyStatus(cmPolicies::CMP0025))
      {
      case cmPolicies::WARN:
828
829
        if(!this->CMakeInstance->GetIsInTryCompile() &&
           mf->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0025"))
830
          {
831
          std::ostringstream w;
Stephen Kelly's avatar
Stephen Kelly committed
832
          w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0025) << "\n"
833
834
835
836
837
838
839
            "Converting " << lang <<
            " compiler id \"AppleClang\" to \"Clang\" for compatibility."
            ;
          mf->IssueMessage(cmake::AUTHOR_WARNING, w.str());
          }
      case cmPolicies::OLD:
        // OLD behavior is to convert AppleClang to Clang.
Stephen Kelly's avatar
Stephen Kelly committed
840
        mf->AddDefinition(compilerIdVar, "Clang");
841
842
843
844
845
        break;
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::REQUIRED_ALWAYS:
        mf->IssueMessage(
          cmake::FATAL_ERROR,
Stephen Kelly's avatar
Stephen Kelly committed
846
          cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0025)
847
848
849
850
851
852
          );
      case cmPolicies::NEW:
        // NEW behavior is to keep AppleClang.
        break;
      }
    }
853
854
855
856
857
858

  if(strcmp(compilerId, "QCC") == 0)
    {
    switch(mf->GetPolicyStatus(cmPolicies::CMP0047))
      {
      case cmPolicies::WARN:
859
860
        if(!this->CMakeInstance->GetIsInTryCompile() &&
           mf->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0047"))
861
          {
862
          std::ostringstream w;
Stephen Kelly's avatar
Stephen Kelly committed
863
          w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0047) << "\n"
864
865
866
867
868
869
870
            "Converting " << lang <<
            " compiler id \"QCC\" to \"GNU\" for compatibility."
            ;
          mf->IssueMessage(cmake::AUTHOR_WARNING, w.str());
          }
      case cmPolicies::OLD:
        // OLD behavior is to convert QCC to GNU.
Stephen Kelly's avatar
Stephen Kelly committed
871
        mf->AddDefinition(compilerIdVar, "GNU");
872
873
874
875
876
877
878
879
        if(lang == "C")
          {
          mf->AddDefinition("CMAKE_COMPILER_IS_GNUCC", "1");
          }
        else if(lang == "CXX")
          {
          mf->AddDefinition("CMAKE_COMPILER_IS_GNUCXX", "1");
          }
880
881
882
883
884
        break;
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::REQUIRED_ALWAYS:
        mf->IssueMessage(
          cmake::FATAL_ERROR,
Stephen Kelly's avatar
Stephen Kelly committed
885
          cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0047)
886
887
888
889
890
891
          );
      case cmPolicies::NEW:
        // NEW behavior is to keep QCC.
        break;
      }
    }
892
893
}

894
//----------------------------------------------------------------------------
895
std::string
896
cmGlobalGenerator::GetLanguageOutputExtension(cmSourceFile const& source) const
897
{
898
899
  const std::string& lang = source.GetLanguage();
  if(!lang.empty())
900
    {
901
    std::map<std::string, std::string>::const_iterator it =
902
903
904
                                  this->LanguageToOutputExtension.find(lang);

    if(it != this->LanguageToOutputExtension.end())
905
      {
906
      return it->second;
907
      }
908
    }
909
  else
910
911
912
913
    {
    // if no language is found then check to see if it is already an
    // ouput extension for some language.  In that case it should be ignored
    // and in this map, so it will not be compiled but will just be used.
914
915
    std::string const& ext = source.GetExtension();
    if(!ext.empty())
916
      {
917
918
      if(this->OutputExtensions.count(ext))
        {
919
        return ext;
920
        }
921
922
      }
    }
923
  return "";
924
925
926
}


927
std::string cmGlobalGenerator::GetLanguageFromExtension(const char* ext) const
928
{
Ken Martin's avatar
Ken Martin committed
929
930
  // if there is an extension and it starts with . then move past the
  // . because the extensions are not stored with a .  in the map
931
932
933
934
  if(ext && *ext == '.')
    {
    ++ext;
    }
935
  std::map<std::string, std::string>::const_iterator it
936
937
                                        = this->ExtensionToLanguage.find(ext);
  if(it != this->ExtensionToLanguage.end())
938
    {
939
    return it->second;
940
    }
941
  return "";
942
}
943

Alexander Neundorf's avatar
   
Alexander Neundorf committed
944
945
946
947
948
949
/* SetLanguageEnabled() is now split in two parts:
at first the enabled-flag is set. This can then be used in EnabledLanguage()
for checking whether the language is already enabled. After setting this
flag still the values from the cmake variables have to be copied into the
internal maps, this is done in SetLanguageEnabledMaps() which is called
after the system- and compiler specific files have been loaded.
950
951
952
953
954

This split was done originally so that compiler-specific configuration
files could change the object file extension
(CMAKE_<LANG>_OUTPUT_EXTENSION) before the CMake variables were copied
to the C++ maps.
Alexander Neundorf's avatar
   
Alexander Neundorf committed
955
*/
956
957
void cmGlobalGenerator::SetLanguageEnabled(const std::string& l,
                                           cmMakefile* mf)
Ken Martin's avatar
Ken Martin committed
958
{
Alexander Neundorf's avatar
   
Alexander Neundorf committed
959
960
961
962
  this->SetLanguageEnabledFlag(l, mf);
  this->SetLanguageEnabledMaps(l, mf);
}

963
964
void cmGlobalGenerator::SetLanguageEnabledFlag(const std::string& l,