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

« back to all changes in this revision

Viewing changes to Source/cmGeneratorExpression.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
  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
============================================================================*/
 
12
#include "cmGeneratorExpression.h"
 
13
 
 
14
#include "cmMakefile.h"
 
15
#include "cmTarget.h"
 
16
 
 
17
//----------------------------------------------------------------------------
 
18
cmGeneratorExpression::cmGeneratorExpression(
 
19
  cmMakefile* mf, const char* config,
 
20
  cmListFileBacktrace const& backtrace):
 
21
  Makefile(mf), Config(config), Backtrace(backtrace)
 
22
{
 
23
  this->TargetInfo.compile("^\\$<TARGET"
 
24
                           "(|_SONAME|_LINKER)"  // File with what purpose?
 
25
                           "_FILE(|_NAME|_DIR):" // Filename component.
 
26
                           "([A-Za-z0-9_-]+)"    // Target name.
 
27
                           ">$");
 
28
}
 
29
 
 
30
//----------------------------------------------------------------------------
 
31
const char* cmGeneratorExpression::Process(std::string const& input)
 
32
{
 
33
  return this->Process(input.c_str());
 
34
}
 
35
 
 
36
//----------------------------------------------------------------------------
 
37
const char* cmGeneratorExpression::Process(const char* input)
 
38
{
 
39
  this->Data.clear();
 
40
 
 
41
  // We construct and evaluate expressions directly in the output
 
42
  // buffer.  Each expression is replaced by its own output value
 
43
  // after evaluation.  A stack of barriers records the starting
 
44
  // indices of open (pending) expressions.
 
45
  for(const char* c = input; *c; ++c)
 
46
    {
 
47
    if(c[0] == '$' && c[1] == '<')
 
48
      {
 
49
      this->Barriers.push(this->Data.size());
 
50
      this->Data.push_back('$');
 
51
      this->Data.push_back('<');
 
52
      c += 1;
 
53
      }
 
54
    else if(c[0] == '>' && !this->Barriers.empty())
 
55
      {
 
56
      this->Data.push_back('>');
 
57
      if(!this->Evaluate()) { break; }
 
58
      this->Barriers.pop();
 
59
      }
 
60
    else
 
61
      {
 
62
      this->Data.push_back(c[0]);
 
63
      }
 
64
    }
 
65
 
 
66
  // Return a null-terminated output value.
 
67
  this->Data.push_back('\0');
 
68
  return &*this->Data.begin();
 
69
}
 
70
 
 
71
//----------------------------------------------------------------------------
 
72
bool cmGeneratorExpression::Evaluate()
 
73
{
 
74
  // The top-most barrier points at the beginning of the expression.
 
75
  size_t barrier = this->Barriers.top();
 
76
 
 
77
  // Construct a null-terminated representation of the expression.
 
78
  this->Data.push_back('\0');
 
79
  const char* expr = &*(this->Data.begin()+barrier);
 
80
 
 
81
  // Evaluate the expression.
 
82
  std::string result;
 
83
  if(this->Evaluate(expr, result))
 
84
    {
 
85
    // Success.  Replace the expression with its evaluation result.
 
86
    this->Data.erase(this->Data.begin()+barrier, this->Data.end());
 
87
    this->Data.insert(this->Data.end(), result.begin(), result.end());
 
88
    return true;
 
89
    }
 
90
  else
 
91
    {
 
92
    // Failure.  Report the error message.
 
93
    cmOStringStream e;
 
94
    e << "Error evaluating generator expression:\n"
 
95
      << "  " << expr << "\n"
 
96
      << result;
 
97
    this->Makefile->GetCMakeInstance()
 
98
      ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
 
99
                     this->Backtrace);
 
100
    return false;
 
101
    }
 
102
}
 
103
 
 
104
//----------------------------------------------------------------------------
 
105
bool cmGeneratorExpression::Evaluate(const char* expr, std::string& result)
 
106
{
 
107
  if(this->TargetInfo.find(expr))
 
108
    {
 
109
    if(!this->EvaluateTargetInfo(result))
 
110
      {
 
111
      return false;
 
112
      }
 
113
    }
 
114
  else if(strcmp(expr, "$<CONFIGURATION>") == 0)
 
115
    {
 
116
    result = this->Config? this->Config : "";
 
117
    }
 
118
  else
 
119
    {
 
120
    result = "Expression syntax not recognized.";
 
121
    return false;
 
122
    }
 
123
  return true;
 
124
}
 
125
 
 
126
//----------------------------------------------------------------------------
 
127
bool cmGeneratorExpression::EvaluateTargetInfo(std::string& result)
 
128
{
 
129
  // Lookup the referenced target.
 
130
  std::string name = this->TargetInfo.match(3);
 
131
  cmTarget* target = this->Makefile->FindTargetToUse(name.c_str());
 
132
  if(!target)
 
133
    {
 
134
    result = "No target \"" + name + "\"";
 
135
    return false;
 
136
    }
 
137
  if(target->GetType() >= cmTarget::UTILITY &&
 
138
     target->GetType() != cmTarget::UNKNOWN_LIBRARY)
 
139
    {
 
140
    result = "Target \"" + name + "\" is not an executable or library.";
 
141
    return false;
 
142
    }
 
143
 
 
144
  // Lookup the target file with the given purpose.
 
145
  std::string purpose = this->TargetInfo.match(1);
 
146
  if(purpose == "")
 
147
    {
 
148
    // The target implementation file (.so.1.2, .dll, .exe, .a).
 
149
    result = target->GetFullPath(this->Config, false, true);
 
150
    }
 
151
  else if(purpose == "_LINKER")
 
152
    {
 
153
    // The file used to link to the target (.so, .lib, .a).
 
154
    if(!target->IsLinkable())
 
155
      {
 
156
      result = ("TARGET_LINKER_FILE is allowed only for libraries and "
 
157
                "executables with ENABLE_EXPORTS.");
 
158
      return false;
 
159
      }
 
160
    result = target->GetFullPath(this->Config, target->HasImportLibrary());
 
161
    }
 
162
  else if(purpose == "_SONAME")
 
163
    {
 
164
    // The target soname file (.so.1).
 
165
    if(target->IsDLLPlatform())
 
166
      {
 
167
      result = "TARGET_SONAME_FILE is not allowed for DLL target platforms.";
 
168
      return false;
 
169
      }
 
170
    if(target->GetType() != cmTarget::SHARED_LIBRARY)
 
171
      {
 
172
      result = "TARGET_SONAME_FILE is allowed only for SHARED libraries.";
 
173
      return false;
 
174
      }
 
175
    result = target->GetDirectory(this->Config);
 
176
    result += "/";
 
177
    result += target->GetSOName(this->Config);
 
178
    }
 
179
 
 
180
  // Extract the requested portion of the full path.
 
181
  std::string part = this->TargetInfo.match(2);
 
182
  if(part == "_NAME")
 
183
    {
 
184
    result = cmSystemTools::GetFilenameName(result);
 
185
    }
 
186
  else if(part == "_DIR")
 
187
    {
 
188
    result = cmSystemTools::GetFilenamePath(result);
 
189
    }
 
190
  return true;
 
191
}