1 /*=========================================================================
3 Program: Insight Segmentation & Registration Toolkit
4 Module: $RCSfile: cmake.cxx,v $
6 Date: $Date: 2002-07-17 15:53:07 $
7 Version: $Revision: 1.70 $
9 Copyright (c) 2002 Insight Consortium. All rights reserved.
10 See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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 =========================================================================*/
19 #include "cmCacheManager.h"
21 // include the generator
22 #if defined(_WIN32) && !defined(__CYGWIN__)
23 #include "cmMSProjectGenerator.h"
24 #include "cmMSDotNETGenerator.h"
25 #include "cmBorlandMakefileGenerator.h"
26 #include "cmNMakeMakefileGenerator.h"
28 #include "cmUnixMakefileGenerator.h"
34 #if defined(_WIN32) && !defined(__CYGWIN__)
35 cmMakefileGenerator::RegisterGenerator(new cmMSProjectGenerator
);
36 cmMakefileGenerator::RegisterGenerator(new cmMSDotNETGenerator
);
37 cmMakefileGenerator::RegisterGenerator(new cmNMakeMakefileGenerator
);
38 cmMakefileGenerator::RegisterGenerator(new cmBorlandMakefileGenerator
);
40 cmMakefileGenerator::RegisterGenerator(new cmUnixMakefileGenerator
);
44 void cmake::Usage(const char* program
)
46 cmStringStream errorStream
;
48 errorStream
<< "cmake version " << cmMakefile::GetMajorVersion()
49 << "." << cmMakefile::GetMinorVersion() << "\n";
50 errorStream
<< "Usage: " << program
<< " [srcdir] [options]\n"
51 << "Where cmake is run from the directory where you want the object files written. If srcdir is not specified, the current directory is used for both source and object files.\n";
52 errorStream
<< "Options are:\n";
53 errorStream
<< "\n-i (puts cmake in wizard mode, not available for ccmake)\n";
54 errorStream
<< "\n-DVAR:TYPE=VALUE (create a cache file entry)\n";
55 errorStream
<< "\n-Cpath_to_initial_cache (a cmake list file that is used to pre-load the cache with values.)\n";
56 errorStream
<< "\n[-GgeneratorName] (where generator name can be one of these: ";
57 std::vector
<std::string
> names
;
58 cmMakefileGenerator::GetRegisteredGenerators(names
);
59 for(std::vector
<std::string
>::iterator i
=names
.begin();
60 i
!= names
.end(); ++i
)
62 errorStream
<< "\"" << i
->c_str() << "\" ";
66 cmSystemTools::Error(errorStream
.str().c_str());
70 void cmake::SetCacheArgs(cmMakefile
& builder
,
71 const std::vector
<std::string
>& args
)
73 for(unsigned int i
=1; i
< args
.size(); ++i
)
75 std::string arg
= args
[i
];
76 if(arg
.find("-D",0) == 0)
78 std::string entry
= arg
.substr(2);
79 std::string var
, value
;
80 cmCacheManager::CacheEntryType type
;
81 if(cmCacheManager::ParseEntry(entry
.c_str(), var
, value
, type
))
83 cmCacheManager::GetInstance()->AddCacheEntry(
86 "No help, variable specified on the command line.",
91 std::cerr
<< "Parse error in command line argument: " << arg
<< "\n"
92 << "Should be: VAR:type=value\n";
95 else if(arg
.find("-C",0) == 0)
97 std::string path
= arg
.substr(2);
98 std::cerr
<< "loading initial cache file " << path
.c_str() << "\n";
99 if(!builder
.ReadListFile(path
.c_str()))
101 std::cerr
<< "Error in reading cmake initial cache file:"
102 << path
.c_str() << "\n";
109 void cmake::SetArgs(cmMakefile
& builder
, const std::vector
<std::string
>& args
)
112 bool directoriesSet
= false;
113 // watch for cmake and cmake srcdir invocations
114 if (args
.size() <= 2)
116 directoriesSet
= true;
117 builder
.SetHomeOutputDirectory
118 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
119 builder
.SetStartOutputDirectory
120 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
121 if (args
.size() == 2)
123 builder
.SetHomeDirectory
124 (cmSystemTools::CollapseFullPath(args
[1].c_str()).c_str());
125 builder
.SetStartDirectory
126 (cmSystemTools::CollapseFullPath(args
[1].c_str()).c_str());
130 builder
.SetHomeDirectory
131 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
132 builder
.SetStartDirectory
133 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
137 for(unsigned int i
=1; i
< args
.size(); ++i
)
139 std::string arg
= args
[i
];
140 if(arg
.find("-H",0) == 0)
142 directoriesSet
= true;
143 std::string path
= arg
.substr(2);
144 builder
.SetHomeDirectory(path
.c_str());
146 else if(arg
.find("-S",0) == 0)
148 directoriesSet
= true;
150 std::string path
= arg
.substr(2);
151 builder
.SetStartDirectory(path
.c_str());
153 else if(arg
.find("-O",0) == 0)
155 directoriesSet
= true;
156 std::string path
= arg
.substr(2);
157 builder
.SetStartOutputDirectory(path
.c_str());
159 else if(arg
.find("-B",0) == 0)
161 directoriesSet
= true;
162 std::string path
= arg
.substr(2);
163 builder
.SetHomeOutputDirectory(path
.c_str());
165 else if(arg
.find("-V",0) == 0)
169 else if(arg
.find("-D",0) == 0)
173 else if(arg
.find("-C",0) == 0)
177 else if(arg
.find("-G",0) == 0)
179 std::string value
= arg
.substr(2);
180 cmMakefileGenerator
* gen
=
181 cmMakefileGenerator::CreateGenerator(value
.c_str());
184 cmSystemTools::Error("Could not create named generator ",
189 builder
.SetMakefileGenerator(gen
);
192 // no option assume it is the path to the source
195 directoriesSet
= true;
196 builder
.SetHomeOutputDirectory
197 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
198 builder
.SetStartOutputDirectory
199 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
200 builder
.SetHomeDirectory
201 (cmSystemTools::CollapseFullPath(arg
.c_str()).c_str());
202 builder
.SetStartDirectory
203 (cmSystemTools::CollapseFullPath(arg
.c_str()).c_str());
208 builder
.SetHomeOutputDirectory
209 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
210 builder
.SetStartOutputDirectory
211 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
212 builder
.SetHomeDirectory
213 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
214 builder
.SetStartDirectory
215 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
219 builder
.SetStartDirectory(builder
.GetHomeDirectory());
220 builder
.SetStartOutputDirectory(builder
.GetHomeOutputDirectory());
224 // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the cache
225 int cmake::AddCMakePaths(const std::vector
<std::string
>& args
)
227 // Find our own executable.
228 std::vector
<cmStdString
> failures
;
229 std::string cMakeSelf
= args
[0];
230 cmSystemTools::ConvertToUnixSlashes(cMakeSelf
);
231 failures
.push_back(cMakeSelf
);
232 cMakeSelf
= cmSystemTools::FindProgram(cMakeSelf
.c_str());
233 if(!cmSystemTools::FileExists(cMakeSelf
.c_str()))
235 #ifdef CMAKE_BUILD_DIR
236 std::string intdir
= ".";
238 intdir
= CMAKE_INTDIR
;
240 cMakeSelf
= CMAKE_BUILD_DIR
;
241 cMakeSelf
+= "/Source/";
243 cMakeSelf
+= "/cmake";
244 cMakeSelf
+= cmSystemTools::GetExecutableExtension();
248 if(!cmSystemTools::FileExists(cMakeSelf
.c_str()))
250 failures
.push_back(cMakeSelf
);
251 cMakeSelf
= CMAKE_PREFIX
"/bin/cmake";
254 if(!cmSystemTools::FileExists(cMakeSelf
.c_str()))
256 failures
.push_back(cMakeSelf
);
258 msg
<< "CMAKE can not find the command line program cmake.\n";
259 msg
<< " argv[0] = \"" << args
[0].c_str() << "\"\n";
260 msg
<< " Attempted paths:\n";
261 std::vector
<cmStdString
>::iterator i
;
262 for(i
=failures
.begin(); i
!= failures
.end(); ++i
)
264 msg
<< " \"" << i
->c_str() << "\"\n";
266 cmSystemTools::Error(msg
.str().c_str());
269 // Save the value in the cache
270 cmCacheManager::GetInstance()->AddCacheEntry
271 ("CMAKE_COMMAND",cMakeSelf
.c_str(), "Path to CMake executable.",
272 cmCacheManager::INTERNAL
);
274 // Find and save the command to edit the cache
275 std::string editCacheCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
276 "/ccmake" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
277 if( !cmSystemTools::FileExists(editCacheCommand
.c_str()))
279 editCacheCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
280 "/CMakeSetup" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
282 if(cmSystemTools::FileExists(editCacheCommand
.c_str()))
284 cmCacheManager::GetInstance()->AddCacheEntry
285 ("CMAKE_EDIT_COMMAND", editCacheCommand
.c_str(),
286 "Path to cache edit program executable.", cmCacheManager::INTERNAL
);
289 // do CMAKE_ROOT, look for the environment variable first
290 std::string cMakeRoot
;
292 if (getenv("CMAKE_ROOT"))
294 cMakeRoot
= getenv("CMAKE_ROOT");
295 modules
= cMakeRoot
+ "/Modules/FindVTK.cmake";
297 if(!cmSystemTools::FileExists(modules
.c_str()))
300 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeSelf
.c_str());
301 std::string::size_type slashPos
= cMakeRoot
.rfind("/");
302 if(slashPos
!= std::string::npos
)
304 cMakeRoot
= cMakeRoot
.substr(0, slashPos
);
306 // is there no Modules direcory there?
307 modules
= cMakeRoot
+ "/Modules/FindVTK.cmake";
310 if (!cmSystemTools::FileExists(modules
.c_str()))
312 // try exe/../share/cmake
313 cMakeRoot
+= "/share/CMake";
314 modules
= cMakeRoot
+ "/Modules/FindVTK.cmake";
316 #ifdef CMAKE_ROOT_DIR
317 if (!cmSystemTools::FileExists(modules
.c_str()))
319 // try compiled in root directory
320 cMakeRoot
= CMAKE_ROOT_DIR
;
321 modules
= cMakeRoot
+ "/Modules/FindVTK.cmake";
325 if (!cmSystemTools::FileExists(modules
.c_str()))
327 // try compiled in install prefix
328 cMakeRoot
= CMAKE_PREFIX
"/share/CMake";
329 modules
= cMakeRoot
+ "/Modules/FindVTK.cmake";
332 if (!cmSystemTools::FileExists(modules
.c_str()))
335 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeSelf
.c_str());
336 cMakeRoot
+= "/share/CMake";
337 modules
= cMakeRoot
+ "/Modules/FindVTK.cmake";
339 if(!cmSystemTools::FileExists(modules
.c_str()))
342 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeSelf
.c_str());
343 // is there no Modules direcory there?
344 modules
= cMakeRoot
+ "/Modules/FindVTK.cmake";
346 if (!cmSystemTools::FileExists(modules
.c_str()))
348 // couldn't find modules
349 cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n",
350 "Modules directory not in directory:\n",
354 cmCacheManager::GetInstance()->AddCacheEntry
355 ("CMAKE_ROOT", cMakeRoot
.c_str(),
356 "Path to CMake installation.", cmCacheManager::INTERNAL
);
362 int cmake::Generate(const std::vector
<std::string
>& args
, bool buildMakefiles
)
364 if(args
.size() == 1 && !cmSystemTools::FileExists("CMakeLists.txt"))
366 this->Usage(args
[0].c_str());
369 // look for obvious request for help
370 for(unsigned int i
=1; i
< args
.size(); ++i
)
372 std::string arg
= args
[i
];
373 if(arg
.find("-help",0) != std::string::npos
||
374 arg
.find("--help",0) != std::string::npos
||
375 arg
.find("/?",0) != std::string::npos
||
376 arg
.find("-usage",0) != std::string::npos
)
378 this->Usage(args
[0].c_str());
384 // extract the directory arguments, could create a Generator
385 this->SetArgs(mf
, args
);
386 // Read and parse the input makefile
387 mf
.MakeStartDirectoriesCurrent();
388 cmCacheManager::GetInstance()->LoadCache(&mf
);
389 if(mf
.GetDefinition("CMAKE_HOME_DIRECTORY"))
391 std::string cacheStart
= mf
.GetDefinition("CMAKE_HOME_DIRECTORY");
392 cacheStart
+= "/CMakeLists.txt";
393 std::string currentStart
= mf
.GetHomeDirectory();
394 currentStart
+= "/CMakeLists.txt";
395 if(!cmSystemTools::SameFile(cacheStart
.c_str(), currentStart
.c_str()))
397 std::string message
= "Error: source : ";
398 message
+= currentStart
;
399 message
+= "\nDoes not match source used to generate cache: ";
400 message
+= cacheStart
;
401 message
+= "\nRe-run cmake with a different source directory.";
402 cmSystemTools::Error(message
.c_str());
406 mf
.AddCacheDefinition("CMAKE_HOME_DIRECTORY", mf
.GetHomeDirectory(),
407 "Start directory with the top level CMakeLists.txt file for this project",
408 cmCacheManager::INTERNAL
);
410 // extract command line arguments that might add cache entries
411 this->SetCacheArgs(mf
, args
);
413 // no generator specified on the command line
414 if(!mf
.GetMakefileGenerator())
416 cmMakefileGenerator
* gen
;
417 const char* genName
= mf
.GetDefinition("CMAKE_GENERATOR");
420 gen
= cmMakefileGenerator::CreateGenerator(genName
);
424 #if defined(__BORLANDC__)
425 gen
= new cmBorlandMakefileGenerator
;
426 #elif defined(_WIN32) && !defined(__CYGWIN__)
427 gen
= new cmMSProjectGenerator
;
429 gen
= new cmUnixMakefileGenerator
;
434 cmSystemTools::Error("Could not create generator");
437 mf
.SetMakefileGenerator(gen
);
440 cmMakefileGenerator
* gen
= mf
.GetMakefileGenerator();
441 gen
->SetLocal(m_Local
);
442 const char* genName
= mf
.GetDefinition("CMAKE_GENERATOR");
445 if(strcmp(gen
->GetName(), genName
) != 0)
447 std::string message
= "Error: generator : ";
448 message
+= gen
->GetName();
449 message
+= "\nDoes not match the generator used previously: ";
452 "\nEither remove the CMakeCache.txt file or choose a different"
453 " binary directory.";
454 cmSystemTools::Error(message
.c_str());
458 if(!mf
.GetDefinition("CMAKE_GENERATOR"))
460 mf
.AddCacheDefinition("CMAKE_GENERATOR",
462 "Name of generator.",
463 cmCacheManager::INTERNAL
);
467 // setup CMAKE_ROOT and CMAKE_COMMAND
468 if(!this->AddCMakePaths(args
))
473 // reset any system configuration information
474 cmMakefileGenerator::ClearEnabledLanguages();
476 std::string lf
= mf
.GetStartDirectory();
477 lf
+= "/CMakeLists.txt";
478 if(!mf
.ReadListFile(lf
.c_str()))
480 this->Usage(args
[0].c_str());
483 // if buildMakefiles, then call GenerateMakefile
486 mf
.GenerateMakefile();
488 else // do not build, but let the commands finalize
490 std::vector
<cmMakefile
*> makefiles
;
491 mf
.FindSubDirectoryCMakeListsFiles(makefiles
);
492 for(std::vector
<cmMakefile
*>::iterator i
= makefiles
.begin();
493 i
!= makefiles
.end(); ++i
)
503 // Before saving the cache
504 // if the project did not define one of the entries below, add them now
505 // so users can edit the values in the cache:
506 // LIBRARY_OUTPUT_PATH
507 // EXECUTABLE_OUTPUT_PATH
508 if(!cmCacheManager::GetInstance()->GetCacheValue("LIBRARY_OUTPUT_PATH"))
510 cmCacheManager::GetInstance()->AddCacheEntry("LIBRARY_OUTPUT_PATH", "",
511 "Single output directory for building all libraries.",
512 cmCacheManager::PATH
);
514 if(!cmCacheManager::GetInstance()->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
516 cmCacheManager::GetInstance()->AddCacheEntry("EXECUTABLE_OUTPUT_PATH", "",
517 "Single output directory for building all executables.",
518 cmCacheManager::PATH
);
521 cmCacheManager::GetInstance()->SaveCache(&mf
);
525 cmCacheManager::GetInstance()->PrintCache(std::cout
);
528 if(cmSystemTools::GetErrorOccuredFlag())
536 void CMakeCommandUsage(const char* program
)
538 cmStringStream errorStream
;
541 << "cmake version " << cmMakefile::GetMajorVersion()
542 << "." << cmMakefile::GetMinorVersion() << "\n";
545 << "Usage: " << program
<< " -E [command] [arguments ...]\n"
546 << "Available commands: \n"
547 << " chdir dir cmd [args]... - run command in a given directory\n"
548 << " copy file destination - copy file to destination (either file or directory)\n"
549 << " remove file1 file2 ... - remove the file(s)\n"
550 << " time command [args] ... - run command and return elapsed time\n";
551 #if defined(_WIN32) && !defined(__CYGWIN__)
553 << " write_regv key value - write registry value\n"
554 << " delete_regv key - delete registry value\n";
557 cmSystemTools::Error(errorStream
.str().c_str());
560 int cmake::CMakeCommand(std::vector
<std::string
>& args
)
565 if (args
[1] == "copy" && args
.size() == 4)
567 cmSystemTools::cmCopyFile(args
[2].c_str(), args
[3].c_str());
568 return cmSystemTools::GetErrorOccuredFlag();
572 else if (args
[1] == "remove" && args
.size() > 2)
574 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
578 if(args
[cc
] == "\\-f")
582 cmSystemTools::RemoveFile(args
[cc
].c_str());
589 else if (args
[1] == "time" && args
.size() > 2)
591 std::string command
= args
[2];
593 for (std::string::size_type cc
= 3; cc
< args
.size(); cc
++)
599 clock_t clock_start
, clock_finish
;
600 time_t time_start
, time_finish
;
603 clock_start
= clock();
605 cmSystemTools::RunCommand(command
.c_str(), output
, 0, true);
607 clock_finish
= clock();
610 std::cout
<< output
.c_str();
612 double clocks_per_sec
= (double)CLOCKS_PER_SEC
;
613 std::cout
<< "Elapsed time: "
614 << (long)(time_finish
- time_start
) << " s. (time)"
616 << (double)(clock_finish
- clock_start
) / clocks_per_sec
623 else if (args
[1] == "chdir" && args
.size() > 2)
625 std::string directory
= args
[2];
626 std::string command
= args
[3];
628 for (std::string::size_type cc
= 4; cc
< args
.size(); cc
++)
635 if ( cmSystemTools::RunCommand(command
.c_str(), output
, retval
,
636 directory
.c_str(), true) )
638 std::cout
<< output
.c_str();
645 #if defined(_WIN32) && !defined(__CYGWIN__)
646 // Write registry value
647 else if (args
[1] == "write_regv" && args
.size() > 3)
649 return cmSystemTools::WriteRegistryValue(args
[2].c_str(),
650 args
[3].c_str()) ? 0 : 1;
653 // Delete registry value
654 else if (args
[1] == "delete_regv" && args
.size() > 2)
656 return cmSystemTools::DeleteRegistryValue(args
[2].c_str()) ? 0 : 1;
661 ::CMakeCommandUsage(args
[0].c_str());