cmCPackNSISGenerator.cxx 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmCPackNSISGenerator.h"
  14. #include "cmGlobalGenerator.h"
  15. #include "cmLocalGenerator.h"
  16. #include "cmSystemTools.h"
  17. #include "cmMakefile.h"
  18. #include "cmGeneratedFileStream.h"
  19. #include "cmCPackLog.h"
  20. #include <cmsys/SystemTools.hxx>
  21. #include <cmsys/Glob.hxx>
  22. #include <cmsys/Directory.hxx>
  23. #include <cmsys/RegularExpression.hxx>
  24. //----------------------------------------------------------------------
  25. cmCPackNSISGenerator::cmCPackNSISGenerator()
  26. {
  27. }
  28. //----------------------------------------------------------------------
  29. cmCPackNSISGenerator::~cmCPackNSISGenerator()
  30. {
  31. }
  32. //----------------------------------------------------------------------
  33. int cmCPackNSISGenerator::CompressFiles(const char* outFileName,
  34. const char* toplevel, const std::vector<std::string>& files)
  35. {
  36. (void)outFileName; // TODO: Fix nsis to force out file name
  37. (void)toplevel;
  38. std::string nsisInFileName = this->FindTemplate("NSIS.template.in");
  39. if ( nsisInFileName.size() == 0 )
  40. {
  41. cmCPackLogger(cmCPackLog::LOG_ERROR,
  42. "CPack error: Could not find NSIS installer template file."
  43. << std::endl);
  44. return false;
  45. }
  46. std::string nsisFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
  47. std::string tmpFile = nsisFileName;
  48. tmpFile += "/NSISOutput.log";
  49. nsisFileName += "/project.nsi";
  50. cmOStringStream str;
  51. std::vector<std::string>::const_iterator it;
  52. for ( it = files.begin(); it != files.end(); ++ it )
  53. {
  54. std::string fileN = cmSystemTools::RelativePath(toplevel,
  55. it->c_str());
  56. cmSystemTools::ReplaceString(fileN, "/", "\\");
  57. str << " Delete \"$INSTDIR\\" << fileN.c_str() << "\"" << std::endl;
  58. }
  59. cmCPackLogger(cmCPackLog::LOG_DEBUG, "Uninstall Files: "
  60. << str.str().c_str() << std::endl);
  61. this->SetOption("CPACK_NSIS_DELETE_FILES", str.str().c_str());
  62. std::vector<std::string> dirs;
  63. this->GetListOfSubdirectories(toplevel, dirs);
  64. std::vector<std::string>::const_iterator sit;
  65. cmOStringStream dstr;
  66. for ( sit = dirs.begin(); sit != dirs.end(); ++ sit )
  67. {
  68. std::string fileN = cmSystemTools::RelativePath(toplevel,
  69. sit->c_str());
  70. if ( fileN.empty() )
  71. {
  72. continue;
  73. }
  74. cmSystemTools::ReplaceString(fileN, "/", "\\");
  75. dstr << " RMDir \"$INSTDIR\\" << fileN.c_str() << "\"" << std::endl;
  76. }
  77. cmCPackLogger(cmCPackLog::LOG_DEBUG, "Uninstall Dirs: "
  78. << dstr.str().c_str() << std::endl);
  79. this->SetOption("CPACK_NSIS_DELETE_DIRECTORIES", dstr.str().c_str());
  80. cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: " << nsisInFileName
  81. << " to " << nsisFileName << std::endl);
  82. this->ConfigureFile(nsisInFileName.c_str(), nsisFileName.c_str());
  83. std::string nsisCmd = "\"";
  84. nsisCmd += this->GetOption("CPACK_INSTALLER_PROGRAM");
  85. nsisCmd += "\" \"" + nsisFileName + "\"";
  86. cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << nsisCmd.c_str()
  87. << std::endl);
  88. std::string output;
  89. int retVal = 1;
  90. bool res = cmSystemTools::RunSingleCommand(nsisCmd.c_str(), &output,
  91. &retVal, 0, this->GeneratorVerbose, 0);
  92. if ( !res || retVal )
  93. {
  94. cmGeneratedFileStream ofs(tmpFile.c_str());
  95. ofs << "# Run command: " << nsisCmd.c_str() << std::endl
  96. << "# Output:" << std::endl
  97. << output.c_str() << std::endl;
  98. cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running NSIS command: "
  99. << nsisCmd.c_str() << std::endl
  100. << "Please check " << tmpFile.c_str() << " for errors" << std::endl);
  101. return 0;
  102. }
  103. return 1;
  104. }
  105. //----------------------------------------------------------------------
  106. int cmCPackNSISGenerator::Initialize(const char* name, cmMakefile* mf)
  107. {
  108. int res = this->Superclass::Initialize(name, mf);
  109. if ( !res )
  110. {
  111. return res;
  112. }
  113. cmCPackLogger(cmCPackLog::LOG_DEBUG, "cmCPackNSISGenerator::Initialize()"
  114. << std::endl);
  115. std::vector<std::string> path;
  116. std::string nsisPath;
  117. if ( !cmsys::SystemTools::ReadRegistryValue(
  118. "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath) )
  119. {
  120. cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find NSIS registry value"
  121. << std::endl);
  122. return 0;
  123. }
  124. path.push_back(nsisPath);
  125. nsisPath = cmSystemTools::FindProgram("makensis", path, false);
  126. if ( nsisPath.empty() )
  127. {
  128. cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find NSIS compiler"
  129. << std::endl);
  130. return 0;
  131. }
  132. std::string nsisCmd = "\"" + nsisPath + "\" /VERSION";
  133. cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Test NSIS version: "
  134. << nsisCmd.c_str() << std::endl);
  135. std::string output;
  136. int retVal = 1;
  137. bool resS = cmSystemTools::RunSingleCommand(nsisCmd.c_str(),
  138. &output, &retVal, 0, this->GeneratorVerbose, 0);
  139. cmsys::RegularExpression versionRex("v([0-9]+.[0-9]+)");
  140. if ( !resS || retVal || !versionRex.find(output))
  141. {
  142. std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
  143. tmpFile += "/NSISOutput.log";
  144. cmGeneratedFileStream ofs(tmpFile.c_str());
  145. ofs << "# Run command: " << nsisCmd.c_str() << std::endl
  146. << "# Output:" << std::endl
  147. << output.c_str() << std::endl;
  148. cmCPackLogger(cmCPackLog::LOG_ERROR,
  149. "Problem checking NSIS version with command: "
  150. << nsisCmd.c_str() << std::endl
  151. << "Please check " << tmpFile.c_str() << " for errors" << std::endl);
  152. return 0;
  153. }
  154. float nsisVersion = atof(versionRex.match(1).c_str());
  155. float minNSISVersion = 2.09;
  156. cmCPackLogger(cmCPackLog::LOG_DEBUG, "NSIS Version: "
  157. << nsisVersion << std::endl);
  158. if ( nsisVersion < minNSISVersion )
  159. {
  160. cmCPackLogger(cmCPackLog::LOG_ERROR,
  161. "CPack requires NSIS Version 2.09 or greater. NSIS found on the system "
  162. "was: "
  163. << nsisVersion << std::endl);
  164. return 0;
  165. }
  166. this->SetOption("CPACK_INSTALLER_PROGRAM", nsisPath.c_str());
  167. const char* cpackPackageExecutables
  168. = this->GetOption("CPACK_PACKAGE_EXECUTABLES");
  169. if ( cpackPackageExecutables )
  170. {
  171. cmCPackLogger(cmCPackLog::LOG_DEBUG, "The cpackPackageExecutables: "
  172. << cpackPackageExecutables << "." << std::endl);
  173. cmOStringStream str;
  174. cmOStringStream deleteStr;
  175. std::vector<std::string> cpackPackageExecutablesVector;
  176. cmSystemTools::ExpandListArgument(cpackPackageExecutables,
  177. cpackPackageExecutablesVector);
  178. if ( cpackPackageExecutablesVector.size() % 2 != 0 )
  179. {
  180. cmCPackLogger(cmCPackLog::LOG_ERROR,
  181. "CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and "
  182. "<icon name>." << std::endl);
  183. return 0;
  184. }
  185. std::vector<std::string>::iterator it;
  186. for ( it = cpackPackageExecutablesVector.begin();
  187. it != cpackPackageExecutablesVector.end();
  188. ++it )
  189. {
  190. std::string execName = *it;
  191. ++ it;
  192. std::string linkName = *it;
  193. str << " CreateShortCut \"$SMPROGRAMS\\$STARTMENU_FOLDER\\"
  194. << linkName << ".lnk\" \"$INSTDIR\\bin\\" << execName << ".exe\""
  195. << std::endl;
  196. deleteStr << " Delete \"$SMPROGRAMS\\$MUI_TEMP\\" << linkName
  197. << ".lnk\"" << std::endl;
  198. }
  199. this->SetOption("CPACK_NSIS_CREATE_ICONS", str.str().c_str());
  200. this->SetOption("CPACK_NSIS_DELETE_ICONS", deleteStr.str().c_str());
  201. }
  202. return res;
  203. }
  204. //----------------------------------------------------------------------
  205. bool cmCPackNSISGenerator::GetListOfSubdirectories(const char* topdir,
  206. std::vector<std::string>& dirs)
  207. {
  208. cmsys::Directory dir;
  209. dir.Load(topdir);
  210. size_t fileNum;
  211. for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum)
  212. {
  213. if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
  214. strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
  215. {
  216. kwsys_stl::string fullPath = topdir;
  217. fullPath += "/";
  218. fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
  219. if(cmsys::SystemTools::FileIsDirectory(fullPath.c_str()) &&
  220. !cmsys::SystemTools::FileIsSymlink(fullPath.c_str()))
  221. {
  222. if (!this->GetListOfSubdirectories(fullPath.c_str(), dirs))
  223. {
  224. return false;
  225. }
  226. }
  227. }
  228. }
  229. dirs.push_back(topdir);
  230. return true;
  231. }