1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cpack.cxx,v $
6 Date: $Date: 2009-01-22 18:56:13 $
7 Version: $Revision: 1.46 $
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>
32 #include <memory> // auto_ptr
34 //----------------------------------------------------------------------------
35 static const char * cmDocumentationName
[][3] =
38 " cpack - Packaging driver provided by CMake.", 0},
42 //----------------------------------------------------------------------------
43 static const char * cmDocumentationUsage
[][3] =
46 " cpack -G <generator> [options]",
51 //----------------------------------------------------------------------------
52 static const char * cmDocumentationDescription
[][3] =
55 "The \"cpack\" executable is the CMake packaging program. "
56 "CMake-generated build trees created for projects that use "
57 "the INSTALL_* commands have packaging support. "
58 "This program will generate the package.", 0},
59 CMAKE_STANDARD_INTRODUCTION
,
63 //----------------------------------------------------------------------------
64 static const char * cmDocumentationOptions
[][3] =
66 {"-G <generator>", "Use the specified generator to generate package.",
67 "CPack may support multiple native packaging systems on certain "
68 "platforms. A generator is responsible for generating input files for "
69 "particular system and invoking that systems. Possible generator names "
70 "are specified in the Generators section." },
71 {"-C <Configuration>", "Specify the project configuration",
72 "This option specifies the configuration that the project was build "
73 "with, for example 'Debug', 'Release'." },
74 {"-D <var>=<value>", "Set a CPack variable.", \
75 "Set a variable that can be used by the generator."}, \
76 {"--config <config file>", "Specify the config file.",
77 "Specify the config file to use to create the package. By default "
78 "CPackConfig.cmake in the current directory will be used." },
82 //----------------------------------------------------------------------------
83 static const char * cmDocumentationSeeAlso
[][3] =
90 //----------------------------------------------------------------------------
91 int cpackUnknownArgument(const char*, void*)
96 //----------------------------------------------------------------------------
97 struct cpackDefinitions
99 typedef std::map
<cmStdString
, cmStdString
> MapType
;
104 //----------------------------------------------------------------------------
105 int cpackDefinitionArgument(const char* argument
, const char* cValue
,
109 cpackDefinitions
* def
= static_cast<cpackDefinitions
*>(call_data
);
110 std::string value
= cValue
;
111 size_t pos
= value
.find_first_of("=");
112 if ( pos
== std::string::npos
)
114 cmCPack_Log(def
->Log
, cmCPackLog::LOG_ERROR
,
115 "Please specify CPack definitions as: KEY=VALUE" << std::endl
);
118 std::string key
= value
.substr(0, pos
);
119 value
= value
.c_str() + pos
+ 1;
120 def
->Map
[key
] = value
;
121 cmCPack_Log(def
->Log
, cmCPackLog::LOG_DEBUG
, "Set CPack variable: "
122 << key
.c_str() << " to \"" << value
.c_str() << "\"" << std::endl
);
126 //----------------------------------------------------------------------------
128 int main (int argc
, char *argv
[])
130 cmSystemTools::FindExecutableDirectory(argv
[0]);
132 log
.SetErrorPrefix("CPack Error: ");
133 log
.SetWarningPrefix("CPack Warning: ");
134 log
.SetOutputPrefix("CPack: ");
135 log
.SetVerbosePrefix("CPack Verbose: ");
137 cmSystemTools::EnableMSVCDebugHook();
139 if ( cmSystemTools::GetCurrentWorkingDirectory().size() == 0 )
141 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
142 "Current working directory cannot be established." << std::endl
);
145 std::string generator
;
147 bool helpVersion
= false;
148 bool verbose
= false;
150 std::string helpFull
;
152 std::string helpHTML
;
154 std::string cpackProjectName
;
155 std::string cpackProjectDirectory
156 = cmsys::SystemTools::GetCurrentWorkingDirectory();
157 std::string cpackBuildConfig
;
158 std::string cpackProjectVersion
;
159 std::string cpackProjectPatch
;
160 std::string cpackProjectVendor
;
161 std::string cpackConfigFile
;
163 cpackDefinitions definitions
;
164 definitions
.Log
= &log
;
166 cpackConfigFile
= "";
169 cmsys::CommandLineArguments arg
;
170 arg
.Initialize(argc
, argv
);
171 typedef cmsys::CommandLineArguments argT
;
173 arg
.AddArgument("--help", argT::NO_ARGUMENT
, &help
, "CPack help");
174 arg
.AddArgument("--help-full", argT::SPACE_ARGUMENT
, &helpFull
,
176 arg
.AddArgument("--help-html", argT::SPACE_ARGUMENT
, &helpHTML
,
178 arg
.AddArgument("--help-man", argT::SPACE_ARGUMENT
, &helpMAN
, "CPack help");
179 arg
.AddArgument("--version", argT::NO_ARGUMENT
, &helpVersion
, "CPack help");
181 arg
.AddArgument("-V", argT::NO_ARGUMENT
, &verbose
, "CPack verbose");
182 arg
.AddArgument("--verbose", argT::NO_ARGUMENT
, &verbose
, "-V");
183 arg
.AddArgument("--debug", argT::NO_ARGUMENT
, &debug
, "-V");
184 arg
.AddArgument("--config", argT::SPACE_ARGUMENT
, &cpackConfigFile
,
185 "CPack configuration file");
186 arg
.AddArgument("-C", argT::SPACE_ARGUMENT
, &cpackBuildConfig
,
187 "CPack build configuration");
188 arg
.AddArgument("-G", argT::SPACE_ARGUMENT
,
189 &generator
, "CPack generator");
190 arg
.AddArgument("-P", argT::SPACE_ARGUMENT
,
191 &cpackProjectName
, "CPack project name");
192 arg
.AddArgument("-R", argT::SPACE_ARGUMENT
,
193 &cpackProjectVersion
, "CPack project version");
194 arg
.AddArgument("-B", argT::SPACE_ARGUMENT
,
195 &cpackProjectDirectory
, "CPack project directory");
196 arg
.AddArgument("--patch", argT::SPACE_ARGUMENT
,
197 &cpackProjectPatch
, "CPack project patch");
198 arg
.AddArgument("--vendor", argT::SPACE_ARGUMENT
,
199 &cpackProjectVendor
, "CPack project vendor");
200 arg
.AddCallback("-D", argT::SPACE_ARGUMENT
,
201 cpackDefinitionArgument
, &definitions
, "CPack Definitions");
202 arg
.SetUnknownArgumentCallback(cpackUnknownArgument
);
204 // Parse command line
205 int parsed
= arg
.Parse();
210 log
.SetVerbose(verbose
);
211 cmCPack_Log(&log
, cmCPackLog::LOG_OUTPUT
, "Enable Verbse" << std::endl
);
216 cmCPack_Log(&log
, cmCPackLog::LOG_OUTPUT
, "Enable Debug" << std::endl
);
219 cmCPack_Log(&log
, cmCPackLog::LOG_VERBOSE
,
220 "Read CPack config file: " << cpackConfigFile
.c_str() << std::endl
);
223 cminst
.RemoveUnscriptableCommands();
224 cmGlobalGenerator cmgg
;
225 cmgg
.SetCMakeInstance(&cminst
);
226 std::auto_ptr
<cmLocalGenerator
> cmlg(cmgg
.CreateLocalGenerator());
227 cmMakefile
* globalMF
= cmlg
->GetMakefile();
229 bool cpackConfigFileSpecified
= true;
230 if ( cpackConfigFile
.empty() )
232 cpackConfigFile
= cmSystemTools::GetCurrentWorkingDirectory();
233 cpackConfigFile
+= "/CPackConfig.cmake";
234 cpackConfigFileSpecified
= false;
237 cmCPackGeneratorFactory generators
;
238 generators
.SetLogger(&log
);
239 cmCPackGenerator
* cpackGenerator
= 0;
241 if ( !helpFull
.empty() || !helpMAN
.empty() ||
242 !helpHTML
.empty() || helpVersion
)
247 if ( parsed
&& !help
)
249 // find out which system cpack is running on, so it can setup the search
250 // paths, so FIND_XXX() commands can be used in scripts
251 cminst
.AddCMakePaths();
252 std::string systemFile
=
253 globalMF
->GetModulesFile("CMakeDetermineSystem.cmake");
254 if (!globalMF
->ReadListFile(0, systemFile
.c_str()))
256 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
257 "Error reading CMakeDetermineSystem.cmake" << std::endl
);
262 globalMF
->GetModulesFile("CMakeSystemSpecificInformation.cmake");
263 if (!globalMF
->ReadListFile(0, systemFile
.c_str()))
265 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
266 "Error reading CMakeSystemSpecificInformation.cmake" << std::endl
);
270 if ( cmSystemTools::FileExists(cpackConfigFile
.c_str()) )
273 cmSystemTools::CollapseFullPath(cpackConfigFile
.c_str());
274 cmCPack_Log(&log
, cmCPackLog::LOG_VERBOSE
,
275 "Read CPack configuration file: " << cpackConfigFile
.c_str()
277 if ( !globalMF
->ReadListFile(0, cpackConfigFile
.c_str()) )
279 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
280 "Problem reading CPack config file: \""
281 << cpackConfigFile
.c_str() << "\"" << std::endl
);
285 else if ( cpackConfigFileSpecified
)
287 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
288 "Cannot find CPack config file: \"" << cpackConfigFile
.c_str()
289 << "\"" << std::endl
);
293 if ( !generator
.empty() )
295 globalMF
->AddDefinition("CPACK_GENERATOR", generator
.c_str());
297 if ( !cpackProjectName
.empty() )
299 globalMF
->AddDefinition("CPACK_PACKAGE_NAME", cpackProjectName
.c_str());
301 if ( !cpackProjectVersion
.empty() )
303 globalMF
->AddDefinition("CPACK_PACKAGE_VERSION",
304 cpackProjectVersion
.c_str());
306 if ( !cpackProjectVendor
.empty() )
308 globalMF
->AddDefinition("CPACK_PACKAGE_VENDOR",
309 cpackProjectVendor
.c_str());
311 if ( !cpackProjectDirectory
.empty() )
313 globalMF
->AddDefinition("CPACK_PACKAGE_DIRECTORY",
314 cpackProjectDirectory
.c_str());
316 if ( !cpackBuildConfig
.empty() )
318 globalMF
->AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig
.c_str());
320 cpackDefinitions::MapType::iterator cdit
;
321 for ( cdit
= definitions
.Map
.begin();
322 cdit
!= definitions
.Map
.end();
325 globalMF
->AddDefinition(cdit
->first
.c_str(), cdit
->second
.c_str());
328 const char* cpackModulesPath
=
329 globalMF
->GetDefinition("CPACK_MODULE_PATH");
330 if ( cpackModulesPath
)
332 globalMF
->AddDefinition("CMAKE_MODULE_PATH", cpackModulesPath
);
334 const char* genList
= globalMF
->GetDefinition("CPACK_GENERATOR");
337 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
338 "CPack generator not specified" << std::endl
);
343 std::vector
<std::string
> generatorsVector
;
344 cmSystemTools::ExpandListArgument(genList
,
346 std::vector
<std::string
>::iterator it
;
347 for ( it
= generatorsVector
.begin();
348 it
!= generatorsVector
.end();
351 const char* gen
= it
->c_str();
352 cmMakefile
newMF(*globalMF
);
353 cmMakefile
* mf
= &newMF
;
354 cmCPack_Log(&log
, cmCPackLog::LOG_VERBOSE
,
355 "Specified generator: " << gen
<< std::endl
);
356 if ( parsed
&& !mf
->GetDefinition("CPACK_PACKAGE_NAME") )
358 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
359 "CPack project name not specified" << std::endl
);
362 if ( parsed
&& !(mf
->GetDefinition("CPACK_PACKAGE_VERSION")
363 || mf
->GetDefinition("CPACK_PACKAGE_VERSION_MAJOR") &&
364 mf
->GetDefinition("CPACK_PACKAGE_VERSION_MINOR")
365 && mf
->GetDefinition("CPACK_PACKAGE_VERSION_PATCH")) )
367 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
368 "CPack project version not specified" << std::endl
369 << "Specify CPACK_PACKAGE_VERSION, or "
370 "CPACK_PACKAGE_VERSION_MAJOR, "
371 "CPACK_PACKAGE_VERSION_MINOR, and CPACK_PACKAGE_VERSION_PATCH."
377 cpackGenerator
= generators
.NewGenerator(gen
);
378 if ( !cpackGenerator
)
380 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
381 "Cannot initialize CPack generator: "
382 << gen
<< std::endl
);
385 if ( parsed
&& !cpackGenerator
->Initialize(gen
, mf
) )
387 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
388 "Cannot initialize the generator " << gen
<< std::endl
);
392 if ( !mf
->GetDefinition("CPACK_INSTALL_COMMANDS") &&
393 !mf
->GetDefinition("CPACK_INSTALLED_DIRECTORIES") &&
394 !mf
->GetDefinition("CPACK_INSTALL_CMAKE_PROJECTS") )
396 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
397 "Please specify build tree of the project that uses CMake "
398 "using CPACK_INSTALL_CMAKE_PROJECTS, specify "
399 "CPACK_INSTALL_COMMANDS, or specify "
400 "CPACK_INSTALLED_DIRECTORIES."
407 std::string comspec
= "cmw9xcom.exe";
408 cmSystemTools::SetWindows9xComspecSubstitute(comspec
.c_str());
411 const char* projName
= mf
->GetDefinition("CPACK_PACKAGE_NAME");
412 cmCPack_Log(&log
, cmCPackLog::LOG_VERBOSE
, "Use generator: "
413 << cpackGenerator
->GetNameOfClass() << std::endl
);
414 cmCPack_Log(&log
, cmCPackLog::LOG_VERBOSE
, "For project: "
415 << projName
<< std::endl
);
417 const char* projVersion
=
418 mf
->GetDefinition("CPACK_PACKAGE_VERSION");
421 const char* projVersionMajor
422 = mf
->GetDefinition("CPACK_PACKAGE_VERSION_MAJOR");
423 const char* projVersionMinor
424 = mf
->GetDefinition("CPACK_PACKAGE_VERSION_MINOR");
425 const char* projVersionPatch
426 = mf
->GetDefinition("CPACK_PACKAGE_VERSION_PATCH");
427 cmOStringStream ostr
;
428 ostr
<< projVersionMajor
<< "." << projVersionMinor
<< "."
430 mf
->AddDefinition("CPACK_PACKAGE_VERSION",
434 int res
= cpackGenerator
->DoPackage();
437 cmCPack_Log(&log
, cmCPackLog::LOG_ERROR
,
438 "Error when generating package: " << projName
<< std::endl
);
449 doc
.CheckOptions(argc
, argv
);
450 // Construct and print requested documentation.
451 doc
.SetName("cpack");
452 doc
.SetSection("Name",cmDocumentationName
);
453 doc
.SetSection("Usage",cmDocumentationUsage
);
454 doc
.SetSection("Description",cmDocumentationDescription
);
455 doc
.SetSection("Options",cmDocumentationOptions
);
457 std::vector
<cmDocumentationEntry
> v
;
458 cmCPackGeneratorFactory::DescriptionsMap::const_iterator generatorIt
;
459 for( generatorIt
= generators
.GetGeneratorsList().begin();
460 generatorIt
!= generators
.GetGeneratorsList().end();
463 cmDocumentationEntry e
;
464 e
.Name
= generatorIt
->first
.c_str();
465 e
.Brief
= generatorIt
->second
.c_str();
469 doc
.SetSection("Generators",v
);
471 doc
.SetSeeAlsoList(cmDocumentationSeeAlso
);
473 return doc
.PrintRequestedDocumentation(std::cout
)? 0:1;
474 #define cout no_cout_use_cmCPack_Log
477 if (cmSystemTools::GetErrorOccuredFlag())