Updates will be applied on October 27th between 12pm - 12:45pm EDT (UTC-0400). Gitlab may be slow during the maintenance window.

cmGlobalGenerator.cxx 97.8 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
568
569
570
      if (cmSystemTools::GetFatalErrorOccured())
        {
        return;
        }
571
      needTestLanguage[lang] = true;
572
573
574
575
      // 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
576
577
578
        // put ${CMake_(LANG)_COMPILER_ENV_VAR}=${CMAKE_(LANG)_COMPILER
        // into the environment, in case user scripts want to run
        // configure, or sub cmakes
579
580
581
582
583
584
        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
585
        std::string envVar = mf->GetRequiredDefinition(compilerEnv);
Alexander Neundorf's avatar
   
Alexander Neundorf committed
586
        std::string envVarValue =
Stephen Kelly's avatar
Stephen Kelly committed
587
          mf->GetRequiredDefinition(compilerName);
588
589
590
        std::string env = envVar;
        env += "=";
        env += envVarValue;
591
        cmSystemTools::PutEnv(env);
592
        }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
593
594
595

      // if determineLanguage was called then load the file it
      // configures CMake(LANG)Compiler.cmake
596
597
598
599
      fpath = rootBin;
      fpath += "/CMake";
      fpath += lang;
      fpath += "Compiler.cmake";
600
      if(!mf->ReadListFile(fpath.c_str()))
601
        {
602
        cmSystemTools::Error("Could not find cmake module file: ",
Ken Martin's avatar
Ken Martin committed
603
                             fpath.c_str());
604
        }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
605
606
      this->SetLanguageEnabledFlag(lang, mf);
      needSetLanguageEnabledMaps[lang] = true;
Ken Martin's avatar
Ken Martin committed
607
608
609
610
      // 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
611
      needTestLanguage[lang] = true;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
612
      } // end if(!this->GetLanguageEnabled(lang) )
613
    }  // end loop over languages
Alexander Neundorf's avatar
   
Alexander Neundorf committed
614

615
  // **** Load the system specific information if not yet loaded
616
  if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED"))
Bill Hoffman's avatar
Bill Hoffman committed
617
    {
618
    fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake");
619
    if(!mf->ReadListFile(fpath.c_str()))
620
      {
621
622
      cmSystemTools::Error("Could not find cmake module file: "
                           "CMakeSystemSpecificInformation.cmake");
623
      }
Bill Hoffman's avatar
Bill Hoffman committed
624
    }
625
626
  // loop over languages again loading CMake(LANG)Information.cmake
  //
627
628
629
630
  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
631
632
633
634
635
    if(*l == "NONE")
      {
      this->SetLanguageEnabled("NONE", mf);
      continue;
      }
636
637
638
639
640
641
642
643

    // Check that the compiler was found.
    std::string compilerName = "CMAKE_";
    compilerName += lang;
    compilerName += "_COMPILER";
    std::string compilerEnv = "CMAKE_";
    compilerEnv += lang;
    compilerEnv += "_COMPILER_ENV_VAR";
644
    std::ostringstream noCompiler;
Stephen Kelly's avatar
Stephen Kelly committed
645
    const char* compilerFile = mf->GetDefinition(compilerName);
646
647
648
649
650
651
652
    if(!compilerFile || !*compilerFile ||
       cmSystemTools::IsNOTFOUND(compilerFile))
      {
      noCompiler <<
        "No " << compilerName << " could be found.\n"
        ;
      }
653
654
    else if(strcmp(lang, "RC") != 0 &&
            strcmp(lang, "ASM_MASM") != 0)
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
681
682
683
684
      {
      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";
685
        cmSystemTools::RemoveFile(compilerLangFile);
686
687
688
        if(!this->CMakeInstance->GetIsInTryCompile())
          {
          this->PrintCompilerAdvice(noCompiler, lang,
Stephen Kelly's avatar
Stephen Kelly committed
689
                                    mf->GetDefinition(compilerEnv));
690
691
692
693
694
695
          mf->IssueMessage(cmake::FATAL_ERROR, noCompiler.str());
          fatalError = true;
          }
        }
      }

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

722
    // Test the compiler for the language just setup
723
    // (but only if a compiler has been actually found)
724
725
    // At this point we should have enough info for a try compile
    // which is used in the backward stuff
726
    // If the language is untested then test it now with a try compile.
727
    if(needTestLanguage[lang])
728
      {
Ken Martin's avatar
Ken Martin committed
729
      if (!this->CMakeInstance->GetIsInTryCompile())
730
        {
731
732
733
734
        std::string testLang = "CMakeTest";
        testLang += lang;
        testLang += "Compiler.cmake";
        std::string ifpath = mf->GetModulesFile(testLang.c_str());
735
        if(!mf->ReadListFile(ifpath.c_str()))
736
          {
737
          cmSystemTools::Error("Could not find cmake module file: ",
738
                               testLang.c_str());
739
          }
740
741
742
        std::string compilerWorks = "CMAKE_";
        compilerWorks += lang;
        compilerWorks += "_COMPILER_WORKS";
Ken Martin's avatar
Ken Martin committed
743
744
745
        // 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
746
        if(!mf->IsOn(compilerWorks))
Alexander Neundorf's avatar
   
Alexander Neundorf committed
747
          {
748
749
750
751
          std::string compilerLangFile = rootBin;
          compilerLangFile += "/CMake";
          compilerLangFile += lang;
          compilerLangFile += "Compiler.cmake";
752
          cmSystemTools::RemoveFile(compilerLangFile);
753
754
755
          }
        } // end if in try compile
      } // end need test language
756
757
758
759
760
    // 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
761
      mf->GetSafeDefinition(sharedLibFlagsVar);
762
763
764
765
    if (sharedLibFlags)
      {
      this->LanguageToOriginalSharedLibFlags[lang] = sharedLibFlags;
      }
766
767
768

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

Ken Martin's avatar
Ken Martin committed
771
772
773
  // 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
774
775
  std::string projectCompatibility = mf->GetDefinition("CMAKE_ROOT");
  projectCompatibility += "/Modules/";
776
  projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME");
777
778
779
  projectCompatibility += "Compatibility.cmake";
  if(cmSystemTools::FileExists(projectCompatibility.c_str()))
    {
780
    mf->ReadListFile(projectCompatibility.c_str());
781
    }
782
783
784
785
786
  // Inform any extra generator of the new language.
  if (this->ExtraGenerator)
    {
    this->ExtraGenerator->EnableLanguage(languages, mf, false);
    }
787
788
789
790
791
792
793
794
795

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

//----------------------------------------------------------------------------
void cmGlobalGenerator::PrintCompilerAdvice(std::ostream& os,
796
                                            std::string const& lang,
797
                                            const char* envVar) const
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
{
  // 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."
    ;
814
815
}

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

  if(strcmp(compilerId, "AppleClang") == 0)
828
829
830
831
    {
    switch(mf->GetPolicyStatus(cmPolicies::CMP0025))
      {
      case cmPolicies::WARN:
832
833
        if(!this->CMakeInstance->GetIsInTryCompile() &&
           mf->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0025"))
834
          {
835
          std::ostringstream w;
Stephen Kelly's avatar
Stephen Kelly committed
836
          w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0025) << "\n"
837
838
839
840
841
842
843
            "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
844
        mf->AddDefinition(compilerIdVar, "Clang");
845
846
847
848
849
        break;
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::REQUIRED_ALWAYS:
        mf->IssueMessage(
          cmake::FATAL_ERROR,
Stephen Kelly's avatar
Stephen Kelly committed
850
          cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0025)
851
852
853
854
855
856
          );
      case cmPolicies::NEW:
        // NEW behavior is to keep AppleClang.
        break;
      }
    }
857
858
859
860
861
862

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

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

    if(it != this->LanguageToOutputExtension.end())
909
      {
910
      return it->second;
911
      }
912
    }
913
  else
914
915
916
917
    {
    // 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.
918
919
    std::string const& ext = source.GetExtension();
    if(!ext.empty())
920
      {
921
922
      if(this->OutputExtensions.count(ext))
        {
923
        return ext;
924
        }
925
926
      }
    }
927
  return "";
928
929
930
}


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

Alexander Neundorf's avatar
   
Alexander Neundorf committed
948
949
950
951
952
953
/* 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.
954
955
956
957
958

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
959
*/
960
961
void cmGlobalGenerator::SetLanguageEnabled(const std::string& l,
                                           cmMakefile* mf)
Ken Martin's avatar
Ken Martin committed
962
{
Alexander Neundorf's avatar
   
Alexander Neundorf committed
963
964
965
966
  this->SetLanguageEnabledFlag(l, mf);
  this->SetLanguageEnabledMaps(l, mf);
}

967
968
void cmGlobalGenerator::SetLanguageEnabledFlag(const std::string& l,
                                               cmMakefile* mf)
Alexander Neundorf's avatar
   
Alexander Neundorf committed
969
{
970
  this->CMakeInstance->GetState()->SetLanguageEnabled(l);
971
972
973
974
975
976
977

  // Fill the language-to-extension map with the current variable
  // settings to make sure it is available for the try_compile()
  // command source file signature.  In SetLanguageEnabledMaps this
  // will be done again to account for any compiler- or
  // platform-specific entries.
  this->FillExtensionToLanguageMap(l, mf);
Alexander Neundorf's avatar
   
Alexander Neundorf committed
978
979
}

980
981
void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l,
                                               cmMakefile* mf)
Alexander Neundorf's avatar
   
Alexander Neundorf committed
982
983
984
985
986
{
  // use LanguageToLinkerPreference to detect whether this functions has
  // run before
  if (this->LanguageToLinkerPreference.find(l) !=
                                        this->LanguageToLinkerPreference.end())
987
988
989
    {
    return;
    }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
990
991
992

  std::string linkerPrefVar = std::string("CMAKE_") +
    std::string(l) + std::string("_LINKER_PREFERENCE");
Stephen Kelly's avatar
Stephen Kelly committed
993
  const char* linkerPref =