1
/*=========================================================================
3
Program: CMake - Cross-Platform Makefile Generator
4
Module: $RCSfile: cmLocalGenerator.cxx,v $
6
Date: $Date: 2009-03-23 17:58:41 $
7
Version: $Revision: 1.269.2.11 $
9
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12
This software is distributed WITHOUT ANY WARRANTY; without even
13
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14
PURPOSE. See the above copyright notices for more information.
16
=========================================================================*/
1
/*============================================================================
2
CMake - Cross Platform Makefile Generator
3
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
5
Distributed under the OSI-approved BSD License (the "License");
6
see accompanying file Copyright.txt for details.
8
This software is distributed WITHOUT ANY WARRANTY; without even the
9
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
See the License for more information.
11
============================================================================*/
17
12
#include "cmLocalGenerator.h"
19
14
#include "cmComputeLinkInformation.h"
40
37
#include <assert.h>
39
#if defined(__HAIKU__)
40
#include <StorageKit.h>
42
43
cmLocalGenerator::cmLocalGenerator()
44
this->Makefile = new cmMakefile;
45
this->Makefile->SetLocalGenerator(this);
45
this->Makefile = 0; // moved to after set on global
47
47
this->WindowsShell = false;
48
48
this->WindowsVSIDE = false;
67
67
delete this->Makefile;
70
//----------------------------------------------------------------------------
71
class cmLocalGeneratorCurrent
73
cmGlobalGenerator* GG;
76
cmLocalGeneratorCurrent(cmLocalGenerator* lg)
78
this->GG = lg->GetGlobalGenerator();
79
this->LG = this->GG->GetCurrentLocalGenerator();
80
this->GG->SetCurrentLocalGenerator(lg);
82
~cmLocalGeneratorCurrent()
84
this->GG->SetCurrentLocalGenerator(this->LG);
88
//----------------------------------------------------------------------------
70
89
void cmLocalGenerator::Configure()
72
cmLocalGenerator* previousLg =
73
this->GetGlobalGenerator()->GetCurrentLocalGenerator();
74
this->GetGlobalGenerator()->SetCurrentLocalGenerator(this);
91
// Manage the global generator's current local generator.
92
cmLocalGeneratorCurrent clg(this);
93
static_cast<void>(clg);
76
95
// make sure the CMakeFiles dir is there
77
96
std::string filesDir = this->Makefile->GetStartOutputDirectory();
79
98
cmSystemTools::MakeDirectory(filesDir.c_str());
81
100
// find & read the list file
82
std::string currentStart = this->Makefile->GetStartDirectory();
83
currentStart += "/CMakeLists.txt";
84
this->Makefile->ReadListFile(currentStart.c_str());
101
this->ReadInputFile();
86
103
// at the end of the ReadListFile handle any old style subdirs
87
104
// first get all the subdirectories
101
118
// relative paths.
102
119
this->UseRelativePaths = this->Makefile->IsOn("CMAKE_USE_RELATIVE_PATHS");
121
this->ComputeObjectMaxPath();
123
this->Configured = true;
126
//----------------------------------------------------------------------------
127
void cmLocalGenerator::ComputeObjectMaxPath()
104
129
// Choose a maximum object file name length.
106
130
#if defined(_WIN32) || defined(__CYGWIN__)
107
131
this->ObjectPathMax = 250;
139
163
this->ObjectMaxPathViolations.clear();
142
this->Configured = true;
144
this->GetGlobalGenerator()->SetCurrentLocalGenerator(previousLg);
166
//----------------------------------------------------------------------------
167
void cmLocalGenerator::ReadInputFile()
169
// Look for the CMakeLists.txt file.
170
std::string currentStart = this->Makefile->GetStartDirectory();
171
currentStart += "/CMakeLists.txt";
172
if(cmSystemTools::FileExists(currentStart.c_str(), true))
174
this->Makefile->ReadListFile(currentStart.c_str());
183
// The file is missing. Check policy CMP0014.
184
cmMakefile* mf = this->Parent->GetMakefile();
186
e << "The source directory\n"
187
<< " " << this->Makefile->GetStartDirectory() << "\n"
188
<< "does not contain a CMakeLists.txt file.";
189
switch (mf->GetPolicyStatus(cmPolicies::CMP0014))
191
case cmPolicies::WARN:
192
// Print the warning.
194
<< "CMake does not support this case but it used "
195
<< "to work accidentally and is being allowed for "
198
<< mf->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0014);
199
mf->IssueMessage(cmake::AUTHOR_WARNING, e.str());
200
case cmPolicies::OLD:
201
// OLD behavior does not warn.
203
case cmPolicies::REQUIRED_IF_USED:
204
case cmPolicies::REQUIRED_ALWAYS:
206
<< mf->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0014);
207
case cmPolicies::NEW:
208
// NEW behavior prints the error.
209
mf->IssueMessage(cmake::FATAL_ERROR, e.str());
147
214
void cmLocalGenerator::SetupPathConversions()
171
238
void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg)
173
240
this->GlobalGenerator = gg;
241
this->Makefile = new cmMakefile;
242
this->Makefile->SetLocalGenerator(this);
175
244
// setup the home directories
176
245
this->Makefile->GetProperties().SetCMakeInstance(gg->GetCMakeInstance());
191
260
cmTargets& targets = this->Makefile->GetTargets();
192
261
for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
194
// INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
195
// so don't build a projectfile for it
196
if (strncmp(t->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0)
263
const char* projectFilename = 0;
264
if (this->IsMakefileGenerator == false) // only use of this variable
198
const char* projectFilename = 0;
199
if (this->IsMakefileGenerator == false) // only use of this variable
201
projectFilename = t->second.GetName();
203
t->second.TraceDependencies(projectFilename);
266
projectFilename = t->second.GetName();
268
t->second.TraceDependencies(projectFilename);
279
// Compute the set of configurations.
280
std::vector<std::string> configurationTypes;
281
if(const char* types =
282
this->Makefile->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
284
cmSystemTools::ExpandListArgument(types, configurationTypes);
286
const char* config = 0;
287
if(configurationTypes.empty())
289
config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
214
292
std::string file = this->Makefile->GetStartOutputDirectory();
216
294
file += "CTestTestfile.cmake";
224
302
<< "# Build directory: "
225
303
<< this->Makefile->GetStartOutputDirectory() << std::endl
226
304
<< "# " << std::endl
227
<< "# This file replicates the SUBDIRS() and ADD_TEST() commands "
228
<< "from the source" << std::endl
229
<< "# tree CMakeLists.txt file, skipping any SUBDIRS() or "
230
<< "ADD_TEST() commands" << std::endl
231
<< "# that are excluded by CMake control structures, i.e. IF() "
232
<< "commands." << std::endl;
305
<< "# This file includes the relevent testing commands "
306
<< "required for " << std::endl
307
<< "# testing this directory and lists subdirectories to "
308
<< "be tested as well." << std::endl;
234
310
const char* testIncludeFile =
235
311
this->Makefile->GetProperty("TEST_INCLUDE_FILE");
238
314
fout << "INCLUDE(\"" << testIncludeFile << "\")" << std::endl;
241
const std::vector<cmTest*> *tests = this->Makefile->GetTests();
242
std::vector<cmTest*>::const_iterator it;
243
for ( it = tests->begin(); it != tests->end(); ++ it )
317
// Ask each test generator to write its code.
318
std::vector<cmTestGenerator*> const&
319
testers = this->Makefile->GetTestGenerators();
320
for(std::vector<cmTestGenerator*>::const_iterator gi = testers.begin();
321
gi != testers.end(); ++gi)
247
fout << test->GetName() << " \"" << test->GetCommand() << "\"";
249
std::vector<cmStdString>::const_iterator argit;
250
for (argit = test->GetArguments().begin();
251
argit != test->GetArguments().end(); ++argit)
253
// Just double-quote all arguments so they are re-parsed
254
// correctly by the test system.
256
for(std::string::const_iterator c = argit->begin();
257
c != argit->end(); ++c)
259
// Escape quotes within arguments. We should escape
260
// backslashes too but we cannot because it makes the result
261
// inconsistent with previous behavior of this command.
270
fout << ")" << std::endl;
271
cmPropertyMap::const_iterator pit;
272
cmPropertyMap* mpit = &test->GetProperties();
275
fout << "SET_TESTS_PROPERTIES(" << test->GetName() << " PROPERTIES ";
276
for ( pit = mpit->begin(); pit != mpit->end(); ++ pit )
278
fout << " " << pit->first.c_str() << " \"";
279
const char* value = pit->second.GetValue();
280
for ( ; *value; ++ value )
292
fout << "\\" << *value;
309
fout << ")" << std::endl;
323
(*gi)->Generate(fout, config, configurationTypes);
312
325
if ( this->Children.size())
972
997
return replaceValues.LinkLibraries;
1000
if(replaceValues.Language)
1002
if(variable == "LANGUAGE")
1004
return replaceValues.Language;
1007
if(replaceValues.CMTarget)
1009
if(variable == "TARGET_NAME")
1011
return replaceValues.CMTarget->GetName();
1013
if(variable == "TARGET_TYPE")
1015
return cmTarget::TargetTypeNames[replaceValues.CMTarget->GetType()];
1018
if(replaceValues.Output)
1020
if(variable == "OUTPUT")
1022
return replaceValues.Output;
975
1025
if(variable == "CMAKE_COMMAND")
977
1027
const char* cmcommand =
1035
1085
std::vector<std::string> enabledLanguages;
1036
1086
this->GlobalGenerator->GetEnabledLanguages(enabledLanguages);
1087
this->InsertRuleLauncher(s, replaceValues.CMTarget,
1088
replaceValues.RuleLauncher);
1037
1089
std::string::size_type start = s.find('<');
1038
1090
// no variables to expand
1039
1091
if(start == s.npos)
1078
1130
//----------------------------------------------------------------------------
1131
const char* cmLocalGenerator::GetRuleLauncher(cmTarget* target,
1136
return target->GetProperty(prop);
1140
return this->Makefile->GetProperty(prop);
1144
//----------------------------------------------------------------------------
1145
void cmLocalGenerator::InsertRuleLauncher(std::string& s, cmTarget* target,
1148
if(const char* val = this->GetRuleLauncher(target, prop))
1150
cmOStringStream wrapped;
1151
wrapped << val << " " << s;
1156
//----------------------------------------------------------------------------
1080
1158
cmLocalGenerator::ConvertToOutputForExistingCommon(const char* remote,
1081
1159
std::string const& result)
1227
1305
std::string flags = includeFlags.str();
1228
1306
// remove trailing separators
1229
if((sep[0] != ' ') && flags[flags.size()-1] == sep[0])
1307
if((sep[0] != ' ') && flags.size()>0 && flags[flags.size()-1] == sep[0])
1231
1309
flags[flags.size()-1] = ' ';
1691
1770
this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT");
1692
1771
const char* sysrootDefault =
1693
1772
this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT_DEFAULT");
1773
const char* deploymentTarget =
1774
this->Makefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET");
1775
std::string isysrootVar = std::string("CMAKE_") + lang + "_HAS_ISYSROOT";
1776
bool hasIsysroot = this->Makefile->IsOn(isysrootVar.c_str());
1694
1777
bool flagsUsed = false;
1695
if(osxArch && sysroot && lang && (lang[0] =='C' || lang[0] == 'F'))
1778
if(osxArch && sysroot && lang && (lang[0] =='C' || lang[0] == 'F'))
1697
1780
std::vector<std::string> archs;
1698
1781
cmSystemTools::ExpandListArgument(std::string(osxArch),
1700
bool addArchFlag = true;
1701
if(archs.size() == 1)
1783
bool addArchFlag = false;
1784
if(archs.size() >= 1)
1703
const char* archOrig =
1704
this->Makefile->GetSafeDefinition("CMAKE_OSX_ARCHITECTURES_DEFAULT");
1705
if(archs[0] == archOrig)
1707
addArchFlag = false;
1710
1791
// if there is more than one arch add the -arch and
1719
1800
flags += " -arch ";
1722
flags += " -isysroot ";
1805
flags += " -isysroot ";
1724
1808
flagsUsed = true;
1727
1812
if(!flagsUsed && sysroot && sysrootDefault &&
1728
strcmp(sysroot, sysrootDefault) != 0)
1813
strcmp(sysroot, sysrootDefault) != 0 && hasIsysroot)
1730
1815
flags += " -isysroot ";
1731
1816
flags += sysroot;
1819
if (deploymentTarget && *deploymentTarget &&
1820
lang && (lang[0] =='C' || lang[0] == 'F'))
1822
flags += " -mmacosx-version-min=";
1823
flags += deploymentTarget;
1734
1827
this->AddConfigVariableFlags(flags, flagsVar.c_str(), config);
1756
1849
// found is part of the inName
1757
1850
if(cmSystemTools::FileIsFullPath(inName))
1759
std::string tLocation = target->GetLocation(config);
1760
tLocation = cmSystemTools::GetFilenamePath(tLocation);
1852
std::string tLocation;
1853
if(target->GetType() >= cmTarget::EXECUTABLE &&
1854
target->GetType() <= cmTarget::MODULE_LIBRARY)
1856
tLocation = target->GetLocation(config);
1857
tLocation = cmSystemTools::GetFilenamePath(tLocation);
1858
tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str());
1761
1860
std::string depLocation = cmSystemTools::GetFilenamePath(
1762
1861
std::string(inName));
1763
1862
depLocation = cmSystemTools::CollapseFullPath(depLocation.c_str());
1764
tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str());
1765
1863
if(depLocation != tLocation)
1767
1865
// it is a full path to a depend that has the same name
1853
1951
flagsVar += "_FLAGS";
1854
1952
this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar.c_str()));
1857
// Add flags specific to shared builds.
1858
if(cmSystemTools::IsOn(this->Makefile->GetDefinition("BUILD_SHARED_LIBS")))
1860
flagsVar = "CMAKE_SHARED_BUILD_";
1862
flagsVar += "_FLAGS";
1863
this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar.c_str()));
1867
1956
//----------------------------------------------------------------------------
1974
// Make the definition appear properly on the command line.
1975
defines += this->EscapeForShell(di->c_str(), true);
2063
// Make the definition appear properly on the command line. Use
2064
// -DNAME="value" instead of -D"NAME=value" to help VS6 parser.
2065
std::string::size_type eq = di->find("=");
2066
defines += di->substr(0, eq);
2070
defines += this->EscapeForShell(di->c_str() + eq + 1, true);
2076
//----------------------------------------------------------------------------
2077
void cmLocalGenerator::AppendFeatureOptions(
2078
std::string& flags, const char* lang, const char* feature)
2080
std::string optVar = "CMAKE_";
2082
optVar += "_COMPILE_OPTIONS_";
2084
if(const char* optionList = this->Makefile->GetDefinition(optVar.c_str()))
2086
std::vector<std::string> options;
2087
cmSystemTools::ExpandListArgument(optionList, options);
2088
for(std::vector<std::string>::const_iterator oi = options.begin();
2089
oi != options.end(); ++oi)
2091
this->AppendFlags(flags, this->EscapeForShell(oi->c_str()).c_str());
2215
2331
//----------------------------------------------------------------------------
2217
2333
cmLocalGenerator::ConvertToRelativePath(const std::vector<std::string>& local,
2218
const char* in_remote)
2334
const char* in_remote, bool force)
2220
2336
// The path should never be quoted.
2221
2337
assert(in_remote[0] != '\"');
2236
2352
this->RelativePathsConfigured = true;
2239
// Skip conversion if the path and local are not both in the source
2240
// or both in the binary tree.
2241
std::string local_path = cmSystemTools::JoinPath(local);
2242
if(!((cmLocalGeneratorNotAbove(local_path.c_str(),
2243
this->RelativePathTopBinary.c_str()) &&
2244
cmLocalGeneratorNotAbove(in_remote,
2245
this->RelativePathTopBinary.c_str())) ||
2246
(cmLocalGeneratorNotAbove(local_path.c_str(),
2247
this->RelativePathTopSource.c_str()) &&
2248
cmLocalGeneratorNotAbove(in_remote,
2249
this->RelativePathTopSource.c_str()))))
2357
// Skip conversion if the path and local are not both in the source
2358
// or both in the binary tree.
2359
std::string local_path = cmSystemTools::JoinPath(local);
2360
if(!((cmLocalGeneratorNotAbove(local_path.c_str(),
2361
this->RelativePathTopBinary.c_str()) &&
2362
cmLocalGeneratorNotAbove(in_remote,
2363
this->RelativePathTopBinary.c_str())) ||
2364
(cmLocalGeneratorNotAbove(local_path.c_str(),
2365
this->RelativePathTopSource.c_str()) &&
2366
cmLocalGeneratorNotAbove(in_remote,
2367
this->RelativePathTopSource.c_str()))))
2254
2373
// Identify the longest shared path component between the remote
2690
2809
strcmp(str, "<<") == 0 ||
2691
2810
strcmp(str, ">>") == 0 ||
2692
2811
strcmp(str, "|") == 0 ||
2812
strcmp(str, "||") == 0 ||
2813
strcmp(str, "&&") == 0 ||
2693
2814
strcmp(str, "&>") == 0 ||
2815
strcmp(str, "1>") == 0 ||
2816
strcmp(str, "2>") == 0 ||
2694
2817
strcmp(str, "2>&1") == 0 ||
2695
2818
strcmp(str, "1>&2") == 0)