ENH: Return utility target after creation
[cmake.git] / Source / cmExportLibraryDependencies.cxx
blob89f96f3e3aee7e7fe61df025ec5635a988c6e862
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmExportLibraryDependencies.cxx,v $
5 Language: C++
6 Date: $Date: 2008-04-27 11:01:05 $
7 Version: $Revision: 1.23 $
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 "cmExportLibraryDependencies.h"
18 #include "cmGlobalGenerator.h"
19 #include "cmLocalGenerator.h"
20 #include "cmGeneratedFileStream.h"
21 #include "cmake.h"
22 #include "cmVersion.h"
24 #include <cmsys/auto_ptr.hxx>
26 bool cmExportLibraryDependenciesCommand
27 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
29 if(args.size() < 1 )
31 this->SetError("called with incorrect number of arguments");
32 return false;
35 // store the arguments for the final pass
36 this->Filename = args[0];
37 this->Append = false;
38 if(args.size() > 1)
40 if(args[1] == "APPEND")
42 this->Append = true;
45 return true;
49 void cmExportLibraryDependenciesCommand::FinalPass()
51 // export_library_dependencies() shouldn't modify anything
52 // ensure this by calling a const method
53 this->ConstFinalPass();
56 void cmExportLibraryDependenciesCommand::ConstFinalPass() const
58 // Use copy-if-different if not appending.
59 cmsys::auto_ptr<std::ofstream> foutPtr;
60 if(this->Append)
62 cmsys::auto_ptr<std::ofstream> ap(
63 new std::ofstream(this->Filename.c_str(), std::ios::app));
64 foutPtr = ap;
66 else
68 cmsys::auto_ptr<cmGeneratedFileStream> ap(
69 new cmGeneratedFileStream(this->Filename.c_str(), true));
70 ap->SetCopyIfDifferent(true);
71 foutPtr = ap;
73 std::ostream& fout = *foutPtr.get();
75 if (!fout)
77 cmSystemTools::Error("Error Writing ", this->Filename.c_str());
78 cmSystemTools::ReportLastSystemError("");
79 return;
82 // Collect dependency information about all library targets built in
83 // the project.
84 cmake* cm = this->Makefile->GetCMakeInstance();
85 cmGlobalGenerator* global = cm->GetGlobalGenerator();
86 const std::vector<cmLocalGenerator *>& locals = global->GetLocalGenerators();
87 std::map<cmStdString, cmStdString> libDepsOld;
88 std::map<cmStdString, cmStdString> libDepsNew;
89 std::map<cmStdString, cmStdString> libTypes;
90 for(std::vector<cmLocalGenerator *>::const_iterator i = locals.begin();
91 i != locals.end(); ++i)
93 const cmLocalGenerator* gen = *i;
94 const cmTargets &tgts = gen->GetMakefile()->GetTargets();
95 for(cmTargets::const_iterator l = tgts.begin();
96 l != tgts.end(); ++l)
98 // Get the current target.
99 cmTarget const& target = l->second;
101 // Skip non-library targets.
102 if(target.GetType() < cmTarget::STATIC_LIBRARY
103 || target.GetType() > cmTarget::MODULE_LIBRARY)
105 continue;
108 // Construct the dependency variable name.
109 std::string targetEntry = target.GetName();
110 targetEntry += "_LIB_DEPENDS";
112 // Construct the dependency variable value. It is safe to use
113 // the target GetLinkLibraries method here because this code is
114 // called at the end of configure but before generate so library
115 // dependencies have yet to be analyzed. Therefore the value
116 // will be the direct link dependencies.
117 std::string valueOld;
118 std::string valueNew;
119 cmTarget::LinkLibraryVectorType const& libs = target.GetLinkLibraries();
120 for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
121 li != libs.end(); ++li)
123 std::string ltVar = li->first;
124 ltVar += "_LINK_TYPE";
125 std::string ltValue;
126 switch(li->second)
128 case cmTarget::GENERAL:
129 valueNew += "general;";
130 ltValue = "general";
131 break;
132 case cmTarget::DEBUG:
133 valueNew += "debug;";
134 ltValue = "debug";
135 break;
136 case cmTarget::OPTIMIZED:
137 valueNew += "optimized;";
138 ltValue = "optimized";
139 break;
141 std::string lib = li->first;
142 if(cmTarget* libtgt = global->FindTarget(0, lib.c_str()))
144 // Handle simple output name changes. This command is
145 // deprecated so we do not support full target name
146 // translation (which requires per-configuration info).
147 if(const char* outname = libtgt->GetProperty("OUTPUT_NAME"))
149 lib = outname;
152 valueOld += lib;
153 valueOld += ";";
154 valueNew += lib;
155 valueNew += ";";
157 std::string& ltEntry = libTypes[ltVar];
158 if(ltEntry.empty())
160 ltEntry = ltValue;
162 else if(ltEntry != ltValue)
164 ltEntry = "general";
167 libDepsNew[targetEntry] = valueNew;
168 libDepsOld[targetEntry] = valueOld;
172 // Generate dependency information for both old and new style CMake
173 // versions.
174 const char* vertest =
175 "\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" GREATER 2.4";
176 fout << "# Generated by CMake " << cmVersion::GetCMakeVersion() << "\n\n";
177 fout << "IF(" << vertest << ")\n";
178 fout << " # Information for CMake 2.6 and above.\n";
179 for(std::map<cmStdString, cmStdString>::const_iterator
180 i = libDepsNew.begin();
181 i != libDepsNew.end(); ++i)
183 if(!i->second.empty())
185 fout << " SET(\"" << i->first << "\" \"" << i->second << "\")\n";
188 fout << "ELSE(" << vertest << ")\n";
189 fout << " # Information for CMake 2.4 and lower.\n";
190 for(std::map<cmStdString, cmStdString>::const_iterator
191 i = libDepsOld.begin();
192 i != libDepsOld.end(); ++i)
194 if(!i->second.empty())
196 fout << " SET(\"" << i->first << "\" \"" << i->second << "\")\n";
199 for(std::map<cmStdString, cmStdString>::const_iterator i = libTypes.begin();
200 i != libTypes.end(); ++i)
202 if(i->second != "general")
204 fout << " SET(\"" << i->first << "\" \"" << i->second << "\")\n";
207 fout << "ENDIF(" << vertest << ")\n";
208 return;