cmMakefile.cxx 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. /*=========================================================================
  2. Program: Insight Segmentation & Registration Toolkit
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2000 National Library of Medicine
  8. All rights reserved.
  9. See COPYRIGHT.txt for copyright details.
  10. =========================================================================*/
  11. #include "cmMakefile.h"
  12. #include "cmCommand.h"
  13. #include "cmStandardIncludes.h"
  14. #include "cmSourceFile.h"
  15. #include "cmDirectory.h"
  16. #include "cmSystemTools.h"
  17. #include "cmMakefileGenerator.h"
  18. #include "cmCommands.h"
  19. #include "cmCacheManager.h"
  20. #include "cmFunctionBlocker.h"
  21. // default is not to be building executables
  22. cmMakefile::cmMakefile()
  23. {
  24. // Setup the default include file regular expression.
  25. // Should be changed to something like "\\.(h|hh|hpp|hxx)$" or "^.*$"
  26. m_IncludeFileRegularExpression = "^itk|^vtk|^vnl|^vcl|^f2c";
  27. m_DefineFlags = " ";
  28. m_MakefileGenerator = 0;
  29. this->AddSourceGroup("", "^.*$");
  30. this->AddSourceGroup("Source Files", "\\.(cpp|C|c|cxx|rc|def|r|odl|idl|hpj|bat)$");
  31. this->AddSourceGroup("Header Files", "\\.(h|hh|hpp|hxx|hm|inl)$");
  32. this->AddDefaultCommands();
  33. this->AddDefaultDefinitions();
  34. }
  35. void cmMakefile::AddDefaultCommands()
  36. {
  37. std::list<cmCommand*> commands;
  38. GetPredefinedCommands(commands);
  39. for(std::list<cmCommand*>::iterator i = commands.begin();
  40. i != commands.end(); ++i)
  41. {
  42. this->AddCommand(*i);
  43. }
  44. #ifdef _WIN32
  45. this->AddDefinition("WIN32", "1");
  46. #else
  47. this->AddDefinition("UNIX", "1");
  48. #endif
  49. // Cygwin is more like unix so enable the unix commands
  50. #if defined(__CYGWIN__)
  51. this->AddDefinition("UNIX", "1");
  52. #endif
  53. }
  54. cmMakefile::~cmMakefile()
  55. {
  56. for(unsigned int i=0; i < m_UsedCommands.size(); i++)
  57. {
  58. delete m_UsedCommands[i];
  59. }
  60. for(RegisteredCommandsMap::iterator j = m_Commands.begin();
  61. j != m_Commands.end(); ++j)
  62. {
  63. delete (*j).second;
  64. }
  65. delete m_MakefileGenerator;
  66. }
  67. void cmMakefile::PrintStringVector(const char* s, const std::vector<std::string>& v) const
  68. {
  69. std::cout << s << ": ( \n";
  70. for(std::vector<std::string>::const_iterator i = v.begin();
  71. i != v.end(); ++i)
  72. {
  73. std::cout << (*i).c_str() << " ";
  74. }
  75. std::cout << " )\n";
  76. }
  77. // call print on all the classes in the makefile
  78. void cmMakefile::Print() const
  79. {
  80. // print the class lists
  81. std::cout << "classes:\n";
  82. for(SourceMap::const_iterator l = m_Sources.begin();
  83. l != m_Sources.end(); l++)
  84. {
  85. std::cout << " Class list named: " << l->first << std::endl;
  86. for(std::vector<cmSourceFile>::const_iterator i = l->second.begin();
  87. i != l->second.end(); i++)
  88. {
  89. i->Print();
  90. }
  91. }
  92. std::cout << " m_Targets: ";
  93. for (cmTargets::const_iterator l = m_Targets.begin();
  94. l != m_Targets.end(); l++)
  95. {
  96. std::cout << l->first << std::endl;
  97. }
  98. std::cout << " m_CurrentOutputDirectory; " <<
  99. m_CurrentOutputDirectory.c_str() << std::endl;
  100. std::cout << " m_StartOutputDirectory; " <<
  101. m_StartOutputDirectory.c_str() << std::endl;
  102. std::cout << " m_HomeOutputDirectory; " <<
  103. m_HomeOutputDirectory.c_str() << std::endl;
  104. std::cout << " m_cmCurrentDirectory; " <<
  105. m_cmCurrentDirectory.c_str() << std::endl;
  106. std::cout << " m_cmStartDirectory; " <<
  107. m_cmStartDirectory.c_str() << std::endl;
  108. std::cout << " m_cmHomeDirectory; " <<
  109. m_cmHomeDirectory.c_str() << std::endl;
  110. std::cout << " m_ProjectName; " << m_ProjectName.c_str() << std::endl;
  111. this->PrintStringVector("m_SubDirectories ", m_SubDirectories);
  112. this->PrintStringVector("m_MakeVerbatim ", m_MakeVerbatim);
  113. this->PrintStringVector("m_IncludeDirectories;", m_IncludeDirectories);
  114. this->PrintStringVector("m_LinkDirectories", m_LinkDirectories);
  115. this->PrintStringVector("m_LinkLibraries", m_LinkLibraries);
  116. this->PrintStringVector("m_LinkLibrariesWin32", m_LinkLibrariesWin32);
  117. this->PrintStringVector("m_LinkLibrariesUnix", m_LinkLibrariesUnix);
  118. this->PrintStringVector("m_Utilities", m_Utilities);
  119. this->PrintStringVector("m_UtilityDirectories", m_UtilityDirectories);
  120. }
  121. // Parse the given CMakeLists.txt file into a list of classes.
  122. // Reads in current CMakeLists file and all parent CMakeLists files
  123. // executing all inherited commands in the parents
  124. bool cmMakefile::ReadListFile(const char* filename)
  125. {
  126. // is there a parent CMakeLists file that does not go beyond the
  127. // Home directory? if so recurse and read in that List file
  128. std::string parentList = this->GetParentListFileName(filename);
  129. if (parentList != "")
  130. {
  131. // save the current directory
  132. std::string srcdir = m_cmCurrentDirectory;
  133. std::string bindir = m_CurrentOutputDirectory;
  134. // compute the new current directories
  135. std::string::size_type pos = m_cmCurrentDirectory.rfind('/');
  136. if(pos != std::string::npos)
  137. {
  138. m_cmCurrentDirectory = m_cmCurrentDirectory.substr(0, pos);
  139. }
  140. pos = m_CurrentOutputDirectory.rfind('/');
  141. if(pos != std::string::npos)
  142. {
  143. m_CurrentOutputDirectory = m_CurrentOutputDirectory.substr(0, pos);
  144. }
  145. this->ReadListFile(parentList.c_str());
  146. // restore the current directory
  147. m_cmCurrentDirectory = srcdir;
  148. m_CurrentOutputDirectory = bindir;
  149. }
  150. // are we at the start CMakeLists file or are we processing a parent
  151. // lists file
  152. bool inheriting = (m_cmCurrentDirectory != m_cmStartDirectory);
  153. // Now read the input file
  154. std::ifstream fin(filename);
  155. if(!fin)
  156. {
  157. cmSystemTools::Error("error can not open file ", filename);
  158. return false;
  159. }
  160. std::string name;
  161. std::vector<std::string> arguments;
  162. while ( fin )
  163. {
  164. if(cmSystemTools::ParseFunction(fin, name, arguments) &&
  165. !this->IsFunctionBlocked(name.c_str(),arguments))
  166. {
  167. // Special command that needs to be removed when
  168. // ADD_COMMAND is implemented
  169. if(name == "VERBATIM")
  170. {
  171. if (!inheriting)
  172. {
  173. m_MakeVerbatim = arguments;
  174. }
  175. }
  176. else
  177. {
  178. RegisteredCommandsMap::iterator pos = m_Commands.find(name);
  179. if(pos != m_Commands.end())
  180. {
  181. cmCommand* rm = (*pos).second;
  182. cmCommand* usedCommand = rm->Clone();
  183. usedCommand->SetMakefile(this);
  184. bool keepCommand = false;
  185. if(usedCommand->GetEnabled())
  186. {
  187. // if not running in inherit mode or
  188. // if the command is inherited then Invoke it.
  189. if(!inheriting || usedCommand->IsInherited())
  190. {
  191. if(!usedCommand->Invoke(arguments))
  192. {
  193. cmSystemTools::Error(usedCommand->GetName(),
  194. ": Error : \n",
  195. usedCommand->GetError(),
  196. m_cmCurrentDirectory.c_str());
  197. }
  198. else
  199. {
  200. // use the command
  201. keepCommand = true;
  202. m_UsedCommands.push_back(usedCommand);
  203. }
  204. }
  205. }
  206. // if the Cloned command was not used
  207. // then delete it
  208. if(!keepCommand)
  209. {
  210. delete usedCommand;
  211. }
  212. }
  213. else
  214. {
  215. cmSystemTools::Error("unknown CMake command ", name.c_str());
  216. }
  217. }
  218. }
  219. }
  220. return true;
  221. }
  222. cmSourceFile *cmMakefile::GetSource(const char *srclist, const char *cname)
  223. {
  224. SourceMap::iterator sl = m_Sources.find(srclist);
  225. // find the src list
  226. if (sl == m_Sources.end())
  227. {
  228. return 0;
  229. }
  230. // find the class
  231. for (std::vector<cmSourceFile>::iterator i = sl->second.begin();
  232. i != sl->second.end(); ++i)
  233. {
  234. if (i->GetSourceName() == cname)
  235. {
  236. return &(*i);
  237. }
  238. }
  239. return 0;
  240. }
  241. void cmMakefile::AddCommand(cmCommand* wg)
  242. {
  243. std::string name = wg->GetName();
  244. m_Commands.insert( RegisteredCommandsMap::value_type(name, wg));
  245. }
  246. // Set the make file
  247. void cmMakefile::SetMakefileGenerator(cmMakefileGenerator* mf)
  248. {
  249. delete m_MakefileGenerator;
  250. m_MakefileGenerator = mf;
  251. }
  252. // Generate the output file
  253. void cmMakefile::GenerateMakefile()
  254. {
  255. // do all the variable expansions here
  256. this->ExpandVariables();
  257. // set the makefile on the generator
  258. m_MakefileGenerator->SetMakefile(this);
  259. // give all the commands a chance to do something
  260. // after the file has been parsed before generation
  261. for(std::vector<cmCommand*>::iterator i = m_UsedCommands.begin();
  262. i != m_UsedCommands.end(); ++i)
  263. {
  264. (*i)->FinalPass();
  265. }
  266. // now do the generation
  267. m_MakefileGenerator->GenerateMakefile();
  268. }
  269. void cmMakefile::AddSource(cmSourceFile& cmfile, const char *srclist)
  270. {
  271. m_Sources[srclist].push_back(cmfile);
  272. }
  273. void cmMakefile::AddCustomCommand(const char* source,
  274. const char* command,
  275. const std::vector<std::string>& depends,
  276. const std::vector<std::string>& outputs,
  277. const char *target)
  278. {
  279. // find the target,
  280. if (m_Targets.find(target) != m_Targets.end())
  281. {
  282. cmCustomCommand cc(source,command,depends,outputs);
  283. m_Targets[target].GetCustomCommands().push_back(cc);
  284. }
  285. }
  286. void cmMakefile::AddCustomCommand(const char* source,
  287. const char* command,
  288. const std::vector<std::string>& depends,
  289. const char* output,
  290. const char *target)
  291. {
  292. std::vector<std::string> outputs;
  293. outputs.push_back(output);
  294. this->AddCustomCommand(source, command, depends, outputs, target);
  295. }
  296. void cmMakefile::AddDefineFlag(const char* flag)
  297. {
  298. m_DefineFlags += " ";
  299. m_DefineFlags += flag;
  300. }
  301. void cmMakefile::AddUtility(const char* util)
  302. {
  303. m_Utilities.push_back(util);
  304. }
  305. void cmMakefile::AddUtilityDirectory(const char* dir)
  306. {
  307. m_UtilityDirectories.push_back(dir);
  308. }
  309. void cmMakefile::AddLinkLibrary(const char* lib)
  310. {
  311. m_LinkLibraries.push_back(lib);
  312. }
  313. void cmMakefile::AddLinkDirectory(const char* dir)
  314. {
  315. m_LinkDirectories.push_back(dir);
  316. }
  317. void cmMakefile::AddSubDirectory(const char* sub)
  318. {
  319. m_SubDirectories.push_back(sub);
  320. }
  321. void cmMakefile::AddIncludeDirectory(const char* inc)
  322. {
  323. m_IncludeDirectories.push_back(inc);
  324. }
  325. void cmMakefile::AddDefinition(const char* name, const char* value)
  326. {
  327. m_Definitions.insert(DefinitionMap::value_type(name, value));
  328. }
  329. void cmMakefile::AddDefinition(const char* name, bool value)
  330. {
  331. if(value)
  332. {
  333. m_Definitions.insert(DefinitionMap::value_type(name, "ON"));
  334. }
  335. else
  336. {
  337. m_Definitions.insert(DefinitionMap::value_type(name, "OFF"));
  338. }
  339. }
  340. void cmMakefile::SetProjectName(const char* p)
  341. {
  342. m_ProjectName = p;
  343. }
  344. void cmMakefile::AddLibrary(const char* lname, const std::vector<std::string> &srcs)
  345. {
  346. cmTarget target;
  347. target.SetIsALibrary(1);
  348. target.GetSourceLists() = srcs;
  349. m_Targets.insert(cmTargets::value_type(lname,target));
  350. }
  351. void cmMakefile::AddExecutable(const char *exeName,
  352. const std::vector<std::string> &srcs)
  353. {
  354. cmTarget target;
  355. target.SetIsALibrary(0);
  356. target.GetSourceLists() = srcs;
  357. m_Targets.insert(cmTargets::value_type(exeName,target));
  358. }
  359. void cmMakefile::AddSourceGroup(const char* name, const char* regex)
  360. {
  361. // First see if the group exists. If so, replace its regular expression.
  362. for(std::vector<cmSourceGroup>::iterator sg = m_SourceGroups.begin();
  363. sg != m_SourceGroups.end(); ++sg)
  364. {
  365. std::string sgName = sg->GetName();
  366. if(sgName == name)
  367. {
  368. // We only want to set the regular expression. If there are already
  369. // source files in the group, we don't want to remove them.
  370. sg->SetGroupRegex(regex);
  371. return;
  372. }
  373. }
  374. // The group doesn't exist. Add it.
  375. m_SourceGroups.push_back(cmSourceGroup(name, regex));
  376. }
  377. void cmMakefile::AddExtraDirectory(const char* dir)
  378. {
  379. m_AuxSourceDirectories.push_back(dir);
  380. }
  381. // return the file name for the parent CMakeLists file to the
  382. // one passed in. Zero is returned if the CMakeLists file is the
  383. // one in the home directory or if for some reason a parent cmake lists
  384. // file cannot be found.
  385. std::string cmMakefile::GetParentListFileName(const char *currentFileName)
  386. {
  387. // extract the directory name
  388. std::string parentFile;
  389. std::string listsDir = currentFileName;
  390. std::string::size_type pos = listsDir.rfind('/');
  391. // if we could not find the directory return 0
  392. if(pos == std::string::npos)
  393. {
  394. return parentFile;
  395. }
  396. listsDir = listsDir.substr(0, pos);
  397. // if we are in the home directory then stop, return 0
  398. if(m_cmHomeDirectory == listsDir)
  399. {
  400. return parentFile;
  401. }
  402. // is there a parent directory we can check
  403. pos = listsDir.rfind('/');
  404. // if we could not find the directory return 0
  405. if(pos == std::string::npos)
  406. {
  407. return parentFile;
  408. }
  409. listsDir = listsDir.substr(0, pos);
  410. // is there a CMakeLists.txt file in the parent directory ?
  411. parentFile = listsDir;
  412. parentFile += "/CMakeLists.txt";
  413. if(!cmSystemTools::FileExists(parentFile.c_str()))
  414. {
  415. parentFile = "";
  416. return parentFile;
  417. }
  418. return parentFile;
  419. }
  420. // expance CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR in the
  421. // include and library directories.
  422. void cmMakefile::ExpandVariables()
  423. {
  424. // Now expand varibles in the include and link strings
  425. std::vector<std::string>::iterator j, begin, end;
  426. begin = m_IncludeDirectories.begin();
  427. end = m_IncludeDirectories.end();
  428. for(j = begin; j != end; ++j)
  429. {
  430. this->ExpandVariablesInString(*j);
  431. }
  432. begin = m_LinkDirectories.begin();
  433. end = m_LinkDirectories.end();
  434. for(j = begin; j != end; ++j)
  435. {
  436. this->ExpandVariablesInString(*j);
  437. }
  438. begin = m_LinkLibraries.begin();
  439. end = m_LinkLibraries.end();
  440. for(j = begin; j != end; ++j)
  441. {
  442. this->ExpandVariablesInString(*j);
  443. }
  444. }
  445. const char* cmMakefile::GetDefinition(const char* name)
  446. {
  447. DefinitionMap::iterator pos = m_Definitions.find(name);
  448. if(pos != m_Definitions.end())
  449. {
  450. return (*pos).second.c_str();
  451. }
  452. return 0;
  453. }
  454. int cmMakefile::DumpDocumentationToFile(const char *fileName)
  455. {
  456. // Open the supplied filename
  457. std::ofstream f;
  458. f.open(fileName, std::ios::out);
  459. if ( f.fail() )
  460. {
  461. return 0;
  462. }
  463. // Loop over all registered commands and print out documentation
  464. const char *name;
  465. const char *terse;
  466. const char *full;
  467. for(RegisteredCommandsMap::iterator j = m_Commands.begin();
  468. j != m_Commands.end(); ++j)
  469. {
  470. name = (*j).second->GetName();
  471. terse = (*j).second->GetTerseDocumentation();
  472. full = (*j).second->GetFullDocumentation();
  473. f << name << " - " << terse << std::endl
  474. << "Usage: " << full << std::endl << std::endl;
  475. }
  476. return 1;
  477. }
  478. void cmMakefile::ExpandVariablesInString(std::string& source) const
  479. {
  480. for(DefinitionMap::const_iterator i = m_Definitions.begin();
  481. i != m_Definitions.end(); ++i)
  482. {
  483. std::string variable = "${";
  484. variable += (*i).first;
  485. variable += "}";
  486. cmSystemTools::ReplaceString(source, variable.c_str(),
  487. (*i).second.c_str());
  488. variable = "@";
  489. variable += (*i).first;
  490. variable += "@";
  491. cmSystemTools::ReplaceString(source, variable.c_str(),
  492. (*i).second.c_str());
  493. }
  494. }
  495. // recursive function to create a vector of cmMakefile objects
  496. // This is done by reading the sub directory CMakeLists.txt files,
  497. // then calling this function with the new cmMakefile object
  498. void
  499. cmMakefile::FindSubDirectoryCMakeListsFiles(std::vector<cmMakefile*>&
  500. makefiles)
  501. {
  502. // loop over all the sub directories of this makefile
  503. const std::vector<std::string>& subdirs = this->GetSubDirectories();
  504. for(std::vector<std::string>::const_iterator i = subdirs.begin();
  505. i != subdirs.end(); ++i)
  506. {
  507. std::string subdir = *i;
  508. // Create a path to the list file in the sub directory
  509. std::string listFile = this->GetCurrentDirectory();
  510. listFile += "/";
  511. listFile += subdir;
  512. listFile += "/CMakeLists.txt";
  513. // if there is a CMakeLists.txt file read it
  514. if(!cmSystemTools::FileExists(listFile.c_str()))
  515. {
  516. cmSystemTools::Error("CMakeLists.txt file missing from sub directory:",
  517. listFile.c_str());
  518. }
  519. else
  520. {
  521. cmMakefile* mf = new cmMakefile;
  522. makefiles.push_back(mf);
  523. // initialize new makefile
  524. mf->SetHomeOutputDirectory(this->GetHomeOutputDirectory());
  525. mf->SetHomeDirectory(this->GetHomeDirectory());
  526. // add the subdir to the start output directory
  527. std::string outdir = this->GetStartOutputDirectory();
  528. outdir += "/";
  529. outdir += subdir;
  530. mf->SetStartOutputDirectory(outdir.c_str());
  531. // add the subdir to the start source directory
  532. std::string currentDir = this->GetStartDirectory();
  533. currentDir += "/";
  534. currentDir += subdir;
  535. mf->SetStartDirectory(currentDir.c_str());
  536. // Parse the CMakeLists.txt file
  537. currentDir += "/CMakeLists.txt";
  538. mf->MakeStartDirectoriesCurrent();
  539. mf->ReadListFile(currentDir.c_str());
  540. // recurse into nextDir
  541. mf->FindSubDirectoryCMakeListsFiles(makefiles);
  542. }
  543. }
  544. }
  545. void cmMakefile::GenerateCacheOnly()
  546. {
  547. std::vector<cmMakefile*> makefiles;
  548. this->FindSubDirectoryCMakeListsFiles(makefiles);
  549. for(unsigned int i =0; i < makefiles.size(); ++i)
  550. {
  551. delete makefiles[i];
  552. }
  553. }
  554. /**
  555. * Add the default definitions to the makefile. These values must not
  556. * be dependent on anything that isn't known when this cmMakefile instance
  557. * is constructed.
  558. */
  559. void cmMakefile::AddDefaultDefinitions()
  560. {
  561. #if defined(_WIN32) && !defined(__CYGWIN__)
  562. this->AddDefinition("CMAKE_CFG_OUTDIR","$(OUTDIR)");
  563. #else
  564. this->AddDefinition("CMAKE_CFG_OUTDIR",".");
  565. #endif
  566. }
  567. /**
  568. * Find a source group whose regular expression matches the filename
  569. * part of the given source name. Search backward through the list of
  570. * source groups, and take the first matching group found. This way
  571. * non-inherited SOURCE_GROUP commands will have precedence over
  572. * inherited ones.
  573. */
  574. cmSourceGroup&
  575. cmMakefile::FindSourceGroup(const char* source,
  576. std::vector<cmSourceGroup> &groups)
  577. {
  578. std::string file = source;
  579. std::string::size_type pos = file.rfind('/');
  580. if(pos != std::string::npos)
  581. {
  582. file = file.substr(pos, file.length()-pos);
  583. }
  584. for(std::vector<cmSourceGroup>::reverse_iterator sg = groups.rbegin();
  585. sg != groups.rend(); ++sg)
  586. {
  587. if(sg->Matches(file.c_str()))
  588. {
  589. return *sg;
  590. }
  591. }
  592. // Shouldn't get here, but just in case, return the default group.
  593. return groups.front();
  594. }
  595. bool cmMakefile::IsFunctionBlocked(const char *name,
  596. std::vector<std::string> &args) const
  597. {
  598. // loop over all function blockers to see if any block this command
  599. std::set<cmFunctionBlocker *>::const_iterator pos;
  600. for (pos = m_FunctionBlockers.begin();
  601. pos != m_FunctionBlockers.end(); ++pos)
  602. {
  603. if ((*pos)->IsFunctionBlocked(name, args, *this))
  604. {
  605. return true;
  606. }
  607. }
  608. return false;
  609. }
  610. void cmMakefile::RemoveFunctionBlocker(const char *name,
  611. const std::vector<std::string> &args)
  612. {
  613. // loop over all function blockers to see if any block this command
  614. std::set<cmFunctionBlocker *>::const_iterator pos;
  615. for (pos = m_FunctionBlockers.begin();
  616. pos != m_FunctionBlockers.end(); ++pos)
  617. {
  618. if ((*pos)->ShouldRemove(name, args, *this))
  619. {
  620. m_FunctionBlockers.erase(*pos);
  621. return;
  622. }
  623. }
  624. return;
  625. }