Coverage Report

Created: 2026-02-09 06:05

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 = outpath + "/" +
76
0
    this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::FullLevel);
77
78
0
  std::string frameworkVersion = this->GT->GetFrameworkVersion();
79
80
0
  std::string name = cmSystemTools::GetFilenameName(targetName);
81
0
  if (!skipParts.InfoPlist) {
82
    // Configure the Info.plist file
83
0
    std::string plist = newoutpath;
84
0
    if (!this->Makefile->PlatformIsAppleEmbedded()) {
85
      // Put the Info.plist file into the Resources directory.
86
0
      this->MacContentFolders->insert("Resources");
87
0
      plist += "/Resources";
88
0
    }
89
0
    plist += "/Info.plist";
90
0
    this->LocalGenerator->GenerateFrameworkInfoPList(this->GT, name, plist);
91
0
  }
92
93
  // Generate Versions directory only for MacOSX frameworks
94
0
  if (this->Makefile->PlatformIsAppleEmbedded()) {
95
0
    return;
96
0
  }
97
98
  // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
99
  // drive rules to create these files at build time.
100
0
  std::string oldName;
101
0
  std::string newName;
102
103
  // Make foo.framework/Versions
104
0
  std::string versions = cmStrCat(contentdir, "Versions");
105
0
  cmSystemTools::MakeDirectory(versions);
106
107
  // Make foo.framework/Versions/version
108
0
  cmSystemTools::MakeDirectory(newoutpath);
109
110
  // Current -> version
111
0
  oldName = frameworkVersion;
112
0
  newName = cmStrCat(versions, "/Current");
113
0
  cmSystemTools::RemoveFile(newName);
114
0
  cmSystemTools::CreateSymlink(oldName, newName);
115
0
  this->Makefile->AddCMakeOutputFile(newName);
116
117
  // foo -> Versions/Current/foo
118
0
  oldName = cmStrCat("Versions/Current/", name);
119
0
  newName = cmStrCat(contentdir, name);
120
0
  cmSystemTools::RemoveFile(newName);
121
0
  cmSystemTools::CreateSymlink(oldName, newName);
122
0
  this->Makefile->AddCMakeOutputFile(newName);
123
124
0
  if (!skipParts.TextStubs) {
125
    // foo.tbd -> Versions/Current/foo.tbd
126
0
    cmValue tbdSuffix =
127
0
      this->Makefile->GetDefinition("CMAKE_APPLE_IMPORT_FILE_SUFFIX");
128
0
    oldName = cmStrCat("Versions/Current/", name, tbdSuffix);
129
0
    newName = cmStrCat(contentdir, name, tbdSuffix);
130
0
    cmSystemTools::RemoveFile(newName);
131
0
    cmSystemTools::CreateSymlink(oldName, newName);
132
0
    this->Makefile->AddCMakeOutputFile(newName);
133
0
  }
134
135
  // Resources -> Versions/Current/Resources
136
0
  if (this->MacContentFolders->find("Resources") !=
137
0
      this->MacContentFolders->end()) {
138
0
    oldName = "Versions/Current/Resources";
139
0
    newName = cmStrCat(contentdir, "Resources");
140
0
    cmSystemTools::RemoveFile(newName);
141
0
    cmSystemTools::CreateSymlink(oldName, newName);
142
0
    this->Makefile->AddCMakeOutputFile(newName);
143
0
  }
144
145
  // Headers -> Versions/Current/Headers
146
0
  if (this->MacContentFolders->find("Headers") !=
147
0
      this->MacContentFolders->end()) {
148
0
    oldName = "Versions/Current/Headers";
149
0
    newName = cmStrCat(contentdir, "Headers");
150
0
    cmSystemTools::RemoveFile(newName);
151
0
    cmSystemTools::CreateSymlink(oldName, newName);
152
0
    this->Makefile->AddCMakeOutputFile(newName);
153
0
  }
154
155
  // PrivateHeaders -> Versions/Current/PrivateHeaders
156
0
  if (this->MacContentFolders->find("PrivateHeaders") !=
157
0
      this->MacContentFolders->end()) {
158
0
    oldName = "Versions/Current/PrivateHeaders";
159
0
    newName = cmStrCat(contentdir, "PrivateHeaders");
160
0
    cmSystemTools::RemoveFile(newName);
161
0
    cmSystemTools::CreateSymlink(oldName, newName);
162
0
    this->Makefile->AddCMakeOutputFile(newName);
163
0
  }
164
0
}
165
166
void cmOSXBundleGenerator::CreateCFBundle(std::string const& targetName,
167
                                          std::string const& root,
168
                                          std::string const& config)
169
0
{
170
0
  if (this->MustSkip()) {
171
0
    return;
172
0
  }
173
174
  // Compute bundle directory names.
175
0
  std::string out = cmStrCat(
176
0
    root, '/',
177
0
    this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::FullLevel));
178
0
  cmSystemTools::MakeDirectory(out);
179
0
  this->Makefile->AddCMakeOutputFile(out);
180
181
  // Configure the Info.plist file.  Note that it needs the executable name
182
  // to be set.
183
0
  std::string plist = cmStrCat(
184
0
    root, '/',
185
0
    this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::ContentLevel),
186
0
    "/Info.plist");
187
0
  std::string name = cmSystemTools::GetFilenameName(targetName);
188
0
  this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist);
189
0
  this->Makefile->AddCMakeOutputFile(plist);
190
0
}
191
192
void cmOSXBundleGenerator::GenerateMacOSXContentStatements(
193
  std::vector<cmSourceFile const*> const& sources,
194
  MacOSXContentGeneratorType* generator, std::string const& config)
195
0
{
196
0
  if (this->MustSkip()) {
197
0
    return;
198
0
  }
199
200
0
  for (cmSourceFile const* source : sources) {
201
0
    cmGeneratorTarget::SourceFileFlags tsFlags =
202
0
      this->GT->GetTargetSourceFileFlags(source);
203
0
    if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) {
204
0
      (*generator)(*source, tsFlags.MacFolder, config);
205
0
    }
206
0
  }
207
0
}
208
209
std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(
210
  char const* pkgloc, std::string const& config)
211
0
{
212
  // Construct the full path to the content subdirectory.
213
214
0
  std::string macdir = cmStrCat(this->GT->GetMacContentDirectory(
215
0
                                  config, cmStateEnums::RuntimeBinaryArtifact),
216
0
                                '/', pkgloc);
217
0
  cmSystemTools::MakeDirectory(macdir);
218
219
  // Record use of this content location.  Only the first level
220
  // directory is needed.
221
0
  {
222
0
    std::string loc = pkgloc;
223
0
    loc = loc.substr(0, loc.find('/'));
224
0
    this->MacContentFolders->insert(loc);
225
0
  }
226
227
0
  return macdir;
228
0
}