1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cpack.cxx,v $
6 Date: $Date: 2007-12-13 22:56:49 $
7 Version: $Revision: 1.42 $
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 "cmSystemTools.h"
19 // Need these for documentation support.
21 #include "cmDocumentation.h"
22 #include "cmCPackGeneratorFactory.h"
23 #include "cmCPackGenerator.h"
25 #include "cmGlobalGenerator.h"
26 #include "cmLocalGenerator.h"
27 #include "cmMakefile.h"
29 #include "cmCPackLog.h"
31 #include <cmsys/CommandLineArguments.hxx>
33 //----------------------------------------------------------------------------
34 static const char * cmDocumentationName
[][3] =
37 " cpack - Packaging driver provided by CMake.", 0},
41 //----------------------------------------------------------------------------
42 static const char * cmDocumentationUsage
[][3] =
45 " cpack -G <generator> [options]",
50 //----------------------------------------------------------------------------
51 static const char * cmDocumentationDescription
[][3] =
54 "The \"cpack\" executable is the CMake packaging program. "
55 "CMake-generated build trees created for projects that use "
56 "the INSTALL_* commands have packaging support. "
57 "This program will generate the package.", 0},
58 CMAKE_STANDARD_INTRODUCTION
,
62 //----------------------------------------------------------------------------
63 static const char * cmDocumentationOptions
[][3] =
65 {"-G <generator>", "Use the specified generator to generate package.",
66 "CPack may support multiple native packaging systems on certain "
67 "platforms. A generator is responsible for generating input files for "
68 "particular system and invoking that systems. Possible generator names "
69 "are specified in the Generators section." },
70 {"-C <Configuration>", "Specify the project configuration",
71 "This option specifies the configuration that the project was build "
72 "with, for example 'Debug', 'Release'." },
73 {"-D <var>=<value>", "Set a CPack variable.", \
74 "Set a variable that can be used by the generator."}, \
75 {"--config <config file>", "Specify the config file.",
76 "Specify the config file to use to create the package. By default "
77 "CPackConfig.cmake in the current directory will be used." },
81 //----------------------------------------------------------------------------
82 static const char * cmDocumentationSeeAlso
[][3] =
89 //----------------------------------------------------------------------------
90 int cpackUnknownArgument(const char*, void*)
95 //----------------------------------------------------------------------------
96 struct cpackDefinitions
98 typedef std::map
<cmStdString
, cmStdString
> MapType
;
103 //----------------------------------------------------------------------------
104 int cpackDefinitionArgument(const char* argument
, const char* cValue
,
108 cpackDefinitions
* def
= static_cast<cpackDefinitions
*>(call_data
);
109 std::string value
= cValue
;
110 size_t pos
= value
.find_first_of("=");
111 if ( pos
== std::string::npos
)
113 cmCPack_Log(def
->Log
, cmCPackLog::LOG_ERROR
,
114 "Please specify CPack definitions as: KEY=VALUE" << std::endl
);
117 std::string key
= value
.substr(0, pos
);
118 value
= value
.c_str() + pos
+ 1;
119 def
->Map
[key
] = value
;
120 cmCPack_Log(def
->Log
, cmCPackLog::LOG_DEBUG
, "Set CPack variable: "
121 << key
.c_str() << " to \"" << value
.c_str() << "\"" << std::endl
);
125 //----------------------------------------------------------------------------
127 int main (int argc
, char *argv
[])
129 cmSystemTools::FindExecutableDirectory(argv
[0]);
131 log
.SetErrorPrefix("CPack Error: ");
132 log
.SetWarningPrefix("CPack Warning: ");
133 log
.SetOutputPrefix("CPack: ");
134 log
.SetVerbosePrefix("CPack Verbose: ");
136 cmSystemTools::EnableMSVCDebugHook();
138 if ( cmSystemTools::GetCurrentWorkingDirectory().size() == 0 )
140 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
141 "Current working directory cannot be established." << std::endl
);
144 std::string generator
;
146 bool helpVersion
= false;
147 bool verbose
= false;
149 std::string helpFull
;
151 std::string helpHTML
;
153 std::string cpackProjectName
;
154 std::string cpackProjectDirectory
155 = cmsys::SystemTools::GetCurrentWorkingDirectory();
156 std::string cpackBuildConfig
;
157 std::string cpackProjectVersion
;
158 std::string cpackProjectPatch
;
159 std::string cpackProjectVendor
;
160 std::string cpackConfigFile
;
162 cpackDefinitions definitions
;
163 definitions
.Log
= &log
;
165 cpackConfigFile
= "";
168 cmsys::CommandLineArguments arg
;
169 arg
.Initialize(argc
, argv
);
170 typedef cmsys::CommandLineArguments argT
;
172 arg
.AddArgument("--help", argT::NO_ARGUMENT
, &help
, "CPack help");
173 arg
.AddArgument("--help-full", argT::SPACE_ARGUMENT
, &helpFull
,
175 arg
.AddArgument("--help-html", argT::SPACE_ARGUMENT
, &helpHTML
,
177 arg
.AddArgument("--help-man", argT::SPACE_ARGUMENT
, &helpMAN
, "CPack help");
178 arg
.AddArgument("--version", argT::NO_ARGUMENT
, &helpVersion
, "CPack help");
180 arg
.AddArgument("-V", argT::NO_ARGUMENT
, &verbose
, "CPack verbose");
181 arg
.AddArgument("--verbose", argT::NO_ARGUMENT
, &verbose
, "-V");
182 arg
.AddArgument("--debug", argT::NO_ARGUMENT
, &debug
, "-V");
183 arg
.AddArgument("--config", argT::SPACE_ARGUMENT
, &cpackConfigFile
,
184 "CPack configuration file");
185 arg
.AddArgument("-C", argT::SPACE_ARGUMENT
, &cpackBuildConfig
,
186 "CPack build configuration");
187 arg
.AddArgument("-G", argT::SPACE_ARGUMENT
,
188 &generator
, "CPack generator");
189 arg
.AddArgument("-P", argT::SPACE_ARGUMENT
,
190 &cpackProjectName
, "CPack project name");
191 arg
.AddArgument("-R", argT::SPACE_ARGUMENT
,
192 &cpackProjectVersion
, "CPack project version");
193 arg
.AddArgument("-B", argT::SPACE_ARGUMENT
,
194 &cpackProjectDirectory
, "CPack project directory");
195 arg
.AddArgument("--patch", argT::SPACE_ARGUMENT
,
196 &cpackProjectPatch
, "CPack project patch");
197 arg
.AddArgument("--vendor", argT::SPACE_ARGUMENT
,
198 &cpackProjectVendor
, "CPack project vendor");
199 arg
.AddCallback("-D", argT::SPACE_ARGUMENT
,
200 cpackDefinitionArgument
, &definitions
, "CPack Definitions");
201 arg
.SetUnknownArgumentCallback(cpackUnknownArgument
);
203 // Parse command line
204 int parsed
= arg
.Parse();
209 log
.SetVerbose(verbose
);
210 cmCPack_Log(&log
, cmCPackLog::LOG_OUTPUT
, "Enable Verbse" << std::endl
);
215 cmCPack_Log(&log
, cmCPackLog::LOG_OUTPUT
, "Enable Debug" << std::endl
);
218 cmCPack_Log(&log
, cmCPackLog::LOG_VERBOSE
,
219 "Read CPack config file: " << cpackConfigFile
.c_str() << std::endl
);
222 cminst
.RemoveUnscriptableCommands();
223 cmGlobalGenerator cmgg
;
224 cmgg
.SetCMakeInstance(&cminst
);
225 cmLocalGenerator
* cmlg
= cmgg
.CreateLocalGenerator();
226 cmMakefile
* globalMF
= cmlg
->GetMakefile();
228 bool cpackConfigFileSpecified
= true;
229 if ( cpackConfigFile
.empty() )
231 cpackConfigFile
= cmSystemTools::GetCurrentWorkingDirectory();
232 cpackConfigFile
+= "/CPackConfig.cmake";
233 cpackConfigFileSpecified
= false;
236 cmCPackGeneratorFactory generators
;
237 generators
.SetLogger(&log
);
238 cmCPackGenerator
* cpackGenerator
= 0;
240 if ( !helpFull
.empty() || !helpMAN
.empty() ||
241 !helpHTML
.empty() || helpVersion
)
246 if ( parsed
&& !help
)
248 // find out which system cpack is running on, so it can setup the search
249 // paths, so FIND_XXX() commands can be used in scripts
250 cminst
.AddCMakePaths();
251 std::string systemFile
=
252 globalMF
->GetModulesFile("CMakeDetermineSystem.cmake");
253 if (!globalMF
->ReadListFile(0, systemFile
.c_str()))
255 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
256 "Error reading CMakeDetermineSystem.cmake" << std::endl
);
261 globalMF
->GetModulesFile("CMakeSystemSpecificInformation.cmake");
262 if (!globalMF
->ReadListFile(0, systemFile
.c_str()))
264 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
265 "Error reading CMakeSystemSpecificInformation.cmake" << std::endl
);
269 if ( cmSystemTools::FileExists(cpackConfigFile
.c_str()) )
272 cmSystemTools::CollapseFullPath(cpackConfigFile
.c_str());
273 cmCPack_Log(&log
, cmCPackLog::LOG_VERBOSE
,
274 "Read CPack configuration file: " << cpackConfigFile
.c_str()
276 if ( !globalMF
->ReadListFile(0, cpackConfigFile
.c_str()) )
278 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
279 "Problem reading CPack config file: \""
280 << cpackConfigFile
.c_str() << "\"" << std::endl
);
284 else if ( cpackConfigFileSpecified
)
286 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
287 "Cannot find CPack config file: \"" << cpackConfigFile
.c_str()
288 << "\"" << std::endl
);
292 if ( !generator
.empty() )
294 globalMF
->AddDefinition("CPACK_GENERATOR", generator
.c_str());
296 if ( !cpackProjectName
.empty() )
298 globalMF
->AddDefinition("CPACK_PACKAGE_NAME", cpackProjectName
.c_str());
300 if ( !cpackProjectVersion
.empty() )
302 globalMF
->AddDefinition("CPACK_PACKAGE_VERSION",
303 cpackProjectVersion
.c_str());
305 if ( !cpackProjectVendor
.empty() )
307 globalMF
->AddDefinition("CPACK_PACKAGE_VENDOR",
308 cpackProjectVendor
.c_str());
310 if ( !cpackProjectDirectory
.empty() )
312 globalMF
->AddDefinition("CPACK_PACKAGE_DIRECTORY",
313 cpackProjectDirectory
.c_str());
315 if ( !cpackBuildConfig
.empty() )
317 globalMF
->AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig
.c_str());
319 cpackDefinitions::MapType::iterator cdit
;
320 for ( cdit
= definitions
.Map
.begin();
321 cdit
!= definitions
.Map
.end();
324 globalMF
->AddDefinition(cdit
->first
.c_str(), cdit
->second
.c_str());
327 const char* cpackModulesPath
=
328 globalMF
->GetDefinition("CPACK_MODULE_PATH");
329 if ( cpackModulesPath
)
331 globalMF
->AddDefinition("CMAKE_MODULE_PATH", cpackModulesPath
);
333 const char* genList
= globalMF
->GetDefinition("CPACK_GENERATOR");
336 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
337 "CPack generator not specified" << std::endl
);
342 std::vector
<std::string
> generatorsVector
;
343 cmSystemTools::ExpandListArgument(genList
,
345 std::vector
<std::string
>::iterator it
;
346 for ( it
= generatorsVector
.begin();
347 it
!= generatorsVector
.end();
350 const char* gen
= it
->c_str();
351 cmMakefile
newMF(*globalMF
);
352 cmMakefile
* mf
= &newMF
;
353 cmCPack_Log(&log
, cmCPackLog::LOG_VERBOSE
,
354 "Specified generator: " << gen
<< std::endl
);
355 if ( parsed
&& !mf
->GetDefinition("CPACK_PACKAGE_NAME") )
357 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
358 "CPack project name not specified" << std::endl
);
361 if ( parsed
&& !(mf
->GetDefinition("CPACK_PACKAGE_VERSION")
362 || mf
->GetDefinition("CPACK_PACKAGE_VERSION_MAJOR") &&
363 mf
->GetDefinition("CPACK_PACKAGE_VERSION_MINOR")
364 && mf
->GetDefinition("CPACK_PACKAGE_VERSION_PATCH")) )
366 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
367 "CPack project version not specified" << std::endl
368 << "Specify CPACK_PACKAGE_VERSION, or "
369 "CPACK_PACKAGE_VERSION_MAJOR, "
370 "CPACK_PACKAGE_VERSION_MINOR, and CPACK_PACKAGE_VERSION_PATCH."
376 cpackGenerator
= generators
.NewGenerator(gen
);
377 if ( !cpackGenerator
)
379 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
380 "Cannot initialize CPack generator: "
381 << gen
<< std::endl
);
384 if ( parsed
&& !cpackGenerator
->Initialize(gen
, mf
, argv
[0]) )
386 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
387 "Cannot initialize the generator " << gen
<< std::endl
);
391 if ( !mf
->GetDefinition("CPACK_INSTALL_COMMANDS") &&
392 !mf
->GetDefinition("CPACK_INSTALLED_DIRECTORIES") &&
393 !mf
->GetDefinition("CPACK_INSTALL_CMAKE_PROJECTS") )
395 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
396 "Please specify build tree of the project that uses CMake "
397 "using CPACK_INSTALL_CMAKE_PROJECTS, specify "
398 "CPACK_INSTALL_COMMANDS, or specify "
399 "CPACK_INSTALLED_DIRECTORIES."
406 std::string comspec
= "cmw9xcom.exe";
407 cmSystemTools::SetWindows9xComspecSubstitute(comspec
.c_str());
410 const char* projName
= mf
->GetDefinition("CPACK_PACKAGE_NAME");
411 cmCPack_Log(&log
, cmCPackLog::LOG_VERBOSE
, "Use generator: "
412 << cpackGenerator
->GetNameOfClass() << std::endl
);
413 cmCPack_Log(&log
, cmCPackLog::LOG_VERBOSE
, "For project: "
414 << projName
<< std::endl
);
416 const char* projVersion
=
417 mf
->GetDefinition("CPACK_PACKAGE_VERSION");
420 const char* projVersionMajor
421 = mf
->GetDefinition("CPACK_PACKAGE_VERSION_MAJOR");
422 const char* projVersionMinor
423 = mf
->GetDefinition("CPACK_PACKAGE_VERSION_MINOR");
424 const char* projVersionPatch
425 = mf
->GetDefinition("CPACK_PACKAGE_VERSION_PATCH");
426 cmOStringStream ostr
;
427 ostr
<< projVersionMajor
<< "." << projVersionMinor
<< "."
429 mf
->AddDefinition("CPACK_PACKAGE_VERSION",
433 int res
= cpackGenerator
->DoPackage();
436 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
437 "Error when generating package: " << projName
<< std::endl
);
448 doc
.CheckOptions(argc
, argv
);
449 // Construct and print requested documentation.
450 doc
.SetName("cpack");
451 doc
.SetSection("Name",cmDocumentationName
);
452 doc
.SetSection("Usage",cmDocumentationUsage
);
453 doc
.SetSection("Description",cmDocumentationDescription
);
454 doc
.SetSection("Options",cmDocumentationOptions
);
456 std::vector
<cmDocumentationEntry
> v
;
457 cmCPackGeneratorFactory::DescriptionsMap::const_iterator generatorIt
;
458 for( generatorIt
= generators
.GetGeneratorsList().begin();
459 generatorIt
!= generators
.GetGeneratorsList().end();
462 cmDocumentationEntry e
;
463 e
.Name
= generatorIt
->first
.c_str();
464 e
.Brief
= generatorIt
->second
.c_str();
468 doc
.SetSection("Generators",v
);
470 doc
.SetSeeAlsoList(cmDocumentationSeeAlso
);
472 return doc
.PrintRequestedDocumentation(std::cout
)? 0:1;
473 #define cout no_cout_use_cmCPack_Log