/src/CMake/Source/cmExtraCodeLiteGenerator.cxx
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | #include "cmExtraCodeLiteGenerator.h" |
4 | | |
5 | | #include <cstring> |
6 | | #include <map> |
7 | | #include <memory> |
8 | | #include <set> |
9 | | #include <sstream> |
10 | | #include <utility> |
11 | | |
12 | | #include "cmsys/SystemInformation.hxx" |
13 | | |
14 | | #include "cmGeneratedFileStream.h" |
15 | | #include "cmGeneratorTarget.h" |
16 | | #include "cmGlobalGenerator.h" |
17 | | #include "cmLocalGenerator.h" |
18 | | #include "cmMakefile.h" |
19 | | #include "cmSourceFile.h" |
20 | | #include "cmStateTypes.h" |
21 | | #include "cmStringAlgorithms.h" |
22 | | #include "cmSystemTools.h" |
23 | | #include "cmXMLWriter.h" |
24 | | #include "cmake.h" |
25 | | |
26 | | cmExtraCodeLiteGenerator::cmExtraCodeLiteGenerator() |
27 | 0 | : ConfigName("NoConfig") |
28 | 0 | { |
29 | 0 | } |
30 | | |
31 | | cmExternalMakefileProjectGeneratorFactory* |
32 | | cmExtraCodeLiteGenerator::GetFactory() |
33 | 35 | { |
34 | 35 | static cmExternalMakefileProjectGeneratorSimpleFactory< |
35 | 35 | cmExtraCodeLiteGenerator> |
36 | 35 | factory("CodeLite", "Generates CodeLite project files (deprecated)."); |
37 | | |
38 | 35 | if (factory.GetSupportedGlobalGenerators().empty()) { |
39 | | #if defined(_WIN32) |
40 | | factory.AddSupportedGlobalGenerator("MinGW Makefiles"); |
41 | | factory.AddSupportedGlobalGenerator("NMake Makefiles"); |
42 | | #endif |
43 | 1 | factory.AddSupportedGlobalGenerator("Ninja"); |
44 | 1 | factory.AddSupportedGlobalGenerator("Unix Makefiles"); |
45 | 1 | } |
46 | | |
47 | 35 | return &factory; |
48 | 35 | } |
49 | | |
50 | | void cmExtraCodeLiteGenerator::Generate() |
51 | 0 | { |
52 | | // Hold root tree information for creating the workspace |
53 | 0 | std::string workspaceProjectName; |
54 | 0 | std::string workspaceOutputDir; |
55 | 0 | std::string workspaceFileName; |
56 | 0 | std::string workspaceSourcePath; |
57 | |
|
58 | 0 | std::map<std::string, std::vector<cmLocalGenerator*>> const& projectMap = |
59 | 0 | this->GlobalGenerator->GetProjectMap(); |
60 | | |
61 | | // loop projects and locate the root project. |
62 | | // and extract the information for creating the workspace |
63 | | // root makefile |
64 | 0 | for (auto const& it : projectMap) { |
65 | 0 | cmLocalGenerator* lg = it.second[0]; |
66 | 0 | cmMakefile const* mf = lg->GetMakefile(); |
67 | 0 | this->ConfigName = this->GetConfigurationName(mf); |
68 | |
|
69 | 0 | if (lg->GetCurrentBinaryDirectory() == lg->GetBinaryDirectory()) { |
70 | 0 | workspaceOutputDir = lg->GetCurrentBinaryDirectory(); |
71 | 0 | workspaceProjectName = lg->GetProjectName(); |
72 | 0 | workspaceSourcePath = lg->GetSourceDirectory(); |
73 | 0 | workspaceFileName = |
74 | 0 | cmStrCat(workspaceOutputDir, '/', workspaceProjectName, ".workspace"); |
75 | 0 | this->WorkspacePath = lg->GetCurrentBinaryDirectory(); |
76 | 0 | break; |
77 | 0 | } |
78 | 0 | } |
79 | |
|
80 | 0 | cmGeneratedFileStream fout(workspaceFileName); |
81 | 0 | cmXMLWriter xml(fout); |
82 | |
|
83 | 0 | xml.StartDocument("utf-8"); |
84 | 0 | xml.StartElement("CodeLite_Workspace"); |
85 | 0 | xml.Attribute("Name", workspaceProjectName); |
86 | |
|
87 | 0 | bool const targetsAreProjects = |
88 | 0 | this->GlobalGenerator->GlobalSettingIsOn("CMAKE_CODELITE_USE_TARGETS"); |
89 | |
|
90 | 0 | std::vector<std::string> ProjectNames; |
91 | 0 | if (targetsAreProjects) { |
92 | 0 | ProjectNames = this->CreateProjectsByTarget(&xml); |
93 | 0 | } else { |
94 | 0 | ProjectNames = this->CreateProjectsByProjectMaps(&xml); |
95 | 0 | } |
96 | |
|
97 | 0 | xml.StartElement("BuildMatrix"); |
98 | 0 | xml.StartElement("WorkspaceConfiguration"); |
99 | 0 | xml.Attribute("Name", this->ConfigName); |
100 | 0 | xml.Attribute("Selected", "yes"); |
101 | |
|
102 | 0 | for (std::string const& it : ProjectNames) { |
103 | 0 | xml.StartElement("Project"); |
104 | 0 | xml.Attribute("Name", it); |
105 | 0 | xml.Attribute("ConfigName", this->ConfigName); |
106 | 0 | xml.EndElement(); |
107 | 0 | } |
108 | |
|
109 | 0 | xml.EndElement(); // WorkspaceConfiguration |
110 | 0 | xml.EndElement(); // BuildMatrix |
111 | 0 | xml.EndElement(); // CodeLite_Workspace |
112 | 0 | } |
113 | | |
114 | | // Create projects where targets are the projects |
115 | | std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget( |
116 | | cmXMLWriter* xml) |
117 | 0 | { |
118 | 0 | std::vector<std::string> retval; |
119 | | // for each target in the workspace create a codelite project |
120 | 0 | auto const& lgs = this->GlobalGenerator->GetLocalGenerators(); |
121 | 0 | for (auto const& lg : lgs) { |
122 | 0 | for (auto const& lt : lg->GetGeneratorTargets()) { |
123 | 0 | cmStateEnums::TargetType type = lt->GetType(); |
124 | 0 | std::string const& outputDir = lg->GetCurrentBinaryDirectory(); |
125 | 0 | std::string targetName = lt->GetName(); |
126 | 0 | std::string filename = cmStrCat(outputDir, '/', targetName, ".project"); |
127 | 0 | retval.push_back(targetName); |
128 | | // Make the project file relative to the workspace |
129 | 0 | std::string relafilename = |
130 | 0 | cmSystemTools::RelativePath(this->WorkspacePath, filename); |
131 | 0 | std::string visualname = targetName; |
132 | 0 | switch (type) { |
133 | 0 | case cmStateEnums::SHARED_LIBRARY: |
134 | 0 | case cmStateEnums::STATIC_LIBRARY: |
135 | 0 | case cmStateEnums::MODULE_LIBRARY: |
136 | 0 | visualname = cmStrCat("lib", visualname); |
137 | 0 | CM_FALLTHROUGH; |
138 | 0 | case cmStateEnums::EXECUTABLE: |
139 | 0 | xml->StartElement("Project"); |
140 | 0 | xml->Attribute("Name", visualname); |
141 | 0 | xml->Attribute("Path", relafilename); |
142 | 0 | xml->Attribute("Active", "No"); |
143 | 0 | xml->EndElement(); |
144 | |
|
145 | 0 | this->CreateNewProjectFile(lt.get(), filename); |
146 | 0 | break; |
147 | 0 | default: |
148 | 0 | break; |
149 | 0 | } |
150 | 0 | } |
151 | 0 | } |
152 | 0 | return retval; |
153 | 0 | } |
154 | | |
155 | | // The "older way of doing it. |
156 | | std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByProjectMaps( |
157 | | cmXMLWriter* xml) |
158 | 0 | { |
159 | 0 | std::vector<std::string> retval; |
160 | | // for each sub project in the workspace create a codelite project |
161 | 0 | for (auto const& it : this->GlobalGenerator->GetProjectMap()) { |
162 | |
|
163 | 0 | std::string const& outputDir = it.second[0]->GetCurrentBinaryDirectory(); |
164 | 0 | std::string projectName = it.second[0]->GetProjectName(); |
165 | 0 | retval.push_back(projectName); |
166 | 0 | std::string filename = cmStrCat(outputDir, '/', projectName, ".project"); |
167 | | |
168 | | // Make the project file relative to the workspace |
169 | 0 | filename = cmSystemTools::RelativePath(this->WorkspacePath, filename); |
170 | | |
171 | | // create a project file |
172 | 0 | this->CreateProjectFile(it.second); |
173 | 0 | xml->StartElement("Project"); |
174 | 0 | xml->Attribute("Name", projectName); |
175 | 0 | xml->Attribute("Path", filename); |
176 | 0 | xml->Attribute("Active", "No"); |
177 | 0 | xml->EndElement(); |
178 | 0 | } |
179 | 0 | return retval; |
180 | 0 | } |
181 | | |
182 | | /* create the project file */ |
183 | | void cmExtraCodeLiteGenerator::CreateProjectFile( |
184 | | std::vector<cmLocalGenerator*> const& lgs) |
185 | 0 | { |
186 | 0 | std::string const& outputDir = lgs[0]->GetCurrentBinaryDirectory(); |
187 | 0 | std::string projectName = lgs[0]->GetProjectName(); |
188 | 0 | std::string filename = cmStrCat(outputDir, '/', projectName, ".project"); |
189 | |
|
190 | 0 | this->CreateNewProjectFile(lgs, filename); |
191 | 0 | } |
192 | | |
193 | | std::string cmExtraCodeLiteGenerator::CollectSourceFiles( |
194 | | cmMakefile const* makefile, cmGeneratorTarget const* gt, |
195 | | std::map<std::string, cmSourceFile*>& cFiles, |
196 | | std::set<std::string>& otherFiles) |
197 | 0 | { |
198 | 0 | std::string projectType; |
199 | 0 | switch (gt->GetType()) { |
200 | 0 | case cmStateEnums::EXECUTABLE: { |
201 | 0 | projectType = "Executable"; |
202 | 0 | } break; |
203 | 0 | case cmStateEnums::STATIC_LIBRARY: { |
204 | 0 | projectType = "Static Library"; |
205 | 0 | } break; |
206 | 0 | case cmStateEnums::SHARED_LIBRARY: |
207 | 0 | case cmStateEnums::MODULE_LIBRARY: { |
208 | 0 | projectType = "Dynamic Library"; |
209 | 0 | } break; |
210 | 0 | default: |
211 | 0 | break; |
212 | 0 | } |
213 | | |
214 | 0 | switch (gt->GetType()) { |
215 | 0 | case cmStateEnums::EXECUTABLE: |
216 | 0 | case cmStateEnums::STATIC_LIBRARY: |
217 | 0 | case cmStateEnums::SHARED_LIBRARY: |
218 | 0 | case cmStateEnums::MODULE_LIBRARY: { |
219 | 0 | cmake const* cm = makefile->GetCMakeInstance(); |
220 | 0 | std::vector<cmSourceFile*> sources; |
221 | 0 | gt->GetSourceFiles(sources, |
222 | 0 | makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); |
223 | 0 | for (cmSourceFile* s : sources) { |
224 | 0 | std::string const& fullPath = s->ResolveFullPath(); |
225 | 0 | std::string const& extLower = |
226 | 0 | cmSystemTools::LowerCase(s->GetExtension()); |
227 | | // check whether it is a source or a include file |
228 | | // then put it accordingly into one of the two containers |
229 | 0 | if (cm->IsAKnownSourceExtension(extLower)) { |
230 | 0 | cFiles[fullPath] = s; |
231 | 0 | } else { |
232 | 0 | otherFiles.insert(fullPath); |
233 | 0 | } |
234 | 0 | } |
235 | 0 | } break; |
236 | 0 | default: |
237 | 0 | break; |
238 | 0 | } |
239 | 0 | return projectType; |
240 | 0 | } |
241 | | |
242 | | void cmExtraCodeLiteGenerator::CreateNewProjectFile( |
243 | | std::vector<cmLocalGenerator*> const& lgs, std::string const& filename) |
244 | 0 | { |
245 | 0 | cmMakefile const* mf = lgs[0]->GetMakefile(); |
246 | 0 | cmGeneratedFileStream fout(filename); |
247 | 0 | if (!fout) { |
248 | 0 | return; |
249 | 0 | } |
250 | 0 | cmXMLWriter xml(fout); |
251 | | |
252 | | //////////////////////////////////// |
253 | 0 | xml.StartDocument("utf-8"); |
254 | 0 | xml.StartElement("CodeLite_Project"); |
255 | 0 | xml.Attribute("Name", lgs[0]->GetProjectName()); |
256 | 0 | xml.Attribute("InternalType", ""); |
257 | |
|
258 | 0 | std::string projectType; |
259 | | |
260 | | // Collect all used source files in the project |
261 | | // Sort them into two containers, one for C/C++ implementation files |
262 | | // which may have an accompanying header, one for all other files |
263 | 0 | std::map<std::string, cmSourceFile*> cFiles; |
264 | 0 | std::set<std::string> otherFiles; |
265 | |
|
266 | 0 | for (cmLocalGenerator* lg : lgs) { |
267 | 0 | cmMakefile* makefile = lg->GetMakefile(); |
268 | 0 | for (auto const& target : lg->GetGeneratorTargets()) { |
269 | 0 | projectType = |
270 | 0 | this->CollectSourceFiles(makefile, target.get(), cFiles, otherFiles); |
271 | 0 | } |
272 | 0 | } |
273 | | |
274 | | // Get the project path ( we need it later to convert files to |
275 | | // their relative path) |
276 | 0 | std::string projectPath = cmSystemTools::GetFilenamePath(filename); |
277 | |
|
278 | 0 | this->CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf, |
279 | 0 | projectType, ""); |
280 | |
|
281 | 0 | xml.EndElement(); // CodeLite_Project |
282 | 0 | } |
283 | | |
284 | | void cmExtraCodeLiteGenerator::FindMatchingHeaderfiles( |
285 | | std::map<std::string, cmSourceFile*>& cFiles, |
286 | | std::set<std::string>& otherFiles) |
287 | 0 | { |
288 | |
|
289 | 0 | std::vector<std::string> const& headerExts = |
290 | 0 | this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions(); |
291 | | |
292 | | // The following loop tries to add header files matching to implementation |
293 | | // files to the project. It does that by iterating over all source files, |
294 | | // replacing the file name extension with ".h" and checks whether such a |
295 | | // file exists. If it does, it is inserted into the map of files. |
296 | | // A very similar version of that code exists also in the CodeBlocks |
297 | | // project generator. |
298 | 0 | for (auto const& sit : cFiles) { |
299 | 0 | std::string headerBasename = |
300 | 0 | cmStrCat(cmSystemTools::GetFilenamePath(sit.first), '/', |
301 | 0 | cmSystemTools::GetFilenameWithoutExtension(sit.first)); |
302 | | |
303 | | // check if there's a matching header around |
304 | 0 | for (std::string const& ext : headerExts) { |
305 | 0 | std::string hname = cmStrCat(headerBasename, '.', ext); |
306 | | // if it's already in the set, don't check if it exists on disk |
307 | 0 | auto headerIt = otherFiles.find(hname); |
308 | 0 | if (headerIt != otherFiles.end()) { |
309 | 0 | break; |
310 | 0 | } |
311 | | |
312 | 0 | if (cmSystemTools::FileExists(hname)) { |
313 | 0 | otherFiles.insert(hname); |
314 | 0 | break; |
315 | 0 | } |
316 | 0 | } |
317 | 0 | } |
318 | 0 | } |
319 | | |
320 | | void cmExtraCodeLiteGenerator::CreateFoldersAndFiles( |
321 | | std::set<std::string>& cFiles, cmXMLWriter& xml, |
322 | | std::string const& projectPath) |
323 | 0 | { |
324 | 0 | std::vector<std::string> tmp_path; |
325 | 0 | std::vector<std::string> components; |
326 | 0 | size_t numOfEndEl = 0; |
327 | |
|
328 | 0 | for (std::string const& cFile : cFiles) { |
329 | 0 | std::string frelapath = cmSystemTools::RelativePath(projectPath, cFile); |
330 | 0 | cmsys::SystemTools::SplitPath(frelapath, components, false); |
331 | 0 | components.pop_back(); // erase last member -> it is file, not folder |
332 | 0 | components.erase(components.begin()); // erase "root" |
333 | |
|
334 | 0 | size_t sizeOfSkip = 0; |
335 | |
|
336 | 0 | for (size_t i = 0; i < components.size(); ++i) { |
337 | | // skip relative path |
338 | 0 | if (components[i] == ".." || components[i] == ".") { |
339 | 0 | sizeOfSkip++; |
340 | 0 | continue; |
341 | 0 | } |
342 | | |
343 | | // same folder |
344 | 0 | if (tmp_path.size() > i - sizeOfSkip && |
345 | 0 | tmp_path[i - sizeOfSkip] == components[i]) { |
346 | 0 | continue; |
347 | 0 | } |
348 | | |
349 | | // delete "old" subfolders |
350 | 0 | if (tmp_path.size() > i - sizeOfSkip) { |
351 | 0 | numOfEndEl = tmp_path.size() - i + sizeOfSkip; |
352 | 0 | tmp_path.erase(tmp_path.end() - numOfEndEl, tmp_path.end()); |
353 | 0 | for (; numOfEndEl--;) { |
354 | 0 | xml.EndElement(); |
355 | 0 | } |
356 | 0 | } |
357 | | |
358 | | // add folder |
359 | 0 | xml.StartElement("VirtualDirectory"); |
360 | 0 | xml.Attribute("Name", components[i]); |
361 | 0 | tmp_path.push_back(components[i]); |
362 | 0 | } |
363 | | |
364 | | // delete "old" subfolders |
365 | 0 | numOfEndEl = tmp_path.size() - components.size() + sizeOfSkip; |
366 | 0 | if (numOfEndEl) { |
367 | 0 | tmp_path.erase(tmp_path.end() - numOfEndEl, tmp_path.end()); |
368 | 0 | for (; numOfEndEl--;) { |
369 | 0 | xml.EndElement(); |
370 | 0 | } |
371 | 0 | } |
372 | | |
373 | | // add file |
374 | 0 | xml.StartElement("File"); |
375 | 0 | xml.Attribute("Name", frelapath); |
376 | 0 | xml.EndElement(); |
377 | 0 | } |
378 | | |
379 | | // end of folders |
380 | 0 | numOfEndEl = tmp_path.size(); |
381 | 0 | for (; numOfEndEl--;) { |
382 | 0 | xml.EndElement(); |
383 | 0 | } |
384 | 0 | } |
385 | | |
386 | | void cmExtraCodeLiteGenerator::CreateFoldersAndFiles( |
387 | | std::map<std::string, cmSourceFile*>& cFiles, cmXMLWriter& xml, |
388 | | std::string const& projectPath) |
389 | 0 | { |
390 | 0 | std::set<std::string> s; |
391 | 0 | for (auto const& it : cFiles) { |
392 | 0 | s.insert(it.first); |
393 | 0 | } |
394 | 0 | this->CreateFoldersAndFiles(s, xml, projectPath); |
395 | 0 | } |
396 | | |
397 | | void cmExtraCodeLiteGenerator::CreateProjectSourceEntries( |
398 | | std::map<std::string, cmSourceFile*>& cFiles, |
399 | | std::set<std::string>& otherFiles, cmXMLWriter* _xml, |
400 | | std::string const& projectPath, cmMakefile const* mf, |
401 | | std::string const& projectType, std::string const& targetName) |
402 | 0 | { |
403 | 0 | cmXMLWriter& xml(*_xml); |
404 | 0 | this->FindMatchingHeaderfiles(cFiles, otherFiles); |
405 | | // Create 2 virtual folders: src and include |
406 | | // and place all the implementation files into the src |
407 | | // folder, the rest goes to the include folder |
408 | 0 | xml.StartElement("VirtualDirectory"); |
409 | 0 | xml.Attribute("Name", "src"); |
410 | | |
411 | | // insert all source files in the codelite project |
412 | | // first the C/C++ implementation files, then all others |
413 | 0 | this->CreateFoldersAndFiles(cFiles, xml, projectPath); |
414 | 0 | xml.EndElement(); // VirtualDirectory |
415 | |
|
416 | 0 | xml.StartElement("VirtualDirectory"); |
417 | 0 | xml.Attribute("Name", "include"); |
418 | 0 | this->CreateFoldersAndFiles(otherFiles, xml, projectPath); |
419 | 0 | xml.EndElement(); // VirtualDirectory |
420 | | |
421 | | // Get the number of CPUs. We use this information for the make -jN |
422 | | // command |
423 | 0 | cmsys::SystemInformation info; |
424 | 0 | info.RunCPUCheck(); |
425 | |
|
426 | 0 | this->CpuCount = |
427 | 0 | info.GetNumberOfLogicalCPU() * info.GetNumberOfPhysicalCPU(); |
428 | |
|
429 | 0 | std::string codeliteCompilerName = this->GetCodeLiteCompilerName(mf); |
430 | |
|
431 | 0 | xml.StartElement("Settings"); |
432 | 0 | xml.Attribute("Type", projectType); |
433 | |
|
434 | 0 | xml.StartElement("Configuration"); |
435 | 0 | xml.Attribute("Name", this->ConfigName); |
436 | 0 | xml.Attribute("CompilerType", this->GetCodeLiteCompilerName(mf)); |
437 | 0 | xml.Attribute("DebuggerType", "GNU gdb debugger"); |
438 | 0 | xml.Attribute("Type", projectType); |
439 | 0 | xml.Attribute("BuildCmpWithGlobalSettings", "append"); |
440 | 0 | xml.Attribute("BuildLnkWithGlobalSettings", "append"); |
441 | 0 | xml.Attribute("BuildResWithGlobalSettings", "append"); |
442 | |
|
443 | 0 | xml.StartElement("Compiler"); |
444 | 0 | xml.Attribute("Options", "-g"); |
445 | 0 | xml.Attribute("Required", "yes"); |
446 | 0 | xml.Attribute("PreCompiledHeader", ""); |
447 | 0 | xml.StartElement("IncludePath"); |
448 | 0 | xml.Attribute("Value", "."); |
449 | 0 | xml.EndElement(); // IncludePath |
450 | 0 | xml.EndElement(); // Compiler |
451 | |
|
452 | 0 | xml.StartElement("Linker"); |
453 | 0 | xml.Attribute("Options", ""); |
454 | 0 | xml.Attribute("Required", "yes"); |
455 | 0 | xml.EndElement(); // Linker |
456 | |
|
457 | 0 | xml.StartElement("ResourceCompiler"); |
458 | 0 | xml.Attribute("Options", ""); |
459 | 0 | xml.Attribute("Required", "no"); |
460 | 0 | xml.EndElement(); // ResourceCompiler |
461 | |
|
462 | 0 | xml.StartElement("General"); |
463 | 0 | std::string outputPath = |
464 | 0 | mf->GetSafeDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY"); |
465 | 0 | if (outputPath.empty()) { |
466 | 0 | outputPath = mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH"); |
467 | 0 | } |
468 | 0 | std::string relapath; |
469 | 0 | if (!outputPath.empty()) { |
470 | 0 | relapath = cmSystemTools::RelativePath(projectPath, outputPath); |
471 | 0 | xml.Attribute("OutputFile", relapath + "/$(ProjectName)"); |
472 | 0 | } else { |
473 | 0 | xml.Attribute("OutputFile", "$(IntermediateDirectory)/$(ProjectName)"); |
474 | 0 | } |
475 | 0 | xml.Attribute("IntermediateDirectory", "./"); |
476 | 0 | xml.Attribute("Command", "./$(ProjectName)"); |
477 | 0 | xml.Attribute("CommandArguments", ""); |
478 | 0 | if (!outputPath.empty()) { |
479 | 0 | xml.Attribute("WorkingDirectory", relapath); |
480 | 0 | } else { |
481 | 0 | xml.Attribute("WorkingDirectory", "$(IntermediateDirectory)"); |
482 | 0 | } |
483 | 0 | xml.Attribute("PauseExecWhenProcTerminates", "yes"); |
484 | 0 | xml.EndElement(); // General |
485 | |
|
486 | 0 | xml.StartElement("Debugger"); |
487 | 0 | xml.Attribute("IsRemote", "no"); |
488 | 0 | xml.Attribute("RemoteHostName", ""); |
489 | 0 | xml.Attribute("RemoteHostPort", ""); |
490 | 0 | xml.Attribute("DebuggerPath", ""); |
491 | 0 | xml.Element("PostConnectCommands"); |
492 | 0 | xml.Element("StartupCommands"); |
493 | 0 | xml.EndElement(); // Debugger |
494 | |
|
495 | 0 | xml.Element("PreBuild"); |
496 | 0 | xml.Element("PostBuild"); |
497 | |
|
498 | 0 | xml.StartElement("CustomBuild"); |
499 | 0 | xml.Attribute("Enabled", "yes"); |
500 | 0 | xml.Element("RebuildCommand", this->GetRebuildCommand(mf, targetName)); |
501 | 0 | xml.Element("CleanCommand", this->GetCleanCommand(mf, targetName)); |
502 | 0 | xml.Element("BuildCommand", this->GetBuildCommand(mf, targetName)); |
503 | 0 | xml.Element("SingleFileCommand", this->GetSingleFileBuildCommand(mf)); |
504 | 0 | xml.Element("PreprocessFileCommand"); |
505 | 0 | xml.Element("WorkingDirectory", "$(WorkspacePath)"); |
506 | 0 | xml.EndElement(); // CustomBuild |
507 | |
|
508 | 0 | xml.StartElement("AdditionalRules"); |
509 | 0 | xml.Element("CustomPostBuild"); |
510 | 0 | xml.Element("CustomPreBuild"); |
511 | 0 | xml.EndElement(); // AdditionalRules |
512 | |
|
513 | 0 | xml.EndElement(); // Configuration |
514 | 0 | xml.StartElement("GlobalSettings"); |
515 | |
|
516 | 0 | xml.StartElement("Compiler"); |
517 | 0 | xml.Attribute("Options", ""); |
518 | 0 | xml.StartElement("IncludePath"); |
519 | 0 | xml.Attribute("Value", "."); |
520 | 0 | xml.EndElement(); // IncludePath |
521 | 0 | xml.EndElement(); // Compiler |
522 | |
|
523 | 0 | xml.StartElement("Linker"); |
524 | 0 | xml.Attribute("Options", ""); |
525 | 0 | xml.StartElement("LibraryPath"); |
526 | 0 | xml.Attribute("Value", "."); |
527 | 0 | xml.EndElement(); // LibraryPath |
528 | 0 | xml.EndElement(); // Linker |
529 | |
|
530 | 0 | xml.StartElement("ResourceCompiler"); |
531 | 0 | xml.Attribute("Options", ""); |
532 | 0 | xml.EndElement(); // ResourceCompiler |
533 | |
|
534 | 0 | xml.EndElement(); // GlobalSettings |
535 | 0 | xml.EndElement(); // Settings |
536 | 0 | } |
537 | | |
538 | | void cmExtraCodeLiteGenerator::CreateNewProjectFile( |
539 | | cmGeneratorTarget const* gt, std::string const& filename) |
540 | 0 | { |
541 | 0 | cmMakefile const* mf = gt->Makefile; |
542 | 0 | cmGeneratedFileStream fout(filename); |
543 | 0 | if (!fout) { |
544 | 0 | return; |
545 | 0 | } |
546 | 0 | cmXMLWriter xml(fout); |
547 | | |
548 | | //////////////////////////////////// |
549 | 0 | xml.StartDocument("utf-8"); |
550 | 0 | xml.StartElement("CodeLite_Project"); |
551 | 0 | std::string targetName = gt->GetName(); |
552 | 0 | std::string visualname = targetName; |
553 | 0 | switch (gt->GetType()) { |
554 | 0 | case cmStateEnums::STATIC_LIBRARY: |
555 | 0 | case cmStateEnums::SHARED_LIBRARY: |
556 | 0 | case cmStateEnums::MODULE_LIBRARY: |
557 | 0 | visualname = "lib" + targetName; |
558 | 0 | break; |
559 | 0 | default: |
560 | 0 | break; |
561 | 0 | } |
562 | 0 | xml.Attribute("Name", visualname); |
563 | 0 | xml.Attribute("InternalType", ""); |
564 | | |
565 | | // Collect all used source files in the project |
566 | | // Sort them into two containers, one for C/C++ implementation files |
567 | | // which may have an accompanying header, one for all other files |
568 | 0 | std::string projectType; |
569 | |
|
570 | 0 | std::map<std::string, cmSourceFile*> cFiles; |
571 | 0 | std::set<std::string> otherFiles; |
572 | |
|
573 | 0 | projectType = this->CollectSourceFiles(mf, gt, cFiles, otherFiles); |
574 | | |
575 | | // Get the project path ( we need it later to convert files to |
576 | | // their relative path) |
577 | 0 | std::string projectPath = cmSystemTools::GetFilenamePath(filename); |
578 | |
|
579 | 0 | this->CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf, |
580 | 0 | projectType, targetName); |
581 | |
|
582 | 0 | xml.EndElement(); // CodeLite_Project |
583 | 0 | } |
584 | | |
585 | | std::string cmExtraCodeLiteGenerator::GetCodeLiteCompilerName( |
586 | | cmMakefile const* mf) const |
587 | 0 | { |
588 | | // figure out which language to use |
589 | | // for now care only for C and C++ |
590 | 0 | std::string compilerIdVar = "CMAKE_CXX_COMPILER_ID"; |
591 | 0 | if (!this->GlobalGenerator->GetLanguageEnabled("CXX")) { |
592 | 0 | compilerIdVar = "CMAKE_C_COMPILER_ID"; |
593 | 0 | } |
594 | |
|
595 | 0 | std::string const& compilerId = mf->GetSafeDefinition(compilerIdVar); |
596 | 0 | std::string compiler = "gnu g++"; // default to g++ |
597 | | |
598 | | // Since we need the compiler for parsing purposes only |
599 | | // it does not matter if we use clang or clang++, same as |
600 | | // "gnu gcc" vs "gnu g++" |
601 | 0 | if (compilerId == "MSVC") { |
602 | 0 | compiler = "VC++"; |
603 | 0 | } else if (compilerId == "Clang") { |
604 | 0 | compiler = "clang++"; |
605 | 0 | } else if (compilerId == "GNU") { |
606 | 0 | compiler = "gnu g++"; |
607 | 0 | } |
608 | 0 | return compiler; |
609 | 0 | } |
610 | | |
611 | | std::string cmExtraCodeLiteGenerator::GetConfigurationName( |
612 | | cmMakefile const* mf) const |
613 | 0 | { |
614 | 0 | std::string confName = mf->GetSafeDefinition("CMAKE_BUILD_TYPE"); |
615 | | // Trim the configuration name from whitespaces (left and right) |
616 | 0 | confName.erase(0, confName.find_first_not_of(" \t\r\v\n")); |
617 | 0 | confName.erase(confName.find_last_not_of(" \t\r\v\n") + 1); |
618 | 0 | if (confName.empty()) { |
619 | 0 | confName = "NoConfig"; |
620 | 0 | } |
621 | 0 | return confName; |
622 | 0 | } |
623 | | |
624 | | std::string cmExtraCodeLiteGenerator::GetBuildCommand( |
625 | | cmMakefile const* mf, std::string const& targetName) const |
626 | 0 | { |
627 | 0 | std::string const& generator = mf->GetSafeDefinition("CMAKE_GENERATOR"); |
628 | 0 | std::string const& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); |
629 | 0 | std::string buildCommand = make; // Default |
630 | 0 | std::ostringstream ss; |
631 | 0 | if (generator == "NMake Makefiles" || generator == "Ninja") { |
632 | 0 | ss << make; |
633 | 0 | } else if (generator == "MinGW Makefiles" || generator == "Unix Makefiles") { |
634 | 0 | ss << make << " -f$(ProjectPath)/Makefile"; |
635 | 0 | if (this->CpuCount > 0) { |
636 | 0 | ss << " -j " << this->CpuCount; |
637 | 0 | } |
638 | 0 | } |
639 | 0 | if (!targetName.empty()) { |
640 | 0 | ss << " " << targetName; |
641 | 0 | } |
642 | 0 | buildCommand = ss.str(); |
643 | 0 | return buildCommand; |
644 | 0 | } |
645 | | |
646 | | std::string cmExtraCodeLiteGenerator::GetCleanCommand( |
647 | | cmMakefile const* mf, std::string const& targetName) const |
648 | 0 | { |
649 | 0 | std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR"); |
650 | 0 | std::ostringstream ss; |
651 | 0 | std::string buildcommand = this->GetBuildCommand(mf, ""); |
652 | 0 | if (!targetName.empty() && generator == "Ninja") { |
653 | 0 | ss << buildcommand << " -t clean " << targetName; |
654 | 0 | } else { |
655 | 0 | ss << buildcommand << " clean"; |
656 | 0 | } |
657 | 0 | return ss.str(); |
658 | 0 | } |
659 | | |
660 | | std::string cmExtraCodeLiteGenerator::GetRebuildCommand( |
661 | | cmMakefile const* mf, std::string const& targetName) const |
662 | 0 | { |
663 | 0 | return cmStrCat(this->GetCleanCommand(mf, targetName), " && ", |
664 | 0 | this->GetBuildCommand(mf, targetName)); |
665 | 0 | } |
666 | | |
667 | | std::string cmExtraCodeLiteGenerator::GetSingleFileBuildCommand( |
668 | | cmMakefile const* mf) const |
669 | 0 | { |
670 | 0 | std::string buildCommand; |
671 | 0 | std::string const& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); |
672 | 0 | std::string const& generator = mf->GetSafeDefinition("CMAKE_GENERATOR"); |
673 | 0 | if (generator == "Unix Makefiles" || generator == "MinGW Makefiles") { |
674 | 0 | std::ostringstream ss; |
675 | | #if defined(_WIN32) |
676 | | ss << make << " -f$(ProjectPath)/Makefile -B $(CurrentFileFullName).obj"; |
677 | | #else |
678 | 0 | ss << make << " -f$(ProjectPath)/Makefile -B $(CurrentFileFullName).o"; |
679 | 0 | #endif |
680 | 0 | buildCommand = ss.str(); |
681 | 0 | } |
682 | 0 | return buildCommand; |
683 | 0 | } |