cmCommonTargetGenerator.cxx 7.41 KB
Newer Older
1
2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
3
4
#include "cmCommonTargetGenerator.h"

5
6
7
8
9
10
#include <cmConfigure.h>
#include <set>
#include <sstream>
#include <utility>

#include "cmAlgorithms.h"
11
#include "cmComputeLinkInformation.h"
12
13
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
14
#include "cmLinkLineComputer.h"
15
#include "cmLocalCommonGenerator.h"
16
#include "cmLocalGenerator.h"
17
#include "cmMakefile.h"
18
#include "cmOutputConverter.h"
19
#include "cmSourceFile.h"
20
#include "cmStateTypes.h"
21

22
23
cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
  : GeneratorTarget(gt)
24
25
26
  , Makefile(gt->Makefile)
  , LocalGenerator(static_cast<cmLocalCommonGenerator*>(gt->LocalGenerator))
  , GlobalGenerator(static_cast<cmGlobalCommonGenerator*>(
27
      gt->LocalGenerator->GetGlobalGenerator()))
28
  , ConfigName(LocalGenerator->GetConfigName())
29
  , ModuleDefinitionFile(GeneratorTarget->GetModuleDefinitionFile(ConfigName))
30
31
32
33
34
35
{
}

cmCommonTargetGenerator::~cmCommonTargetGenerator()
{
}
36
37
38
39
40

std::string const& cmCommonTargetGenerator::GetConfigName() const
{
  return this->ConfigName;
}
41
42
43
44
45
46
47
48
49
50
51

const char* cmCommonTargetGenerator::GetFeature(const std::string& feature)
{
  return this->GeneratorTarget->GetFeature(feature, this->ConfigName);
}

bool cmCommonTargetGenerator::GetFeatureAsBool(const std::string& feature)
{
  return this->GeneratorTarget->GetFeatureAsBool(feature, this->ConfigName);
}

52
53
void cmCommonTargetGenerator::AddFeatureFlags(std::string& flags,
                                              const std::string& lang)
54
55
56
57
{
  // Add language-specific flags.
  this->LocalGenerator->AddLanguageFlags(flags, lang, this->ConfigName);

58
  if (this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION")) {
59
    this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO");
60
  }
61
}
62

63
64
void cmCommonTargetGenerator::AddModuleDefinitionFlag(
  cmLinkLineComputer* linkLineComputer, std::string& flags)
65
{
66
  if (!this->ModuleDefinitionFile) {
67
    return;
68
  }
69
70
71
72

  // TODO: Create a per-language flag variable.
  const char* defFileFlag =
    this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG");
73
  if (!defFileFlag) {
74
    return;
75
  }
76
77
78
79

  // Append the flag and value.  Use ConvertToLinkReference to help
  // vs6's "cl -link" pass it to the linker.
  std::string flag = defFileFlag;
80
  flag += this->LocalGenerator->ConvertToOutputFormat(
81
    linkLineComputer->ConvertToLinkReference(
82
83
      this->ModuleDefinitionFile->GetFullPath()),
    cmOutputConverter::SHELL);
84
85
  this->LocalGenerator->AppendFlags(flags, flag);
}
86

87
88
void cmCommonTargetGenerator::AppendFortranFormatFlags(
  std::string& flags, cmSourceFile const& source)
89
90
{
  const char* srcfmt = source.GetProperty("Fortran_FORMAT");
91
  cmOutputConverter::FortranFormat format =
92
    cmOutputConverter::GetFortranFormat(srcfmt);
93
  if (format == cmOutputConverter::FortranFormatNone) {
94
    const char* tgtfmt = this->GeneratorTarget->GetProperty("Fortran_FORMAT");
95
    format = cmOutputConverter::GetFortranFormat(tgtfmt);
96
  }
Daniel Pfeifer's avatar
Daniel Pfeifer committed
97
  const char* var = CM_NULLPTR;
98
  switch (format) {
99
    case cmOutputConverter::FortranFormatFixed:
100
101
      var = "CMAKE_Fortran_FORMAT_FIXED_FLAG";
      break;
102
    case cmOutputConverter::FortranFormatFree:
103
104
105
106
107
108
109
110
111
      var = "CMAKE_Fortran_FORMAT_FREE_FLAG";
      break;
    default:
      break;
  }
  if (var) {
    this->LocalGenerator->AppendFlags(flags,
                                      this->Makefile->GetDefinition(var));
  }
112
}
113

114
std::string cmCommonTargetGenerator::GetFlags(const std::string& l)
115
116
{
  ByLanguageMap::iterator i = this->FlagsByLanguage.find(l);
117
  if (i == this->FlagsByLanguage.end()) {
118
119
    std::string flags;

120
121
    this->LocalGenerator->GetTargetCompileFlags(this->GeneratorTarget,
                                                this->ConfigName, l, flags);
122
123
124

    ByLanguageMap::value_type entry(l, flags);
    i = this->FlagsByLanguage.insert(entry).first;
125
  }
126
127
  return i->second;
}
128

129
std::string cmCommonTargetGenerator::GetDefines(const std::string& l)
130
131
{
  ByLanguageMap::iterator i = this->DefinesByLanguage.find(l);
132
  if (i == this->DefinesByLanguage.end()) {
133
    std::set<std::string> defines;
134
135
    this->LocalGenerator->GetTargetDefines(this->GeneratorTarget,
                                           this->ConfigName, l, defines);
136
137

    std::string definesString;
138
    this->LocalGenerator->JoinDefines(defines, definesString, l);
139
140
141

    ByLanguageMap::value_type entry(l, definesString);
    i = this->DefinesByLanguage.insert(entry).first;
142
  }
143
144
  return i->second;
}
145
146
147
148

std::string cmCommonTargetGenerator::GetIncludes(std::string const& l)
{
  ByLanguageMap::iterator i = this->IncludesByLanguage.find(l);
149
  if (i == this->IncludesByLanguage.end()) {
150
151
152
153
    std::string includes;
    this->AddIncludeFlags(includes, l);
    ByLanguageMap::value_type entry(l, includes);
    i = this->IncludesByLanguage.insert(entry).first;
154
  }
155
156
  return i->second;
}
157

158
159
std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories()
  const
160
161
{
  std::vector<std::string> dirs;
162
  std::set<cmGeneratorTarget const*> emitted;
163
  if (cmComputeLinkInformation* cli =
164
        this->GeneratorTarget->GetLinkInformation(this->ConfigName)) {
165
    cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
166
167
168
    for (cmComputeLinkInformation::ItemVector::const_iterator i =
           items.begin();
         i != items.end(); ++i) {
169
      cmGeneratorTarget const* linkee = i->Target;
170
171
172
173
      if (linkee && !linkee->IsImported()
          // We can ignore the INTERFACE_LIBRARY items because
          // Target->GetLinkInformation already processed their
          // link interface and they don't have any output themselves.
174
          && linkee->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
175
          emitted.insert(linkee).second) {
176
        cmLocalGenerator* lg = linkee->GetLocalGenerator();
177
        std::string di = lg->GetCurrentBinaryDirectory();
178
        di += "/";
179
        di += lg->GetTargetDirectory(linkee);
180
181
182
        dirs.push_back(di);
      }
    }
183
  }
184
185
  return dirs;
}
186
187
188
189
190
191
192
193

std::string cmCommonTargetGenerator::GetManifests()
{
  std::vector<cmSourceFile const*> manifest_srcs;
  this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName);

  std::vector<std::string> manifests;
  for (std::vector<cmSourceFile const*>::iterator mi = manifest_srcs.begin();
194
       mi != manifest_srcs.end(); ++mi) {
195
196
197
    manifests.push_back(this->LocalGenerator->ConvertToOutputFormat(
      this->LocalGenerator->ConvertToRelativePath(
        this->LocalGenerator->GetWorkingDirectory(), (*mi)->GetFullPath()),
198
      cmOutputConverter::SHELL));
199
  }
200
201
202

  return cmJoin(manifests, " ");
}
203

204
205
206
void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags,
                                               const std::string& lang,
                                               const char* name, bool so)
207
208
209
210
211
212
213
214
215
216
{
  // Lookup the flag to specify the version.
  std::string fvar = "CMAKE_";
  fvar += lang;
  fvar += "_OSX_";
  fvar += name;
  fvar += "_VERSION_FLAG";
  const char* flag = this->Makefile->GetDefinition(fvar);

  // Skip if no such flag.
217
  if (!flag) {
218
    return;
219
  }
220
221
222
223
224
225

  // Lookup the target version information.
  int major;
  int minor;
  int patch;
  this->GeneratorTarget->GetTargetVersion(so, major, minor, patch);
226
  if (major > 0 || minor > 0 || patch > 0) {
227
228
229
230
    // Append the flag since a non-zero version is specified.
    std::ostringstream vflag;
    vflag << flag << major << "." << minor << "." << patch;
    this->LocalGenerator->AppendFlags(flags, vflag.str());
231
  }
232
}