| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file Copyright.txt or https://cmake.org/licensing for details. */ |
| #include "cmExtraCodeBlocksGenerator.h" |
| |
| #include <map> |
| #include <memory> |
| #include <ostream> |
| #include <set> |
| #include <utility> |
| |
| #include <cmext/algorithm> |
| |
| #include "cmAlgorithms.h" |
| #include "cmGeneratedFileStream.h" |
| #include "cmGeneratorTarget.h" |
| #include "cmGlobalGenerator.h" |
| #include "cmList.h" |
| #include "cmLocalGenerator.h" |
| #include "cmMakefile.h" |
| #include "cmRange.h" |
| #include "cmSourceFile.h" |
| #include "cmStateTypes.h" |
| #include "cmStringAlgorithms.h" |
| #include "cmSystemTools.h" |
| #include "cmValue.h" |
| #include "cmXMLWriter.h" |
| #include "cmake.h" |
| |
| /* Some useful URLs: |
| Homepage: |
| http://www.codeblocks.org |
| |
| File format docs: |
| http://wiki.codeblocks.org/index.php?title=File_formats_description |
| http://wiki.codeblocks.org/index.php?title=Workspace_file |
| http://wiki.codeblocks.org/index.php?title=Project_file |
| |
| Discussion: |
| http://forums.codeblocks.org/index.php/topic,6789.0.html |
| */ |
| |
| cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator() = default; |
| |
| cmExternalMakefileProjectGeneratorFactory* |
| cmExtraCodeBlocksGenerator::GetFactory() |
| { |
| static cmExternalMakefileProjectGeneratorSimpleFactory< |
| cmExtraCodeBlocksGenerator> |
| factory("CodeBlocks", "Generates CodeBlocks project files (deprecated)."); |
| |
| if (factory.GetSupportedGlobalGenerators().empty()) { |
| #if defined(_WIN32) |
| factory.AddSupportedGlobalGenerator("MinGW Makefiles"); |
| factory.AddSupportedGlobalGenerator("NMake Makefiles"); |
| factory.AddSupportedGlobalGenerator("NMake Makefiles JOM"); |
| // disable until somebody actually tests it: |
| // this->AddSupportedGlobalGenerator("MSYS Makefiles"); |
| #endif |
| factory.AddSupportedGlobalGenerator("Ninja"); |
| factory.AddSupportedGlobalGenerator("Unix Makefiles"); |
| } |
| |
| return &factory; |
| } |
| |
| void cmExtraCodeBlocksGenerator::Generate() |
| { |
| // for each sub project in the project create a codeblocks project |
| for (auto const& it : this->GlobalGenerator->GetProjectMap()) { |
| // create a project file |
| this->CreateProjectFile(it.second); |
| } |
| } |
| |
| /* create the project file */ |
| void cmExtraCodeBlocksGenerator::CreateProjectFile( |
| const std::vector<cmLocalGenerator*>& lgs) |
| { |
| std::string outputDir = lgs[0]->GetCurrentBinaryDirectory(); |
| std::string projectName = lgs[0]->GetProjectName(); |
| |
| std::string filename = cmStrCat(outputDir, '/', projectName, ".cbp"); |
| std::string sessionFilename = |
| cmStrCat(outputDir, '/', projectName, ".layout"); |
| |
| this->CreateNewProjectFile(lgs, filename); |
| } |
| |
| /* Tree is used to create a "Virtual Folder" in CodeBlocks, in which all |
| CMake files this project depends on will be put. This means additionally |
| to the "Sources" and "Headers" virtual folders of CodeBlocks, there will |
| now also be a "CMake Files" virtual folder. |
| Patch by Daniel Teske <daniel.teske AT nokia.com> (which use C::B project |
| files in QtCreator).*/ |
| struct Tree |
| { |
| std::string path; // only one component of the path |
| std::vector<Tree> folders; |
| std::set<std::string> files; |
| void InsertPath(const std::vector<std::string>& split, |
| std::vector<std::string>::size_type start, |
| const std::string& fileName); |
| void BuildVirtualFolder(cmXMLWriter& xml) const; |
| void BuildVirtualFolderImpl(std::string& virtualFolders, |
| const std::string& prefix) const; |
| void BuildUnit(cmXMLWriter& xml, const std::string& fsPath) const; |
| void BuildUnitImpl(cmXMLWriter& xml, const std::string& virtualFolderPath, |
| const std::string& fsPath) const; |
| }; |
| |
| void Tree::InsertPath(const std::vector<std::string>& split, |
| std::vector<std::string>::size_type start, |
| const std::string& fileName) |
| { |
| if (start == split.size()) { |
| this->files.insert(fileName); |
| return; |
| } |
| for (Tree& folder : this->folders) { |
| if (folder.path == split[start]) { |
| if (start + 1 < split.size()) { |
| folder.InsertPath(split, start + 1, fileName); |
| return; |
| } |
| // last part of split |
| folder.files.insert(fileName); |
| return; |
| } |
| } |
| // Not found in folders, thus insert |
| Tree newFolder; |
| newFolder.path = split[start]; |
| if (start + 1 < split.size()) { |
| newFolder.InsertPath(split, start + 1, fileName); |
| this->folders.push_back(newFolder); |
| return; |
| } |
| // last part of split |
| newFolder.files.insert(fileName); |
| this->folders.push_back(newFolder); |
| } |
| |
| void Tree::BuildVirtualFolder(cmXMLWriter& xml) const |
| { |
| xml.StartElement("Option"); |
| std::string virtualFolders = "CMake Files\\;"; |
| for (Tree const& folder : this->folders) { |
| folder.BuildVirtualFolderImpl(virtualFolders, ""); |
| } |
| xml.Attribute("virtualFolders", virtualFolders); |
| xml.EndElement(); |
| } |
| |
| void Tree::BuildVirtualFolderImpl(std::string& virtualFolders, |
| const std::string& prefix) const |
| { |
| virtualFolders += "CMake Files\\" + prefix + this->path + "\\;"; |
| for (Tree const& folder : this->folders) { |
| folder.BuildVirtualFolderImpl(virtualFolders, prefix + this->path + "\\"); |
| } |
| } |
| |
| void Tree::BuildUnit(cmXMLWriter& xml, const std::string& fsPath) const |
| { |
| for (std::string const& f : this->files) { |
| xml.StartElement("Unit"); |
| xml.Attribute("filename", fsPath + f); |
| |
| xml.StartElement("Option"); |
| xml.Attribute("virtualFolder", "CMake Files\\"); |
| xml.EndElement(); |
| |
| xml.EndElement(); |
| } |
| for (Tree const& folder : this->folders) { |
| folder.BuildUnitImpl(xml, "", fsPath); |
| } |
| } |
| |
| void Tree::BuildUnitImpl(cmXMLWriter& xml, |
| const std::string& virtualFolderPath, |
| const std::string& fsPath) const |
| { |
| for (std::string const& f : this->files) { |
| xml.StartElement("Unit"); |
| xml.Attribute("filename", cmStrCat(fsPath, this->path, "/", f)); |
| |
| xml.StartElement("Option"); |
| xml.Attribute( |
| "virtualFolder", |
| cmStrCat("CMake Files\\", virtualFolderPath, this->path, "\\")); |
| xml.EndElement(); |
| |
| xml.EndElement(); |
| } |
| for (Tree const& folder : this->folders) { |
| folder.BuildUnitImpl(xml, cmStrCat(virtualFolderPath, this->path, "\\"), |
| cmStrCat(fsPath, this->path, "/")); |
| } |
| } |
| |
| void cmExtraCodeBlocksGenerator::CreateNewProjectFile( |
| const std::vector<cmLocalGenerator*>& lgs, const std::string& filename) |
| { |
| const cmMakefile* mf = lgs[0]->GetMakefile(); |
| cmGeneratedFileStream fout(filename); |
| if (!fout) { |
| return; |
| } |
| |
| Tree tree; |
| |
| // build tree of virtual folders |
| for (auto const& it : this->GlobalGenerator->GetProjectMap()) { |
| // Collect all files |
| std::vector<std::string> listFiles; |
| for (cmLocalGenerator* lg : it.second) { |
| cm::append(listFiles, lg->GetMakefile()->GetListFiles()); |
| } |
| |
| // Convert |
| for (std::string const& listFile : listFiles) { |
| // don't put cmake's own files into the project (#12110): |
| if (cmHasPrefix(listFile, cmSystemTools::GetCMakeRoot())) { |
| continue; |
| } |
| |
| const std::string& relative = cmSystemTools::RelativePath( |
| it.second[0]->GetSourceDirectory(), listFile); |
| std::vector<std::string> split; |
| cmSystemTools::SplitPath(relative, split, false); |
| // Split filename from path |
| std::string fileName = *(split.end() - 1); |
| split.erase(split.end() - 1, split.end()); |
| |
| // We don't want paths with CMakeFiles in them |
| // or do we? |
| // In speedcrunch those where purely internal |
| // |
| // Also we can disable external (outside the project) files by setting ON |
| // CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES variable. |
| const bool excludeExternal = it.second[0]->GetMakefile()->IsOn( |
| "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES"); |
| if (!split.empty() && |
| (!excludeExternal || (relative.find("..") == std::string::npos)) && |
| relative.find("CMakeFiles") == std::string::npos) { |
| tree.InsertPath(split, 1, fileName); |
| } |
| } |
| } |
| |
| // figure out the compiler |
| std::string compiler = this->GetCBCompilerId(mf); |
| const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); |
| const std::string& makeArgs = |
| mf->GetSafeDefinition("CMAKE_CODEBLOCKS_MAKE_ARGUMENTS"); |
| |
| cmXMLWriter xml(fout); |
| xml.StartDocument(); |
| xml.StartElement("CodeBlocks_project_file"); |
| |
| xml.StartElement("FileVersion"); |
| xml.Attribute("major", 1); |
| xml.Attribute("minor", 6); |
| xml.EndElement(); |
| |
| xml.StartElement("Project"); |
| |
| xml.StartElement("Option"); |
| xml.Attribute("title", lgs[0]->GetProjectName()); |
| xml.EndElement(); |
| |
| xml.StartElement("Option"); |
| xml.Attribute("makefile_is_custom", 1); |
| xml.EndElement(); |
| |
| xml.StartElement("Option"); |
| xml.Attribute("compiler", compiler); |
| xml.EndElement(); |
| |
| // Now build a virtual tree |
| tree.BuildVirtualFolder(xml); |
| |
| xml.StartElement("Build"); |
| |
| this->AppendTarget(xml, "all", nullptr, make, lgs[0], compiler, makeArgs); |
| |
| // add all executable and library targets and some of the GLOBAL |
| // and UTILITY targets |
| for (cmLocalGenerator* lg : lgs) { |
| const auto& targets = lg->GetGeneratorTargets(); |
| for (const auto& target : targets) { |
| std::string targetName = target->GetName(); |
| switch (target->GetType()) { |
| case cmStateEnums::GLOBAL_TARGET: { |
| // Only add the global targets from CMAKE_BINARY_DIR, |
| // not from the subdirs |
| if (lg->GetCurrentBinaryDirectory() == lg->GetBinaryDirectory()) { |
| this->AppendTarget(xml, targetName, nullptr, make, lg, compiler, |
| makeArgs); |
| } |
| } break; |
| case cmStateEnums::UTILITY: |
| // Add all utility targets, except the Nightly/Continuous/ |
| // Experimental-"sub"targets as e.g. NightlyStart |
| if ((cmHasLiteralPrefix(targetName, "Nightly") && |
| (targetName != "Nightly")) || |
| (cmHasLiteralPrefix(targetName, "Continuous") && |
| (targetName != "Continuous")) || |
| (cmHasLiteralPrefix(targetName, "Experimental") && |
| (targetName != "Experimental"))) { |
| break; |
| } |
| |
| this->AppendTarget(xml, targetName, nullptr, make, lg, compiler, |
| makeArgs); |
| break; |
| case cmStateEnums::EXECUTABLE: |
| case cmStateEnums::STATIC_LIBRARY: |
| case cmStateEnums::SHARED_LIBRARY: |
| case cmStateEnums::MODULE_LIBRARY: |
| case cmStateEnums::OBJECT_LIBRARY: { |
| cmGeneratorTarget* gt = target.get(); |
| this->AppendTarget(xml, targetName, gt, make, lg, compiler, |
| makeArgs); |
| std::string fastTarget = cmStrCat(targetName, "/fast"); |
| this->AppendTarget(xml, fastTarget, gt, make, lg, compiler, |
| makeArgs); |
| } break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| xml.EndElement(); // Build |
| |
| // Collect all used source files in the project. |
| // Keep a list of C/C++ source files which might have an accompanying header |
| // that should be looked for. |
| using all_files_map_t = std::map<std::string, CbpUnit>; |
| all_files_map_t allFiles; |
| std::vector<std::string> cFiles; |
| |
| auto* cm = this->GlobalGenerator->GetCMakeInstance(); |
| |
| for (cmLocalGenerator* lg : lgs) { |
| cmMakefile* makefile = lg->GetMakefile(); |
| const auto& targets = lg->GetGeneratorTargets(); |
| for (const auto& target : targets) { |
| switch (target->GetType()) { |
| case cmStateEnums::EXECUTABLE: |
| case cmStateEnums::STATIC_LIBRARY: |
| case cmStateEnums::SHARED_LIBRARY: |
| case cmStateEnums::MODULE_LIBRARY: |
| case cmStateEnums::OBJECT_LIBRARY: |
| case cmStateEnums::UTILITY: // can have sources since 2.6.3 |
| { |
| std::vector<cmSourceFile*> sources; |
| target->GetSourceFiles( |
| sources, makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); |
| for (cmSourceFile* s : sources) { |
| // don't add source files from UTILITY target which have the |
| // GENERATED property set: |
| if (target->GetType() == cmStateEnums::UTILITY && |
| s->GetIsGenerated()) { |
| continue; |
| } |
| |
| // check whether it is a C/C++/CUDA/HIP implementation file |
| bool isCFile = false; |
| std::string lang = s->GetOrDetermineLanguage(); |
| if (lang == "C" || lang == "CXX" || lang == "CUDA" || |
| lang == "HIP") { |
| std::string const& srcext = s->GetExtension(); |
| isCFile = cm->IsACLikeSourceExtension(srcext); |
| } |
| |
| std::string const& fullPath = s->ResolveFullPath(); |
| |
| // Check file position relative to project root dir. |
| const std::string relative = |
| cmSystemTools::RelativePath(lg->GetSourceDirectory(), fullPath); |
| // Do not add this file if it has ".." in relative path and |
| // if CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES variable is on. |
| const bool excludeExternal = lg->GetMakefile()->IsOn( |
| "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES"); |
| if (excludeExternal && |
| (relative.find("..") != std::string::npos)) { |
| continue; |
| } |
| |
| if (isCFile) { |
| cFiles.push_back(fullPath); |
| } |
| |
| CbpUnit& cbpUnit = allFiles[fullPath]; |
| cbpUnit.Targets.push_back(target.get()); |
| } |
| } break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| std::vector<std::string> const& headerExts = |
| this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions(); |
| |
| // The following loop tries to add header files matching to implementation |
| // files to the project. It does that by iterating over all |
| // C/C++ source files, |
| // replacing the file name extension with ".h" and checks whether such a |
| // file exists. If it does, it is inserted into the map of files. |
| // A very similar version of that code exists also in the CodeLite |
| // project generator. |
| for (std::string const& fileName : cFiles) { |
| std::string headerBasename = |
| cmStrCat(cmSystemTools::GetFilenamePath(fileName), '/', |
| cmSystemTools::GetFilenameWithoutExtension(fileName)); |
| |
| // check if there's a matching header around |
| for (std::string const& ext : headerExts) { |
| std::string hname = cmStrCat(headerBasename, '.', ext); |
| // if it's already in the set, don't check if it exists on disk |
| if (allFiles.find(hname) != allFiles.end()) { |
| break; |
| } |
| |
| if (cmSystemTools::FileExists(hname)) { |
| allFiles[hname].Targets = allFiles[fileName].Targets; |
| break; |
| } |
| } |
| } |
| |
| // insert all source files in the CodeBlocks project |
| for (auto const& s : allFiles) { |
| std::string const& unitFilename = s.first; |
| CbpUnit const& unit = s.second; |
| |
| xml.StartElement("Unit"); |
| xml.Attribute("filename", unitFilename); |
| |
| for (cmGeneratorTarget const* tgt : unit.Targets) { |
| xml.StartElement("Option"); |
| xml.Attribute("target", tgt->GetName()); |
| xml.EndElement(); |
| } |
| |
| xml.EndElement(); |
| } |
| |
| // Add CMakeLists.txt |
| tree.BuildUnit(xml, mf->GetHomeDirectory() + "/"); |
| |
| xml.EndElement(); // Project |
| xml.EndElement(); // CodeBlocks_project_file |
| xml.EndDocument(); |
| } |
| |
| // Write a dummy file for OBJECT libraries, so C::B can reference some file |
| std::string cmExtraCodeBlocksGenerator::CreateDummyTargetFile( |
| cmLocalGenerator* lg, cmGeneratorTarget* target) const |
| { |
| // this file doesn't seem to be used by C::B in custom makefile mode, |
| // but we generate a unique file for each OBJECT library so in case |
| // C::B uses it in some way, the targets don't interfere with each other. |
| std::string filename = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', |
| lg->GetTargetDirectory(target), '/', |
| target->GetName(), ".objlib"); |
| cmGeneratedFileStream fout(filename); |
| if (fout) { |
| /* clang-format off */ |
| fout << "# This is a dummy file for the OBJECT library " |
| << target->GetName() |
| << " for the CMake CodeBlocks project generator.\n" |
| << "# Don't edit, this file will be overwritten.\n"; |
| /* clang-format on */ |
| } |
| return filename; |
| } |
| |
| // Generate the xml code for one target. |
| void cmExtraCodeBlocksGenerator::AppendTarget( |
| cmXMLWriter& xml, const std::string& targetName, cmGeneratorTarget* target, |
| const std::string& make, const cmLocalGenerator* lg, |
| const std::string& compiler, const std::string& makeFlags) |
| { |
| cmMakefile const* makefile = lg->GetMakefile(); |
| std::string makefileName = |
| cmStrCat(lg->GetCurrentBinaryDirectory(), "/Makefile"); |
| |
| xml.StartElement("Target"); |
| xml.Attribute("title", targetName); |
| |
| if (target != nullptr) { |
| int cbTargetType = this->GetCBTargetType(target); |
| std::string workingDir = lg->GetCurrentBinaryDirectory(); |
| if (target->GetType() == cmStateEnums::EXECUTABLE) { |
| // Determine the directory where the executable target is created, and |
| // set the working directory to this dir. |
| cmValue runtimeOutputDir = |
| makefile->GetDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY"); |
| if (runtimeOutputDir) { |
| workingDir = *runtimeOutputDir; |
| } else { |
| cmValue executableOutputDir = |
| makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"); |
| if (executableOutputDir) { |
| workingDir = *executableOutputDir; |
| } |
| } |
| } |
| |
| std::string buildType = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); |
| std::string location; |
| if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) { |
| location = |
| this->CreateDummyTargetFile(const_cast<cmLocalGenerator*>(lg), target); |
| } else { |
| location = target->GetLocation(buildType); |
| } |
| |
| xml.StartElement("Option"); |
| xml.Attribute("output", location); |
| xml.Attribute("prefix_auto", 0); |
| xml.Attribute("extension_auto", 0); |
| xml.EndElement(); |
| |
| xml.StartElement("Option"); |
| xml.Attribute("working_dir", workingDir); |
| xml.EndElement(); |
| |
| xml.StartElement("Option"); |
| xml.Attribute("object_output", "./"); |
| xml.EndElement(); |
| |
| xml.StartElement("Option"); |
| xml.Attribute("type", cbTargetType); |
| xml.EndElement(); |
| |
| xml.StartElement("Option"); |
| xml.Attribute("compiler", compiler); |
| xml.EndElement(); |
| |
| xml.StartElement("Compiler"); |
| |
| // the compilerdefines for this target |
| std::vector<std::string> cdefs; |
| target->GetCompileDefinitions(cdefs, buildType, "C"); |
| |
| // Expand the list. |
| for (std::string const& d : cdefs) { |
| xml.StartElement("Add"); |
| xml.Attribute("option", "-D" + d); |
| xml.EndElement(); |
| } |
| |
| // the include directories for this target |
| std::vector<std::string> allIncludeDirs; |
| { |
| std::vector<std::string> includes; |
| lg->GetIncludeDirectories(includes, target, "C", buildType); |
| cm::append(allIncludeDirs, includes); |
| } |
| |
| std::string systemIncludeDirs = makefile->GetSafeDefinition( |
| "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS"); |
| if (!systemIncludeDirs.empty()) { |
| cm::append(allIncludeDirs, cmList{ systemIncludeDirs }); |
| } |
| |
| systemIncludeDirs = makefile->GetSafeDefinition( |
| "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS"); |
| if (!systemIncludeDirs.empty()) { |
| cm::append(allIncludeDirs, cmList{ systemIncludeDirs }); |
| } |
| |
| auto end = cmRemoveDuplicates(allIncludeDirs); |
| |
| for (std::string const& str : cmMakeRange(allIncludeDirs.cbegin(), end)) { |
| xml.StartElement("Add"); |
| xml.Attribute("directory", str); |
| xml.EndElement(); |
| } |
| |
| xml.EndElement(); // Compiler |
| } else // e.g. all and the GLOBAL and UTILITY targets |
| { |
| xml.StartElement("Option"); |
| xml.Attribute("working_dir", lg->GetCurrentBinaryDirectory()); |
| xml.EndElement(); |
| |
| xml.StartElement("Option"); |
| xml.Attribute("type", 4); |
| xml.EndElement(); |
| } |
| |
| xml.StartElement("MakeCommands"); |
| |
| xml.StartElement("Build"); |
| xml.Attribute( |
| "command", |
| this->BuildMakeCommand(make, makefileName, targetName, makeFlags)); |
| xml.EndElement(); |
| |
| xml.StartElement("CompileFile"); |
| xml.Attribute( |
| "command", |
| this->BuildMakeCommand(make, makefileName, "\"$file\"", makeFlags)); |
| xml.EndElement(); |
| |
| xml.StartElement("Clean"); |
| xml.Attribute( |
| "command", this->BuildMakeCommand(make, makefileName, "clean", makeFlags)); |
| xml.EndElement(); |
| |
| xml.StartElement("DistClean"); |
| xml.Attribute( |
| "command", this->BuildMakeCommand(make, makefileName, "clean", makeFlags)); |
| xml.EndElement(); |
| |
| xml.EndElement(); // MakeCommands |
| xml.EndElement(); // Target |
| } |
| |
| // Translate the cmake compiler id into the CodeBlocks compiler id |
| std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf) |
| { |
| // allow the user to overwrite the detected compiler |
| std::string userCompiler = |
| mf->GetSafeDefinition("CMAKE_CODEBLOCKS_COMPILER_ID"); |
| if (!userCompiler.empty()) { |
| return userCompiler; |
| } |
| |
| // figure out which language to use |
| // for now care only for C, C++, and Fortran |
| |
| // projects with C/C++ and Fortran are handled as C/C++ projects |
| bool pureFortran = false; |
| std::string compilerIdVar; |
| if (this->GlobalGenerator->GetLanguageEnabled("CXX")) { |
| compilerIdVar = "CMAKE_CXX_COMPILER_ID"; |
| } else if (this->GlobalGenerator->GetLanguageEnabled("C")) { |
| compilerIdVar = "CMAKE_C_COMPILER_ID"; |
| } else if (this->GlobalGenerator->GetLanguageEnabled("Fortran")) { |
| compilerIdVar = "CMAKE_Fortran_COMPILER_ID"; |
| pureFortran = true; |
| } |
| |
| std::string const& compilerId = mf->GetSafeDefinition(compilerIdVar); |
| std::string compiler = "gcc"; // default to gcc |
| if (compilerId == "MSVC") { |
| if (mf->IsDefinitionSet("MSVC10")) { |
| compiler = "msvc10"; |
| } else { |
| compiler = "msvc8"; |
| } |
| } else if (compilerId == "Borland") { |
| compiler = "bcc"; |
| } else if (compilerId == "SDCC") { |
| compiler = "sdcc"; |
| } else if (compilerId == "Intel") { |
| if (pureFortran && mf->IsDefinitionSet("WIN32")) { |
| compiler = "ifcwin"; // Intel Fortran for Windows (known by cbFortran) |
| } else { |
| compiler = "icc"; |
| } |
| } else if (compilerId == "Watcom" || compilerId == "OpenWatcom") { |
| compiler = "ow"; |
| } else if (compilerId == "Clang") { |
| compiler = "clang"; |
| } else if (compilerId == "PGI") { |
| if (pureFortran) { |
| compiler = "pgifortran"; |
| } else { |
| compiler = "pgi"; // does not exist as default in CodeBlocks 16.01 |
| } |
| } else if (compilerId == "LCC") { |
| if (pureFortran) { |
| compiler = "lfortran"; |
| } else { |
| compiler = "lcc"; |
| } |
| } else if (compilerId == "GNU") { |
| if (pureFortran) { |
| compiler = "gfortran"; |
| } else { |
| compiler = "gcc"; |
| } |
| } |
| return compiler; |
| } |
| |
| // Translate the cmake target type into the CodeBlocks target type id |
| int cmExtraCodeBlocksGenerator::GetCBTargetType(cmGeneratorTarget* target) |
| { |
| switch (target->GetType()) { |
| case cmStateEnums::EXECUTABLE: |
| if ((target->IsWin32Executable( |
| target->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"))) || |
| (target->GetPropertyAsBool("MACOSX_BUNDLE"))) { |
| return 0; |
| } |
| return 1; |
| case cmStateEnums::STATIC_LIBRARY: |
| case cmStateEnums::OBJECT_LIBRARY: |
| return 2; |
| case cmStateEnums::SHARED_LIBRARY: |
| case cmStateEnums::MODULE_LIBRARY: |
| return 3; |
| default: |
| return 4; |
| } |
| } |
| |
| // Create the command line for building the given target using the selected |
| // make |
| std::string cmExtraCodeBlocksGenerator::BuildMakeCommand( |
| const std::string& make, const std::string& makefile, |
| const std::string& target, const std::string& makeFlags) |
| { |
| std::string command = make; |
| if (!makeFlags.empty()) { |
| command += " "; |
| command += makeFlags; |
| } |
| |
| std::string generator = this->GlobalGenerator->GetName(); |
| if (generator == "NMake Makefiles" || generator == "NMake Makefiles JOM") { |
| // For Windows ConvertToOutputPath already adds quotes when required. |
| // These need to be escaped, see |
| // https://gitlab.kitware.com/cmake/cmake/-/issues/13952 |
| std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile); |
| command += " /NOLOGO /f "; |
| command += makefileName; |
| command += " VERBOSE=1 "; |
| command += target; |
| } else if (generator == "MinGW Makefiles") { |
| // no escaping of spaces in this case, see |
| // https://gitlab.kitware.com/cmake/cmake/-/issues/10014 |
| std::string const& makefileName = makefile; |
| command += " -f \""; |
| command += makefileName; |
| command += "\" "; |
| command += " VERBOSE=1 "; |
| command += target; |
| } else if (generator == "Ninja") { |
| command += " -v "; |
| command += target; |
| } else { |
| std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile); |
| command += " -f \""; |
| command += makefileName; |
| command += "\" "; |
| command += " VERBOSE=1 "; |
| command += target; |
| } |
| return command; |
| } |