Merge branch 'release-3.29'
[kiteware-cmake.git] / Source / cmExtraCodeBlocksGenerator.cxx
blob8d7f33e7ef62c40206b8caa0df3826f8cb090df1
1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmExtraCodeBlocksGenerator.h"
5 #include <map>
6 #include <memory>
7 #include <ostream>
8 #include <set>
9 #include <utility>
11 #include <cmext/algorithm>
13 #include "cmAlgorithms.h"
14 #include "cmGeneratedFileStream.h"
15 #include "cmGeneratorTarget.h"
16 #include "cmGlobalGenerator.h"
17 #include "cmList.h"
18 #include "cmLocalGenerator.h"
19 #include "cmMakefile.h"
20 #include "cmRange.h"
21 #include "cmSourceFile.h"
22 #include "cmStateTypes.h"
23 #include "cmStringAlgorithms.h"
24 #include "cmSystemTools.h"
25 #include "cmValue.h"
26 #include "cmXMLWriter.h"
27 #include "cmake.h"
29 /* Some useful URLs:
30 Homepage:
31 http://www.codeblocks.org
33 File format docs:
34 http://wiki.codeblocks.org/index.php?title=File_formats_description
35 http://wiki.codeblocks.org/index.php?title=Workspace_file
36 http://wiki.codeblocks.org/index.php?title=Project_file
38 Discussion:
39 http://forums.codeblocks.org/index.php/topic,6789.0.html
42 cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator() = default;
44 cmExternalMakefileProjectGeneratorFactory*
45 cmExtraCodeBlocksGenerator::GetFactory()
47 static cmExternalMakefileProjectGeneratorSimpleFactory<
48 cmExtraCodeBlocksGenerator>
49 factory("CodeBlocks", "Generates CodeBlocks project files (deprecated).");
51 if (factory.GetSupportedGlobalGenerators().empty()) {
52 #if defined(_WIN32)
53 factory.AddSupportedGlobalGenerator("MinGW Makefiles");
54 factory.AddSupportedGlobalGenerator("NMake Makefiles");
55 factory.AddSupportedGlobalGenerator("NMake Makefiles JOM");
56 // disable until somebody actually tests it:
57 // this->AddSupportedGlobalGenerator("MSYS Makefiles");
58 #endif
59 factory.AddSupportedGlobalGenerator("Ninja");
60 factory.AddSupportedGlobalGenerator("Unix Makefiles");
63 return &factory;
66 void cmExtraCodeBlocksGenerator::Generate()
68 // for each sub project in the project create a codeblocks project
69 for (auto const& it : this->GlobalGenerator->GetProjectMap()) {
70 // create a project file
71 this->CreateProjectFile(it.second);
75 /* create the project file */
76 void cmExtraCodeBlocksGenerator::CreateProjectFile(
77 const std::vector<cmLocalGenerator*>& lgs)
79 std::string outputDir = lgs[0]->GetCurrentBinaryDirectory();
80 std::string projectName = lgs[0]->GetProjectName();
82 std::string filename = cmStrCat(outputDir, '/', projectName, ".cbp");
83 std::string sessionFilename =
84 cmStrCat(outputDir, '/', projectName, ".layout");
86 this->CreateNewProjectFile(lgs, filename);
89 /* Tree is used to create a "Virtual Folder" in CodeBlocks, in which all
90 CMake files this project depends on will be put. This means additionally
91 to the "Sources" and "Headers" virtual folders of CodeBlocks, there will
92 now also be a "CMake Files" virtual folder.
93 Patch by Daniel Teske <daniel.teske AT nokia.com> (which use C::B project
94 files in QtCreator).*/
95 struct Tree
97 std::string path; // only one component of the path
98 std::vector<Tree> folders;
99 std::set<std::string> files;
100 void InsertPath(const std::vector<std::string>& split,
101 std::vector<std::string>::size_type start,
102 const std::string& fileName);
103 void BuildVirtualFolder(cmXMLWriter& xml) const;
104 void BuildVirtualFolderImpl(std::string& virtualFolders,
105 const std::string& prefix) const;
106 void BuildUnit(cmXMLWriter& xml, const std::string& fsPath) const;
107 void BuildUnitImpl(cmXMLWriter& xml, const std::string& virtualFolderPath,
108 const std::string& fsPath) const;
111 void Tree::InsertPath(const std::vector<std::string>& split,
112 std::vector<std::string>::size_type start,
113 const std::string& fileName)
115 if (start == split.size()) {
116 this->files.insert(fileName);
117 return;
119 for (Tree& folder : this->folders) {
120 if (folder.path == split[start]) {
121 if (start + 1 < split.size()) {
122 folder.InsertPath(split, start + 1, fileName);
123 return;
125 // last part of split
126 folder.files.insert(fileName);
127 return;
130 // Not found in folders, thus insert
131 Tree newFolder;
132 newFolder.path = split[start];
133 if (start + 1 < split.size()) {
134 newFolder.InsertPath(split, start + 1, fileName);
135 this->folders.push_back(newFolder);
136 return;
138 // last part of split
139 newFolder.files.insert(fileName);
140 this->folders.push_back(newFolder);
143 void Tree::BuildVirtualFolder(cmXMLWriter& xml) const
145 xml.StartElement("Option");
146 std::string virtualFolders = "CMake Files\\;";
147 for (Tree const& folder : this->folders) {
148 folder.BuildVirtualFolderImpl(virtualFolders, "");
150 xml.Attribute("virtualFolders", virtualFolders);
151 xml.EndElement();
154 void Tree::BuildVirtualFolderImpl(std::string& virtualFolders,
155 const std::string& prefix) const
157 virtualFolders += "CMake Files\\" + prefix + this->path + "\\;";
158 for (Tree const& folder : this->folders) {
159 folder.BuildVirtualFolderImpl(virtualFolders, prefix + this->path + "\\");
163 void Tree::BuildUnit(cmXMLWriter& xml, const std::string& fsPath) const
165 for (std::string const& f : this->files) {
166 xml.StartElement("Unit");
167 xml.Attribute("filename", fsPath + f);
169 xml.StartElement("Option");
170 xml.Attribute("virtualFolder", "CMake Files\\");
171 xml.EndElement();
173 xml.EndElement();
175 for (Tree const& folder : this->folders) {
176 folder.BuildUnitImpl(xml, "", fsPath);
180 void Tree::BuildUnitImpl(cmXMLWriter& xml,
181 const std::string& virtualFolderPath,
182 const std::string& fsPath) const
184 for (std::string const& f : this->files) {
185 xml.StartElement("Unit");
186 xml.Attribute("filename", cmStrCat(fsPath, this->path, "/", f));
188 xml.StartElement("Option");
189 xml.Attribute(
190 "virtualFolder",
191 cmStrCat("CMake Files\\", virtualFolderPath, this->path, "\\"));
192 xml.EndElement();
194 xml.EndElement();
196 for (Tree const& folder : this->folders) {
197 folder.BuildUnitImpl(xml, cmStrCat(virtualFolderPath, this->path, "\\"),
198 cmStrCat(fsPath, this->path, "/"));
202 void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
203 const std::vector<cmLocalGenerator*>& lgs, const std::string& filename)
205 const cmMakefile* mf = lgs[0]->GetMakefile();
206 cmGeneratedFileStream fout(filename);
207 if (!fout) {
208 return;
211 Tree tree;
213 // build tree of virtual folders
214 for (auto const& it : this->GlobalGenerator->GetProjectMap()) {
215 // Collect all files
216 std::vector<std::string> listFiles;
217 for (cmLocalGenerator* lg : it.second) {
218 cm::append(listFiles, lg->GetMakefile()->GetListFiles());
221 // Convert
222 for (std::string const& listFile : listFiles) {
223 // don't put cmake's own files into the project (#12110):
224 if (cmHasPrefix(listFile, cmSystemTools::GetCMakeRoot())) {
225 continue;
228 const std::string& relative = cmSystemTools::RelativePath(
229 it.second[0]->GetSourceDirectory(), listFile);
230 std::vector<std::string> split;
231 cmSystemTools::SplitPath(relative, split, false);
232 // Split filename from path
233 std::string fileName = *(split.end() - 1);
234 split.erase(split.end() - 1, split.end());
236 // We don't want paths with CMakeFiles in them
237 // or do we?
238 // In speedcrunch those where purely internal
240 // Also we can disable external (outside the project) files by setting ON
241 // CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES variable.
242 const bool excludeExternal = it.second[0]->GetMakefile()->IsOn(
243 "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES");
244 if (!split.empty() &&
245 (!excludeExternal || (relative.find("..") == std::string::npos)) &&
246 relative.find("CMakeFiles") == std::string::npos) {
247 tree.InsertPath(split, 1, fileName);
252 // figure out the compiler
253 std::string compiler = this->GetCBCompilerId(mf);
254 const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
255 const std::string& makeArgs =
256 mf->GetSafeDefinition("CMAKE_CODEBLOCKS_MAKE_ARGUMENTS");
258 cmXMLWriter xml(fout);
259 xml.StartDocument();
260 xml.StartElement("CodeBlocks_project_file");
262 xml.StartElement("FileVersion");
263 xml.Attribute("major", 1);
264 xml.Attribute("minor", 6);
265 xml.EndElement();
267 xml.StartElement("Project");
269 xml.StartElement("Option");
270 xml.Attribute("title", lgs[0]->GetProjectName());
271 xml.EndElement();
273 xml.StartElement("Option");
274 xml.Attribute("makefile_is_custom", 1);
275 xml.EndElement();
277 xml.StartElement("Option");
278 xml.Attribute("compiler", compiler);
279 xml.EndElement();
281 // Now build a virtual tree
282 tree.BuildVirtualFolder(xml);
284 xml.StartElement("Build");
286 this->AppendTarget(xml, "all", nullptr, make, lgs[0], compiler, makeArgs);
288 // add all executable and library targets and some of the GLOBAL
289 // and UTILITY targets
290 for (cmLocalGenerator* lg : lgs) {
291 const auto& targets = lg->GetGeneratorTargets();
292 for (const auto& target : targets) {
293 std::string targetName = target->GetName();
294 switch (target->GetType()) {
295 case cmStateEnums::GLOBAL_TARGET: {
296 // Only add the global targets from CMAKE_BINARY_DIR,
297 // not from the subdirs
298 if (lg->GetCurrentBinaryDirectory() == lg->GetBinaryDirectory()) {
299 this->AppendTarget(xml, targetName, nullptr, make, lg, compiler,
300 makeArgs);
302 } break;
303 case cmStateEnums::UTILITY:
304 // Add all utility targets, except the Nightly/Continuous/
305 // Experimental-"sub"targets as e.g. NightlyStart
306 if ((cmHasLiteralPrefix(targetName, "Nightly") &&
307 (targetName != "Nightly")) ||
308 (cmHasLiteralPrefix(targetName, "Continuous") &&
309 (targetName != "Continuous")) ||
310 (cmHasLiteralPrefix(targetName, "Experimental") &&
311 (targetName != "Experimental"))) {
312 break;
315 this->AppendTarget(xml, targetName, nullptr, make, lg, compiler,
316 makeArgs);
317 break;
318 case cmStateEnums::EXECUTABLE:
319 case cmStateEnums::STATIC_LIBRARY:
320 case cmStateEnums::SHARED_LIBRARY:
321 case cmStateEnums::MODULE_LIBRARY:
322 case cmStateEnums::OBJECT_LIBRARY: {
323 cmGeneratorTarget* gt = target.get();
324 this->AppendTarget(xml, targetName, gt, make, lg, compiler,
325 makeArgs);
326 std::string fastTarget = cmStrCat(targetName, "/fast");
327 this->AppendTarget(xml, fastTarget, gt, make, lg, compiler,
328 makeArgs);
329 } break;
330 default:
331 break;
336 xml.EndElement(); // Build
338 // Collect all used source files in the project.
339 // Keep a list of C/C++ source files which might have an accompanying header
340 // that should be looked for.
341 using all_files_map_t = std::map<std::string, CbpUnit>;
342 all_files_map_t allFiles;
343 std::vector<std::string> cFiles;
345 auto* cm = this->GlobalGenerator->GetCMakeInstance();
347 for (cmLocalGenerator* lg : lgs) {
348 cmMakefile* makefile = lg->GetMakefile();
349 const auto& targets = lg->GetGeneratorTargets();
350 for (const auto& target : targets) {
351 switch (target->GetType()) {
352 case cmStateEnums::EXECUTABLE:
353 case cmStateEnums::STATIC_LIBRARY:
354 case cmStateEnums::SHARED_LIBRARY:
355 case cmStateEnums::MODULE_LIBRARY:
356 case cmStateEnums::OBJECT_LIBRARY:
357 case cmStateEnums::UTILITY: // can have sources since 2.6.3
359 std::vector<cmSourceFile*> sources;
360 target->GetSourceFiles(
361 sources, makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
362 for (cmSourceFile* s : sources) {
363 // don't add source files from UTILITY target which have the
364 // GENERATED property set:
365 if (target->GetType() == cmStateEnums::UTILITY &&
366 s->GetIsGenerated()) {
367 continue;
370 // check whether it is a C/C++/CUDA/HIP implementation file
371 bool isCFile = false;
372 std::string lang = s->GetOrDetermineLanguage();
373 if (lang == "C" || lang == "CXX" || lang == "CUDA" ||
374 lang == "HIP") {
375 std::string const& srcext = s->GetExtension();
376 isCFile = cm->IsACLikeSourceExtension(srcext);
379 std::string const& fullPath = s->ResolveFullPath();
381 // Check file position relative to project root dir.
382 const std::string relative =
383 cmSystemTools::RelativePath(lg->GetSourceDirectory(), fullPath);
384 // Do not add this file if it has ".." in relative path and
385 // if CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES variable is on.
386 const bool excludeExternal = lg->GetMakefile()->IsOn(
387 "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES");
388 if (excludeExternal &&
389 (relative.find("..") != std::string::npos)) {
390 continue;
393 if (isCFile) {
394 cFiles.push_back(fullPath);
397 CbpUnit& cbpUnit = allFiles[fullPath];
398 cbpUnit.Targets.push_back(target.get());
400 } break;
401 default:
402 break;
407 std::vector<std::string> const& headerExts =
408 this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions();
410 // The following loop tries to add header files matching to implementation
411 // files to the project. It does that by iterating over all
412 // C/C++ source files,
413 // replacing the file name extension with ".h" and checks whether such a
414 // file exists. If it does, it is inserted into the map of files.
415 // A very similar version of that code exists also in the CodeLite
416 // project generator.
417 for (std::string const& fileName : cFiles) {
418 std::string headerBasename =
419 cmStrCat(cmSystemTools::GetFilenamePath(fileName), '/',
420 cmSystemTools::GetFilenameWithoutExtension(fileName));
422 // check if there's a matching header around
423 for (std::string const& ext : headerExts) {
424 std::string hname = cmStrCat(headerBasename, '.', ext);
425 // if it's already in the set, don't check if it exists on disk
426 if (allFiles.find(hname) != allFiles.end()) {
427 break;
430 if (cmSystemTools::FileExists(hname)) {
431 allFiles[hname].Targets = allFiles[fileName].Targets;
432 break;
437 // insert all source files in the CodeBlocks project
438 for (auto const& s : allFiles) {
439 std::string const& unitFilename = s.first;
440 CbpUnit const& unit = s.second;
442 xml.StartElement("Unit");
443 xml.Attribute("filename", unitFilename);
445 for (cmGeneratorTarget const* tgt : unit.Targets) {
446 xml.StartElement("Option");
447 xml.Attribute("target", tgt->GetName());
448 xml.EndElement();
451 xml.EndElement();
454 // Add CMakeLists.txt
455 tree.BuildUnit(xml, mf->GetHomeDirectory() + "/");
457 xml.EndElement(); // Project
458 xml.EndElement(); // CodeBlocks_project_file
459 xml.EndDocument();
462 // Write a dummy file for OBJECT libraries, so C::B can reference some file
463 std::string cmExtraCodeBlocksGenerator::CreateDummyTargetFile(
464 cmLocalGenerator* lg, cmGeneratorTarget* target) const
466 // this file doesn't seem to be used by C::B in custom makefile mode,
467 // but we generate a unique file for each OBJECT library so in case
468 // C::B uses it in some way, the targets don't interfere with each other.
469 std::string filename = cmStrCat(lg->GetCurrentBinaryDirectory(), '/',
470 lg->GetTargetDirectory(target), '/',
471 target->GetName(), ".objlib");
472 cmGeneratedFileStream fout(filename);
473 if (fout) {
474 /* clang-format off */
475 fout << "# This is a dummy file for the OBJECT library "
476 << target->GetName()
477 << " for the CMake CodeBlocks project generator.\n"
478 << "# Don't edit, this file will be overwritten.\n";
479 /* clang-format on */
481 return filename;
484 // Generate the xml code for one target.
485 void cmExtraCodeBlocksGenerator::AppendTarget(
486 cmXMLWriter& xml, const std::string& targetName, cmGeneratorTarget* target,
487 const std::string& make, const cmLocalGenerator* lg,
488 const std::string& compiler, const std::string& makeFlags)
490 cmMakefile const* makefile = lg->GetMakefile();
491 std::string makefileName =
492 cmStrCat(lg->GetCurrentBinaryDirectory(), "/Makefile");
494 xml.StartElement("Target");
495 xml.Attribute("title", targetName);
497 if (target != nullptr) {
498 int cbTargetType = this->GetCBTargetType(target);
499 std::string workingDir = lg->GetCurrentBinaryDirectory();
500 if (target->GetType() == cmStateEnums::EXECUTABLE) {
501 // Determine the directory where the executable target is created, and
502 // set the working directory to this dir.
503 cmValue runtimeOutputDir =
504 makefile->GetDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY");
505 if (runtimeOutputDir) {
506 workingDir = *runtimeOutputDir;
507 } else {
508 cmValue executableOutputDir =
509 makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
510 if (executableOutputDir) {
511 workingDir = *executableOutputDir;
516 std::string buildType = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
517 std::string location;
518 if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
519 location =
520 this->CreateDummyTargetFile(const_cast<cmLocalGenerator*>(lg), target);
521 } else {
522 location = target->GetLocation(buildType);
525 xml.StartElement("Option");
526 xml.Attribute("output", location);
527 xml.Attribute("prefix_auto", 0);
528 xml.Attribute("extension_auto", 0);
529 xml.EndElement();
531 xml.StartElement("Option");
532 xml.Attribute("working_dir", workingDir);
533 xml.EndElement();
535 xml.StartElement("Option");
536 xml.Attribute("object_output", "./");
537 xml.EndElement();
539 xml.StartElement("Option");
540 xml.Attribute("type", cbTargetType);
541 xml.EndElement();
543 xml.StartElement("Option");
544 xml.Attribute("compiler", compiler);
545 xml.EndElement();
547 xml.StartElement("Compiler");
549 // the compilerdefines for this target
550 std::vector<std::string> cdefs;
551 target->GetCompileDefinitions(cdefs, buildType, "C");
553 // Expand the list.
554 for (std::string const& d : cdefs) {
555 xml.StartElement("Add");
556 xml.Attribute("option", "-D" + d);
557 xml.EndElement();
560 // the include directories for this target
561 std::vector<std::string> allIncludeDirs;
563 std::vector<std::string> includes;
564 lg->GetIncludeDirectories(includes, target, "C", buildType);
565 cm::append(allIncludeDirs, includes);
568 std::string systemIncludeDirs = makefile->GetSafeDefinition(
569 "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
570 if (!systemIncludeDirs.empty()) {
571 cm::append(allIncludeDirs, cmList{ systemIncludeDirs });
574 systemIncludeDirs = makefile->GetSafeDefinition(
575 "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
576 if (!systemIncludeDirs.empty()) {
577 cm::append(allIncludeDirs, cmList{ systemIncludeDirs });
580 auto end = cmRemoveDuplicates(allIncludeDirs);
582 for (std::string const& str : cmMakeRange(allIncludeDirs.cbegin(), end)) {
583 xml.StartElement("Add");
584 xml.Attribute("directory", str);
585 xml.EndElement();
588 xml.EndElement(); // Compiler
589 } else // e.g. all and the GLOBAL and UTILITY targets
591 xml.StartElement("Option");
592 xml.Attribute("working_dir", lg->GetCurrentBinaryDirectory());
593 xml.EndElement();
595 xml.StartElement("Option");
596 xml.Attribute("type", 4);
597 xml.EndElement();
600 xml.StartElement("MakeCommands");
602 xml.StartElement("Build");
603 xml.Attribute(
604 "command",
605 this->BuildMakeCommand(make, makefileName, targetName, makeFlags));
606 xml.EndElement();
608 xml.StartElement("CompileFile");
609 xml.Attribute(
610 "command",
611 this->BuildMakeCommand(make, makefileName, "\"$file\"", makeFlags));
612 xml.EndElement();
614 xml.StartElement("Clean");
615 xml.Attribute(
616 "command", this->BuildMakeCommand(make, makefileName, "clean", makeFlags));
617 xml.EndElement();
619 xml.StartElement("DistClean");
620 xml.Attribute(
621 "command", this->BuildMakeCommand(make, makefileName, "clean", makeFlags));
622 xml.EndElement();
624 xml.EndElement(); // MakeCommands
625 xml.EndElement(); // Target
628 // Translate the cmake compiler id into the CodeBlocks compiler id
629 std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf)
631 // allow the user to overwrite the detected compiler
632 std::string userCompiler =
633 mf->GetSafeDefinition("CMAKE_CODEBLOCKS_COMPILER_ID");
634 if (!userCompiler.empty()) {
635 return userCompiler;
638 // figure out which language to use
639 // for now care only for C, C++, and Fortran
641 // projects with C/C++ and Fortran are handled as C/C++ projects
642 bool pureFortran = false;
643 std::string compilerIdVar;
644 if (this->GlobalGenerator->GetLanguageEnabled("CXX")) {
645 compilerIdVar = "CMAKE_CXX_COMPILER_ID";
646 } else if (this->GlobalGenerator->GetLanguageEnabled("C")) {
647 compilerIdVar = "CMAKE_C_COMPILER_ID";
648 } else if (this->GlobalGenerator->GetLanguageEnabled("Fortran")) {
649 compilerIdVar = "CMAKE_Fortran_COMPILER_ID";
650 pureFortran = true;
653 std::string const& compilerId = mf->GetSafeDefinition(compilerIdVar);
654 std::string compiler = "gcc"; // default to gcc
655 if (compilerId == "MSVC") {
656 if (mf->IsDefinitionSet("MSVC10")) {
657 compiler = "msvc10";
658 } else {
659 compiler = "msvc8";
661 } else if (compilerId == "Borland") {
662 compiler = "bcc";
663 } else if (compilerId == "SDCC") {
664 compiler = "sdcc";
665 } else if (compilerId == "Intel") {
666 if (pureFortran && mf->IsDefinitionSet("WIN32")) {
667 compiler = "ifcwin"; // Intel Fortran for Windows (known by cbFortran)
668 } else {
669 compiler = "icc";
671 } else if (compilerId == "Watcom" || compilerId == "OpenWatcom") {
672 compiler = "ow";
673 } else if (compilerId == "Clang") {
674 compiler = "clang";
675 } else if (compilerId == "PGI") {
676 if (pureFortran) {
677 compiler = "pgifortran";
678 } else {
679 compiler = "pgi"; // does not exist as default in CodeBlocks 16.01
681 } else if (compilerId == "LCC") {
682 if (pureFortran) {
683 compiler = "lfortran";
684 } else {
685 compiler = "lcc";
687 } else if (compilerId == "GNU") {
688 if (pureFortran) {
689 compiler = "gfortran";
690 } else {
691 compiler = "gcc";
694 return compiler;
697 // Translate the cmake target type into the CodeBlocks target type id
698 int cmExtraCodeBlocksGenerator::GetCBTargetType(cmGeneratorTarget* target)
700 switch (target->GetType()) {
701 case cmStateEnums::EXECUTABLE:
702 if ((target->IsWin32Executable(
703 target->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"))) ||
704 (target->GetPropertyAsBool("MACOSX_BUNDLE"))) {
705 return 0;
707 return 1;
708 case cmStateEnums::STATIC_LIBRARY:
709 case cmStateEnums::OBJECT_LIBRARY:
710 return 2;
711 case cmStateEnums::SHARED_LIBRARY:
712 case cmStateEnums::MODULE_LIBRARY:
713 return 3;
714 default:
715 return 4;
719 // Create the command line for building the given target using the selected
720 // make
721 std::string cmExtraCodeBlocksGenerator::BuildMakeCommand(
722 const std::string& make, const std::string& makefile,
723 const std::string& target, const std::string& makeFlags)
725 std::string command = make;
726 if (!makeFlags.empty()) {
727 command += " ";
728 command += makeFlags;
731 std::string generator = this->GlobalGenerator->GetName();
732 if (generator == "NMake Makefiles" || generator == "NMake Makefiles JOM") {
733 // For Windows ConvertToOutputPath already adds quotes when required.
734 // These need to be escaped, see
735 // https://gitlab.kitware.com/cmake/cmake/-/issues/13952
736 std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
737 command += " /NOLOGO /f ";
738 command += makefileName;
739 command += " VERBOSE=1 ";
740 command += target;
741 } else if (generator == "MinGW Makefiles") {
742 // no escaping of spaces in this case, see
743 // https://gitlab.kitware.com/cmake/cmake/-/issues/10014
744 std::string const& makefileName = makefile;
745 command += " -f \"";
746 command += makefileName;
747 command += "\" ";
748 command += " VERBOSE=1 ";
749 command += target;
750 } else if (generator == "Ninja") {
751 command += " -v ";
752 command += target;
753 } else {
754 std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
755 command += " -f \"";
756 command += makefileName;
757 command += "\" ";
758 command += " VERBOSE=1 ";
759 command += target;
761 return command;