Coverage Report

Created: 2026-10-28 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmOSXBundleGenerator.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#include "cmOSXBundleGenerator.h"
4
5
#include <cassert>
6
7
#include "cmGeneratorTarget.h"
8
#include "cmLocalGenerator.h"
9
#include "cmMakefile.h"
10
#include "cmStateTypes.h"
11
#include "cmStringAlgorithms.h"
12
#include "cmSystemTools.h"
13
#include "cmTarget.h"
14
#include "cmValue.h"
15
16
class cmSourceFile;
17
18
cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target)
19
0
  : GT(target)
20
0
  , Makefile(target->Target->GetMakefile())
21
0
  , LocalGenerator(target->GetLocalGenerator())
22
0
{
23
0
  if (this->MustSkip()) {
24
0
    return;
25
0
  }
26
0
}
27
28
bool cmOSXBundleGenerator::MustSkip()
29
0
{
30
0
  return !this->GT->HaveWellDefinedOutputFiles();
31
0
}
32
33
void cmOSXBundleGenerator::CreateAppBundle(std::string const& targetName,
34
                                           std::string& outpath,
35
                                           std::string const& config)
36
0
{
37
0
  if (this->MustSkip()) {
38
0
    return;
39
0
  }
40
41
  // Compute bundle directory names.
42
0
  std::string out = cmStrCat(
43
0
    outpath, '/',
44
0
    this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::FullLevel));
45
0
  cmSystemTools::MakeDirectory(out);
46
0
  this->Makefile->AddCMakeOutputFile(out);
47
48
  // Configure the Info.plist file.  Note that it needs the executable name
49
  // to be set.
50
0
  std::string plist = cmStrCat(
51
0
    outpath, '/',
52
0
    this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::ContentLevel),
53
0
    "/Info.plist");
54
0
  this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName, plist);
55
0
  this->Makefile->AddCMakeOutputFile(plist);
56
0
  outpath = out;
57
0
}
58
59
void cmOSXBundleGenerator::CreateFramework(
60
  std::string const& targetName, std::string const& outpath,
61
  std::string const& config, cmOSXBundleGenerator::SkipParts skipParts)
62
0
{
63
0
  if (this->MustSkip()) {
64
0
    return;
65
0
  }
66
67
0
  assert(this->MacContentFolders);
68
69
  // Compute the location of the top-level foo.framework directory.
70
0
  std::string contentdir = cmStrCat(
71
0
    outpath, '/',
72
0
    this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::ContentLevel),
73
0
    '/');
74
75
0
  std::string newoutpath = cmStrCat(
76
0
    outpath, '/',
77
0
    this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::FullLevel));
78
79
0
  std::string frameworkVersion = this->GT->GetFrameworkVersion();
80
81
0
  std::string name = cmSystemTools::GetFilenameName(targetName);
82
0
  if (!skipParts.InfoPlist) {
83
    // Configure the Info.plist file
84
0
    std::string plist = newoutpath;
85
0
    if (!this->Makefile->PlatformIsAppleEmbedded()) {
86
      // Put the Info.plist file into the Resources directory.
87
0
      this->MacContentFolders->insert("Resources");
88
0
      plist += "/Resources";
89
0
    }
90
0
    plist += "/Info.plist";
91
0
    this->LocalGenerator->GenerateFrameworkInfoPList(this->GT, name, plist);
92
0
  }
93
94
  // Generate Versions directory only for MacOSX frameworks
95
0
  if (this->Makefile->PlatformIsAppleEmbedded()) {
96
0
    return;
97
0
  }
98
99
  // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
100
  // drive rules to create these files at build time.
101
0
  std::string oldName;
102
0
  std::string newName;
103
104
  // Make foo.framework/Versions
105
0
  std::string versions = cmStrCat(contentdir, "Versions");
106
0
  cmSystemTools::MakeDirectory(versions);
107
108
  // Make foo.framework/Versions/version
109
0
  cmSystemTools::MakeDirectory(newoutpath);
110
111
  // Current -> version
112
0
  oldName = frameworkVersion;
113
0
  newName = cmStrCat(versions, "/Current");
114
0
  cmSystemTools::RemoveFile(newName);
115
0
  cmSystemTools::CreateSymlink(oldName, newName);
116
0
  this->Makefile->AddCMakeOutputFile(newName);
117
118
  // foo -> Versions/Current/foo
119
0
  oldName = cmStrCat("Versions/Current/", name);
120
0
  newName = cmStrCat(contentdir, name);
121
0
  cmSystemTools::RemoveFile(newName);
122
0
  cmSystemTools::CreateSymlink(oldName, newName);
123
0
  this->Makefile->AddCMakeOutputFile(newName);
124
125
0
  if (!skipParts.TextStubs) {
126
    // foo.tbd -> Versions/Current/foo.tbd
127
0
    cmValue tbdSuffix =
128
0
      this->Makefile->GetDefinition("CMAKE_APPLE_IMPORT_FILE_SUFFIX");
129
0
    oldName = cmStrCat("Versions/Current/", name, tbdSuffix);
130
0
    newName = cmStrCat(contentdir, name, tbdSuffix);
131
0
    cmSystemTools::RemoveFile(newName);
132
0
    cmSystemTools::CreateSymlink(oldName, newName);
133
0
    this->Makefile->AddCMakeOutputFile(newName);
134
0
  }
135
136
  // Resources -> Versions/Current/Resources
137
0
  if (this->MacContentFolders->find("Resources") !=
138
0
      this->MacContentFolders->end()) {
139
0
    oldName = "Versions/Current/Resources";
140
0
    newName = cmStrCat(contentdir, "Resources");
141
0
    cmSystemTools::RemoveFile(newName);
142
0
    cmSystemTools::CreateSymlink(oldName, newName);
143
0
    this->Makefile->AddCMakeOutputFile(newName);
144
0
  }
145
146
  // Headers -> Versions/Current/Headers
147
0
  if (this->MacContentFolders->find("Headers") !=
148
0
      this->MacContentFolders->end()) {
149
0
    oldName = "Versions/Current/Headers";
150
0
    newName = cmStrCat(contentdir, "Headers");
151
0
    cmSystemTools::RemoveFile(newName);
152
0
    cmSystemTools::CreateSymlink(oldName, newName);
153
0
    this->Makefile->AddCMakeOutputFile(newName);
154
0
  }
155
156
  // PrivateHeaders -> Versions/Current/PrivateHeaders
157
0
  if (this->MacContentFolders->find("PrivateHeaders") !=
158
0
      this->MacContentFolders->end()) {
159
0
    oldName = "Versions/Current/PrivateHeaders";
160
0
    newName = cmStrCat(contentdir, "PrivateHeaders");
161
0
    cmSystemTools::RemoveFile(newName);
162
0
    cmSystemTools::CreateSymlink(oldName, newName);
163
0
    this->Makefile->AddCMakeOutputFile(newName);
164
0
  }
165
0
}
166
167
void cmOSXBundleGenerator::CreateCFBundle(std::string const& targetName,
168
                                          std::string const& root,
169
                                          std::string const& config)
170
0
{
171
0
  if (this->MustSkip()) {
172
0
    return;
173
0
  }
174
175
  // Compute bundle directory names.
176
0
  std::string out = cmStrCat(
177
0
    root, '/',
178
0
    this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::FullLevel));
179
0
  cmSystemTools::MakeDirectory(out);
180
0
  this->Makefile->AddCMakeOutputFile(out);
181
182
  // Configure the Info.plist file.  Note that it needs the executable name
183
  // to be set.
184
0
  std::string plist = cmStrCat(
185
0
    root, '/',
186
0
    this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::ContentLevel),
187
0
    "/Info.plist");
188
0
  std::string name = cmSystemTools::GetFilenameName(targetName);
189
0
  this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist);
190
0
  this->Makefile->AddCMakeOutputFile(plist);
191
0
}
192
193
void cmOSXBundleGenerator::GenerateMacOSXContentStatements(
194
  std::vector<cmSourceFile const*> const& sources,
195
  MacOSXContentGeneratorType* generator, std::string const& config)
196
0
{
197
0
  if (this->MustSkip()) {
198
0
    return;
199
0
  }
200
201
0
  for (cmSourceFile const* source : sources) {
202
0
    cmGeneratorTarget::SourceFileFlags tsFlags =
203
0
      this->GT->GetTargetSourceFileFlags(source);
204
0
    if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) {
205
0
      (*generator)(*source, tsFlags.MacFolder, config);
206
0
    }
207
0
  }
208
0
}
209
210
std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(
211
  char const* pkgloc, std::string const& config)
212
0
{
213
  // Construct the full path to the content subdirectory.
214
215
0
  std::string macdir = cmStrCat(this->GT->GetMacContentDirectory(
216
0
                                  config, cmStateEnums::RuntimeBinaryArtifact),
217
0
                                '/', pkgloc);
218
0
  cmSystemTools::MakeDirectory(macdir);
219
220
  // Record use of this content location.  Only the first level
221
  // directory is needed.
222
0
  {
223
0
    std::string loc = pkgloc;
224
0
    loc = loc.substr(0, loc.find('/'));
225
0
    this->MacContentFolders->insert(loc);
226
0
  }
227
228
0
  return macdir;
229
0
}