Resync.
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / CPack / cmCPackPackageMakerGenerator.cxx
blobe93bd67ab10a5aa406ca99e868473c24e8cefb1c
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCPackPackageMakerGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2008/02/19 19:26:19 $
7 Version: $Revision: 1.23 $
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 "cmCPackPackageMakerGenerator.h"
19 #include "cmake.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 cmCPackPackageMakerGenerator::cmCPackPackageMakerGenerator()
33 this->PackageMakerVersion = 0.0;
36 //----------------------------------------------------------------------
37 cmCPackPackageMakerGenerator::~cmCPackPackageMakerGenerator()
41 int cmCPackPackageMakerGenerator::CopyInstallScript(const char* resdir,
42 const char* script,
43 const char* name)
45 std::string dst = resdir;
46 dst += "/";
47 dst += name;
48 cmSystemTools::CopyFileAlways(script, dst.c_str());
49 cmSystemTools::SetPermissions(dst.c_str(),0777);
50 cmCPackLogger(cmCPackLog::LOG_VERBOSE,
51 "copy script : " << script << "\ninto " << dst.c_str() <<
52 std::endl);
54 return 1;
57 //----------------------------------------------------------------------
58 int cmCPackPackageMakerGenerator::CompressFiles(const char* outFileName,
59 const char* toplevel,
60 const std::vector<std::string>& files)
62 (void) files; // TODO: Fix api to not need files.
63 (void) toplevel; // TODO: Use toplevel
64 // Create directory structure
65 std::string resDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
66 resDir += "/Resources";
67 std::string preflightDirName = resDir + "/PreFlight";
68 std::string postflightDirName = resDir + "/PostFlight";
69 const char* preflight = this->GetOption("CPACK_PREFLIGHT_SCRIPT");
70 const char* postflight = this->GetOption("CPACK_POSTFLIGHT_SCRIPT");
71 const char* postupgrade = this->GetOption("CPACK_POSTUPGRADE_SCRIPT");
72 // if preflight or postflight scripts not there create directories
73 // of the same name, I think this makes it work
74 if(!preflight)
76 if ( !cmsys::SystemTools::MakeDirectory(preflightDirName.c_str()))
78 cmCPackLogger(cmCPackLog::LOG_ERROR,
79 "Problem creating installer directory: "
80 << preflightDirName.c_str() << std::endl);
81 return 0;
84 if(!postflight)
86 if ( !cmsys::SystemTools::MakeDirectory(postflightDirName.c_str()))
88 cmCPackLogger(cmCPackLog::LOG_ERROR,
89 "Problem creating installer directory: "
90 << postflightDirName.c_str() << std::endl);
91 return 0;
94 // if preflight, postflight, or postupgrade are set
95 // then copy them into the resource directory and make
96 // them executable
97 if(preflight)
99 this->CopyInstallScript(resDir.c_str(),
100 preflight,
101 "preflight");
103 if(postflight)
105 this->CopyInstallScript(resDir.c_str(),
106 postflight,
107 "postflight");
109 if(postupgrade)
111 this->CopyInstallScript(resDir.c_str(),
112 postupgrade,
113 "postupgrade");
116 if ( !this->CopyCreateResourceFile("License")
117 || !this->CopyCreateResourceFile("ReadMe")
118 || !this->CopyCreateResourceFile("Welcome")
119 || !this->CopyResourcePlistFile("Info.plist")
120 || !this->CopyResourcePlistFile("Description.plist") )
122 cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files"
123 << std::endl);
124 return 0;
127 std::string packageDirFileName
128 = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
129 packageDirFileName += ".pkg";
131 std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
132 tmpFile += "/PackageMakerOutput.log";
133 cmOStringStream pkgCmd;
134 pkgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM")
135 << "\" -build -p \"" << packageDirFileName << "\" -f \""
136 << this->GetOption("CPACK_TEMPORARY_DIRECTORY")
137 << "\" -r \"" << this->GetOption("CPACK_TOPLEVEL_DIRECTORY")
138 << "/Resources\" -i \""
139 << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "/Info.plist\" -d \""
140 << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "/Description.plist\"";
141 if ( this->PackageMakerVersion > 2.0 )
143 pkgCmd << " -v";
145 cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << pkgCmd.str().c_str()
146 << std::endl);
147 std::string output;
148 int retVal = 1;
149 //bool res = cmSystemTools::RunSingleCommand(pkgCmd.str().c_str(), &output,
150 //&retVal, 0, this->GeneratorVerbose, 0);
151 bool res = true;
152 retVal = system(pkgCmd.str().c_str());
153 cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running package maker"
154 << std::endl);
155 if ( !res || retVal )
157 cmGeneratedFileStream ofs(tmpFile.c_str());
158 ofs << "# Run command: " << pkgCmd.str().c_str() << std::endl
159 << "# Output:" << std::endl
160 << output.c_str() << std::endl;
161 cmCPackLogger(cmCPackLog::LOG_ERROR,
162 "Problem running PackageMaker command: " << pkgCmd.str().c_str()
163 << std::endl << "Please check " << tmpFile.c_str() << " for errors"
164 << std::endl);
165 return 0;
167 // sometimes the pkgCmd finishes but the directory is not yet
168 // created, so try 10 times to see if it shows up
169 int tries = 10;
170 while(tries > 0 &&
171 !cmSystemTools::FileExists(packageDirFileName.c_str()))
173 cmSystemTools::Delay(500);
174 tries--;
176 if(!cmSystemTools::FileExists(packageDirFileName.c_str()))
178 cmCPackLogger(
179 cmCPackLog::LOG_ERROR,
180 "Problem running PackageMaker command: " << pkgCmd.str().c_str()
181 << std::endl << "Package not created: " << packageDirFileName.c_str()
182 << std::endl);
184 tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
185 tmpFile += "/hdiutilOutput.log";
186 cmOStringStream dmgCmd;
187 dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE")
188 << "\" create -ov -format UDZO -srcfolder \"" << packageDirFileName
189 << "\" \"" << outFileName << "\"";
190 res = cmSystemTools::RunSingleCommand(dmgCmd.str().c_str(), &output,
191 &retVal, 0, this->GeneratorVerbose, 0);
192 if ( !res || retVal )
194 cmGeneratedFileStream ofs(tmpFile.c_str());
195 ofs << "# Run command: " << dmgCmd.str().c_str() << std::endl
196 << "# Output:" << std::endl
197 << output.c_str() << std::endl;
198 cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running hdiutil command: "
199 << dmgCmd.str().c_str() << std::endl
200 << "Please check " << tmpFile.c_str() << " for errors" << std::endl);
201 return 0;
204 return 1;
207 //----------------------------------------------------------------------
208 int cmCPackPackageMakerGenerator::InitializeInternal()
210 cmCPackLogger(cmCPackLog::LOG_DEBUG,
211 "cmCPackPackageMakerGenerator::Initialize()" << std::endl);
212 this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr");
213 std::vector<std::string> path;
214 std::string pkgPath
215 = "/Developer/Applications/Utilities/PackageMaker.app/Contents";
216 std::string versionFile = pkgPath + "/version.plist";
217 if ( !cmSystemTools::FileExists(versionFile.c_str()) )
219 pkgPath = "/Developer/Applications/PackageMaker.app/Contents";
220 std::string newVersionFile = pkgPath + "/version.plist";
221 if ( !cmSystemTools::FileExists(newVersionFile.c_str()) )
223 cmCPackLogger(cmCPackLog::LOG_ERROR,
224 "Cannot find PackageMaker compiler version file: "
225 << versionFile.c_str() << " or " << newVersionFile.c_str()
226 << std::endl);
227 return 0;
229 versionFile = newVersionFile;
231 std::ifstream ifs(versionFile.c_str());
232 if ( !ifs )
234 cmCPackLogger(cmCPackLog::LOG_ERROR,
235 "Cannot open PackageMaker compiler version file" << std::endl);
236 return 0;
238 // Check the PackageMaker version
239 cmsys::RegularExpression rexKey("<key>CFBundleShortVersionString</key>");
240 cmsys::RegularExpression rexVersion("<string>([0-9]+.[0-9.]+)</string>");
241 std::string line;
242 bool foundKey = false;
243 while ( cmSystemTools::GetLineFromStream(ifs, line) )
245 if ( rexKey.find(line) )
247 foundKey = true;
248 break;
251 if ( !foundKey )
253 cmCPackLogger(cmCPackLog::LOG_ERROR,
254 "Cannot find CFBundleShortVersionString in the PackageMaker compiler "
255 "version file" << std::endl);
256 return 0;
258 if ( !cmSystemTools::GetLineFromStream(ifs, line) ||
259 !rexVersion.find(line) )
261 cmCPackLogger(cmCPackLog::LOG_ERROR,
262 "Problem reading the PackageMaker compiler version file: "
263 << versionFile.c_str() << std::endl);
264 return 0;
266 this->PackageMakerVersion = atof(rexVersion.match(1).c_str());
267 if ( this->PackageMakerVersion < 1.0 )
269 cmCPackLogger(cmCPackLog::LOG_ERROR, "Require PackageMaker 1.0 or higher"
270 << std::endl);
271 return 0;
273 cmCPackLogger(cmCPackLog::LOG_DEBUG, "PackageMaker version is: "
274 << this->PackageMakerVersion << std::endl);
276 pkgPath += "/MacOS";
277 path.push_back(pkgPath);
278 pkgPath = cmSystemTools::FindProgram("PackageMaker", path, false);
279 if ( pkgPath.empty() )
281 cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find PackageMaker compiler"
282 << std::endl);
283 return 0;
285 this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", pkgPath.c_str());
286 pkgPath = cmSystemTools::FindProgram("hdiutil", path, false);
287 if ( pkgPath.empty() )
289 cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find hdiutil compiler"
290 << std::endl);
291 return 0;
293 this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE",
294 pkgPath.c_str());
296 return this->Superclass::InitializeInternal();
299 //----------------------------------------------------------------------
300 bool cmCPackPackageMakerGenerator::CopyCreateResourceFile(const char* name)
302 std::string uname = cmSystemTools::UpperCase(name);
303 std::string cpackVar = "CPACK_RESOURCE_FILE_" + uname;
304 const char* inFileName = this->GetOption(cpackVar.c_str());
305 if ( !inFileName )
307 cmCPackLogger(cmCPackLog::LOG_ERROR, "CPack option: " << cpackVar.c_str()
308 << " not specified. It should point to "
309 << (name ? name : "(NULL)")
310 << ".rtf, " << name
311 << ".html, or " << name << ".txt file" << std::endl);
312 return false;
314 if ( !cmSystemTools::FileExists(inFileName) )
316 cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find "
317 << (name ? name : "(NULL)")
318 << " resource file: " << inFileName << std::endl);
319 return false;
321 std::string ext = cmSystemTools::GetFilenameLastExtension(inFileName);
322 if ( ext != ".rtfd" && ext != ".rtf" && ext != ".html" && ext != ".txt" )
324 cmCPackLogger(cmCPackLog::LOG_ERROR, "Bad file extension specified: "
325 << ext << ". Currently only .rtfd, .rtf, .html, and .txt files allowed."
326 << std::endl);
327 return false;
330 std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
331 destFileName += "/Resources/";
332 destFileName += name + ext;
335 cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
336 << (inFileName ? inFileName : "(NULL)")
337 << " to " << destFileName.c_str() << std::endl);
338 this->ConfigureFile(inFileName, destFileName.c_str());
339 return true;
342 bool cmCPackPackageMakerGenerator::CopyResourcePlistFile(const char* name)
344 std::string inFName = "CPack.";
345 inFName += name;
346 inFName += ".in";
347 std::string inFileName = this->FindTemplate(inFName.c_str());
348 if ( inFileName.empty() )
350 cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find input file: "
351 << inFName << std::endl);
352 return false;
355 std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
356 destFileName += "/";
357 destFileName += name;
359 cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
360 << inFileName.c_str() << " to " << destFileName.c_str() << std::endl);
361 this->ConfigureFile(inFileName.c_str(), destFileName.c_str());
362 return true;