~ubuntu-branches/ubuntu/lucid/cmake/lucid

« back to all changes in this revision

Viewing changes to Source/cmLocalGenerator.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Artur Rona
  • Date: 2009-12-16 11:11:54 UTC
  • mfrom: (3.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20091216111154-6accvv6yq86h2hkc
Tags: 2.8.0-5ubuntu1
* Merge from debian testing (LP: #497349). Remaining changes:
  - Keep the Replaces: on cmake-data to cover the Kubuntu version from
    Jaunty in case someone decides to do an (unsupported) Jaunty->Lucid
    upgrade.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*=========================================================================
2
 
 
3
 
  Program:   CMake - Cross-Platform Makefile Generator
4
 
  Module:    $RCSfile: cmLocalGenerator.cxx,v $
5
 
  Language:  C++
6
 
  Date:      $Date: 2009-03-23 17:58:41 $
7
 
  Version:   $Revision: 1.269.2.11 $
8
 
 
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.
11
 
 
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.
15
 
 
16
 
=========================================================================*/
 
1
/*============================================================================
 
2
  CMake - Cross Platform Makefile Generator
 
3
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
 
4
 
 
5
  Distributed under the OSI-approved BSD License (the "License");
 
6
  see accompanying file Copyright.txt for details.
 
7
 
 
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"
18
13
 
19
14
#include "cmComputeLinkInformation.h"
26
21
#include "cmMakefile.h"
27
22
#include "cmSourceFile.h"
28
23
#include "cmTest.h"
 
24
#include "cmTestGenerator.h"
 
25
#include "cmVersion.h"
29
26
#include "cmake.h"
30
27
 
31
28
#if defined(CMAKE_BUILD_WITH_CMAKE)
39
36
 
40
37
#include <assert.h>
41
38
 
 
39
#if defined(__HAIKU__)
 
40
#include <StorageKit.h>
 
41
#endif
 
42
 
42
43
cmLocalGenerator::cmLocalGenerator()
43
44
{
44
 
  this->Makefile = new cmMakefile;
45
 
  this->Makefile->SetLocalGenerator(this);
 
45
  this->Makefile = 0; // moved to after set on global
46
46
  this->Parent = 0;
47
47
  this->WindowsShell = false;
48
48
  this->WindowsVSIDE = false;
67
67
  delete this->Makefile;
68
68
}
69
69
 
 
70
//----------------------------------------------------------------------------
 
71
class cmLocalGeneratorCurrent
 
72
{
 
73
  cmGlobalGenerator* GG;
 
74
  cmLocalGenerator* LG;
 
75
public:
 
76
  cmLocalGeneratorCurrent(cmLocalGenerator* lg)
 
77
    {
 
78
    this->GG = lg->GetGlobalGenerator();
 
79
    this->LG = this->GG->GetCurrentLocalGenerator();
 
80
    this->GG->SetCurrentLocalGenerator(lg);
 
81
    }
 
82
  ~cmLocalGeneratorCurrent()
 
83
    {
 
84
    this->GG->SetCurrentLocalGenerator(this->LG);
 
85
    }
 
86
};
 
87
 
 
88
//----------------------------------------------------------------------------
70
89
void cmLocalGenerator::Configure()
71
90
{
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);
75
94
 
76
95
  // make sure the CMakeFiles dir is there
77
96
  std::string filesDir = this->Makefile->GetStartOutputDirectory();
79
98
  cmSystemTools::MakeDirectory(filesDir.c_str());
80
99
  
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();
85
102
 
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");
103
120
 
 
121
  this->ComputeObjectMaxPath();
 
122
 
 
123
  this->Configured = true;
 
124
}
 
125
 
 
126
//----------------------------------------------------------------------------
 
127
void cmLocalGenerator::ComputeObjectMaxPath()
 
128
{
104
129
  // Choose a maximum object file name length.
105
 
  {
106
130
#if defined(_WIN32) || defined(__CYGWIN__)
107
131
  this->ObjectPathMax = 250;
108
132
#else
137
161
      }
138
162
    }
139
163
  this->ObjectMaxPathViolations.clear();
140
 
  }
141
 
 
142
 
  this->Configured = true;
143
 
 
144
 
  this->GetGlobalGenerator()->SetCurrentLocalGenerator(previousLg);
 
164
}
 
165
 
 
166
//----------------------------------------------------------------------------
 
167
void cmLocalGenerator::ReadInputFile()
 
168
{
 
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))
 
173
    {
 
174
    this->Makefile->ReadListFile(currentStart.c_str());
 
175
    return;
 
176
    }
 
177
 
 
178
  if(!this->Parent)
 
179
    {
 
180
    return;
 
181
    }
 
182
 
 
183
  // The file is missing.  Check policy CMP0014.
 
184
  cmMakefile* mf = this->Parent->GetMakefile();
 
185
  cmOStringStream e;
 
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))
 
190
    {
 
191
    case cmPolicies::WARN:
 
192
      // Print the warning.
 
193
      e << "\n"
 
194
        << "CMake does not support this case but it used "
 
195
        << "to work accidentally and is being allowed for "
 
196
        << "compatibility."
 
197
        << "\n"
 
198
        << mf->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0014);
 
199
      mf->IssueMessage(cmake::AUTHOR_WARNING, e.str());
 
200
    case cmPolicies::OLD:
 
201
      // OLD behavior does not warn.
 
202
      return;
 
203
    case cmPolicies::REQUIRED_IF_USED:
 
204
    case cmPolicies::REQUIRED_ALWAYS:
 
205
      e << "\n"
 
206
        << mf->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0014);
 
207
    case cmPolicies::NEW:
 
208
      // NEW behavior prints the error.
 
209
      mf->IssueMessage(cmake::FATAL_ERROR, e.str());
 
210
      break;
 
211
    }
145
212
}
146
213
 
147
214
void cmLocalGenerator::SetupPathConversions()
171
238
void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg)
172
239
{
173
240
  this->GlobalGenerator = gg;
 
241
  this->Makefile = new cmMakefile;
 
242
  this->Makefile->SetLocalGenerator(this);
174
243
 
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)
193
262
    {
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
197
265
      {
198
 
      const char* projectFilename = 0;
199
 
      if (this->IsMakefileGenerator == false)  // only use of this variable
200
 
        {
201
 
        projectFilename = t->second.GetName();
202
 
        }
203
 
      t->second.TraceDependencies(projectFilename);
 
266
      projectFilename = t->second.GetName();
204
267
      }
 
268
    t->second.TraceDependencies(projectFilename);
205
269
    }
206
270
}
207
271
 
211
275
    {
212
276
    return;
213
277
    }
 
278
 
 
279
  // Compute the set of configurations.
 
280
  std::vector<std::string> configurationTypes;
 
281
  if(const char* types =
 
282
     this->Makefile->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
 
283
    {
 
284
    cmSystemTools::ExpandListArgument(types, configurationTypes);
 
285
    }
 
286
  const char* config = 0;
 
287
  if(configurationTypes.empty())
 
288
    {
 
289
    config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
 
290
    }
 
291
 
214
292
  std::string file = this->Makefile->GetStartOutputDirectory();
215
293
  file += "/";
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;
233
309
  
234
310
  const char* testIncludeFile = 
235
311
    this->Makefile->GetProperty("TEST_INCLUDE_FILE");
237
313
    {
238
314
    fout << "INCLUDE(\"" << testIncludeFile << "\")" << std::endl;
239
315
    }
240
 
  
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 )
 
316
 
 
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)
244
322
    {
245
 
    cmTest* test = *it;
246
 
    fout << "ADD_TEST(";
247
 
    fout << test->GetName() << " \"" << test->GetCommand() << "\"";
248
 
    
249
 
    std::vector<cmStdString>::const_iterator argit;
250
 
    for (argit = test->GetArguments().begin();
251
 
         argit != test->GetArguments().end(); ++argit)
252
 
      {
253
 
      // Just double-quote all arguments so they are re-parsed
254
 
      // correctly by the test system.
255
 
      fout << " \"";
256
 
      for(std::string::const_iterator c = argit->begin(); 
257
 
          c != argit->end(); ++c)
258
 
        {
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.
262
 
        if((*c == '"'))
263
 
          {
264
 
          fout << '\\';
265
 
          }
266
 
        fout << *c;
267
 
        }
268
 
      fout << "\"";
269
 
      }
270
 
    fout << ")" << std::endl;
271
 
    cmPropertyMap::const_iterator pit;
272
 
    cmPropertyMap* mpit = &test->GetProperties();
273
 
    if ( mpit->size() )
274
 
      {
275
 
      fout << "SET_TESTS_PROPERTIES(" << test->GetName() << " PROPERTIES ";
276
 
      for ( pit = mpit->begin(); pit != mpit->end(); ++ pit )
277
 
        {
278
 
        fout << " " << pit->first.c_str() << " \"";
279
 
        const char* value = pit->second.GetValue();
280
 
        for ( ; *value; ++ value )
281
 
          {
282
 
          switch ( *value )
283
 
            {
284
 
          case '\\':
285
 
          case '"':
286
 
          case ' ':
287
 
          case '#':
288
 
          case '(':
289
 
          case ')':
290
 
          case '$':
291
 
          case '^':
292
 
            fout << "\\" << *value;
293
 
            break;
294
 
          case '\t':
295
 
            fout << "\\t";
296
 
            break;
297
 
          case '\n':
298
 
            fout << "\\n";
299
 
            break;
300
 
          case '\r':
301
 
            fout << "\\r";
302
 
            break;
303
 
          default:
304
 
            fout << *value;
305
 
            }
306
 
          }
307
 
        fout << "\"";
308
 
        }
309
 
      fout << ")" << std::endl;
310
 
      }
 
323
    (*gi)->Generate(fout, config, configurationTypes);
311
324
    }
312
325
  if ( this->Children.size())
313
326
    {
348
361
      }
349
362
    prefix = prefix_win32.c_str();
350
363
    }
 
364
#elif defined(__HAIKU__)
 
365
  if (!prefix)
 
366
    {
 
367
    BPath dir;
 
368
    if (find_directory(B_COMMON_DIRECTORY, &dir) == B_OK)
 
369
      {
 
370
      prefix = dir.Path();
 
371
      }
 
372
    else
 
373
      {
 
374
      prefix = "/boot/common";
 
375
      }
 
376
    }
351
377
#else
352
378
  if (!prefix)
353
379
    {
744
770
      case cmTarget::MODULE_LIBRARY:
745
771
      case cmTarget::EXECUTABLE: 
746
772
        {
747
 
        const char* llang = 
748
 
          target.GetLinkerLanguage(this->GetGlobalGenerator());
 
773
        const char* llang = target.GetLinkerLanguage();
749
774
        if(!llang)
750
775
          {
751
776
          cmSystemTools::Error
972
997
      return replaceValues.LinkLibraries;
973
998
      }
974
999
    }
 
1000
  if(replaceValues.Language)
 
1001
    {
 
1002
    if(variable == "LANGUAGE")
 
1003
      {
 
1004
      return replaceValues.Language;
 
1005
      }
 
1006
    }
 
1007
  if(replaceValues.CMTarget)
 
1008
    {
 
1009
    if(variable == "TARGET_NAME")
 
1010
      {
 
1011
      return replaceValues.CMTarget->GetName();
 
1012
      }
 
1013
    if(variable == "TARGET_TYPE")
 
1014
      {
 
1015
      return cmTarget::TargetTypeNames[replaceValues.CMTarget->GetType()];
 
1016
      }
 
1017
    }
 
1018
  if(replaceValues.Output)
 
1019
    {
 
1020
    if(variable == "OUTPUT")
 
1021
      {
 
1022
      return replaceValues.Output;
 
1023
      }
 
1024
    }
975
1025
  if(variable == "CMAKE_COMMAND")
976
1026
    {
977
1027
    const char* cmcommand =
1034
1084
{
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)
1076
1128
}
1077
1129
 
1078
1130
//----------------------------------------------------------------------------
 
1131
const char* cmLocalGenerator::GetRuleLauncher(cmTarget* target,
 
1132
                                              const char* prop)
 
1133
{
 
1134
  if(target)
 
1135
    {
 
1136
    return target->GetProperty(prop);
 
1137
    }
 
1138
  else
 
1139
    {
 
1140
    return this->Makefile->GetProperty(prop);
 
1141
    }
 
1142
}
 
1143
 
 
1144
//----------------------------------------------------------------------------
 
1145
void cmLocalGenerator::InsertRuleLauncher(std::string& s, cmTarget* target,
 
1146
                                          const char* prop)
 
1147
{
 
1148
  if(const char* val = this->GetRuleLauncher(target, prop))
 
1149
    {
 
1150
    cmOStringStream wrapped;
 
1151
    wrapped << val << " " << s;
 
1152
    s = wrapped.str();
 
1153
    }
 
1154
}
 
1155
 
 
1156
//----------------------------------------------------------------------------
1079
1157
std::string
1080
1158
cmLocalGenerator::ConvertToOutputForExistingCommon(const char* remote,
1081
1159
                                                   std::string const& result)
1226
1304
    }
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])
1230
1308
    {
1231
1309
    flags[flags.size()-1] = ' ';
1232
1310
    }
1449
1527
        linkFlags += this->Makefile->GetSafeDefinition(build.c_str());
1450
1528
        linkFlags += " ";
1451
1529
        } 
1452
 
      const char* linkLanguage = 
1453
 
        target.GetLinkerLanguage(this->GetGlobalGenerator());
 
1530
      const char* linkLanguage = target.GetLinkerLanguage();
1454
1531
      if(!linkLanguage)
1455
1532
        {
1456
1533
        cmSystemTools::Error
1683
1760
  std::string flagsVar = "CMAKE_";
1684
1761
  flagsVar += lang;
1685
1762
  flagsVar += "_FLAGS";
 
1763
  // Add special OSX flags
 
1764
#ifdef __APPLE__
1686
1765
  if(this->EmitUniversalBinaryFlags)
1687
1766
    {
1688
1767
    const char* osxArch = 
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'))
1696
 
      { 
 
1778
    if(osxArch && sysroot && lang && (lang[0] =='C' || lang[0] == 'F'))
 
1779
      {
1697
1780
      std::vector<std::string> archs;
1698
1781
      cmSystemTools::ExpandListArgument(std::string(osxArch),
1699
1782
                                        archs);
1700
 
      bool addArchFlag = true;
1701
 
      if(archs.size() == 1)
 
1783
      bool addArchFlag = false;
 
1784
      if(archs.size() >= 1)
1702
1785
        {
1703
 
        const char* archOrig = 
1704
 
          this->Makefile->GetSafeDefinition("CMAKE_OSX_ARCHITECTURES_DEFAULT");
1705
 
        if(archs[0] == archOrig)
 
1786
        if(archs[0] != "")
1706
1787
          {
1707
 
          addArchFlag = false;
 
1788
          addArchFlag = true;
1708
1789
          }
1709
1790
        }
1710
1791
      // if there is more than one arch add the -arch and
1719
1800
          flags += " -arch ";
1720
1801
          flags += *i;
1721
1802
          }
1722
 
        flags += " -isysroot ";
1723
 
        flags += sysroot;
 
1803
        if(hasIsysroot)
 
1804
          {
 
1805
          flags += " -isysroot ";
 
1806
          flags += sysroot;
 
1807
          }
1724
1808
        flagsUsed = true;
1725
1809
        }
1726
1810
      }
 
1811
 
1727
1812
    if(!flagsUsed && sysroot && sysrootDefault &&
1728
 
       strcmp(sysroot, sysrootDefault) != 0)
 
1813
       strcmp(sysroot, sysrootDefault) != 0 && hasIsysroot)
1729
1814
      {
1730
1815
      flags += " -isysroot ";
1731
1816
      flags += sysroot;
1732
1817
      }
 
1818
 
 
1819
    if (deploymentTarget && *deploymentTarget &&
 
1820
        lang && (lang[0] =='C' || lang[0] == 'F'))
 
1821
      {
 
1822
      flags += " -mmacosx-version-min=";
 
1823
      flags += deploymentTarget;
 
1824
      }
1733
1825
    }
 
1826
#endif
1734
1827
  this->AddConfigVariableFlags(flags, flagsVar.c_str(), config);
1735
1828
}
1736
1829
 
1756
1849
    // found is part of the inName
1757
1850
    if(cmSystemTools::FileIsFullPath(inName))
1758
1851
      {
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)
 
1855
        {
 
1856
        tLocation = target->GetLocation(config);
 
1857
        tLocation = cmSystemTools::GetFilenamePath(tLocation);
 
1858
        tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str());
 
1859
        }
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)
1766
1864
        {
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()));
1855
1953
    }
1856
 
 
1857
 
  // Add flags specific to shared builds.
1858
 
  if(cmSystemTools::IsOn(this->Makefile->GetDefinition("BUILD_SHARED_LIBS")))
1859
 
    {
1860
 
    flagsVar = "CMAKE_SHARED_BUILD_";
1861
 
    flagsVar += lang;
1862
 
    flagsVar += "_FLAGS";
1863
 
    this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar.c_str()));
1864
 
    }
1865
1954
}
1866
1955
 
1867
1956
//----------------------------------------------------------------------------
1971
2060
      }
1972
2061
    else
1973
2062
      {
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);
 
2067
      if(eq != di->npos)
 
2068
        {
 
2069
        defines += "=";
 
2070
        defines += this->EscapeForShell(di->c_str() + eq + 1, true);
 
2071
        }
 
2072
      }
 
2073
    }
 
2074
}
 
2075
 
 
2076
//----------------------------------------------------------------------------
 
2077
void cmLocalGenerator::AppendFeatureOptions(
 
2078
  std::string& flags, const char* lang, const char* feature)
 
2079
{
 
2080
  std::string optVar = "CMAKE_";
 
2081
  optVar += lang;
 
2082
  optVar += "_COMPILE_OPTIONS_";
 
2083
  optVar += feature;
 
2084
  if(const char* optionList = this->Makefile->GetDefinition(optVar.c_str()))
 
2085
    {
 
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)
 
2090
      {
 
2091
      this->AppendFlags(flags, this->EscapeForShell(oi->c_str()).c_str());
1976
2092
      }
1977
2093
    }
1978
2094
}
2215
2331
//----------------------------------------------------------------------------
2216
2332
std::string
2217
2333
cmLocalGenerator::ConvertToRelativePath(const std::vector<std::string>& local,
2218
 
                                        const char* in_remote)
 
2334
                                        const char* in_remote, bool force)
2219
2335
{
2220
2336
  // The path should never be quoted.
2221
2337
  assert(in_remote[0] != '\"');
2236
2352
    this->RelativePathsConfigured = true;
2237
2353
    }
2238
2354
 
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()))))
 
2355
  if(!force)
2250
2356
    {
2251
 
    return in_remote;
 
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()))))
 
2368
      {
 
2369
      return in_remote;
 
2370
      }
2252
2371
    }
2253
2372
 
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)
2696
2819
    {