1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCPackOSXX11Generator.cxx,v $
6 Date: $Date: 2009-01-21 16:54:30 $
7 Version: $Revision: 1.6 $
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.
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.
16 =========================================================================*/
17 #include "cmCPackOSXX11Generator.h"
20 #include "cmGlobalGenerator.h"
21 #include "cmLocalGenerator.h"
22 #include "cmSystemTools.h"
23 #include "cmMakefile.h"
24 #include "cmGeneratedFileStream.h"
25 #include "cmCPackLog.h"
27 #include <cmsys/SystemTools.hxx>
28 #include <cmsys/Glob.hxx>
30 //----------------------------------------------------------------------
31 cmCPackOSXX11Generator::cmCPackOSXX11Generator()
35 //----------------------------------------------------------------------
36 cmCPackOSXX11Generator::~cmCPackOSXX11Generator()
40 //----------------------------------------------------------------------
41 int cmCPackOSXX11Generator::CompressFiles(const char* outFileName
,
43 const std::vector
<std::string
>& files
)
45 (void) files
; // TODO: Fix api to not need files.
46 (void) toplevel
; // TODO: Use toplevel
48 const char* cpackPackageExecutables
49 = this->GetOption("CPACK_PACKAGE_EXECUTABLES");
50 if ( cpackPackageExecutables
)
52 cmCPackLogger(cmCPackLog::LOG_DEBUG
, "The cpackPackageExecutables: "
53 << cpackPackageExecutables
<< "." << std::endl
);
55 cmOStringStream deleteStr
;
56 std::vector
<std::string
> cpackPackageExecutablesVector
;
57 cmSystemTools::ExpandListArgument(cpackPackageExecutables
,
58 cpackPackageExecutablesVector
);
59 if ( cpackPackageExecutablesVector
.size() % 2 != 0 )
61 cmCPackLogger(cmCPackLog::LOG_ERROR
,
62 "CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and "
63 "<icon name>." << std::endl
);
66 std::vector
<std::string
>::iterator it
;
67 for ( it
= cpackPackageExecutablesVector
.begin();
68 it
!= cpackPackageExecutablesVector
.end();
71 std::string cpackExecutableName
= *it
;
73 this->SetOptionIfNotSet("CPACK_EXECUTABLE_NAME",
74 cpackExecutableName
.c_str());
78 // Disk image directories
79 std::string diskImageDirectory
= toplevel
;
80 std::string diskImageBackgroundImageDir
81 = diskImageDirectory
+ "/.background";
84 // App bundle directories
85 std::string packageDirFileName
= toplevel
;
86 packageDirFileName
+= "/";
87 packageDirFileName
+= this->GetOption("CPACK_PACKAGE_FILE_NAME");
88 packageDirFileName
+= ".app";
89 std::string contentsDirectory
= packageDirFileName
+ "/Contents";
90 std::string resourcesDirectory
= contentsDirectory
+ "/Resources";
91 std::string appDirectory
= contentsDirectory
+ "/MacOS";
92 std::string scriptDirectory
= resourcesDirectory
+ "/Scripts";
93 std::string resourceFileName
= this->GetOption("CPACK_PACKAGE_FILE_NAME");
94 resourceFileName
+= ".rsrc";
96 const char* dir
= resourcesDirectory
.c_str();
97 const char* appdir
= appDirectory
.c_str();
98 const char* scrDir
= scriptDirectory
.c_str();
99 const char* contDir
= contentsDirectory
.c_str();
100 const char* rsrcFile
= resourceFileName
.c_str();
101 const char* iconFile
= this->GetOption("CPACK_PACKAGE_ICON");
104 std::string iconFileName
= cmsys::SystemTools::GetFilenameName(
106 if ( !cmSystemTools::FileExists(iconFile
) )
108 cmCPackLogger(cmCPackLog::LOG_ERROR
, "Cannot find icon file: "
109 << iconFile
<< ". Please check CPACK_PACKAGE_ICON setting."
113 std::string destFileName
= resourcesDirectory
+ "/" + iconFileName
;
114 this->ConfigureFile(iconFile
, destFileName
.c_str(), true);
115 this->SetOptionIfNotSet("CPACK_APPLE_GUI_ICON", iconFileName
.c_str());
118 std::string applicationsLinkName
= diskImageDirectory
+ "/Applications";
119 cmSystemTools::CreateSymlink("/Applications", applicationsLinkName
.c_str());
122 !this->CopyResourcePlistFile("VolumeIcon.icns",
123 diskImageDirectory
.c_str(),
124 ".VolumeIcon.icns", true ) ||
125 !this->CopyResourcePlistFile("DS_Store", diskImageDirectory
.c_str(),
126 ".DS_Store", true ) ||
127 !this->CopyResourcePlistFile("background.png",
128 diskImageBackgroundImageDir
.c_str(), "background.png", true ) ||
129 !this->CopyResourcePlistFile("RuntimeScript", dir
) ||
130 !this->CopyResourcePlistFile("OSXX11.Info.plist", contDir
,
132 !this->CopyResourcePlistFile("OSXX11.main.scpt", scrDir
,
133 "main.scpt", true ) ||
134 !this->CopyResourcePlistFile("OSXScriptLauncher.rsrc", dir
,
136 !this->CopyResourcePlistFile("OSXScriptLauncher", appdir
,
137 this->GetOption("CPACK_PACKAGE_FILE_NAME"), true)
140 cmCPackLogger(cmCPackLog::LOG_ERROR
, "Problem copying the resource files"
146 std::string tmpFile
= this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
147 tmpFile
+= "/hdiutilOutput.log";
148 cmOStringStream dmgCmd
;
149 dmgCmd
<< "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE")
150 << "\" create -ov -format UDZO -srcfolder \""
151 << diskImageDirectory
.c_str()
152 << "\" \"" << outFileName
<< "\"";
154 cmCPackLogger(cmCPackLog::LOG_VERBOSE
,
155 "Compress disk image using command: "
156 << dmgCmd
.str().c_str() << std::endl
);
157 bool res
= cmSystemTools::RunSingleCommand(dmgCmd
.str().c_str(), &output
,
158 &retVal
, 0, this->GeneratorVerbose
, 0);
159 if ( !res
|| retVal
)
161 cmGeneratedFileStream
ofs(tmpFile
.c_str());
162 ofs
<< "# Run command: " << dmgCmd
.str().c_str() << std::endl
163 << "# Output:" << std::endl
164 << output
.c_str() << std::endl
;
165 cmCPackLogger(cmCPackLog::LOG_ERROR
, "Problem running hdiutil command: "
166 << dmgCmd
.str().c_str() << std::endl
167 << "Please check " << tmpFile
.c_str() << " for errors" << std::endl
);
174 //----------------------------------------------------------------------
175 int cmCPackOSXX11Generator::InitializeInternal()
177 cmCPackLogger(cmCPackLog::LOG_DEBUG
,
178 "cmCPackOSXX11Generator::Initialize()" << std::endl
);
179 std::vector
<std::string
> path
;
180 std::string pkgPath
= cmSystemTools::FindProgram("hdiutil", path
, false);
181 if ( pkgPath
.empty() )
183 cmCPackLogger(cmCPackLog::LOG_ERROR
, "Cannot find hdiutil compiler"
187 this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE",
190 return this->Superclass::InitializeInternal();
193 //----------------------------------------------------------------------
195 bool cmCPackOSXX11Generator::CopyCreateResourceFile(const char* name)
197 std::string uname = cmSystemTools::UpperCase(name);
198 std::string cpackVar = "CPACK_RESOURCE_FILE_" + uname;
199 const char* inFileName = this->GetOption(cpackVar.c_str());
202 cmCPackLogger(cmCPackLog::LOG_ERROR, "CPack option: " << cpackVar.c_str()
203 << " not specified. It should point to "
204 << (name ? name : "(NULL)")
206 << ".html, or " << name << ".txt file" << std::endl);
209 if ( !cmSystemTools::FileExists(inFileName) )
211 cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find "
212 << (name ? name : "(NULL)")
213 << " resource file: " << inFileName << std::endl);
216 std::string ext = cmSystemTools::GetFilenameLastExtension(inFileName);
217 if ( ext != ".rtfd" && ext != ".rtf" && ext != ".html" && ext != ".txt" )
219 cmCPackLogger(cmCPackLog::LOG_ERROR, "Bad file extension specified: "
220 << ext << ". Currently only .rtfd, .rtf, .html, and .txt files allowed."
225 std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
226 destFileName += "/Resources/";
227 destFileName += name + ext;
230 cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
231 << (inFileName ? inFileName : "(NULL)")
232 << " to " << destFileName.c_str() << std::endl);
233 this->ConfigureFile(inFileName, destFileName.c_str());
238 //----------------------------------------------------------------------
239 bool cmCPackOSXX11Generator::CopyResourcePlistFile(const char* name
,
240 const char* dir
, const char* outputFileName
/* = 0 */,
241 bool copyOnly
/* = false */)
243 std::string inFName
= "CPack.";
246 std::string inFileName
= this->FindTemplate(inFName
.c_str());
247 if ( inFileName
.empty() )
249 cmCPackLogger(cmCPackLog::LOG_ERROR
, "Cannot find input file: "
250 << inFName
<< std::endl
);
254 if ( !outputFileName
)
256 outputFileName
= name
;
259 std::string destFileName
= dir
;
261 destFileName
+= outputFileName
;
263 cmCPackLogger(cmCPackLog::LOG_VERBOSE
, "Configure file: "
264 << inFileName
.c_str() << " to " << destFileName
.c_str() << std::endl
);
265 this->ConfigureFile(inFileName
.c_str(), destFileName
.c_str(), copyOnly
);
269 //----------------------------------------------------------------------
270 const char* cmCPackOSXX11Generator::GetPackagingInstallPrefix()
272 this->InstallPrefix
= "/";
273 this->InstallPrefix
+= this->GetOption("CPACK_PACKAGE_FILE_NAME");
274 this->InstallPrefix
+= ".app/Contents/Resources";
275 return this->InstallPrefix
.c_str();