├── .gitignore ├── 3rdparty ├── cmake │ ├── Copyright.txt │ ├── README.md │ ├── cmListFileCache.cxx │ ├── cmListFileCache.h │ ├── cmListFileLexer.cxx │ ├── cmListFileLexer.h │ ├── cmListFileLexer.in.l │ └── cmStandardLexer.h └── rstparser │ ├── README.qt │ ├── README.rst │ ├── rstparser-test.cc │ ├── rstparser.cc │ └── rstparser.h ├── CMakeLists.txt ├── CMakeProjectManager2.json.in ├── README.md ├── appy-patch.sh ├── builddirparameters.cpp ├── builddirparameters.h ├── cmake_global.h ├── cmakeabstractprocessstep.cpp ├── cmakeabstractprocessstep.h ├── cmakeautocompleter.cpp ├── cmakeautocompleter.h ├── cmakebuildconfiguration.cpp ├── cmakebuildconfiguration.h ├── cmakebuildstep.cpp ├── cmakebuildstep.h ├── cmakebuildsystem.cpp ├── cmakebuildsystem.h ├── cmakebuildsystem.md ├── cmakebuildtarget.h ├── cmakeconfigitem.cpp ├── cmakeconfigitem.h ├── cmakeeditor.cpp ├── cmakeeditor.h ├── cmakefilecompletionassist.cpp ├── cmakefilecompletionassist.h ├── cmakeformatter.cpp ├── cmakeformatter.h ├── cmakeindenter.cpp ├── cmakeindenter.h ├── cmakeinstallstep.cpp ├── cmakeinstallstep.h ├── cmakekitaspect.cpp ├── cmakekitaspect.h ├── cmakelocatorfilter.cpp ├── cmakelocatorfilter.h ├── cmakeparser.cpp ├── cmakeparser.h ├── cmakeprocess.cpp ├── cmakeprocess.h ├── cmakeproject.cpp ├── cmakeproject.h ├── cmakeproject.qrc ├── cmakeprojectconstants.h ├── cmakeprojectimporter.cpp ├── cmakeprojectimporter.h ├── cmakeprojectmanager.cpp ├── cmakeprojectmanager.h ├── cmakeprojectmanager.qbs ├── cmakeprojectmanagertr.h ├── cmakeprojectnodes.cpp ├── cmakeprojectnodes.h ├── cmakeprojectplugin.cpp ├── cmakeprojectplugin.h ├── cmakesettingspage.cpp ├── cmakesettingspage.h ├── cmakespecificsettings.cpp ├── cmakespecificsettings.h ├── cmaketool.cpp ├── cmaketool.h ├── cmaketoolmanager.cpp ├── cmaketoolmanager.h ├── cmaketoolsettingsaccessor.cpp ├── cmaketoolsettingsaccessor.h ├── configmodel.cpp ├── configmodel.h ├── configmodelitemdelegate.cpp ├── configmodelitemdelegate.h ├── fileapidataextractor.cpp ├── fileapidataextractor.h ├── fileapiparser.cpp ├── fileapiparser.h ├── fileapireader.cpp ├── fileapireader.h ├── images ├── fileoverlay_cmake.png ├── fileoverlay_cmake@2x.png ├── settingscategory_cmakeprojectmanager.png └── settingscategory_cmakeprojectmanager@2x.png ├── mk-cmake-patches.sh ├── presetsmacros.cpp ├── presetsmacros.h ├── presetsparser.cpp ├── presetsparser.h ├── projecttreehelper.cpp ├── projecttreehelper.h ├── simplefileapireader.cpp ├── simplefileapireader.h └── wizard └── cmake2 ├── CMakeLists.txt ├── CMakeLists_qt5.txt ├── cmake └── modules │ └── .dummy ├── main.c ├── main.cpp └── wizard.json /.gitignore: -------------------------------------------------------------------------------- 1 | ide_version.h 2 | app_version.h 3 | cmakeprojectmanager.pro.user 4 | *.orig 5 | 6 | -------------------------------------------------------------------------------- /3rdparty/cmake/Copyright.txt: -------------------------------------------------------------------------------- 1 | CMake - Cross Platform Makefile Generator 2 | Copyright 2000-2023 Kitware, Inc. and Contributors 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions 7 | are met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | * Neither the name of Kitware, Inc. nor the names of Contributors 17 | may be used to endorse or promote products derived from this 18 | software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | ------------------------------------------------------------------------------ 33 | 34 | The following individuals and institutions are among the Contributors: 35 | 36 | * Aaron C. Meadows 37 | * Adriaan de Groot 38 | * Aleksey Avdeev 39 | * Alexander Neundorf 40 | * Alexander Smorkalov 41 | * Alexey Sokolov 42 | * Alex Merry 43 | * Alex Turbov 44 | * Andreas Pakulat 45 | * Andreas Schneider 46 | * André Rigland Brodtkorb 47 | * Axel Huebl, Helmholtz-Zentrum Dresden - Rossendorf 48 | * Benjamin Eikel 49 | * Bjoern Ricks 50 | * Brad Hards 51 | * Christopher Harvey 52 | * Christoph Grüninger 53 | * Clement Creusot 54 | * Daniel Blezek 55 | * Daniel Pfeifer 56 | * Dawid Wróbel 57 | * Enrico Scholz 58 | * Eran Ifrah 59 | * Esben Mose Hansen, Ange Optimization ApS 60 | * Geoffrey Viola 61 | * Google Inc 62 | * Gregor Jasny 63 | * Helio Chissini de Castro 64 | * Ilya Lavrenov 65 | * Insight Software Consortium 66 | * Intel Corporation 67 | * Jan Woetzel 68 | * Jordan Williams 69 | * Julien Schueller 70 | * Kelly Thompson 71 | * Konstantin Podsvirov 72 | * Laurent Montel 73 | * Mario Bensi 74 | * Martin Gräßlin 75 | * Mathieu Malaterre 76 | * Matthaeus G. Chajdas 77 | * Matthias Kretz 78 | * Matthias Maennich 79 | * Michael Hirsch, Ph.D. 80 | * Michael Stürmer 81 | * Miguel A. Figueroa-Villanueva 82 | * Mike Durso 83 | * Mike Jackson 84 | * Mike McQuaid 85 | * Nicolas Bock 86 | * Nicolas Despres 87 | * Nikita Krupen'ko 88 | * NVIDIA Corporation 89 | * OpenGamma Ltd. 90 | * Patrick Stotko 91 | * Per Øyvind Karlsen 92 | * Peter Collingbourne 93 | * Petr Gotthard 94 | * Philip Lowman 95 | * Philippe Proulx 96 | * Raffi Enficiaud, Max Planck Society 97 | * Raumfeld 98 | * Roger Leigh 99 | * Rolf Eike Beer 100 | * Roman Donchenko 101 | * Roman Kharitonov 102 | * Ruslan Baratov 103 | * Sebastian Holtermann 104 | * Stephen Kelly 105 | * Sylvain Joubert 106 | * The Qt Company Ltd. 107 | * Thomas Sondergaard 108 | * Tobias Hunger 109 | * Todd Gamblin 110 | * Tristan Carel 111 | * University of Dundee 112 | * Vadim Zhukov 113 | * Will Dicharry 114 | 115 | See version control history for details of individual contributions. 116 | 117 | The above copyright and license notice applies to distributions of 118 | CMake in source and binary form. Third-party software packages supplied 119 | with CMake under compatible licenses provide their own copyright notices 120 | documented in corresponding subdirectories or source files. 121 | 122 | ------------------------------------------------------------------------------ 123 | 124 | CMake was initially developed by Kitware with the following sponsorship: 125 | 126 | * National Library of Medicine at the National Institutes of Health 127 | as part of the Insight Segmentation and Registration Toolkit (ITK). 128 | 129 | * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel 130 | Visualization Initiative. 131 | 132 | * National Alliance for Medical Image Computing (NAMIC) is funded by the 133 | National Institutes of Health through the NIH Roadmap for Medical Research, 134 | Grant U54 EB005149. 135 | 136 | * Kitware, Inc. 137 | -------------------------------------------------------------------------------- /3rdparty/cmake/README.md: -------------------------------------------------------------------------------- 1 | Files taken from the CMake repository https://gitlab.kitware.com/cmake/cmake.git 2 | 3 | 624461526f4707a2406ebbd40245a605b6bd41fa (tag: v3.26.3) 4 | 5 | -------------------------------------------------------------------------------- /3rdparty/cmake/cmListFileCache.cxx: -------------------------------------------------------------------------------- 1 | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2 | file Copyright.txt or https://cmake.org/licensing for details. */ 3 | #define cmListFileCache_cxx 4 | #include "cmListFileCache.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "cmListFileLexer.h" 11 | 12 | struct cmListFileParser 13 | { 14 | cmListFileParser(cmListFile* lf, std::string &error); 15 | ~cmListFileParser(); 16 | cmListFileParser(const cmListFileParser&) = delete; 17 | cmListFileParser& operator=(const cmListFileParser&) = delete; 18 | void IssueError(std::string const& text) const; 19 | bool ParseFile(const char* filename); 20 | bool ParseString(const std::string &str, const std::string &virtual_filename); 21 | bool Parse(); 22 | bool ParseFunction(const char* name, long line); 23 | bool AddArgument(cmListFileLexer_Token* token, 24 | cmListFileArgument::Delimiter delim); 25 | cmListFile* ListFile; 26 | cmListFileLexer* Lexer; 27 | std::string FunctionName; 28 | long FunctionLine; 29 | long FunctionLineEnd; 30 | std::vector FunctionArguments; 31 | std::string &Error; 32 | enum 33 | { 34 | SeparationOkay, 35 | SeparationWarning, 36 | SeparationError 37 | } Separation; 38 | }; 39 | 40 | cmListFileParser::cmListFileParser(cmListFile *lf, std::string &error) 41 | : ListFile(lf) 42 | , Lexer(cmListFileLexer_New()) 43 | , Error(error) 44 | { 45 | } 46 | 47 | cmListFileParser::~cmListFileParser() 48 | { 49 | cmListFileLexer_Delete(this->Lexer); 50 | } 51 | 52 | void cmListFileParser::IssueError(const std::string& text) const 53 | { 54 | Error += text; 55 | Error += "\n"; 56 | } 57 | 58 | bool cmListFileParser::ParseString(const std::string &str, 59 | const std::string &/*virtual_filename*/) 60 | { 61 | if (!cmListFileLexer_SetString(this->Lexer, str.c_str(), (int)str.size())) { 62 | this->IssueError("cmListFileCache: cannot allocate buffer."); 63 | return false; 64 | } 65 | 66 | return this->Parse(); 67 | } 68 | 69 | bool cmListFileParser::Parse() 70 | { 71 | // Use a simple recursive-descent parser to process the token 72 | // stream. 73 | bool haveNewline = true; 74 | while (cmListFileLexer_Token* token = cmListFileLexer_Scan(this->Lexer)) { 75 | if (token->type == cmListFileLexer_Token_Space) { 76 | } else if (token->type == cmListFileLexer_Token_Newline) { 77 | haveNewline = true; 78 | } else if (token->type == cmListFileLexer_Token_CommentBracket) { 79 | haveNewline = false; 80 | } else if (token->type == cmListFileLexer_Token_Identifier) { 81 | if (haveNewline) { 82 | haveNewline = false; 83 | if (this->ParseFunction(token->text, token->line)) { 84 | this->ListFile->Functions.emplace_back( 85 | std::move(this->FunctionName), this->FunctionLine, 86 | this->FunctionLineEnd, std::move(this->FunctionArguments)); 87 | } else { 88 | return false; 89 | } 90 | } else { 91 | std::ostringstream error; 92 | error << "Parse error. Expected a newline, got " 93 | << cmListFileLexer_GetTypeAsString(this->Lexer, token->type) 94 | << " with text \"" << token->text << "\"."; 95 | this->IssueError(error.str()); 96 | return false; 97 | } 98 | } else { 99 | std::ostringstream error; 100 | error << "Parse error. Expected a command name, got " 101 | << cmListFileLexer_GetTypeAsString(this->Lexer, token->type) 102 | << " with text \"" << token->text << "\"."; 103 | this->IssueError(error.str()); 104 | return false; 105 | } 106 | } 107 | 108 | return true; 109 | } 110 | 111 | bool cmListFile::ParseString(const std::string &str, const std::string& virtual_filename, std::string &error) 112 | { 113 | bool parseError = false; 114 | 115 | { 116 | cmListFileParser parser(this, error); 117 | parseError = !parser.ParseString(str, virtual_filename); 118 | } 119 | 120 | return !parseError; 121 | } 122 | 123 | bool cmListFileParser::ParseFunction(const char* name, long line) 124 | { 125 | // Ininitialize a new function call. 126 | this->FunctionName = name; 127 | this->FunctionLine = line; 128 | 129 | // Command name has already been parsed. Read the left paren. 130 | cmListFileLexer_Token* token; 131 | while ((token = cmListFileLexer_Scan(this->Lexer)) && 132 | token->type == cmListFileLexer_Token_Space) { 133 | } 134 | if (!token) { 135 | std::ostringstream error; 136 | /* clang-format off */ 137 | error << "Unexpected end of file.\n" 138 | << "Parse error. Function missing opening \"(\"."; 139 | /* clang-format on */ 140 | this->IssueError(error.str()); 141 | return false; 142 | } 143 | if (token->type != cmListFileLexer_Token_ParenLeft) { 144 | std::ostringstream error; 145 | error << "Parse error. Expected \"(\", got " 146 | << cmListFileLexer_GetTypeAsString(this->Lexer, token->type) 147 | << " with text \"" << token->text << "\"."; 148 | this->IssueError(error.str()); 149 | return false; 150 | } 151 | 152 | // Arguments. 153 | unsigned long parenDepth = 0; 154 | this->Separation = SeparationOkay; 155 | while ((token = cmListFileLexer_Scan(this->Lexer))) { 156 | if (token->type == cmListFileLexer_Token_Space || 157 | token->type == cmListFileLexer_Token_Newline) { 158 | this->Separation = SeparationOkay; 159 | continue; 160 | } 161 | if (token->type == cmListFileLexer_Token_ParenLeft) { 162 | parenDepth++; 163 | this->Separation = SeparationOkay; 164 | if (!this->AddArgument(token, cmListFileArgument::Unquoted)) { 165 | return false; 166 | } 167 | } else if (token->type == cmListFileLexer_Token_ParenRight) { 168 | if (parenDepth == 0) { 169 | this->FunctionLineEnd = token->line; 170 | return true; 171 | } 172 | parenDepth--; 173 | this->Separation = SeparationOkay; 174 | if (!this->AddArgument(token, cmListFileArgument::Unquoted)) { 175 | return false; 176 | } 177 | this->Separation = SeparationWarning; 178 | } else if (token->type == cmListFileLexer_Token_Identifier || 179 | token->type == cmListFileLexer_Token_ArgumentUnquoted) { 180 | if (!this->AddArgument(token, cmListFileArgument::Unquoted)) { 181 | return false; 182 | } 183 | this->Separation = SeparationWarning; 184 | } else if (token->type == cmListFileLexer_Token_ArgumentQuoted) { 185 | if (!this->AddArgument(token, cmListFileArgument::Quoted)) { 186 | return false; 187 | } 188 | this->Separation = SeparationWarning; 189 | } else if (token->type == cmListFileLexer_Token_ArgumentBracket) { 190 | if (!this->AddArgument(token, cmListFileArgument::Bracket)) { 191 | return false; 192 | } 193 | this->Separation = SeparationError; 194 | } else if (token->type == cmListFileLexer_Token_CommentBracket) { 195 | this->Separation = SeparationError; 196 | } else { 197 | // Error. 198 | std::ostringstream error; 199 | error << "Parse error. Function missing ending \")\". " 200 | << "Instead found " 201 | << cmListFileLexer_GetTypeAsString(this->Lexer, token->type) 202 | << " with text \"" << token->text << "\"."; 203 | this->IssueError(error.str()); 204 | return false; 205 | } 206 | } 207 | 208 | std::ostringstream error; 209 | error << "Parse error. Function missing ending \")\". " 210 | << "End of file reached."; 211 | IssueError(error.str()); 212 | return false; 213 | } 214 | 215 | bool cmListFileParser::AddArgument(cmListFileLexer_Token* token, 216 | cmListFileArgument::Delimiter delim) 217 | { 218 | this->FunctionArguments.emplace_back(token->text, delim, token->line, token->column); 219 | if (this->Separation == SeparationOkay) { 220 | return true; 221 | } 222 | bool isError = (this->Separation == SeparationError || 223 | delim == cmListFileArgument::Bracket); 224 | std::ostringstream m; 225 | 226 | m << "Syntax " << (isError ? "Error" : "Warning") << " in cmake code at " 227 | << "column " << token->column << "\n" 228 | << "Argument not separated from preceding token by whitespace."; 229 | /* clang-format on */ 230 | if (isError) { 231 | IssueError(m.str()); 232 | return false; 233 | } 234 | return true; 235 | } 236 | -------------------------------------------------------------------------------- /3rdparty/cmake/cmListFileCache.h: -------------------------------------------------------------------------------- 1 | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2 | file Copyright.txt or https://cmake.org/licensing for details. */ 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /** \class cmListFileCache 13 | * \brief A class to cache list file contents. 14 | * 15 | * cmListFileCache is a class used to cache the contents of parsed 16 | * cmake list files. 17 | */ 18 | 19 | struct cmListFileArgument 20 | { 21 | enum Delimiter 22 | { 23 | Unquoted, 24 | Quoted, 25 | Bracket 26 | }; 27 | cmListFileArgument() = default; 28 | cmListFileArgument(std::string v, Delimiter d, long line, long column) 29 | : Value(std::move(v)) 30 | , Delim(d) 31 | , Line(line) 32 | , Column(column) 33 | { 34 | } 35 | bool operator==(const cmListFileArgument& r) const 36 | { 37 | return (this->Value == r.Value) && (this->Delim == r.Delim); 38 | } 39 | bool operator!=(const cmListFileArgument& r) const { return !(*this == r); } 40 | std::string Value; 41 | Delimiter Delim = Unquoted; 42 | long Line = 0; 43 | long Column = 0; 44 | }; 45 | 46 | class cmListFileFunction 47 | { 48 | public: 49 | cmListFileFunction(std::string name, long line, long lineEnd, 50 | std::vector args) 51 | : Impl{ std::make_shared(std::move(name), line, lineEnd, 52 | std::move(args)) } 53 | { 54 | } 55 | 56 | std::string const& OriginalName() const noexcept 57 | { 58 | return this->Impl->OriginalName; 59 | } 60 | 61 | std::string const& LowerCaseName() const noexcept 62 | { 63 | return this->Impl->LowerCaseName; 64 | } 65 | 66 | long Line() const noexcept { return this->Impl->Line; } 67 | long LineEnd() const noexcept { return this->Impl->LineEnd; } 68 | 69 | std::vector const& Arguments() const noexcept 70 | { 71 | return this->Impl->Arguments; 72 | } 73 | 74 | private: 75 | struct Implementation 76 | { 77 | Implementation(std::string name, long line, long lineEnd, 78 | std::vector args) 79 | : OriginalName{ std::move(name) } 80 | , LowerCaseName{ tolower(this->OriginalName) } 81 | , Line{ line } 82 | , LineEnd{ lineEnd } 83 | , Arguments{ std::move(args) } 84 | { 85 | } 86 | 87 | // taken from yaml-cpp 88 | static bool IsLower(char ch) { return 'a' <= ch && ch <= 'z'; } 89 | static bool IsUpper(char ch) { return 'A' <= ch && ch <= 'Z'; } 90 | static char ToLower(char ch) { return IsUpper(ch) ? ch + 'a' - 'A' : ch; } 91 | 92 | std::string tolower(const std::string& str) 93 | { 94 | std::string s(str); 95 | std::transform(s.begin(), s.end(), s.begin(), ToLower); 96 | return s; 97 | } 98 | 99 | std::string OriginalName; 100 | std::string LowerCaseName; 101 | long Line = 0; 102 | long LineEnd = 0; 103 | std::vector Arguments; 104 | }; 105 | 106 | std::shared_ptr Impl; 107 | }; 108 | 109 | struct cmListFile 110 | { 111 | bool ParseString(const std::string &str, const std::string &virtual_filename, std::string &error); 112 | 113 | std::vector Functions; 114 | }; 115 | -------------------------------------------------------------------------------- /3rdparty/cmake/cmListFileLexer.h: -------------------------------------------------------------------------------- 1 | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2 | file Copyright.txt or https://cmake.org/licensing for details. */ 3 | #pragma once 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | /* NOLINTNEXTLINE(modernize-use-using) */ 10 | typedef enum cmListFileLexer_Type_e 11 | { 12 | cmListFileLexer_Token_None, 13 | cmListFileLexer_Token_Space, 14 | cmListFileLexer_Token_Newline, 15 | cmListFileLexer_Token_Identifier, 16 | cmListFileLexer_Token_ParenLeft, 17 | cmListFileLexer_Token_ParenRight, 18 | cmListFileLexer_Token_ArgumentUnquoted, 19 | cmListFileLexer_Token_ArgumentQuoted, 20 | cmListFileLexer_Token_ArgumentBracket, 21 | cmListFileLexer_Token_CommentBracket, 22 | cmListFileLexer_Token_BadCharacter, 23 | cmListFileLexer_Token_BadBracket, 24 | cmListFileLexer_Token_BadString 25 | } cmListFileLexer_Type; 26 | 27 | /* NOLINTNEXTLINE(modernize-use-using) */ 28 | typedef struct cmListFileLexer_Token_s cmListFileLexer_Token; 29 | struct cmListFileLexer_Token_s 30 | { 31 | cmListFileLexer_Type type; 32 | char* text; 33 | int length; 34 | int line; 35 | int column; 36 | }; 37 | 38 | enum cmListFileLexer_BOM_e 39 | { 40 | cmListFileLexer_BOM_None, 41 | cmListFileLexer_BOM_Broken, 42 | cmListFileLexer_BOM_UTF8, 43 | cmListFileLexer_BOM_UTF16BE, 44 | cmListFileLexer_BOM_UTF16LE, 45 | cmListFileLexer_BOM_UTF32BE, 46 | cmListFileLexer_BOM_UTF32LE 47 | }; 48 | 49 | /* NOLINTNEXTLINE(modernize-use-using) */ 50 | typedef enum cmListFileLexer_BOM_e cmListFileLexer_BOM; 51 | 52 | /* NOLINTNEXTLINE(modernize-use-using) */ 53 | typedef struct cmListFileLexer_s cmListFileLexer; 54 | 55 | cmListFileLexer* cmListFileLexer_New(void); 56 | int cmListFileLexer_SetFileName(cmListFileLexer*, const char*, 57 | cmListFileLexer_BOM* bom); 58 | int cmListFileLexer_SetString(cmListFileLexer*, const char*, int length); 59 | cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer*); 60 | long cmListFileLexer_GetCurrentLine(cmListFileLexer*); 61 | long cmListFileLexer_GetCurrentColumn(cmListFileLexer*); 62 | const char* cmListFileLexer_GetTypeAsString(cmListFileLexer*, 63 | cmListFileLexer_Type); 64 | void cmListFileLexer_Delete(cmListFileLexer*); 65 | 66 | #ifdef __cplusplus 67 | } /* extern "C" */ 68 | #endif 69 | -------------------------------------------------------------------------------- /3rdparty/cmake/cmStandardLexer.h: -------------------------------------------------------------------------------- 1 | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2 | file Copyright.txt or https://cmake.org/licensing for details. */ 3 | #pragma once 4 | 5 | #if !defined(_POSIX_C_SOURCE) && !defined(_WIN32) && !defined(__sun) && \ 6 | !defined(__OpenBSD__) 7 | /* POSIX APIs are needed */ 8 | // NOLINTNEXTLINE(bugprone-reserved-identifier) 9 | # define _POSIX_C_SOURCE 200809L 10 | #endif 11 | #if defined(__sun) && defined(__GNUC__) && !defined(__cplusplus) 12 | /* C sources: for fileno and strdup */ 13 | // NOLINTNEXTLINE(bugprone-reserved-identifier) 14 | # define _XOPEN_SOURCE 600 15 | #endif 16 | #if defined(__FreeBSD__) || defined(__NetBSD__) 17 | /* For isascii */ 18 | // NOLINTNEXTLINE(bugprone-reserved-identifier) 19 | # define _XOPEN_SOURCE 700 20 | #endif 21 | 22 | /* Disable some warnings. */ 23 | #if defined(_MSC_VER) 24 | # pragma warning(disable : 4018) 25 | # pragma warning(disable : 4127) 26 | # pragma warning(disable : 4131) 27 | # pragma warning(disable : 4244) 28 | # pragma warning(disable : 4251) 29 | # pragma warning(disable : 4267) 30 | # pragma warning(disable : 4305) 31 | # pragma warning(disable : 4309) 32 | # pragma warning(disable : 4706) 33 | # pragma warning(disable : 4786) 34 | # pragma warning(disable : 4996) 35 | #endif 36 | 37 | #if defined(__GNUC__) && !defined(__INTEL_COMPILER) 38 | # if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402 39 | # pragma GCC diagnostic ignored "-Wconversion" 40 | # pragma GCC diagnostic ignored "-Wsign-compare" 41 | # endif 42 | # if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 403 43 | # pragma GCC diagnostic ignored "-Wsign-conversion" 44 | # endif 45 | #endif 46 | 47 | #if defined(__LCC__) 48 | # pragma diag_suppress 1873 /* comparison between signed and unsigned */ 49 | #endif 50 | 51 | #if defined(__NVCOMPILER) 52 | # pragma diag_suppress 111 /* statement is unreachable */ 53 | # pragma diag_suppress 550 /* variable set but never used */ 54 | #endif 55 | 56 | /* Make sure isatty is available. */ 57 | #if defined(_WIN32) && !defined(__CYGWIN__) 58 | # include 59 | # if defined(_MSC_VER) 60 | # define isatty _isatty 61 | # endif 62 | #else 63 | # include // IWYU pragma: export 64 | #endif 65 | 66 | /* Make sure malloc and free are available on QNX. */ 67 | #ifdef __QNX__ 68 | # include 69 | #endif 70 | 71 | /* Disable features we do not need. */ 72 | #define YY_NEVER_INTERACTIVE 1 73 | #define YY_NO_INPUT 1 74 | #define YY_NO_UNPUT 1 75 | #define ECHO 76 | 77 | #include 78 | typedef int8_t flex_int8_t; 79 | typedef uint8_t flex_uint8_t; 80 | typedef int16_t flex_int16_t; 81 | typedef uint16_t flex_uint16_t; 82 | typedef int32_t flex_int32_t; 83 | typedef uint32_t flex_uint32_t; 84 | -------------------------------------------------------------------------------- /3rdparty/rstparser/README.qt: -------------------------------------------------------------------------------- 1 | Files taken from the CMake repository https://github.com/vitaut-archive/rstparser.git 2 | 3 | 49e1e6626ba28357749acfe3bf07c4a19e5bc4ef 4 | -------------------------------------------------------------------------------- /3rdparty/rstparser/README.rst: -------------------------------------------------------------------------------- 1 | RSTParser 2 | ========= 3 | 4 | RSTParser is an open-source C++ library for parsing 5 | `reStructuredText `__. 6 | 7 | License 8 | ------- 9 | 10 | Copyright (c) 2013, Victor Zverovich 11 | 12 | All rights reserved. 13 | 14 | Redistribution and use in source and binary forms, with or without 15 | modification, are permitted provided that the following conditions are met: 16 | 17 | 1. Redistributions of source code must retain the above copyright notice, this 18 | list of conditions and the following disclaimer. 19 | 2. Redistributions in binary form must reproduce the above copyright notice, 20 | this list of conditions and the following disclaimer in the documentation 21 | and/or other materials provided with the distribution. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 24 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 27 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 30 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /3rdparty/rstparser/rstparser-test.cc: -------------------------------------------------------------------------------- 1 | /* 2 | reStructuredText parser tests. 3 | 4 | Copyright (c) 2012, Victor Zverovich 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | 30 | #include 31 | 32 | #ifdef _WIN32 33 | # include 34 | #endif 35 | 36 | #include "rstparser.h" 37 | 38 | namespace { 39 | 40 | class TestHandler : public rst::ContentHandler { 41 | private: 42 | std::stack tags_; 43 | std::string content_; 44 | 45 | public: 46 | const std::string &content() const { return content_; } 47 | 48 | void StartBlock(rst::BlockType type) { 49 | std::string tag; 50 | switch (type) { 51 | case rst::REFERENCE_LINK: 52 | // not used, HandleReferenceLink is used instead 53 | break; 54 | case rst::H1: 55 | tag = "h1"; 56 | break; 57 | case rst::H2: 58 | tag = "h2"; 59 | break; 60 | case rst::H3: 61 | tag = "h3"; 62 | break; 63 | case rst::H4: 64 | tag = "h4"; 65 | break; 66 | case rst::H5: 67 | tag = "h5"; 68 | break; 69 | case rst::CODE: 70 | tag = "code"; 71 | break; 72 | case rst::PARAGRAPH: 73 | tag = "p"; 74 | break; 75 | case rst::LINE_BLOCK: 76 | tag = "lineblock"; 77 | break; 78 | case rst::BLOCK_QUOTE: 79 | tag = "blockquote"; 80 | break; 81 | case rst::BULLET_LIST: 82 | tag = "ul"; 83 | break; 84 | case rst::LIST_ITEM: 85 | tag = "li"; 86 | break; 87 | case rst::LITERAL_BLOCK: 88 | tag = "code"; 89 | break; 90 | } 91 | content_ += "<" + tag + ">"; 92 | tags_.push(tag); 93 | } 94 | 95 | void EndBlock() { 96 | content_ += ""; 97 | tags_.pop(); 98 | } 99 | 100 | void HandleText(const char *text, std::size_t size) { 101 | content_.append(text, size); 102 | } 103 | 104 | void HandleDirective(const std::string &type, const std::string &name) { 105 | content_ += std::string("
" + type + "
"; 106 | } 107 | 108 | void HandleReferenceLink(const std::string &type, const std::string &text) { 109 | content_ += std::string("" + text + ""; 110 | } 111 | }; 112 | 113 | std::string Parse(const char *s) { 114 | TestHandler handler; 115 | rst::Parser parser(&handler); 116 | parser.Parse(s); 117 | return handler.content(); 118 | } 119 | } 120 | 121 | TEST(ParserTest, HX) { 122 | EXPECT_EQ("

test

", Parse("====\ntest\n====")); 123 | EXPECT_EQ("

test

", Parse("test\n====")); 124 | EXPECT_EQ("

test

", Parse("test\n----")); 125 | EXPECT_EQ("

test

", Parse("test\n^^^^")); 126 | EXPECT_EQ("
test
", Parse("test\n\"\"\"\"")); 127 | } 128 | 129 | TEST(ParserTest, Paragraph) { 130 | EXPECT_EQ("

test

", Parse("test")); 131 | EXPECT_EQ("

test

", Parse("\ntest")); 132 | EXPECT_EQ("

.

", Parse(".")); 133 | EXPECT_EQ("

..test

", Parse("..test")); 134 | } 135 | 136 | TEST(ParserTest, LineBlock) { 137 | EXPECT_EQ("test", Parse("| test")); 138 | EXPECT_EQ(" abc\ndef", Parse("| abc\n| def")); 139 | } 140 | 141 | TEST(ParserTest, BlockQuote) { 142 | EXPECT_EQ("
test
", Parse(" test")); 143 | } 144 | 145 | TEST(ParserTest, PreserveInnerSpace) { 146 | EXPECT_EQ("

a b

", Parse("a b")); 147 | } 148 | 149 | TEST(ParserTest, ReplaceWhitespace) { 150 | EXPECT_EQ("

a b

", Parse("a\tb")); 151 | EXPECT_EQ("
a b
", Parse(" a\tb")); 152 | EXPECT_EQ("

a b

", Parse("a\vb")); 153 | } 154 | 155 | TEST(ParserTest, StripTrailingSpace) { 156 | EXPECT_EQ("

test

", Parse("test \t")); 157 | } 158 | 159 | TEST(ParserTest, MultiLineBlock) { 160 | EXPECT_EQ("

line 1\nline 2

", Parse("line 1\nline 2")); 161 | } 162 | 163 | TEST(ParserTest, UnindentBlock) { 164 | EXPECT_EQ("
abc

def

", Parse(" abc\ndef")); 165 | } 166 | 167 | TEST(ParserTest, BulletList) { 168 | EXPECT_EQ("
  • item
", Parse("* item")); 169 | EXPECT_EQ("
  • abc\ndef
", Parse("* abc\n def")); 170 | } 171 | 172 | TEST(ParserTest, Literal) { 173 | EXPECT_EQ("

abc:

def", Parse("abc::\n\n def")); 174 | EXPECT_EQ("abc\ndef", Parse("::\n\n abc\n def")); 175 | EXPECT_EQ("

abc\ndef

", Parse("::\n\nabc\ndef")); 176 | EXPECT_EQ("

::\nabc\ndef

", Parse("::\nabc\ndef")); 177 | } 178 | 179 | TEST(ParserTest, InlineCode) { 180 | EXPECT_EQ("

code

", Parse("``code``")); 181 | EXPECT_EQ("

`code``

", Parse("`code``")); 182 | EXPECT_EQ("

some code

", Parse("some ``code``")); 183 | EXPECT_EQ("

code some

", Parse("``code`` some")); 184 | EXPECT_EQ("

some code and more

", Parse("some ``code`` and more")); 185 | } 186 | 187 | TEST(ParserTest, Comment) { 188 | EXPECT_EQ("", Parse("..")); 189 | EXPECT_EQ("", Parse("..\n")); 190 | EXPECT_EQ("", Parse(".. comment")); 191 | EXPECT_EQ("", Parse(".. comment:")); 192 | } 193 | 194 | TEST(ParserTest, Directive) { 195 | EXPECT_EQ("
test
", Parse(".. test::")); 196 | EXPECT_EQ("
test
", Parse(".. test:: name")); 197 | EXPECT_EQ("
test
", Parse(".. test::")); 198 | EXPECT_EQ("
test
", Parse("..\ttest::")); 199 | 200 | EXPECT_EQ("
|from-text| replace
", Parse(".. |from-text| replace:: to-text")); 201 | 202 | std::string rst = 203 | R"(.. code-block:: c++ 204 | int main() { 205 | if (false) 206 | return 1; 207 | return 0; 208 | })"; 209 | 210 | std::string html = 211 | R"(
code-block
int main() { 212 | if (false) 213 | return 1; 214 | return 0; 215 | }
)"; 216 | 217 | EXPECT_EQ(html, Parse(rst.c_str())); 218 | 219 | rst = 220 | R"(.. note:: This is a cool 221 | note. Such a cool note.)"; 222 | 223 | html = 224 | R"(
note
This is a cool 225 | note. Such a cool note.
)"; 226 | 227 | EXPECT_EQ(html, Parse(rst.c_str())); 228 | } 229 | 230 | TEST(ParserTest, ReferenceLinks) { 231 | EXPECT_EQ("

info

", Parse(":ref:`info`")); 232 | EXPECT_EQ("

some info

", Parse("some :ref:`info`")); 233 | EXPECT_EQ("

some info and more

", Parse("some :ref:`info` and more")); 234 | EXPECT_EQ("

info.

", Parse(":ref:`info`.")); 235 | } 236 | 237 | 238 | int main(int argc, char **argv) { 239 | #ifdef _WIN32 240 | // Disable message boxes on assertion failures. 241 | _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); 242 | _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); 243 | _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); 244 | _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); 245 | #endif 246 | testing::InitGoogleTest(&argc, argv); 247 | return RUN_ALL_TESTS(); 248 | } 249 | -------------------------------------------------------------------------------- /3rdparty/rstparser/rstparser.h: -------------------------------------------------------------------------------- 1 | /* 2 | A reStructuredText parser written in C++. 3 | 4 | Copyright (c) 2013, Victor Zverovich 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef RSTPARSER_H_ 29 | #define RSTPARSER_H_ 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | namespace rst { 36 | 37 | enum BlockType { 38 | H1, 39 | H2, 40 | H3, 41 | H4, 42 | H5, 43 | CODE, 44 | REFERENCE_LINK, 45 | PARAGRAPH, 46 | LINE_BLOCK, 47 | BLOCK_QUOTE, 48 | BULLET_LIST, 49 | LIST_ITEM, 50 | LITERAL_BLOCK 51 | }; 52 | 53 | // Receive notification of the logical content of a document. 54 | class ContentHandler { 55 | public: 56 | virtual ~ContentHandler(); 57 | 58 | // Receives notification of the beginning of a text block. 59 | virtual void StartBlock(BlockType type) = 0; 60 | 61 | // Receives notification of the end of a text block. 62 | virtual void EndBlock() = 0; 63 | 64 | // Receives notification of text. 65 | virtual void HandleText(const char *text, std::size_t size) = 0; 66 | 67 | // Receives notification of a directive. 68 | virtual void HandleDirective(const std::string &type, const std::string &name) = 0; 69 | 70 | // Receives notification of a link. 71 | virtual void HandleReferenceLink(const std::string &type, const std::string &text) = 0; 72 | }; 73 | 74 | // A parser for a subset of reStructuredText. 75 | class Parser { 76 | private: 77 | ContentHandler *handler_; 78 | const char *ptr_; 79 | 80 | // Skips whitespace. 81 | void SkipSpace(); 82 | 83 | // Parses a directive type. 84 | std::string ParseDirectiveType(); 85 | 86 | // Parses a paragraph. 87 | void ParseParagraph(); 88 | 89 | // Changes the current block type sending notifications if necessary. 90 | void EnterBlock(rst::BlockType &prev_type, rst::BlockType type); 91 | 92 | // Parses a block of text. 93 | void ParseBlock(rst::BlockType type, rst::BlockType &prev_type, int indent); 94 | 95 | // Parses a line block. 96 | void ParseLineBlock(rst::BlockType &prev_type, int indent); 97 | 98 | // Parses inline ``code`` 99 | bool ParseCode(const char* s, std::size_t size, std::string &code); 100 | 101 | // Parses :reference:`link` 102 | bool ParseReferenceLink(const char* s, std::size_t size, std::string &type, std::string &text); 103 | 104 | public: 105 | explicit Parser(ContentHandler *h) : handler_(h), ptr_(0) {} 106 | 107 | // Parses a string containing reStructuredText and returns a document node. 108 | void Parse(const char *s); 109 | }; 110 | } 111 | 112 | #endif // RSTPARSER_H_ 113 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(CMakeProjectManager2) 4 | 5 | set(CMAKE_AUTOMOC ON) 6 | set(CMAKE_AUTORCC ON) 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_CXX_STANDARD 17) 9 | 10 | find_package(QtCreator REQUIRED COMPONENTS Core CppEditor ProjectExplorer TextEditor QtSupport) 11 | find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets) 12 | #find_package(QT NAMES Qt5 REQUIRED COMPONENTS Widgets) 13 | set(QtX Qt${QT_VERSION_MAJOR}) 14 | 15 | 16 | add_qtc_plugin(CMakeProjectManager2 17 | PLUGIN_CLASS CMakeProjectPlugin 18 | DEPENDS 19 | QtCreator::QmlJS 20 | QtCreator::app_version 21 | PLUGIN_DEPENDS 22 | QtCreator::CppEditor 23 | QtCreator::ProjectExplorer 24 | QtCreator::TextEditor 25 | QtCreator::QtSupport 26 | SYSTEM_INCLUDES 3dparty/cmake 27 | SOURCES 28 | builddirparameters.cpp builddirparameters.h 29 | cmake_global.h 30 | cmakeabstractprocessstep.cpp cmakeabstractprocessstep.h 31 | cmakeautocompleter.cpp cmakeautocompleter.h 32 | cmakebuildconfiguration.cpp cmakebuildconfiguration.h 33 | cmakebuildsystem.cpp cmakebuildsystem.h 34 | cmakebuildstep.cpp cmakebuildstep.h 35 | cmakebuildtarget.h 36 | cmakeconfigitem.cpp cmakeconfigitem.h 37 | cmakeeditor.cpp cmakeeditor.h 38 | cmakefilecompletionassist.cpp cmakefilecompletionassist.h 39 | cmakeformatter.cpp cmakeformatter.h 40 | cmakeindenter.cpp cmakeindenter.h 41 | cmakeinstallstep.cpp cmakeinstallstep.h 42 | cmakekitaspect.cpp cmakekitaspect.h 43 | cmakelocatorfilter.cpp cmakelocatorfilter.h 44 | cmakeparser.cpp cmakeparser.h 45 | cmakeprocess.cpp cmakeprocess.h 46 | cmakeproject.cpp cmakeproject.h 47 | cmakeproject.qrc 48 | cmakeprojectconstants.h 49 | cmakeprojectimporter.cpp cmakeprojectimporter.h 50 | cmakeprojectmanager.cpp cmakeprojectmanager.h 51 | cmakeprojectmanagertr.h 52 | cmakeprojectnodes.cpp cmakeprojectnodes.h 53 | cmakeprojectplugin.cpp cmakeprojectplugin.h 54 | cmakesettingspage.cpp cmakesettingspage.h 55 | cmakespecificsettings.cpp cmakespecificsettings.h 56 | cmaketool.cpp cmaketool.h 57 | cmaketoolmanager.cpp cmaketoolmanager.h 58 | cmaketoolsettingsaccessor.cpp cmaketoolsettingsaccessor.h 59 | configmodel.cpp configmodel.h 60 | configmodelitemdelegate.cpp configmodelitemdelegate.h 61 | fileapidataextractor.cpp fileapidataextractor.h 62 | fileapiparser.cpp fileapiparser.h 63 | fileapireader.cpp fileapireader.h 64 | presetsparser.cpp presetsparser.h 65 | presetsmacros.cpp presetsmacros.h 66 | projecttreehelper.cpp projecttreehelper.h 67 | simplefileapireader.cpp simplefileapireader.h 68 | 3rdparty/cmake/cmListFileCache.cxx 69 | 3rdparty/cmake/cmListFileLexer.cxx 70 | 3rdparty/cmake/cmListFileCache.h 71 | 3rdparty/rstparser/rstparser.cc 3rdparty/rstparser/rstparser.h 72 | ) 73 | 74 | 75 | # create install rule for resource directories 76 | install( 77 | DIRECTORY wizard/cmake2 78 | DESTINATION "${IDE_DATA_PATH}/templates/wizards/projects/" 79 | USE_SOURCE_PERMISSIONS 80 | ) 81 | 82 | -------------------------------------------------------------------------------- /CMakeProjectManager2.json.in: -------------------------------------------------------------------------------- 1 | { 2 | "Name" : "CMakeProjectManager2", 3 | "Version" : "${IDE_VERSION}", 4 | "CompatVersion" : "${IDE_VERSION_COMPAT}", 5 | "Vendor" : "Alexander Drozdov", 6 | "Copyright" : "(C) ${IDE_COPYRIGHT_YEAR} Alexander Drozdov", 7 | "License" : [ "Commercial Usage", 8 | "", 9 | "Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and The Qt Company.", 10 | "", 11 | "GNU General Public License Usage", 12 | "", 13 | "Alternatively, this plugin may be used under the terms of the GNU General Public License version 3 as published by the Free Software Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT included in the packaging of this plugin. Please review the following information to ensure the GNU General Public License requirements will be met: https://www.gnu.org/licenses/gpl-3.0.html." 14 | ], 15 | "Category" : "Build Systems", 16 | "Description" : "Enhanced CMake support.", 17 | "Url" : "https://github.com/h4tr3d/cmakeprojectmanager2", 18 | ${IDE_PLUGIN_DEPENDENCIES}, 19 | 20 | "Mimetypes" : [ 21 | "", 22 | "", 23 | " ", 24 | " ", 25 | " CMake Project file", 26 | " ", 27 | " ", 28 | " ", 29 | " ", 30 | " CMake Project file", 31 | " ", 32 | " ", 33 | "" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CMakeProjectManager2 2 | ==================== 3 | 4 | **NOTE: Project are discontinued and repository will be frozen. Use upstream plugin that started to be more usable that this one. Now it contains next killer features:** 5 | - **Edit relative target sources entries in the CMakeLists.txt when new files added/created** 6 | - **It still does not display all files, but it can be simple work arounded via adding needed files (without impact existing project structure): [https://github.com/h4tr3d/qtc-other-files-helper](https://github.com/h4tr3d/qtc-other-files-helper?tab=readme-ov-file#per-project-configuration-without-any-ide-impact) ([short description in Russian](https://htrd.su/blog/2023/08/18/qtc-other-files-helper/))** 7 | - **Vcpkg integration** 8 | 9 | Alternative CMake support for Qt Creator. 10 | 11 | Main differents from original CMakeProject plugin: 12 | 13 | * Project file list readed from file system instead of parsing .cbp (CodeBlocks) project file. 14 | It can be slow on big projects, but reloading initiating only during open project, run CMake, 15 | or user-initiated tree changes (add new files, erase files, rename file) 16 | * ~You can add new files from Qt Creator. Note, you can create file outside project tree, 17 | but Qt Creator will display only files that present in project tree. Also, you should 18 | manualy describe this files in CMakeLists.txt~ *NOTE:* done in the more proper way in the upstream. 19 | * ~You can rename files in file system from Qt Creator now.~ *NOTE:* done in the more proper way in the upstream. 20 | * ~You can erase files from files system from Qt Creator now.~ *NOTE:* done in the more proper way in the upstream. 21 | * Classic tree view for CMake Server mode (uses automatically with CMake >= 3.7) 22 | 23 | This functionality is not compatible with QtC Project View idea: **Project View == Build System view**. So, upstream accepts only changes that can be done via build system tools and API. 24 | CMake does not provide way to modify CMakeLists.txt and related files, add/remove/rename file to targets and so on. So such changes in plugin (different kinds of work arounds) will be 25 | dropped. But in my opinion: usability of IDE must be putted to first place. If some kind of WA that simplify work with CMake cab be implemented - it must be implemented. 26 | 27 | 28 | 29 | Build plugin 30 | ------------ 31 | 32 | This plugin is oriented to latest Git version of Qt Creator, sorry I use it and I have no time 33 | to support other stable versions. 34 | 35 | 36 | 37 | ### Prepare Qt Creator 38 | 39 | Commit 9d8a419d107ae8219c84bc9178bfed76b94fa930 of the Qt Creator completely remove build using `qmake`. So, instruction updated to build plugin with CMake. 40 | 41 | If you have QtC binary installation that contains `lib/cmake/QtCreator` and headers you should not do anything. 42 | 43 | Otherwise, you must get full copy of the Qt Creator from the Git, build it and install to some prefix. 44 | 45 | For example, all actions runs in directory `/tmp/qt-creator` 46 | 47 | - Take full Qt Creator source tree from Git: 48 | 49 | ```bash 50 | git clone https://github.com/qtproject/qt-creator.git qt-creator 51 | ``` 52 | 53 | - Create Qt Crator build tree: 54 | 55 | ```bash 56 | mkdir qt-creator-build 57 | cd qt-creator-build 58 | ``` 59 | 60 | - Create shadow build: 61 | 62 | ```bash 63 | cmake -DCMAKE_BUILD_TYPE=Release \ 64 | -DCMAKE_INSTALL_PREFIX=/opt/qtcreator-git \ 65 | -DCMAKE_PREFIX_PATH=/usr \ 66 | .. 67 | # CMAKE_PREFIX_PATH needed to point right location of the LLVM 68 | ``` 69 | 70 | - Build and install it 71 | 72 | ```bash 73 | cmake --build . -j 8 && \ 74 | sudo cmake --install . && \ 75 | sudo cmake --install . --component Devel 76 | # Devel strongly are needed 77 | ``` 78 | - Latest QtC missed `tl_expected` packages, copy it manually 79 | ```bash 80 | cp -a "$qtc_source/src/libs/3rdparty/tl_expected" "$PREFIX/include/qtcreator/src/libs/3rdparty/" 81 | ``` 82 | 83 | Also, refer to the next page for more details: 84 | 85 | * https://wiki.qt.io/Building-Qt-Creator-Packages 86 | 87 | 88 | 89 | ### Build plugin 90 | 91 | - Change directory to `/tmp/qt-creator` 92 | 93 | - Take sources of CMakeProjectManager2 from repository 94 | 95 | - Create directory for shadow build: 96 | ```bash 97 | mkdir cmakeprojectmanager2-build 98 | cd cmakeprojectmanager2-build 99 | ``` 100 | 101 | - Configure plugin: 102 | ```bash 103 | cmake -DCMAKE_PREFIX_PATH="/opt/qtcreator-git" \ 104 | -DCMAKE_INSTALL_PREFIX="/opt/qtcreator-git" \ 105 | ../cmakeprojectmanager2-git/ 106 | # CMAKE_PREFIX_PATH strogly needed if QtC installed to the non-default CMake prefix (/usr in most cases) 107 | ``` 108 | Build: 109 | 110 | ```bash 111 | cmake --build . -j 8 112 | ``` 113 | 114 | - Install 115 | 116 | ```bash 117 | sudo cmake --install . 118 | ``` 119 | 120 | Restart Qt Creator, go to Help -> About plugins and turn off default CMakeProjectManager plugin. 121 | 122 | 123 | 124 | ### Build plugin from Qt Creator 125 | 126 | - Open `cmakeprojectmanager2-git/CMakeLists.txt`, go to Projects layout (see left panel) 127 | - Look to Build Steps section and add next params for CMake: 128 | ```bash 129 | -DCMAKE_PREFIX_PATH="/opt/qtcreator-git" 130 | ``` 131 | 132 | Now you can build plugin from Qt Creator. 133 | 134 | Also, refer to the Qt Creator WiKi about plugins development: 135 | 136 | * https://doc.qt.io/qtcreator-extending/first-plugin.html 137 | * https://bugreports.qt.io/browse/QTCREATORBUG-22514 138 | 139 | 140 | 141 | Prebuilt binaries 142 | ----------------- 143 | 144 | Unsupported anymore. Sorry, just have no a time :-( 145 | 146 | 147 | 148 | TODO & Roadmap 149 | -------------- 150 | 151 | Actual tasks and todo can be looks at the Issue page: https://github.com/h4tr3d/cmakeprojectmanager2/issues 152 | 153 | 154 | 155 | Sync with Qt Creator upstream plugin 156 | ------------------------------------ 157 | 158 | 1. Update Qt Creator git repository, moves to the master branch 159 | 2. Create patches for new changes 160 | ``` 161 | git format-patch -- src/plugins/cmakeprojectmanager 162 | ``` 163 | REVISION_SINCE can be found via 'git log' by comments or Change-Id. 164 | 3. Go to CMakeProjectManager2 source tree and change branch to the `qtc-master` 165 | 4. Copy patches from the step 2 to the CMakeProjectManager2 source tree root 166 | 5. Apply patches: 167 | ``` 168 | git am -p4 *.patch 169 | ``` 170 | 6. Change branch to the `master`, merge new changes and resolve conflicts 171 | -------------------------------------------------------------------------------- /appy-patch.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Compose list to apply 4 | FILES= 5 | 6 | # Filter out some patches 7 | for p in *.patch 8 | do 9 | id=$(cat $p | grep 'Change-Id:') 10 | git log | grep "$id" > /dev/null 2>&1 11 | rez=$? 12 | if [ $rez -eq 1 ]; then 13 | FILES="$FILES $p" 14 | else 15 | echo "skip: $p" 16 | fi 17 | done 18 | 19 | if [ -z "$FILES" ]; then 20 | echo "no changes" 21 | exit 0 22 | fi 23 | 24 | echo "new changes:" 25 | for p in $FILES 26 | do 27 | echo " $p" 28 | done 29 | 30 | # Apply 31 | git am -p4 $FILES 32 | -------------------------------------------------------------------------------- /builddirparameters.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #include "builddirparameters.h" 5 | 6 | #include "cmakebuildconfiguration.h" 7 | #include "cmakebuildsystem.h" 8 | #include "cmakekitaspect.h" 9 | #include "cmaketoolmanager.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace ProjectExplorer; 21 | 22 | namespace CMakeProjectManager::Internal { 23 | 24 | BuildDirParameters::BuildDirParameters() = default; 25 | 26 | BuildDirParameters::BuildDirParameters(CMakeBuildSystem *buildSystem) 27 | { 28 | QTC_ASSERT(buildSystem, return); 29 | auto bc = buildSystem->cmakeBuildConfiguration(); 30 | QTC_ASSERT(bc, return); 31 | 32 | expander = bc->macroExpander(); 33 | 34 | const QStringList expandedArguments = Utils::transform(bc->initialCMakeArguments.allValues(), 35 | [this](const QString &s) { 36 | return expander->expand(s); 37 | }); 38 | initialCMakeArguments = Utils::filtered(expandedArguments, 39 | [](const QString &s) { return !s.isEmpty(); }); 40 | configurationChangesArguments = Utils::transform(buildSystem->configurationChangesArguments(), 41 | [this](const QString &s) { 42 | return expander->expand(s); 43 | }); 44 | additionalCMakeArguments = Utils::transform(bc->additionalCMakeArguments(), 45 | [this](const QString &s) { 46 | return expander->expand(s); 47 | }); 48 | const Target *t = bc->target(); 49 | const Kit *k = t->kit(); 50 | const Project *p = t->project(); 51 | 52 | projectName = p->displayName(); 53 | 54 | sourceDirectory = bc->sourceDirectory(); 55 | if (sourceDirectory.isEmpty()) 56 | sourceDirectory = p->projectDirectory(); 57 | buildDirectory = bc->buildDirectory(); 58 | 59 | cmakeBuildType = buildSystem->cmakeBuildType(); 60 | 61 | environment = bc->configureEnvironment(); 62 | // Disable distributed building for configuration runs. CMake does not do those in parallel, 63 | // so there is no win in sending data over the network. 64 | // Unfortunately distcc does not have a simple environment flag to turn it off:-/ 65 | if (Utils::HostOsInfo::isAnyUnixHost()) 66 | environment.set("ICECC", "no"); 67 | 68 | environment.set("QTC_RUN", "1"); 69 | environment.setFallback("CMAKE_COLOR_DIAGNOSTICS", "1"); 70 | environment.setFallback("CLICOLOR_FORCE", "1"); 71 | 72 | cmakeToolId = CMakeKitAspect::cmakeToolId(k); 73 | } 74 | 75 | bool BuildDirParameters::isValid() const 76 | { 77 | return cmakeTool(); 78 | } 79 | 80 | CMakeTool *BuildDirParameters::cmakeTool() const 81 | { 82 | return CMakeToolManager::findById(cmakeToolId); 83 | } 84 | 85 | } // CMakeProjectManager::Internal 86 | -------------------------------------------------------------------------------- /builddirparameters.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmaketool.h" 7 | 8 | #include 9 | #include 10 | 11 | namespace Utils { class MacroExpander; } 12 | 13 | namespace CMakeProjectManager::Internal { 14 | 15 | class CMakeBuildSystem; 16 | 17 | class BuildDirParameters 18 | { 19 | public: 20 | BuildDirParameters(); 21 | explicit BuildDirParameters(CMakeBuildSystem *buildSystem); 22 | 23 | bool isValid() const; 24 | CMakeTool *cmakeTool() const; 25 | 26 | QString projectName; 27 | 28 | Utils::FilePath sourceDirectory; 29 | Utils::FilePath buildDirectory; 30 | QString cmakeBuildType; 31 | 32 | Utils::Environment environment; 33 | 34 | Utils::Id cmakeToolId; 35 | 36 | QStringList initialCMakeArguments; 37 | QStringList configurationChangesArguments; 38 | QStringList additionalCMakeArguments; 39 | 40 | Utils::MacroExpander* expander = nullptr; 41 | }; 42 | 43 | } // CMakeProjectManager::Internal 44 | -------------------------------------------------------------------------------- /cmake_global.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Canonical Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #if defined(CMAKEPROJECTMANAGER_LIBRARY) 9 | # define CMAKE_EXPORT Q_DECL_EXPORT 10 | #elif defined(CMAKEPROJECTMANAGER_STATIC_LIBRARY) 11 | # define CMAKE_EXPORT 12 | #else 13 | # define CMAKE_EXPORT Q_DECL_IMPORT 14 | #endif 15 | -------------------------------------------------------------------------------- /cmakeabstractprocessstep.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #include "cmakeabstractprocessstep.h" 5 | 6 | #include "cmakekitaspect.h" 7 | #include "cmakeprojectmanagertr.h" 8 | #include "cmaketool.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace Core; 15 | using namespace ProjectExplorer; 16 | using namespace Utils; 17 | 18 | namespace CMakeProjectManager::Internal { 19 | 20 | // CMakeAbstractProcessStep 21 | 22 | CMakeAbstractProcessStep::CMakeAbstractProcessStep(BuildStepList *bsl, Utils::Id id) 23 | : AbstractProcessStep(bsl, id) 24 | {} 25 | 26 | bool CMakeAbstractProcessStep::init() 27 | { 28 | if (!AbstractProcessStep::init()) 29 | return false; 30 | 31 | BuildConfiguration *bc = buildConfiguration(); 32 | QTC_ASSERT(bc, return false); 33 | 34 | if (!bc->isEnabled()) { 35 | emit addTask( 36 | BuildSystemTask(Task::Error, Tr::tr("The build configuration is currently disabled."))); 37 | emitFaultyConfigurationMessage(); 38 | return false; 39 | } 40 | 41 | CMakeTool *tool = CMakeKitAspect::cmakeTool(kit()); 42 | if (!tool || !tool->isValid()) { 43 | emit addTask(BuildSystemTask(Task::Error, 44 | Tr::tr("A CMake tool must be set up for building. " 45 | "Configure a CMake tool in the kit options."))); 46 | emitFaultyConfigurationMessage(); 47 | return false; 48 | } 49 | 50 | // Warn if doing out-of-source builds with a CMakeCache.txt is the source directory 51 | const Utils::FilePath projectDirectory = bc->target()->project()->projectDirectory(); 52 | if (bc->buildDirectory() != projectDirectory) { 53 | if (projectDirectory.pathAppended("CMakeCache.txt").exists()) { 54 | emit addTask(BuildSystemTask( 55 | Task::Warning, 56 | Tr::tr("There is a CMakeCache.txt file in \"%1\", which suggest an " 57 | "in-source build was done before. You are now building in \"%2\", " 58 | "and the CMakeCache.txt file might confuse CMake.") 59 | .arg(projectDirectory.toUserOutput(), bc->buildDirectory().toUserOutput()))); 60 | } 61 | } 62 | 63 | return true; 64 | } 65 | 66 | } // namespace CMakeProjectManager::Internal 67 | -------------------------------------------------------------------------------- /cmakeabstractprocessstep.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace CMakeProjectManager::Internal { 9 | 10 | class CMakeAbstractProcessStep : public ProjectExplorer::AbstractProcessStep 11 | { 12 | Q_OBJECT 13 | public: 14 | CMakeAbstractProcessStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id); 15 | 16 | protected: 17 | bool init() override; 18 | }; 19 | 20 | 21 | } // namespace CMakeProjectManager::Internal 22 | -------------------------------------------------------------------------------- /cmakeautocompleter.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Jan Dalheimer 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #include "cmakeautocompleter.h" 5 | 6 | #include 7 | 8 | namespace CMakeProjectManager::Internal { 9 | 10 | CMakeAutoCompleter::CMakeAutoCompleter() 11 | { 12 | setAutoInsertBracketsEnabled(true); 13 | } 14 | 15 | bool CMakeAutoCompleter::isInComment(const QTextCursor &cursor) const 16 | { 17 | // NOTE: This doesn't handle '#' inside quotes, nor multi-line comments 18 | QTextCursor moved = cursor; 19 | moved.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); 20 | return moved.selectedText().contains(QLatin1Char('#')); 21 | } 22 | 23 | bool CMakeAutoCompleter::isInString(const QTextCursor &cursor) const 24 | { 25 | // NOTE: multiline strings are currently not supported, since they rarely, if ever, seem to be used 26 | QTextCursor moved = cursor; 27 | moved.movePosition(QTextCursor::StartOfLine); 28 | const int positionInLine = cursor.position() - moved.position(); 29 | moved.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor); 30 | const QString line = moved.selectedText(); 31 | 32 | bool isEscaped = false; 33 | bool inString = false; 34 | for (int i = 0; i < positionInLine; ++i) { 35 | const QChar c = line.at(i); 36 | if (c == QLatin1Char('\\') && !isEscaped) 37 | isEscaped = true; 38 | else if (c == QLatin1Char('"') && !isEscaped) 39 | inString = !inString; 40 | else 41 | isEscaped = false; 42 | } 43 | return inString; 44 | } 45 | 46 | QString CMakeAutoCompleter::insertMatchingBrace(const QTextCursor &cursor, 47 | const QString &text, 48 | QChar lookAhead, 49 | bool skipChars, 50 | int *skippedChars) const 51 | { 52 | Q_UNUSED(cursor) 53 | if (text.isEmpty()) 54 | return QString(); 55 | const QChar current = text.at(0); 56 | switch (current.unicode()) { 57 | case '(': 58 | return QStringLiteral(")"); 59 | 60 | case ')': 61 | if (current == lookAhead && skipChars) 62 | ++*skippedChars; 63 | break; 64 | 65 | default: 66 | break; 67 | } 68 | 69 | return QString(); 70 | } 71 | 72 | QString CMakeAutoCompleter::insertMatchingQuote(const QTextCursor &cursor, 73 | const QString &text, 74 | QChar lookAhead, 75 | bool skipChars, 76 | int *skippedChars) const 77 | { 78 | Q_UNUSED(cursor) 79 | static const QChar quote(QLatin1Char('"')); 80 | if (text.isEmpty() || text != quote) 81 | return QString(); 82 | if (lookAhead == quote && skipChars) { 83 | ++*skippedChars; 84 | return QString(); 85 | } 86 | return quote; 87 | } 88 | 89 | int CMakeAutoCompleter::paragraphSeparatorAboutToBeInserted(QTextCursor &cursor) 90 | { 91 | const QString line = cursor.block().text().trimmed(); 92 | if (line.contains(QRegularExpression(QStringLiteral("^(endfunction|endmacro|endif|endforeach|endwhile|endblock)\\w*\\(")))) 93 | tabSettings().indentLine(cursor.block(), tabSettings().indentationColumn(cursor.block().text())); 94 | return 0; 95 | } 96 | 97 | bool CMakeAutoCompleter::contextAllowsAutoBrackets(const QTextCursor &cursor, 98 | const QString &textToInsert) const 99 | { 100 | if (textToInsert.isEmpty()) 101 | return false; 102 | 103 | const QChar c = textToInsert.at(0); 104 | if (c == QLatin1Char('(') || c == QLatin1Char(')')) 105 | return !isInComment(cursor); 106 | return false; 107 | } 108 | 109 | bool CMakeAutoCompleter::contextAllowsAutoQuotes(const QTextCursor &cursor, const QString &textToInsert) const 110 | { 111 | if (textToInsert.isEmpty()) 112 | return false; 113 | 114 | const QChar c = textToInsert.at(0); 115 | if (c == QLatin1Char('"')) 116 | return !isInComment(cursor); 117 | return false; 118 | } 119 | 120 | bool CMakeAutoCompleter::contextAllowsElectricCharacters(const QTextCursor &cursor) const 121 | { 122 | return !isInComment(cursor) && !isInString(cursor); 123 | } 124 | 125 | } // CMakeProjectManager::Internal 126 | -------------------------------------------------------------------------------- /cmakeautocompleter.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Jan Dalheimer 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmake_global.h" 7 | 8 | #include 9 | 10 | namespace CMakeProjectManager::Internal { 11 | 12 | class CMAKE_EXPORT CMakeAutoCompleter : public TextEditor::AutoCompleter 13 | { 14 | public: 15 | CMakeAutoCompleter(); 16 | 17 | bool isInComment(const QTextCursor &cursor) const override; 18 | bool isInString(const QTextCursor &cursor) const override; 19 | QString insertMatchingBrace(const QTextCursor &cursor, const QString &text, 20 | QChar lookAhead, bool skipChars, int *skippedChars) const override; 21 | QString insertMatchingQuote(const QTextCursor &cursor, const QString &text, 22 | QChar lookAhead, bool skipChars, int *skippedChars) const override; 23 | int paragraphSeparatorAboutToBeInserted(QTextCursor &cursor) override; 24 | bool contextAllowsAutoBrackets(const QTextCursor &cursor, const QString &textToInsert) const override; 25 | bool contextAllowsAutoQuotes(const QTextCursor &cursor, const QString &textToInsert) const override; 26 | bool contextAllowsElectricCharacters(const QTextCursor &cursor) const override; 27 | }; 28 | 29 | } // CMakeProjectManager::Internal 30 | -------------------------------------------------------------------------------- /cmakebuildconfiguration.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmake_global.h" 7 | #include "cmakeconfigitem.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | namespace CMakeProjectManager { 16 | class CMakeProject; 17 | 18 | namespace Internal { 19 | 20 | class CMakeBuildSystem; 21 | class CMakeBuildSettingsWidget; 22 | class CMakeProjectImporter; 23 | 24 | class InitialCMakeArgumentsAspect final : public Utils::StringAspect 25 | { 26 | public: 27 | InitialCMakeArgumentsAspect(Utils::AspectContainer *container); 28 | 29 | const CMakeConfig &cmakeConfiguration() const; 30 | const QStringList allValues() const; 31 | void setAllValues(const QString &values, QStringList &additionalArguments); 32 | void setCMakeConfiguration(const CMakeConfig &config); 33 | 34 | void fromMap(const Utils::Store &map) final; 35 | void toMap(Utils::Store &map) const final; 36 | 37 | private: 38 | CMakeConfig m_cmakeConfiguration; 39 | }; 40 | 41 | class ConfigureEnvironmentAspect final: public ProjectExplorer::EnvironmentAspect 42 | { 43 | public: 44 | ConfigureEnvironmentAspect(Utils::AspectContainer *container, 45 | ProjectExplorer::BuildConfiguration *buildConfig); 46 | 47 | void fromMap(const Utils::Store &map) override; 48 | void toMap(Utils::Store &map) const override; 49 | }; 50 | 51 | } // namespace Internal 52 | 53 | class CMAKE_EXPORT CMakeBuildConfiguration : public ProjectExplorer::BuildConfiguration 54 | { 55 | Q_OBJECT 56 | 57 | public: 58 | CMakeBuildConfiguration(ProjectExplorer::Target *target, Utils::Id id); 59 | ~CMakeBuildConfiguration() override; 60 | 61 | static Utils::FilePath 62 | shadowBuildDirectory(const Utils::FilePath &projectFilePath, const ProjectExplorer::Kit *k, 63 | const QString &bcName, BuildConfiguration::BuildType buildType); 64 | static bool isIos(const ProjectExplorer::Kit *k); 65 | static bool hasQmlDebugging(const CMakeConfig &config); 66 | 67 | // Context menu action: 68 | void buildTarget(const QString &buildTarget); 69 | ProjectExplorer::BuildSystem *buildSystem() const final; 70 | 71 | void addToEnvironment(Utils::Environment &env) const override; 72 | 73 | Utils::Environment configureEnvironment() const; 74 | Internal::CMakeBuildSystem *cmakeBuildSystem() const; 75 | 76 | QStringList additionalCMakeArguments() const; 77 | void setAdditionalCMakeArguments(const QStringList &args); 78 | 79 | void setInitialCMakeArguments(const QStringList &args); 80 | void setCMakeBuildType(const QString &cmakeBuildType, bool quiet = false); 81 | 82 | Internal::InitialCMakeArgumentsAspect initialCMakeArguments{this}; 83 | Utils::StringAspect additionalCMakeOptions{this}; 84 | Utils::FilePathAspect sourceDirectory{this}; 85 | Utils::StringAspect buildTypeAspect{this}; 86 | QtSupport::QmlDebuggingAspect qmlDebugging{this}; 87 | Internal::ConfigureEnvironmentAspect configureEnv{this, this}; 88 | 89 | signals: 90 | void signingFlagsChanged(); 91 | void configureEnvironmentChanged(); 92 | 93 | private: 94 | BuildType buildType() const override; 95 | 96 | ProjectExplorer::NamedWidget *createConfigWidget() override; 97 | 98 | virtual CMakeConfig signingFlags() const; 99 | 100 | void setInitialBuildAndCleanSteps(const ProjectExplorer::Target *target); 101 | void setBuildPresetToBuildSteps(const ProjectExplorer::Target *target); 102 | void filterConfigArgumentsFromAdditionalCMakeArguments(); 103 | 104 | Internal::CMakeBuildSystem *m_buildSystem = nullptr; 105 | 106 | friend class Internal::CMakeBuildSettingsWidget; 107 | friend class Internal::CMakeBuildSystem; 108 | }; 109 | 110 | class CMAKE_EXPORT CMakeBuildConfigurationFactory 111 | : public ProjectExplorer::BuildConfigurationFactory 112 | { 113 | public: 114 | CMakeBuildConfigurationFactory(); 115 | 116 | enum BuildType { 117 | BuildTypeNone = 0, 118 | BuildTypeDebug = 1, 119 | BuildTypeRelease = 2, 120 | BuildTypeRelWithDebInfo = 3, 121 | BuildTypeProfile = 4, 122 | BuildTypeMinSizeRel = 5, 123 | BuildTypeLast = 6 124 | }; 125 | static BuildType buildTypeFromByteArray(const QByteArray &in); 126 | static ProjectExplorer::BuildConfiguration::BuildType cmakeBuildTypeToBuildType(const BuildType &in); 127 | 128 | private: 129 | static ProjectExplorer::BuildInfo createBuildInfo(BuildType buildType); 130 | 131 | friend class Internal::CMakeProjectImporter; 132 | }; 133 | 134 | } // namespace CMakeProjectManager 135 | -------------------------------------------------------------------------------- /cmakebuildstep.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmakeabstractprocessstep.h" 7 | #include 8 | 9 | namespace Utils { 10 | class CommandLine; 11 | class StringAspect; 12 | } // Utils 13 | 14 | namespace CMakeProjectManager::Internal { 15 | 16 | class CMakeBuildStep; 17 | 18 | class CMakeTargetItem : public Utils::TreeItem 19 | { 20 | public: 21 | CMakeTargetItem() = default; 22 | CMakeTargetItem(const QString &target, CMakeBuildStep *step, bool special); 23 | 24 | private: 25 | QVariant data(int column, int role) const final; 26 | bool setData(int column, const QVariant &data, int role) final; 27 | Qt::ItemFlags flags(int column) const final; 28 | 29 | QString m_target; 30 | CMakeBuildStep *m_step = nullptr; 31 | bool m_special = false; 32 | }; 33 | 34 | class CMakeBuildStep : public CMakeAbstractProcessStep 35 | { 36 | Q_OBJECT 37 | 38 | public: 39 | CMakeBuildStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id); 40 | 41 | QStringList buildTargets() const; 42 | void setBuildTargets(const QStringList &target); 43 | 44 | bool buildsBuildTarget(const QString &target) const; 45 | void setBuildsBuildTarget(const QString &target, bool on); 46 | 47 | void toMap(Utils::Store &map) const override; 48 | 49 | QString cleanTarget() const; 50 | QString allTarget() const ; 51 | QString installTarget() const; 52 | static QStringList specialTargets(bool allCapsTargets); 53 | 54 | QString activeRunConfigTarget() const; 55 | 56 | void setBuildPreset(const QString &preset); 57 | 58 | Utils::Environment environment() const; 59 | void setUserEnvironmentChanges(const Utils::EnvironmentItems &diff); 60 | Utils::EnvironmentItems userEnvironmentChanges() const; 61 | bool useClearEnvironment() const; 62 | void setUseClearEnvironment(bool b); 63 | void updateAndEmitEnvironmentChanged(); 64 | 65 | Utils::Environment baseEnvironment() const; 66 | QString baseEnvironmentText() const; 67 | 68 | void setCMakeArguments(const QStringList &cmakeArguments); 69 | void setToolArguments(const QStringList &nativeToolArguments); 70 | 71 | void setConfiguration(const QString &configuration); 72 | 73 | Utils::StringAspect cmakeArguments{this}; 74 | Utils::StringAspect toolArguments{this}; 75 | Utils::BoolAspect useiOSAutomaticProvisioningUpdates{this}; 76 | Utils::BoolAspect useStaging{this}; 77 | Utils::FilePathAspect stagingDir{this}; 78 | 79 | signals: 80 | void buildTargetsChanged(); 81 | void environmentChanged(); 82 | 83 | private: 84 | Utils::CommandLine cmakeCommand() const; 85 | 86 | void fromMap(const Utils::Store &map) override; 87 | 88 | bool init() override; 89 | void setupOutputFormatter(Utils::OutputFormatter *formatter) override; 90 | Tasking::GroupItem runRecipe() final; 91 | QWidget *createConfigWidget() override; 92 | 93 | Utils::FilePath cmakeExecutable() const; 94 | QString currentInstallPrefix() const; 95 | 96 | QString defaultBuildTarget() const; 97 | bool isCleanStep() const; 98 | 99 | void handleBuildTargetsChanges(bool success); 100 | void recreateBuildTargetsModel(); 101 | void updateBuildTargetsModel(); 102 | void updateDeploymentData(); 103 | 104 | friend class CMakeBuildStepConfigWidget; 105 | QStringList m_buildTargets; // Convention: Empty string member signifies "Current executable" 106 | 107 | QString m_allTarget = "all"; 108 | QString m_installTarget = "install"; 109 | 110 | Utils::TreeModel m_buildTargetModel; 111 | 112 | Utils::Environment m_environment; 113 | Utils::EnvironmentItems m_userEnvironmentChanges; 114 | bool m_clearSystemEnvironment = false; 115 | QString m_buildPreset; 116 | std::optional m_configuration; 117 | }; 118 | 119 | class CMakeBuildStepFactory : public ProjectExplorer::BuildStepFactory 120 | { 121 | public: 122 | CMakeBuildStepFactory(); 123 | }; 124 | 125 | } // CMakeProjectManager::Internal 126 | -------------------------------------------------------------------------------- /cmakebuildsystem.md: -------------------------------------------------------------------------------- 1 | # `CMakeBuildSystem` 2 | 3 | ## Big Picture: `BuildSystem` 4 | 5 | This is a sequence diagram of how `ProjectExplorer::BuildSystem` interacts with 6 | its implementations: 7 | 8 | ```mermaid 9 | sequenceDiagram 10 | User ->> BuildSystemImpl: provide data and ask for parse (impl. defined!) 11 | BuildSystemImpl ->> BuildSystem: call requestParse() or requestDelayedParse() 12 | activate BuildSystem 13 | BuildSystem ->> BuildSys tem: m_delayedParsingTimer sends timeout() 14 | BuildSystem ->> BuildSystemImpl: call triggerParsing() 15 | deactivate BuildSystem 16 | activate BuildSystemImpl 17 | BuildSystemImpl ->> BuildSystem: call guardParsingRun() 18 | activate BuildSystem 19 | BuildSystem ->> ParseGuard: Construct 20 | activate ParseGuard 21 | ParseGuard ->> BuildSystem: call emitParsingStarted 22 | BuildSystem ->> User: signal parsingStarted() 23 | BuildSystem ->> BuildSystemImpl: Hand over ParseGuard 24 | deactivate BuildSystem 25 | BuildSystemImpl ->> BuildSystemImpl: Do parsing 26 | opt Report Success 27 | BuildSystemImpl ->> ParseGuard: markAsSuccess() 28 | end 29 | BuildSystemImpl ->> ParseGuard: Destruct 30 | ParseGuard ->> BuildSystem: emitParsingFinished() 31 | activate BuildSystem 32 | BuildSystem ->> User: Signal ParsingFinished(...) 33 | deactivate BuildSystem 34 | deactivate ParseGuard 35 | deactivate BuildSystemImpl 36 | ``` 37 | 38 | ## The Details of `CMakeBuildSystem` 39 | 40 | ### States Overview 41 | 42 | ```mermaid 43 | graph TD 44 | parse --> TreeScanner::asyncScanForFiles 45 | 46 | parse --> FileApiReader::parse 47 | FileApiReader::parse --> handleParsingSucceeded 48 | handleParsingSucceeded --> combineScanAndParse 49 | FileApiReader::parse --> handleParsingFailed 50 | handleParsingFailed --> combineScanAndParse 51 | 52 | TreeScanner::asyncScanForFiles --> handleTreeScanningFinished 53 | handleTreeScanningFinished --> combineScanAndParse 54 | ``` 55 | 56 | ### Full Sequence Diagram 57 | 58 | ```mermaid 59 | sequenceDiagram 60 | participant User 61 | participant ParseGuard 62 | participant CMakeBuildSystem 63 | participant FileApiReader 64 | 65 | alt Trigger Parsing 66 | User ->> CMakeBuildSystem: Any of the Actions defined for CMakeBuildSystem 67 | else 68 | User ->> CMakeBuildSystem: Signal from outside the CMakeBuildSystem 69 | end 70 | activate CMakeBuildSystem 71 | CMakeBuildSystem ->> CMakeBuildSystem: call setParametersAndRequestReparse() 72 | CMakeBuildSystem ->> CMakeBuildSystem: Validate parameters 73 | CMakeBuildSystem ->> FileApiReader: Construct 74 | activate FileApiReader 75 | CMakeBuildSystem ->> FileApiReader: call setParameters 76 | CMakeBuildSystem ->> CMakeBuildSystem: call request*Reparse() 77 | deactivate CMakeBuildSystem 78 | 79 | CMakeBuildSystem ->> CMakeBuildSystem: m_delayedParsingTimer sends timeout() triggering triggerParsing() 80 | 81 | activate CMakeBuildSystem 82 | 83 | CMakeBuildSystem ->>+ CMakeBuildSystem: call guardParsingRun() 84 | CMakeBuildSystem ->> ParseGuard: Construct 85 | activate ParseGuard 86 | ParseGuard ->> CMakeBuildSystem: call emitParsingStarted 87 | CMakeBuildSystem ->> User: signal parsingStarted() 88 | CMakeBuildSystem ->>- CMakeBuildSystem: Hand over ParseGuard 89 | 90 | CMakeBuildSystem ->>+ TreeScanner: call asyncScanForFiles() 91 | 92 | CMakeBuildSystem ->>+ FileApiReader: call parse(...) 93 | FileApiReader ->> FileApiReader: startState() 94 | deactivate CMakeBuildSystem 95 | 96 | opt Parse 97 | FileApiReader ->> FileApiReader: call startCMakeState(...) 98 | FileApiReader ->> FileApiReader: call cmakeFinishedState(...) 99 | end 100 | 101 | FileApiReader ->> FileApiReader: call endState(...) 102 | 103 | alt Return Result from FileApiReader 104 | FileApiReader ->> CMakeBuildSystem: signal dataAvailable() and trigger handleParsingSucceeded() 105 | CMakeBuildSystem ->> FileApiReader: call takeBuildTargets() 106 | CMakeBuildSystem ->> FileApiReader: call takeParsedConfiguration(....) 107 | else 108 | FileApiReader ->> CMakeBuildSystem: signal errorOccurred(...) and trigger handelParsingFailed(...) 109 | CMakeBuildSystem ->> FileApiReader: call takeParsedConfiguration(....) 110 | end 111 | 112 | deactivate FileApiReader 113 | Note right of CMakeBuildSystem: TreeScanner is still missing here 114 | CMakeBuildSystem ->> CMakeBuildSystem: call combineScanAndParse() 115 | 116 | TreeScanner ->> CMakeBuildSystem: signal finished() triggering handleTreeScanningFinished() 117 | CMakeBuildSystem ->> TreeScanner: call release() to get files 118 | deactivate TreeScanner 119 | Note right of CMakeBuildSystem: All results are in now... 120 | CMakeBuildSystem ->> CMakeBuildSystem: call combineScanAndParse() 121 | 122 | activate CMakeBuildSystem 123 | opt: Parsing was a success 124 | CMakeBuildSystem ->> CMakeBuildSystem: call updateProjectData() 125 | CMakeBuildSystem ->> FileApiReader: call projectFilesToWatch() 126 | CMakeBuildSystem ->> FileApiReader: call createRawProjectParts(...) 127 | CMakeBuildSystem ->> FileApiReader: call resetData() 128 | CMakeBuildSystem ->> ParseGuard: call markAsSuccess() 129 | end 130 | 131 | CMakeBuildSystem ->> ParseGuard: Destruct 132 | deactivate ParseGuard 133 | 134 | CMakeBuildSystem ->> CMakeBuildSystem: call emitBuildSystemUpdated() 135 | deactivate FileApiReader 136 | deactivate CMakeBuildSystem 137 | ``` 138 | 139 | # `FileApiReader` 140 | 141 | States in the `FileApiReader`. 142 | 143 | ```mermaid 144 | graph TD 145 | startState --> startCMakeState 146 | startState --> endState 147 | startCMakeState --> cmakeFinishedState 148 | cmakeFinishedState --> endState 149 | ``` 150 | 151 | -------------------------------------------------------------------------------- /cmakebuildtarget.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmake_global.h" 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace CMakeProjectManager { 16 | 17 | enum TargetType { 18 | ExecutableType, 19 | StaticLibraryType, 20 | DynamicLibraryType, 21 | ObjectLibraryType, 22 | UtilityType 23 | }; 24 | 25 | using Backtrace = QVector; 26 | using Backtraces = QVector; 27 | 28 | class CMAKE_EXPORT CMakeBuildTarget 29 | { 30 | public: 31 | QString title; 32 | Utils::FilePath executable; // TODO: rename to output? 33 | TargetType targetType = UtilityType; 34 | bool linksToQtGui = false; 35 | bool qtcRunnable = true; 36 | Utils::FilePath workingDirectory; 37 | Utils::FilePath sourceDirectory; 38 | Utils::FilePath makeCommand; 39 | Utils::FilePaths libraryDirectories; 40 | 41 | Backtrace backtrace; 42 | 43 | Backtraces dependencyDefinitions; 44 | Backtraces sourceDefinitions; 45 | Backtraces defineDefinitions; 46 | Backtraces includeDefinitions; 47 | Backtraces installDefinitions; 48 | 49 | // code model 50 | QList includeFiles; 51 | QStringList compilerOptions; 52 | ProjectExplorer::Macros macros; 53 | QList files; 54 | }; 55 | 56 | } // namespace CMakeProjectManager 57 | -------------------------------------------------------------------------------- /cmakeconfigitem.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmake_global.h" 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | namespace Utils { 14 | class FilePath; 15 | class MacroExpander; 16 | } // namespace Utils 17 | 18 | namespace ProjectExplorer { 19 | class Kit; 20 | } 21 | 22 | namespace CMakeProjectManager { 23 | 24 | class CMAKE_EXPORT CMakeConfigItem 25 | { 26 | public: 27 | enum Type { FILEPATH, PATH, BOOL, STRING, INTERNAL, STATIC, UNINITIALIZED }; 28 | CMakeConfigItem(); 29 | CMakeConfigItem(const QByteArray &k, Type t, const QByteArray &d, const QByteArray &v, const QStringList &s = {}); 30 | CMakeConfigItem(const QByteArray &k, Type t, const QByteArray &v); 31 | CMakeConfigItem(const QByteArray &k, const QByteArray &v); 32 | 33 | static QStringList cmakeSplitValue(const QString &in, bool keepEmpty = false); 34 | static Type typeStringToType(const QByteArray &typeString); 35 | static QString typeToTypeString(const Type t); 36 | static std::optional toBool(const QString &value); 37 | bool isNull() const { return key.isEmpty(); } 38 | 39 | QString expandedValue(const ProjectExplorer::Kit *k) const; 40 | QString expandedValue(const Utils::MacroExpander *expander) const; 41 | 42 | static bool less(const CMakeConfigItem &a, const CMakeConfigItem &b); 43 | static CMakeConfigItem fromString(const QString &s); 44 | QString toString(const Utils::MacroExpander *expander = nullptr) const; 45 | QString toArgument() const; 46 | QString toArgument(const Utils::MacroExpander *expander) const; 47 | QString toCMakeSetLine(const Utils::MacroExpander *expander = nullptr) const; 48 | 49 | bool operator==(const CMakeConfigItem &o) const; 50 | friend size_t qHash(const CMakeConfigItem &it); // needed for MSVC 51 | 52 | QByteArray key; 53 | Type type = STRING; 54 | bool isAdvanced = false; 55 | bool inCMakeCache = false; 56 | bool isUnset = false; 57 | bool isInitial = false; 58 | QByteArray value; // converted to string as needed 59 | QByteArray documentation; 60 | QStringList values; 61 | }; 62 | 63 | class CMAKE_EXPORT CMakeConfig : public QList 64 | { 65 | public: 66 | CMakeConfig() = default; 67 | CMakeConfig(const QList &items) : QList(items) {} 68 | CMakeConfig(std::initializer_list items) : QList(items) {} 69 | 70 | const QList &toList() const { return *this; } 71 | 72 | static CMakeConfig fromArguments(const QStringList &list, QStringList &unknownOptions); 73 | static CMakeConfig fromFile(const Utils::FilePath &input, QString *errorMessage); 74 | 75 | QByteArray valueOf(const QByteArray &key) const; 76 | QString stringValueOf(const QByteArray &key) const; 77 | Utils::FilePath filePathValueOf(const QByteArray &key) const; 78 | QString expandedValueOf(const ProjectExplorer::Kit *k, const QByteArray &key) const; 79 | }; 80 | 81 | } // namespace CMakeProjectManager 82 | -------------------------------------------------------------------------------- /cmakeeditor.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace CMakeProjectManager::Internal { 9 | 10 | class CMakeEditorFactory : public TextEditor::TextEditorFactory 11 | { 12 | public: 13 | CMakeEditorFactory(); 14 | }; 15 | 16 | } // CMakeProjectManager::Internal 17 | -------------------------------------------------------------------------------- /cmakefilecompletionassist.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace CMakeProjectManager::Internal { 9 | 10 | class CMakeFileCompletionAssistProvider : public TextEditor::CompletionAssistProvider 11 | { 12 | public: 13 | TextEditor::IAssistProcessor *createProcessor(const TextEditor::AssistInterface *) const final; 14 | int activationCharSequenceLength() const final; 15 | bool isActivationCharSequence(const QString &sequence) const final; 16 | }; 17 | 18 | } // CMakeProjectManager::Internal 19 | -------------------------------------------------------------------------------- /cmakeformatter.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Lorenz Haas 2 | // Copyright (C) 2022 Xavier BESSON 3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 4 | 5 | #pragma once 6 | 7 | namespace Core { class IDocument; } 8 | 9 | namespace CMakeProjectManager::Internal { 10 | 11 | class CMakeFormatter 12 | { 13 | public: 14 | CMakeFormatter(); 15 | }; 16 | 17 | } // CMakeProjectManager::Internal 18 | -------------------------------------------------------------------------------- /cmakeindenter.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Jan Dalheimer 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #include "cmakeindenter.h" 5 | 6 | namespace CMakeProjectManager::Internal { 7 | 8 | CMakeIndenter::CMakeIndenter(QTextDocument *doc) 9 | : TextEditor::TextIndenter(doc) 10 | {} 11 | 12 | bool CMakeIndenter::isElectricCharacter(const QChar &ch) const 13 | { 14 | return ch == QLatin1Char('(') || ch == QLatin1Char(')'); 15 | } 16 | 17 | static int startsWithChar(const QString &line, char character) 18 | { 19 | int occurrences = 0; 20 | for (int i = 0; i < line.size(); ++i) { 21 | if (line.at(i) == character) { 22 | occurrences++; 23 | } else if (!line.at(i).isSpace()) { 24 | break; 25 | } 26 | } 27 | return occurrences; 28 | } 29 | 30 | static bool lineContainsFunction(const QString &line, const QString &function) 31 | { 32 | const int indexOfFunction = line.indexOf(function); 33 | if (indexOfFunction == -1) 34 | return false; 35 | for (int i = 0; i < indexOfFunction; ++i) { 36 | if (!line.at(i).isSpace()) 37 | return false; 38 | } 39 | for (int i = indexOfFunction + function.size(); i < line.size(); ++i) { 40 | if (line.at(i) == QLatin1Char('(')) 41 | return true; 42 | else if (!line.at(i).isSpace()) 43 | return false; 44 | } 45 | return false; 46 | } 47 | static bool lineStartsBlock(const QString &line) 48 | { 49 | return lineContainsFunction(line, QStringLiteral("function")) || 50 | lineContainsFunction(line, QStringLiteral("macro")) || 51 | lineContainsFunction(line, QStringLiteral("foreach")) || 52 | lineContainsFunction(line, QStringLiteral("while")) || 53 | lineContainsFunction(line, QStringLiteral("if")) || 54 | lineContainsFunction(line, QStringLiteral("elseif")) || 55 | lineContainsFunction(line, QStringLiteral("else")) || 56 | lineContainsFunction(line, QStringLiteral("block")); 57 | } 58 | static bool lineEndsBlock(const QString &line) 59 | { 60 | return lineContainsFunction(line, QStringLiteral("endfunction")) || 61 | lineContainsFunction(line, QStringLiteral("endmacro")) || 62 | lineContainsFunction(line, QStringLiteral("endforeach")) || 63 | lineContainsFunction(line, QStringLiteral("endwhile")) || 64 | lineContainsFunction(line, QStringLiteral("endif")) || 65 | lineContainsFunction(line, QStringLiteral("elseif")) || 66 | lineContainsFunction(line, QStringLiteral("else")) || 67 | lineContainsFunction(line, QStringLiteral("endblock")); 68 | } 69 | static bool lineIsEmpty(const QString &line) 70 | { 71 | for (const QChar &c : line) { 72 | if (!c.isSpace()) 73 | return false; 74 | } 75 | return true; 76 | } 77 | 78 | static int paranthesesLevel(const QString &line) 79 | { 80 | const QString beforeComment = line.mid(0, line.indexOf(QLatin1Char('#'))); 81 | const int opening = beforeComment.count(QLatin1Char('(')); 82 | const int closing = beforeComment.count(QLatin1Char(')')); 83 | 84 | return opening - closing; 85 | } 86 | 87 | int CMakeIndenter::indentFor(const QTextBlock &block, 88 | const TextEditor::TabSettings &tabSettings, 89 | int /*cursorPositionInEditor*/) 90 | { 91 | QTextBlock previousBlock = block.previous(); 92 | // find the next previous block that is non-empty (contains non-whitespace characters) 93 | while (previousBlock.isValid() && lineIsEmpty(previousBlock.text())) 94 | previousBlock = previousBlock.previous(); 95 | if (!previousBlock.isValid()) 96 | return 0; 97 | 98 | const QString previousLine = previousBlock.text(); 99 | const QString currentLine = block.text(); 100 | int indentation = tabSettings.indentationColumn(previousLine); 101 | 102 | if (lineStartsBlock(previousLine)) 103 | indentation += tabSettings.m_indentSize; 104 | if (lineEndsBlock(currentLine)) 105 | indentation -= tabSettings.m_indentSize; 106 | 107 | // de-dent lines that start with closing parantheses immediately 108 | indentation -= tabSettings.m_indentSize * startsWithChar(currentLine, ')'); 109 | 110 | if (int paranthesesCount = paranthesesLevel(previousLine) - startsWithChar(previousLine, ')')) 111 | indentation += tabSettings.m_indentSize * (paranthesesCount > 0 ? 1 : -1); 112 | return qMax(0, indentation); 113 | } 114 | 115 | } // CMakeProjectManager::Internal 116 | -------------------------------------------------------------------------------- /cmakeindenter.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Jan Dalheimer 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmake_global.h" 7 | 8 | #include 9 | 10 | namespace CMakeProjectManager::Internal { 11 | 12 | class CMAKE_EXPORT CMakeIndenter : public TextEditor::TextIndenter 13 | { 14 | public: 15 | explicit CMakeIndenter(QTextDocument *doc); 16 | bool isElectricCharacter(const QChar &ch) const override; 17 | 18 | int indentFor(const QTextBlock &block, 19 | const TextEditor::TabSettings &tabSettings, 20 | int cursorPositionInEditor = -1) override; 21 | }; 22 | 23 | } // CMakeProjectManager::Internal 24 | -------------------------------------------------------------------------------- /cmakeinstallstep.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #include "cmakeinstallstep.h" 5 | 6 | #include "cmakeabstractprocessstep.h" 7 | #include "cmakebuildsystem.h" 8 | #include "cmakekitaspect.h" 9 | #include "cmakeparser.h" 10 | #include "cmakeprojectconstants.h" 11 | #include "cmakeprojectmanagertr.h" 12 | #include "cmaketool.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | using namespace Core; 23 | using namespace ProjectExplorer; 24 | using namespace Utils; 25 | 26 | namespace CMakeProjectManager::Internal { 27 | 28 | // CMakeInstallStep 29 | 30 | class CMakeInstallStep : public CMakeAbstractProcessStep 31 | { 32 | public: 33 | CMakeInstallStep(BuildStepList *bsl, Id id) 34 | : CMakeAbstractProcessStep(bsl, id) 35 | { 36 | cmakeArguments.setSettingsKey("CMakeProjectManager.InstallStep.CMakeArguments"); 37 | cmakeArguments.setLabelText(Tr::tr("CMake arguments:")); 38 | cmakeArguments.setDisplayStyle(StringAspect::LineEditDisplay); 39 | 40 | setCommandLineProvider([this] { return cmakeCommand(); }); 41 | } 42 | 43 | private: 44 | CommandLine cmakeCommand() const; 45 | 46 | void setupOutputFormatter(OutputFormatter *formatter) override; 47 | QWidget *createConfigWidget() override; 48 | 49 | StringAspect cmakeArguments{this}; 50 | }; 51 | 52 | void CMakeInstallStep::setupOutputFormatter(OutputFormatter *formatter) 53 | { 54 | CMakeParser *cmakeParser = new CMakeParser; 55 | cmakeParser->setSourceDirectory(project()->projectDirectory()); 56 | formatter->addLineParsers({cmakeParser}); 57 | formatter->addSearchDir(processParameters()->effectiveWorkingDirectory()); 58 | CMakeAbstractProcessStep::setupOutputFormatter(formatter); 59 | } 60 | 61 | CommandLine CMakeInstallStep::cmakeCommand() const 62 | { 63 | CommandLine cmd; 64 | if (CMakeTool *tool = CMakeKitAspect::cmakeTool(kit())) 65 | cmd.setExecutable(tool->cmakeExecutable()); 66 | 67 | FilePath buildDirectory = "."; 68 | if (buildConfiguration()) 69 | buildDirectory = buildConfiguration()->buildDirectory(); 70 | 71 | cmd.addArgs({"--install", buildDirectory.path()}); 72 | 73 | auto bs = qobject_cast(buildSystem()); 74 | if (bs && bs->isMultiConfigReader()) { 75 | cmd.addArg("--config"); 76 | cmd.addArg(bs->cmakeBuildType()); 77 | } 78 | 79 | cmd.addArgs(cmakeArguments(), CommandLine::Raw); 80 | 81 | return cmd; 82 | } 83 | 84 | QWidget *CMakeInstallStep::createConfigWidget() 85 | { 86 | auto updateDetails = [this] { 87 | ProcessParameters param; 88 | setupProcessParameters(¶m); 89 | param.setCommandLine(cmakeCommand()); 90 | 91 | setSummaryText(param.summary(displayName())); 92 | }; 93 | 94 | setDisplayName(Tr::tr("Install", "ConfigWidget display name.")); 95 | 96 | using namespace Layouting; 97 | auto widget = Form { cmakeArguments, noMargin }.emerge(); 98 | 99 | updateDetails(); 100 | 101 | connect(&cmakeArguments, &StringAspect::changed, this, updateDetails); 102 | 103 | connect(ProjectExplorerPlugin::instance(), 104 | &ProjectExplorerPlugin::settingsChanged, 105 | this, 106 | updateDetails); 107 | connect(buildConfiguration(), &BuildConfiguration::buildDirectoryChanged, this, updateDetails); 108 | connect(buildConfiguration(), &BuildConfiguration::buildTypeChanged, this, updateDetails); 109 | 110 | return widget; 111 | } 112 | 113 | // CMakeInstallStepFactory 114 | 115 | CMakeInstallStepFactory::CMakeInstallStepFactory() 116 | { 117 | registerStep(Constants::CMAKE_INSTALL_STEP_ID); 118 | setDisplayName( 119 | Tr::tr("CMake Install", "Display name for CMakeProjectManager::CMakeInstallStep id.")); 120 | setSupportedProjectType(Constants::CMAKE_PROJECT_ID); 121 | setSupportedStepLists({ProjectExplorer::Constants::BUILDSTEPS_DEPLOY}); 122 | } 123 | 124 | } // CMakeProjectManager::Internal 125 | 126 | -------------------------------------------------------------------------------- /cmakeinstallstep.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace CMakeProjectManager::Internal { 9 | 10 | class CMakeInstallStepFactory : public ProjectExplorer::BuildStepFactory 11 | { 12 | public: 13 | CMakeInstallStepFactory(); 14 | }; 15 | 16 | } // CMakeProjectManager::Internal 17 | -------------------------------------------------------------------------------- /cmakekitaspect.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Canonical Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmake_global.h" 7 | 8 | #include "cmakeconfigitem.h" 9 | 10 | #include 11 | 12 | namespace CMakeProjectManager { 13 | 14 | class CMakeTool; 15 | 16 | class CMAKE_EXPORT CMakeKitAspect 17 | { 18 | public: 19 | static Utils::Id id(); 20 | 21 | static Utils::Id cmakeToolId(const ProjectExplorer::Kit *k); 22 | static CMakeTool *cmakeTool(const ProjectExplorer::Kit *k); 23 | static void setCMakeTool(ProjectExplorer::Kit *k, const Utils::Id id); 24 | static QString msgUnsupportedVersion(const QByteArray &versionString); 25 | 26 | static ProjectExplorer::KitAspect *createKitAspect(ProjectExplorer::Kit *k); 27 | 28 | private: 29 | friend class CMakeToolManager; 30 | static void createFactories(); 31 | }; 32 | 33 | class CMAKE_EXPORT CMakeGeneratorKitAspect 34 | { 35 | public: 36 | static QString generator(const ProjectExplorer::Kit *k); 37 | static QString platform(const ProjectExplorer::Kit *k); 38 | static QString toolset(const ProjectExplorer::Kit *k); 39 | static void setGenerator(ProjectExplorer::Kit *k, const QString &generator); 40 | static void setPlatform(ProjectExplorer::Kit *k, const QString &platform); 41 | static void setToolset(ProjectExplorer::Kit *k, const QString &toolset); 42 | static void set(ProjectExplorer::Kit *k, const QString &generator, 43 | const QString &platform, const QString &toolset); 44 | static QStringList generatorArguments(const ProjectExplorer::Kit *k); 45 | static CMakeConfig generatorCMakeConfig(const ProjectExplorer::Kit *k); 46 | static bool isMultiConfigGenerator(const ProjectExplorer::Kit *k); 47 | 48 | static ProjectExplorer::KitAspect *createKitAspect(ProjectExplorer::Kit *k); 49 | }; 50 | 51 | class CMAKE_EXPORT CMakeConfigurationKitAspect 52 | { 53 | public: 54 | static CMakeConfig configuration(const ProjectExplorer::Kit *k); 55 | static void setConfiguration(ProjectExplorer::Kit *k, const CMakeConfig &config); 56 | 57 | static QString additionalConfiguration(const ProjectExplorer::Kit *k); 58 | static void setAdditionalConfiguration(ProjectExplorer::Kit *k, const QString &config); 59 | 60 | static QStringList toStringList(const ProjectExplorer::Kit *k); 61 | static void fromStringList(ProjectExplorer::Kit *k, const QStringList &in); 62 | 63 | static QStringList toArgumentsList(const ProjectExplorer::Kit *k); 64 | 65 | static CMakeConfig defaultConfiguration(const ProjectExplorer::Kit *k); 66 | 67 | static void setCMakePreset(ProjectExplorer::Kit *k, const QString &presetName); 68 | static CMakeConfigItem cmakePresetConfigItem(const ProjectExplorer::Kit *k); 69 | 70 | static ProjectExplorer::KitAspect *createKitAspect(ProjectExplorer::Kit *k); 71 | }; 72 | 73 | } // CMakeProjectManager 74 | -------------------------------------------------------------------------------- /cmakelocatorfilter.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Kläralvdalens Datakonsult AB, a KDAB Group company. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #include "cmakelocatorfilter.h" 5 | 6 | #include "cmakebuildstep.h" 7 | #include "cmakebuildsystem.h" 8 | #include "cmakeproject.h" 9 | #include "cmakeprojectmanagertr.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | using namespace Core; 19 | using namespace ProjectExplorer; 20 | using namespace Utils; 21 | 22 | namespace CMakeProjectManager::Internal { 23 | 24 | using BuildAcceptor = std::function; 25 | 26 | static LocatorMatcherTasks cmakeMatchers(const BuildAcceptor &acceptor) 27 | { 28 | using namespace Tasking; 29 | 30 | Storage storage; 31 | 32 | const auto onSetup = [storage, acceptor] { 33 | const QString input = storage->input(); 34 | const QList projects = ProjectManager::projects(); 35 | LocatorFilterEntries entries; 36 | for (Project *project : projects) { 37 | const auto cmakeProject = qobject_cast(project); 38 | if (!cmakeProject || !cmakeProject->activeTarget()) 39 | continue; 40 | const auto bs = qobject_cast( 41 | cmakeProject->activeTarget()->buildSystem()); 42 | if (!bs) 43 | continue; 44 | 45 | const QList buildTargets = bs->buildTargets(); 46 | for (const CMakeBuildTarget &target : buildTargets) { 47 | if (CMakeBuildSystem::filteredOutTarget(target)) 48 | continue; 49 | const int index = target.title.indexOf(input, 0, Qt::CaseInsensitive); 50 | if (index >= 0) { 51 | const FilePath path = target.backtrace.isEmpty() 52 | ? cmakeProject->projectFilePath() 53 | : target.backtrace.last().path; 54 | const int line = target.backtrace.isEmpty() ? 0 : target.backtrace.last().line; 55 | const FilePath projectPath = cmakeProject->projectFilePath(); 56 | const QString displayName = target.title; 57 | LocatorFilterEntry entry; 58 | entry.displayName = displayName; 59 | if (acceptor) { 60 | entry.acceptor = [projectPath, displayName, acceptor] { 61 | acceptor(projectPath, displayName); 62 | return AcceptResult(); 63 | }; 64 | } 65 | entry.linkForEditor = {path, line}; 66 | entry.extraInfo = path.shortNativePath(); 67 | entry.highlightInfo = {index, int(input.length())}; 68 | entry.filePath = cmakeProject->projectFilePath(); 69 | entries.append(entry); 70 | } 71 | } 72 | } 73 | storage->reportOutput(entries); 74 | }; 75 | return {{Sync(onSetup), storage}}; 76 | } 77 | 78 | void setupFilter(ILocatorFilter *filter) 79 | { 80 | const auto projectListUpdated = [filter] { 81 | filter->setEnabled(Utils::contains(ProjectManager::projects(), 82 | [](Project *p) { return qobject_cast(p); })); 83 | }; 84 | QObject::connect(ProjectManager::instance(), &ProjectManager::projectAdded, 85 | filter, projectListUpdated); 86 | QObject::connect(ProjectManager::instance(), &ProjectManager::projectRemoved, 87 | filter, projectListUpdated); 88 | } 89 | 90 | // -------------------------------------------------------------------- 91 | // BuildCMakeTargetLocatorFilter: 92 | // -------------------------------------------------------------------- 93 | 94 | static void buildAcceptor(const FilePath &projectPath, const QString &displayName) 95 | { 96 | // Get the project containing the target selected 97 | const auto cmakeProject = qobject_cast( 98 | Utils::findOrDefault(ProjectManager::projects(), [projectPath](Project *p) { 99 | return p->projectFilePath() == projectPath; 100 | })); 101 | if (!cmakeProject || !cmakeProject->activeTarget() 102 | || !cmakeProject->activeTarget()->activeBuildConfiguration()) 103 | return; 104 | 105 | if (BuildManager::isBuilding(cmakeProject)) 106 | BuildManager::cancel(); 107 | 108 | // Find the make step 109 | const BuildStepList *buildStepList = 110 | cmakeProject->activeTarget()->activeBuildConfiguration()->buildSteps(); 111 | const auto buildStep = buildStepList->firstOfType(); 112 | if (!buildStep) 113 | return; 114 | 115 | // Change the make step to build only the given target 116 | const QStringList oldTargets = buildStep->buildTargets(); 117 | buildStep->setBuildTargets({displayName}); 118 | 119 | // Build 120 | BuildManager::buildProjectWithDependencies(cmakeProject); 121 | buildStep->setBuildTargets(oldTargets); 122 | } 123 | 124 | CMakeBuildTargetFilter::CMakeBuildTargetFilter() 125 | { 126 | setId("Build CMake target"); 127 | setDisplayName(Tr::tr("Build CMake Target")); 128 | setDescription(Tr::tr("Builds a target of any open CMake project.")); 129 | setDefaultShortcutString("cm"); 130 | setPriority(High); 131 | setupFilter(this); 132 | } 133 | 134 | Core::LocatorMatcherTasks CMakeBuildTargetFilter::matchers() 135 | { 136 | return cmakeMatchers(&buildAcceptor); 137 | } 138 | 139 | // -------------------------------------------------------------------- 140 | // OpenCMakeTargetLocatorFilter: 141 | // -------------------------------------------------------------------- 142 | 143 | CMakeOpenTargetFilter::CMakeOpenTargetFilter() 144 | { 145 | setId("Open CMake target definition"); 146 | setDisplayName(Tr::tr("Open CMake Target")); 147 | setDescription(Tr::tr("Locates the definition of a target of any open CMake project.")); 148 | setDefaultShortcutString("cmo"); 149 | setPriority(Medium); 150 | setupFilter(this); 151 | } 152 | 153 | Core::LocatorMatcherTasks CMakeOpenTargetFilter::matchers() 154 | { 155 | return cmakeMatchers({}); 156 | } 157 | 158 | } // namespace CMakeProjectManager::Internal 159 | -------------------------------------------------------------------------------- /cmakelocatorfilter.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Kläralvdalens Datakonsult AB, a KDAB Group company. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace CMakeProjectManager::Internal { 9 | 10 | class CMakeBuildTargetFilter : Core::ILocatorFilter 11 | { 12 | public: 13 | CMakeBuildTargetFilter(); 14 | 15 | private: 16 | Core::LocatorMatcherTasks matchers() final; 17 | }; 18 | 19 | class CMakeOpenTargetFilter : Core::ILocatorFilter 20 | { 21 | public: 22 | CMakeOpenTargetFilter(); 23 | 24 | private: 25 | Core::LocatorMatcherTasks matchers() final; 26 | }; 27 | 28 | } // namespace CMakeProjectManager::Internal 29 | -------------------------------------------------------------------------------- /cmakeparser.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Axonian LLC. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmake_global.h" 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | namespace CMakeProjectManager { 18 | 19 | class CMAKE_EXPORT CMakeParser : public ProjectExplorer::OutputTaskParser 20 | { 21 | Q_OBJECT 22 | 23 | public: 24 | explicit CMakeParser(); 25 | void setSourceDirectory(const Utils::FilePath &sourceDir); 26 | 27 | private: 28 | Result handleLine(const QString &line, Utils::OutputFormat type) override; 29 | void flush() override; 30 | Utils::FilePath resolvePath(const QString &path) const; 31 | 32 | enum TripleLineError { NONE, LINE_LOCATION, LINE_DESCRIPTION, LINE_DESCRIPTION2 }; 33 | 34 | TripleLineError m_expectTripleLineErrorData = NONE; 35 | 36 | std::optional m_sourceDirectory; 37 | ProjectExplorer::Task m_lastTask; 38 | QRegularExpression m_commonError; 39 | QRegularExpression m_nextSubError; 40 | QRegularExpression m_commonWarning; 41 | QRegularExpression m_locationLine; 42 | QRegularExpression m_sourceLineAndFunction; 43 | bool m_skippedFirstEmptyLine = false; 44 | int m_lines = 0; 45 | 46 | struct CallStackLine 47 | { 48 | Utils::FilePath file; 49 | int line = -1; 50 | QString function; 51 | }; 52 | std::optional> m_callStack; 53 | CallStackLine m_errorOrWarningLine; 54 | }; 55 | 56 | } // CMakeProjectManager 57 | -------------------------------------------------------------------------------- /cmakeprocess.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #include "cmakeprocess.h" 5 | 6 | #include "builddirparameters.h" 7 | #include "cmakeparser.h" 8 | #include "cmakeprojectconstants.h" 9 | #include "cmakeprojectmanagertr.h" 10 | #include "cmakespecificsettings.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | using namespace Core; 30 | using namespace ProjectExplorer; 31 | using namespace Utils; 32 | 33 | namespace CMakeProjectManager::Internal { 34 | 35 | static QString stripTrailingNewline(QString str) 36 | { 37 | if (str.endsWith('\n')) 38 | str.chop(1); 39 | return str; 40 | } 41 | 42 | CMakeProcess::CMakeProcess() = default; 43 | 44 | CMakeProcess::~CMakeProcess() 45 | { 46 | m_parser.flush(); 47 | } 48 | 49 | static const int failedToStartExitCode = 0xFF; // See ProcessPrivate::handleDone() impl 50 | 51 | void CMakeProcess::run(const BuildDirParameters ¶meters, const QStringList &arguments) 52 | { 53 | QTC_ASSERT(!m_process, return); 54 | 55 | CMakeTool *cmake = parameters.cmakeTool(); 56 | QTC_ASSERT(parameters.isValid() && cmake, return); 57 | 58 | const FilePath cmakeExecutable = cmake->cmakeExecutable(); 59 | 60 | if (!cmakeExecutable.ensureReachable(parameters.sourceDirectory)) { 61 | const QString msg = ::CMakeProjectManager::Tr::tr( 62 | "The source directory %1 is not reachable by the CMake executable %2.") 63 | .arg(parameters.sourceDirectory.displayName()).arg(cmakeExecutable.displayName()); 64 | BuildSystem::appendBuildSystemOutput(addCMakePrefix({QString(), msg}).join('\n')); 65 | emit finished(failedToStartExitCode); 66 | return; 67 | } 68 | 69 | if (!cmakeExecutable.ensureReachable(parameters.buildDirectory)) { 70 | const QString msg = ::CMakeProjectManager::Tr::tr( 71 | "The build directory %1 is not reachable by the CMake executable %2.") 72 | .arg(parameters.buildDirectory.displayName()).arg(cmakeExecutable.displayName()); 73 | BuildSystem::appendBuildSystemOutput(addCMakePrefix({QString(), msg}).join('\n')); 74 | emit finished(failedToStartExitCode); 75 | return; 76 | } 77 | 78 | const FilePath sourceDirectory = cmakeExecutable.withNewMappedPath(parameters.sourceDirectory); 79 | const FilePath buildDirectory = parameters.buildDirectory; 80 | 81 | if (!buildDirectory.exists()) { 82 | const QString msg = ::CMakeProjectManager::Tr::tr( 83 | "The build directory \"%1\" does not exist").arg(buildDirectory.toUserOutput()); 84 | BuildSystem::appendBuildSystemOutput(addCMakePrefix({QString(), msg}).join('\n')); 85 | emit finished(failedToStartExitCode); 86 | return; 87 | } 88 | 89 | if (buildDirectory.needsDevice()) { 90 | if (!cmake->cmakeExecutable().isSameDevice(buildDirectory)) { 91 | const QString msg = ::CMakeProjectManager::Tr::tr( 92 | "CMake executable \"%1\" and build directory \"%2\" must be on the same device.") 93 | .arg(cmake->cmakeExecutable().toUserOutput(), buildDirectory.toUserOutput()); 94 | BuildSystem::appendBuildSystemOutput(addCMakePrefix({QString(), msg}).join('\n')); 95 | emit finished(failedToStartExitCode); 96 | return; 97 | } 98 | } 99 | 100 | // Copy the "package-manager" CMake code from the ${IDE:ResourcePath} to the build directory 101 | if (settings().packageManagerAutoSetup()) { 102 | const FilePath localPackageManagerDir = buildDirectory.pathAppended(Constants::PACKAGE_MANAGER_DIR); 103 | const FilePath idePackageManagerDir = FilePath::fromString( 104 | parameters.expander->expand(QStringLiteral("%{IDE:ResourcePath}/package-manager"))); 105 | 106 | if (!localPackageManagerDir.exists() && idePackageManagerDir.exists()) 107 | idePackageManagerDir.copyRecursively(localPackageManagerDir); 108 | } 109 | 110 | const auto parser = new CMakeParser; 111 | parser->setSourceDirectory(parameters.sourceDirectory); 112 | m_parser.addLineParser(parser); 113 | 114 | // Always use the sourceDir: If we are triggered because the build directory is getting deleted 115 | // then we are racing against CMakeCache.txt also getting deleted. 116 | 117 | m_process.reset(new Process); 118 | 119 | m_process->setWorkingDirectory(buildDirectory); 120 | m_process->setEnvironment(parameters.environment); 121 | 122 | m_process->setStdOutLineCallback([this](const QString &s) { 123 | BuildSystem::appendBuildSystemOutput(addCMakePrefix(stripTrailingNewline(s))); 124 | emit stdOutReady(s); 125 | }); 126 | 127 | m_process->setStdErrLineCallback([this](const QString &s) { 128 | m_parser.appendMessage(s, StdErrFormat); 129 | BuildSystem::appendBuildSystemOutput(addCMakePrefix(stripTrailingNewline(s))); 130 | }); 131 | 132 | connect(m_process.get(), &Process::done, this, [this] { 133 | handleProcessDone(m_process->resultData()); 134 | }); 135 | 136 | CommandLine commandLine(cmakeExecutable); 137 | commandLine.addArgs({"-S", sourceDirectory.path(), "-B", buildDirectory.path()}); 138 | commandLine.addArgs(arguments); 139 | 140 | TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM); 141 | 142 | BuildSystem::startNewBuildSystemOutput( 143 | addCMakePrefix(::CMakeProjectManager::Tr::tr("Running %1 in %2.") 144 | .arg(commandLine.toUserOutput(), buildDirectory.toUserOutput()))); 145 | 146 | ProcessProgress *progress = new ProcessProgress(m_process.get()); 147 | progress->setDisplayName(::CMakeProjectManager::Tr::tr("Configuring \"%1\"") 148 | .arg(parameters.projectName)); 149 | m_process->setTimeoutS(10); // for process progress timeout estimation 150 | m_process->setCommand(commandLine); 151 | m_elapsed.start(); 152 | m_process->start(); 153 | } 154 | 155 | void CMakeProcess::stop() 156 | { 157 | if (m_process) 158 | m_process->stop(); 159 | } 160 | 161 | void CMakeProcess::handleProcessDone(const Utils::ProcessResultData &resultData) 162 | { 163 | const int code = resultData.m_exitCode; 164 | QString msg; 165 | if (resultData.m_error == QProcess::FailedToStart) { 166 | msg = ::CMakeProjectManager::Tr::tr("CMake process failed to start."); 167 | } else if (resultData.m_exitStatus != QProcess::NormalExit) { 168 | if (resultData.m_canceledByUser) 169 | msg = ::CMakeProjectManager::Tr::tr("CMake process was canceled by the user."); 170 | else 171 | msg = ::CMakeProjectManager::Tr::tr("CMake process crashed."); 172 | } else if (code != 0) { 173 | msg = ::CMakeProjectManager::Tr::tr("CMake process exited with exit code %1.").arg(code); 174 | } 175 | 176 | if (!msg.isEmpty()) { 177 | BuildSystem::appendBuildSystemOutput(addCMakePrefix({QString(), msg}).join('\n')); 178 | TaskHub::addTask(BuildSystemTask(Task::Error, msg)); 179 | } 180 | 181 | emit finished(code); 182 | 183 | const QString elapsedTime = Utils::formatElapsedTime(m_elapsed.elapsed()); 184 | BuildSystem::appendBuildSystemOutput(addCMakePrefix({QString(), elapsedTime}).join('\n')); 185 | } 186 | 187 | QString addCMakePrefix(const QString &str) 188 | { 189 | auto qColorToAnsiCode = [] (const QColor &color) { 190 | return QString::fromLatin1("\033[38;2;%1;%2;%3m") 191 | .arg(color.red()).arg(color.green()).arg(color.blue()); 192 | }; 193 | static const QColor bgColor = creatorTheme()->color(Theme::BackgroundColorNormal); 194 | static const QColor fgColor = creatorTheme()->color(Theme::TextColorNormal); 195 | static const QColor grey = StyleHelper::mergedColors(fgColor, bgColor, 80); 196 | static const QString prefixString = qColorToAnsiCode(grey) + Constants::OUTPUT_PREFIX 197 | + qColorToAnsiCode(fgColor); 198 | return QString("%1%2").arg(prefixString, str); 199 | } 200 | 201 | QStringList addCMakePrefix(const QStringList &list) 202 | { 203 | return Utils::transform(list, [](const QString &str) { return addCMakePrefix(str); }); 204 | } 205 | 206 | } // CMakeProjectManager::Internal 207 | -------------------------------------------------------------------------------- /cmakeprocess.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | namespace Utils { 15 | class ProcessResultData; 16 | class Process; 17 | } 18 | 19 | namespace CMakeProjectManager::Internal { 20 | 21 | class BuildDirParameters; 22 | 23 | class CMakeProcess : public QObject 24 | { 25 | Q_OBJECT 26 | 27 | public: 28 | CMakeProcess(); 29 | ~CMakeProcess(); 30 | 31 | void run(const BuildDirParameters ¶meters, const QStringList &arguments); 32 | void stop(); 33 | 34 | signals: 35 | void finished(int exitCode); 36 | void stdOutReady(const QString &s); 37 | 38 | private: 39 | void handleProcessDone(const Utils::ProcessResultData &resultData); 40 | 41 | std::unique_ptr m_process; 42 | Utils::OutputFormatter m_parser; 43 | QElapsedTimer m_elapsed; 44 | }; 45 | 46 | QString addCMakePrefix(const QString &str); 47 | QStringList addCMakePrefix(const QStringList &list); 48 | 49 | } // CMakeProjectManager::Internal 50 | -------------------------------------------------------------------------------- /cmakeproject.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmake_global.h" 7 | #include "presetsparser.h" 8 | 9 | #include 10 | 11 | namespace CMakeProjectManager { 12 | 13 | namespace Internal { class CMakeProjectImporter; } 14 | 15 | class CMAKE_EXPORT CMakeProject final : public ProjectExplorer::Project 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | explicit CMakeProject(const Utils::FilePath &filename); 21 | ~CMakeProject() final; 22 | 23 | ProjectExplorer::Tasks projectIssues(const ProjectExplorer::Kit *k) const final; 24 | 25 | ProjectExplorer::ProjectImporter *projectImporter() const final; 26 | 27 | using IssueType = ProjectExplorer::Task::TaskType; 28 | void addIssue(IssueType type, const QString &text); 29 | void clearIssues(); 30 | 31 | Internal::PresetsData presetsData() const; 32 | void readPresets(); 33 | 34 | void setOldPresetKits(const QList &presetKits) const; 35 | QList oldPresetKits() const; 36 | 37 | protected: 38 | bool setupTarget(ProjectExplorer::Target *t) final; 39 | 40 | private: 41 | ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override; 42 | void configureAsExampleProject(ProjectExplorer::Kit *kit) override; 43 | 44 | Internal::PresetsData combinePresets(Internal::PresetsData &cmakePresetsData, 45 | Internal::PresetsData &cmakeUserPresetsData); 46 | void setupBuildPresets(Internal::PresetsData &presetsData); 47 | 48 | mutable Internal::CMakeProjectImporter *m_projectImporter = nullptr; 49 | mutable QList m_oldPresetKits; 50 | 51 | ProjectExplorer::Tasks m_issues; 52 | Internal::PresetsData m_presetsData; 53 | }; 54 | 55 | } // namespace CMakeProjectManager 56 | -------------------------------------------------------------------------------- /cmakeproject.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/fileoverlay_cmake.png 4 | images/fileoverlay_cmake@2x.png 5 | images/settingscategory_cmakeprojectmanager.png 6 | images/settingscategory_cmakeprojectmanager@2x.png 7 | 8 | 9 | -------------------------------------------------------------------------------- /cmakeprojectconstants.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | namespace CMakeProjectManager { 7 | namespace Constants { 8 | 9 | const char CMAKE_EDITOR_ID[] = "CMakeProject.CMakeEditor"; 10 | const char RUN_CMAKE[] = "CMakeProject.RunCMake"; 11 | const char RUN_CMAKE_PROFILER[] = "CMakeProject.RunCMakeProfiler"; 12 | const char RUN_CMAKE_DEBUGGER[] = "CMakeProject.RunCMakeDebugger"; 13 | const char CLEAR_CMAKE_CACHE[] = "CMakeProject.ClearCache"; 14 | const char RESCAN_PROJECT[] = "CMakeProject.RescanProject"; 15 | const char RUN_CMAKE_CONTEXT_MENU[] = "CMakeProject.RunCMakeContextMenu"; 16 | const char BUILD_FILE_CONTEXT_MENU[] = "CMakeProject.BuildFileContextMenu"; 17 | const char BUILD_FILE[] = "CMakeProject.BuildFile"; 18 | const char CMAKE_HOME_DIR[] = "CMakeProject.HomeDirectory"; 19 | const char QML_DEBUG_SETTING[] = "CMakeProject.EnableQmlDebugging"; 20 | const char RELOAD_CMAKE_PRESETS[] = "CMakeProject.ReloadCMakePresets"; 21 | 22 | const char CMAKEFORMATTER_SETTINGS_GROUP[] = "CMakeFormatter"; 23 | const char CMAKEFORMATTER_GENERAL_GROUP[] = "General"; 24 | const char CMAKEFORMATTER_ACTION_ID[] = "CMakeFormatter.Action"; 25 | const char CMAKEFORMATTER_MENU_ID[] = "CMakeFormatter.Menu"; 26 | const char CMAKE_DEBUGGING_GROUP[] = "Debugger.Group.CMake"; 27 | 28 | const char PACKAGE_MANAGER_DIR[] = ".qtc/package-manager"; 29 | 30 | // Project 31 | const char CMAKE_PROJECT_ID[] = "CMakeProjectManager.CMakeProject"; 32 | 33 | const char CMAKE_BUILDCONFIGURATION_ID[] = "CMakeProjectManager.CMakeBuildConfiguration"; 34 | 35 | // Menu 36 | const char M_CONTEXT[] = "CMakeEditor.ContextMenu"; 37 | 38 | namespace Settings { 39 | const char GENERAL_ID[] = "CMakeSpecifcSettings"; 40 | const char TOOLS_ID[] = "K.CMake.Tools"; 41 | const char FORMATTER_ID[] = "K.CMake.Formatter"; 42 | const char CATEGORY[] = "K.CMake"; 43 | } // namespace Settings 44 | 45 | // Snippets 46 | const char CMAKE_SNIPPETS_GROUP_ID[] = "CMake"; 47 | 48 | namespace Icons { 49 | const char FILE_OVERLAY[] = ":/cmakeproject/images/fileoverlay_cmake.png"; 50 | const char SETTINGS_CATEGORY[] = ":/cmakeproject/images/settingscategory_cmakeprojectmanager.png"; 51 | } // namespace Icons 52 | 53 | // Actions 54 | const char BUILD_TARGET_CONTEXT_MENU[] = "CMake.BuildTargetContextMenu"; 55 | 56 | // Build Step 57 | const char CMAKE_BUILD_STEP_ID[] = "CMakeProjectManager.MakeStep"; 58 | 59 | // Install Step 60 | const char CMAKE_INSTALL_STEP_ID[] = "CMakeProjectManager.InstallStep"; 61 | 62 | 63 | // Features 64 | const char CMAKE_FEATURE_ID[] = "CMakeProjectManager.Wizard.FeatureCMake"; 65 | 66 | // Tool 67 | const char TOOL_ID[] = "CMakeProjectManager.CMakeKitInformation"; 68 | 69 | // Data 70 | const char BUILD_FOLDER_ROLE[] = "CMakeProjectManager.data.buildFolder"; 71 | 72 | // Output 73 | const char OUTPUT_PREFIX[] = "[cmake] "; 74 | 75 | } // namespace Constants 76 | } // namespace CMakeProjectManager 77 | -------------------------------------------------------------------------------- /cmakeprojectimporter.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "presetsparser.h" 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace CMakeProjectManager { 13 | 14 | class CMakeProject; 15 | class CMakeTool; 16 | 17 | namespace Internal { 18 | 19 | struct DirectoryData; 20 | 21 | class CMakeProjectImporter : public QtSupport::QtProjectImporter 22 | { 23 | public: 24 | CMakeProjectImporter(const Utils::FilePath &path, 25 | const CMakeProjectManager::CMakeProject *project); 26 | 27 | Utils::FilePaths importCandidates() final; 28 | ProjectExplorer::Target *preferredTarget(const QList &possibleTargets) final; 29 | 30 | private: 31 | QList examineDirectory(const Utils::FilePath &importPath, 32 | QString *warningMessage) const final; 33 | bool matchKit(void *directoryData, const ProjectExplorer::Kit *k) const final; 34 | ProjectExplorer::Kit *createKit(void *directoryData) const final; 35 | const QList buildInfoList(void *directoryData) const final; 36 | 37 | struct CMakeToolData { 38 | bool isTemporary = false; 39 | CMakeTool *cmakeTool = nullptr; 40 | }; 41 | CMakeToolData findOrCreateCMakeTool(const Utils::FilePath &cmakeToolPath) const; 42 | 43 | void deleteDirectoryData(void *directoryData) const final; 44 | 45 | void cleanupTemporaryCMake(ProjectExplorer::Kit *k, const QVariantList &vl); 46 | void persistTemporaryCMake(ProjectExplorer::Kit *k, const QVariantList &vl); 47 | 48 | void ensureBuildDirectory(DirectoryData &data, const ProjectExplorer::Kit *k) const; 49 | 50 | const CMakeProject *m_project; 51 | Utils::TemporaryDirectory m_presetsTempDir; 52 | }; 53 | 54 | } // namespace Internal 55 | } // namespace CMakeProjectManager 56 | -------------------------------------------------------------------------------- /cmakeprojectmanager.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace Utils { class ParameterAction; } 9 | 10 | QT_BEGIN_NAMESPACE 11 | class QAction; 12 | QT_END_NAMESPACE 13 | 14 | namespace CMakeProjectManager { 15 | namespace Internal { 16 | 17 | class CMakeManager : public QObject 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | CMakeManager(); 23 | 24 | private: 25 | void updateCmakeActions(ProjectExplorer::Node *node); 26 | void clearCMakeCache(ProjectExplorer::BuildSystem *buildSystem); 27 | void runCMake(ProjectExplorer::BuildSystem *buildSystem); 28 | void runCMakeWithProfiling(ProjectExplorer::BuildSystem *buildSystem); 29 | void rescanProject(ProjectExplorer::BuildSystem *buildSystem); 30 | void buildFileContextMenu(); 31 | void buildFile(ProjectExplorer::Node *node = nullptr); 32 | void updateBuildFileAction(); 33 | void enableBuildFileMenus(ProjectExplorer::Node *node); 34 | void reloadCMakePresets(); 35 | 36 | QAction *m_runCMakeAction; 37 | QAction *m_clearCMakeCacheAction; 38 | QAction *m_runCMakeActionContextMenu; 39 | QAction *m_rescanProjectAction; 40 | QAction *m_buildFileContextMenu; 41 | QAction *m_reloadCMakePresetsAction; 42 | Utils::ParameterAction *m_buildFileAction; 43 | QAction *m_cmakeProfilerAction; 44 | QAction *m_cmakeDebuggerAction; 45 | QAction *m_cmakeDebuggerSeparator; 46 | bool m_canDebugCMake = false; 47 | }; 48 | 49 | } // namespace Internal 50 | } // namespace CMakeProjectManager 51 | -------------------------------------------------------------------------------- /cmakeprojectmanager.qbs: -------------------------------------------------------------------------------- 1 | import qbs 1.0 2 | 3 | QtcPlugin { 4 | name: "CMakeProjectManager2" 5 | 6 | Depends { name: "Qt.widgets" } 7 | Depends { name: "Utils" } 8 | 9 | Depends { name: "Core" } 10 | Depends { name: "CppEditor" } 11 | Depends { name: "QmlJS" } 12 | Depends { name: "ProjectExplorer" } 13 | Depends { name: "TextEditor" } 14 | Depends { name: "QtSupport" } 15 | 16 | files: [ 17 | "builddirparameters.cpp", 18 | "builddirparameters.h", 19 | "cmake_global.h", 20 | "cmakeabstractprocessstep.cpp", 21 | "cmakeabstractprocessstep.h", 22 | "cmakebuildconfiguration.cpp", 23 | "cmakebuildconfiguration.h", 24 | "cmakebuildstep.cpp", 25 | "cmakebuildstep.h", 26 | "cmakebuildsystem.cpp", 27 | "cmakebuildsystem.h", 28 | "cmakebuildtarget.h", 29 | "cmakeconfigitem.cpp", 30 | "cmakeconfigitem.h", 31 | "cmakeeditor.cpp", 32 | "cmakeeditor.h", 33 | "cmakefilecompletionassist.cpp", 34 | "cmakefilecompletionassist.h", 35 | "cmakeformatter.cpp", 36 | "cmakeformatter.h", 37 | "cmakeinstallstep.cpp", 38 | "cmakeinstallstep.h", 39 | "cmakekitaspect.h", 40 | "cmakekitaspect.cpp", 41 | "cmakelocatorfilter.cpp", 42 | "cmakelocatorfilter.h", 43 | "cmakeparser.cpp", 44 | "cmakeparser.h", 45 | "cmakeprocess.cpp", 46 | "cmakeprocess.h", 47 | "cmakeproject.cpp", 48 | "cmakeproject.h", 49 | "cmakeproject.qrc", 50 | "cmakeprojectimporter.cpp", 51 | "cmakeprojectimporter.h", 52 | "cmakeprojectconstants.h", 53 | "cmakeprojectmanager.cpp", 54 | "cmakeprojectmanager.h", 55 | "cmakeprojectmanagertr.h", 56 | "cmakeprojectnodes.cpp", 57 | "cmakeprojectnodes.h", 58 | "cmakeprojectplugin.cpp", 59 | "cmakeprojectplugin.h", 60 | "cmaketool.cpp", 61 | "cmaketool.h", 62 | "cmaketoolmanager.cpp", 63 | "cmaketoolmanager.h", 64 | "cmaketoolsettingsaccessor.cpp", 65 | "cmaketoolsettingsaccessor.h", 66 | "cmakesettingspage.h", 67 | "cmakesettingspage.cpp", 68 | "cmakeindenter.h", 69 | "cmakeindenter.cpp", 70 | "cmakeautocompleter.h", 71 | "cmakeautocompleter.cpp", 72 | "cmakespecificsettings.h", 73 | "cmakespecificsettings.cpp", 74 | "configmodel.cpp", 75 | "configmodel.h", 76 | "configmodelitemdelegate.cpp", 77 | "configmodelitemdelegate.h", 78 | "fileapidataextractor.cpp", 79 | "fileapidataextractor.h", 80 | "fileapiparser.cpp", 81 | "fileapiparser.h", 82 | "fileapireader.cpp", 83 | "fileapireader.h", 84 | "presetsparser.cpp", 85 | "presetsparser.h", 86 | "presetsmacros.cpp", 87 | "presetsmacros.h", 88 | "projecttreehelper.cpp", 89 | "projecttreehelper.h", 90 | "simplefileapireader.cpp", 91 | "simplefileapireader.h" 92 | ] 93 | 94 | Group { 95 | name: "3rdparty" 96 | cpp.includePaths: base.concat("3rdparty/cmake") 97 | 98 | prefix: "3rdparty/" 99 | files: [ 100 | "cmake/cmListFileCache.cxx", 101 | "cmake/cmListFileCache.h", 102 | "cmake/cmListFileLexer.cxx", 103 | "cmake/cmListFileLexer.h", 104 | "cmake/cmStandardLexer.h", 105 | "rstparser/rstparser.cc", 106 | "rstparser/rstparser.h" 107 | ] 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /cmakeprojectmanagertr.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace CMakeProjectManager { 9 | 10 | struct Tr 11 | { 12 | Q_DECLARE_TR_FUNCTIONS(QtC::CMakeProjectManager) 13 | }; 14 | 15 | } // namespace CMakeProjectManager 16 | -------------------------------------------------------------------------------- /cmakeprojectnodes.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #include "cmakeprojectnodes.h" 5 | #include "cmakebuildsystem.h" 6 | #include "cmakeprojectconstants.h" 7 | #include "cmakeprojectmanagertr.h" 8 | #include "cmakekitinformation.h" 9 | #include "cmaketool.h" 10 | #include "cmakeproject.h" 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | using namespace ProjectExplorer; 22 | using namespace Utils; 23 | 24 | namespace CMakeProjectManager::Internal { 25 | 26 | CMakeInputsNode::CMakeInputsNode(const FilePath &cmakeLists) : 27 | ProjectExplorer::ProjectNode(cmakeLists) 28 | { 29 | setPriority(Node::DefaultPriority - 10); // Bottom most! 30 | setDisplayName(Tr::tr("CMake Modules")); 31 | setIcon(DirectoryIcon(ProjectExplorer::Constants::FILEOVERLAY_MODULES)); 32 | setListInProject(false); 33 | } 34 | 35 | CMakePresetsNode::CMakePresetsNode(const FilePath &projectPath) : 36 | ProjectExplorer::ProjectNode(projectPath) 37 | { 38 | setPriority(Node::DefaultPriority - 9); 39 | setDisplayName(Tr::tr("CMake Presets")); 40 | setIcon(DirectoryIcon(ProjectExplorer::Constants::FILEOVERLAY_PRODUCT)); 41 | setListInProject(false); 42 | } 43 | 44 | CMakeListsNode::CMakeListsNode(const FilePath &cmakeListPath) : 45 | ProjectExplorer::ProjectNode(cmakeListPath) 46 | { 47 | setIcon(DirectoryIcon(Constants::Icons::FILE_OVERLAY)); 48 | setListInProject(false); 49 | } 50 | 51 | bool CMakeListsNode::showInSimpleTree() const 52 | { 53 | return false; 54 | } 55 | 56 | std::optional CMakeListsNode::visibleAfterAddFileAction() const 57 | { 58 | return filePath().pathAppended("CMakeLists.txt"); 59 | } 60 | 61 | CMakeProjectNode::CMakeProjectNode(const FilePath &directory) : 62 | ProjectExplorer::ProjectNode(directory) 63 | { 64 | setPriority(Node::DefaultProjectPriority + 1000); 65 | setIcon(DirectoryIcon(ProjectExplorer::Constants::FILEOVERLAY_PRODUCT)); 66 | setListInProject(false); 67 | } 68 | 69 | QString CMakeProjectNode::tooltip() const 70 | { 71 | return QString(); 72 | } 73 | 74 | CMakeTargetNode::CMakeTargetNode(const FilePath &directory, const QString &target) : 75 | 76 | ProjectExplorer::ProjectNode(directory) 77 | { 78 | m_target = target; 79 | setPriority(Node::DefaultProjectPriority + 900); 80 | setIcon(":/projectexplorer/images/build.png"); // TODO: Use proper icon! 81 | setListInProject(false); 82 | setProductType(ProductType::Other); 83 | } 84 | 85 | QString CMakeTargetNode::tooltip() const 86 | { 87 | return m_tooltip; 88 | } 89 | 90 | QString CMakeTargetNode::buildKey() const 91 | { 92 | return m_target; 93 | } 94 | 95 | FilePath CMakeTargetNode::buildDirectory() const 96 | { 97 | return m_buildDirectory; 98 | } 99 | 100 | void CMakeTargetNode::setBuildDirectory(const FilePath &directory) 101 | { 102 | m_buildDirectory = directory; 103 | } 104 | 105 | QVariant CMakeTargetNode::data(Id role) const 106 | { 107 | auto value = [this](const QByteArray &key) -> QVariant { 108 | for (const CMakeConfigItem &configItem : m_config) { 109 | if (configItem.key == key) 110 | return configItem.value; 111 | } 112 | return {}; 113 | }; 114 | 115 | auto values = [this](const QByteArray &key) -> QVariant { 116 | for (const CMakeConfigItem &configItem : m_config) { 117 | if (configItem.key == key) 118 | return configItem.values; 119 | } 120 | return {}; 121 | }; 122 | 123 | if (role == Constants::BUILD_FOLDER_ROLE) 124 | return m_buildDirectory.toVariant(); 125 | 126 | if (role == Android::Constants::AndroidAbi) 127 | return value(Android::Constants::ANDROID_ABI); 128 | 129 | if (role == Android::Constants::AndroidAbis) 130 | return value(Android::Constants::ANDROID_ABIS); 131 | 132 | // TODO: Concerns the variables below. Qt 6 uses target properties which cannot be read 133 | // by the current mechanism, and the variables start with "Qt_" prefix. 134 | 135 | if (role == Android::Constants::AndroidPackageSourceDir) 136 | return value(Android::Constants::ANDROID_PACKAGE_SOURCE_DIR); 137 | 138 | if (role == Android::Constants::AndroidExtraLibs) 139 | return value(Android::Constants::ANDROID_EXTRA_LIBS); 140 | 141 | if (role == Android::Constants::AndroidDeploySettingsFile) 142 | return value(Android::Constants::ANDROID_DEPLOYMENT_SETTINGS_FILE); 143 | 144 | if (role == Android::Constants::AndroidApplicationArgs) 145 | return value(Android::Constants::ANDROID_APPLICATION_ARGUMENTS); 146 | 147 | if (role == Android::Constants::ANDROID_ABIS) 148 | return value(Android::Constants::ANDROID_ABIS); 149 | 150 | if (role == Android::Constants::AndroidSoLibPath) 151 | return values(Android::Constants::ANDROID_SO_LIBS_PATHS); 152 | 153 | if (role == Android::Constants::AndroidTargets) 154 | return values("TARGETS_BUILD_PATH"); 155 | 156 | if (role == Android::Constants::AndroidApk) 157 | return {}; 158 | 159 | if (role == Ios::Constants::IosTarget) { 160 | // For some reason the artifact is e.g. "Debug/untitled.app/untitled" which is wrong. 161 | // It actually is e.g. "Debug-iphonesimulator/untitled.app/untitled". 162 | // Anyway, the iOS plugin is only interested in the app bundle name without .app. 163 | return m_artifact.fileName(); 164 | } 165 | 166 | if (role == Ios::Constants::IosBuildDir) { 167 | // This is a path relative to root build directory. 168 | // When generating Xcode project, CMake may put here a "${EFFECTIVE_PLATFORM_NAME}" macro, 169 | // which is expanded by Xcode at build time. 170 | // To get an actual executable path, iOS plugin replaces this macro with either "-iphoneos" 171 | // or "-iphonesimulator" depending on the device type (which is unavailable here). 172 | 173 | // dir/target.app/target -> dir 174 | return m_artifact.parentDir().parentDir().toString(); 175 | } 176 | 177 | if (role == Ios::Constants::IosCmakeGenerator) 178 | return value("CMAKE_GENERATOR"); 179 | 180 | if (role == ProjectExplorer::Constants::QT_KEYWORDS_ENABLED) // FIXME handle correctly 181 | return value(role.toString().toUtf8()); 182 | 183 | QTC_ASSERT(false, qDebug() << "Unknown role" << role.toString()); 184 | // Better guess than "not present". 185 | return value(role.toString().toUtf8()); 186 | } 187 | 188 | void CMakeTargetNode::setConfig(const CMakeConfig &config) 189 | { 190 | m_config = config; 191 | } 192 | 193 | 194 | std::optional CMakeTargetNode::visibleAfterAddFileAction() const 195 | { 196 | return filePath().pathAppended("CMakeLists.txt"); 197 | } 198 | 199 | void CMakeTargetNode::build() 200 | { 201 | Project *p = getProject(); 202 | Target *t = p ? p->activeTarget() : nullptr; 203 | if (t) 204 | static_cast(t->buildSystem())->buildCMakeTarget(displayName()); 205 | } 206 | 207 | void CMakeTargetNode::setTargetInformation(const QList &artifacts, const QString &type) 208 | { 209 | m_tooltip = Tr::tr("Target type:") + " " + type + "
"; 210 | if (artifacts.isEmpty()) { 211 | m_tooltip += Tr::tr("No build artifacts"); 212 | } else { 213 | const QStringList tmp = Utils::transform(artifacts, &FilePath::toUserOutput); 214 | m_tooltip += Tr::tr("Build artifacts:") + "
" + tmp.join("
"); 215 | m_artifact = artifacts.first(); 216 | } 217 | if (type == "EXECUTABLE") 218 | setProductType(ProductType::App); 219 | else if (type == "SHARED_LIBRARY" || type == "STATIC_LIBRARY") 220 | setProductType(ProductType::Lib); 221 | } 222 | 223 | } // CMakeProjectManager::Internal 224 | -------------------------------------------------------------------------------- /cmakeprojectnodes.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmakeconfigitem.h" 7 | 8 | #include 9 | 10 | namespace CMakeProjectManager { 11 | class CMakeProject; 12 | } // CMakeProjectManager 13 | 14 | namespace CMakeProjectManager::Internal { 15 | 16 | 17 | class CMakeInputsNode : public ProjectExplorer::ProjectNode 18 | { 19 | public: 20 | CMakeInputsNode(const Utils::FilePath &cmakeLists); 21 | }; 22 | 23 | class CMakePresetsNode : public ProjectExplorer::ProjectNode 24 | { 25 | public: 26 | CMakePresetsNode(const Utils::FilePath &projectPath); 27 | }; 28 | 29 | class CMakeListsNode : public ProjectExplorer::ProjectNode 30 | { 31 | public: 32 | explicit CMakeListsNode(const Utils::FilePath &cmakeListPath); 33 | 34 | bool showInSimpleTree() const final; 35 | std::optional visibleAfterAddFileAction() const override; 36 | }; 37 | 38 | class CMakeProjectNode : public ProjectExplorer::ProjectNode 39 | { 40 | public: 41 | explicit CMakeProjectNode(const Utils::FilePath &directory); 42 | 43 | QString tooltip() const final; 44 | }; 45 | 46 | class CMakeTargetNode : public ProjectExplorer::ProjectNode 47 | { 48 | public: 49 | CMakeTargetNode(const Utils::FilePath &directory, const QString &target); 50 | 51 | void setTargetInformation(const QList &artifacts, const QString &type); 52 | 53 | QString tooltip() const final; 54 | QString buildKey() const final; 55 | Utils::FilePath buildDirectory() const; 56 | void setBuildDirectory(const Utils::FilePath &directory); 57 | 58 | std::optional visibleAfterAddFileAction() const override; 59 | 60 | void build() override; 61 | 62 | QVariant data(Utils::Id role) const override; 63 | void setConfig(const CMakeConfig &config); 64 | 65 | private: 66 | QString m_tooltip; 67 | Utils::FilePath m_buildDirectory; 68 | Utils::FilePath m_artifact; 69 | CMakeConfig m_config; 70 | }; 71 | 72 | } // CMakeProjectManager::Internal 73 | -------------------------------------------------------------------------------- /cmakeprojectplugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #include "cmakeprojectplugin.h" 5 | 6 | #include "cmakebuildconfiguration.h" 7 | #include "cmakebuildstep.h" 8 | #include "cmakebuildsystem.h" 9 | #include "cmakeeditor.h" 10 | #include "cmakeformatter.h" 11 | #include "cmakeinstallstep.h" 12 | #include "cmakelocatorfilter.h" 13 | #include "cmakeproject.h" 14 | #include "cmakeprojectconstants.h" 15 | #include "cmakeprojectmanager.h" 16 | #include "cmakeprojectmanagertr.h" 17 | #include "cmakeprojectnodes.h" 18 | #include "cmakesettingspage.h" 19 | #include "cmaketoolmanager.h" 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | 38 | using namespace Core; 39 | using namespace ProjectExplorer; 40 | using namespace Utils; 41 | 42 | namespace CMakeProjectManager::Internal { 43 | 44 | class CMakeProjectPluginPrivate : public QObject 45 | { 46 | public: 47 | // This can't be stand-alone yet as it registers in the plugin object pool 48 | CMakeToolManager cmakeToolManager; 49 | 50 | ParameterAction buildTargetContextAction{ 51 | Tr::tr("Build"), 52 | Tr::tr("Build \"%1\""), 53 | ParameterAction::AlwaysEnabled/*handled manually*/ 54 | }; 55 | 56 | CMakeSettingsPage settingsPage; 57 | 58 | CMakeManager manager; 59 | CMakeBuildStepFactory buildStepFactory; 60 | CMakeBuildConfigurationFactory buildConfigFactory; 61 | CMakeEditorFactory editorFactor; 62 | CMakeInstallStepFactory installStepFactory; 63 | CMakeBuildTargetFilter cMakeBuildTargetFilter; 64 | CMakeOpenTargetFilter cMakeOpenTargetFilter; 65 | 66 | CMakeFormatter cmakeFormatter; 67 | }; 68 | 69 | CMakeProjectPlugin::~CMakeProjectPlugin() 70 | { 71 | delete d; 72 | } 73 | 74 | void CMakeProjectPlugin::initialize() 75 | { 76 | d = new CMakeProjectPluginPrivate; 77 | 78 | const Context projectContext{CMakeProjectManager::Constants::CMAKE_PROJECT_ID}; 79 | 80 | FileIconProvider::registerIconOverlayForSuffix(Constants::Icons::FILE_OVERLAY, "cmake"); 81 | FileIconProvider::registerIconOverlayForFilename(Constants::Icons::FILE_OVERLAY, 82 | "CMakeLists.txt"); 83 | 84 | TextEditor::SnippetProvider::registerGroup(Constants::CMAKE_SNIPPETS_GROUP_ID, 85 | Tr::tr("CMake", "SnippetProvider")); 86 | ProjectManager::registerProjectType(Utils::Constants::CMAKE_PROJECT_MIMETYPE); 87 | 88 | //register actions 89 | Command *command = ActionManager::registerAction(&d->buildTargetContextAction, 90 | Constants::BUILD_TARGET_CONTEXT_MENU, 91 | projectContext); 92 | command->setAttribute(Command::CA_Hide); 93 | command->setAttribute(Command::CA_UpdateText); 94 | command->setDescription(d->buildTargetContextAction.text()); 95 | 96 | ActionManager::actionContainer(ProjectExplorer::Constants::M_SUBPROJECTCONTEXT) 97 | ->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD); 98 | 99 | // Wire up context menu updates: 100 | connect(ProjectTree::instance(), &ProjectTree::currentNodeChanged, 101 | this, &CMakeProjectPlugin::updateContextActions); 102 | 103 | connect(&d->buildTargetContextAction, &ParameterAction::triggered, this, [] { 104 | if (auto bs = qobject_cast(ProjectTree::currentBuildSystem())) { 105 | auto targetNode = dynamic_cast(ProjectTree::currentNode()); 106 | bs->buildCMakeTarget(targetNode ? targetNode->displayName() : QString()); 107 | } 108 | }); 109 | } 110 | 111 | void CMakeProjectPlugin::extensionsInitialized() 112 | { 113 | // Delay the restoration to allow the devices to load first. 114 | QTimer::singleShot(0, this, [] { CMakeToolManager::restoreCMakeTools(); }); 115 | } 116 | 117 | void CMakeProjectPlugin::updateContextActions(Node *node) 118 | { 119 | auto targetNode = dynamic_cast(node); 120 | const QString targetDisplayName = targetNode ? targetNode->displayName() : QString(); 121 | 122 | // Build Target: 123 | d->buildTargetContextAction.setParameter(targetDisplayName); 124 | d->buildTargetContextAction.setEnabled(targetNode); 125 | d->buildTargetContextAction.setVisible(targetNode); 126 | } 127 | 128 | } // CMakeProjectManager::Internal 129 | 130 | -------------------------------------------------------------------------------- /cmakeprojectplugin.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace ProjectExplorer { class Node; } 9 | 10 | namespace CMakeProjectManager::Internal { 11 | 12 | class CMakeProjectPlugin final : public ExtensionSystem::IPlugin 13 | { 14 | Q_OBJECT 15 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "CMakeProjectManager2.json") 16 | 17 | public: 18 | ~CMakeProjectPlugin(); 19 | 20 | #ifdef WITH_TESTS 21 | private slots: 22 | void testCMakeParser_data(); 23 | void testCMakeParser(); 24 | 25 | void testCMakeSplitValue_data(); 26 | void testCMakeSplitValue(); 27 | 28 | void testCMakeProjectImporterQt_data(); 29 | void testCMakeProjectImporterQt(); 30 | 31 | void testCMakeProjectImporterToolChain_data(); 32 | void testCMakeProjectImporterToolChain(); 33 | #endif 34 | 35 | private: 36 | void initialize() final; 37 | void extensionsInitialized() final; 38 | 39 | void updateContextActions(ProjectExplorer::Node *node); 40 | 41 | class CMakeProjectPluginPrivate *d = nullptr; 42 | }; 43 | 44 | } // CMakeProjectManager::Internal 45 | -------------------------------------------------------------------------------- /cmakesettingspage.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace CMakeProjectManager::Internal { 9 | 10 | class CMakeSettingsPage final : public Core::IOptionsPage 11 | { 12 | public: 13 | CMakeSettingsPage(); 14 | }; 15 | 16 | } // CMakeProjectManager::Internal 17 | -------------------------------------------------------------------------------- /cmakespecificsettings.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #include "cmakespecificsettings.h" 5 | 6 | #include "cmakeprojectconstants.h" 7 | #include "cmakeprojectmanagertr.h" 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | using namespace Utils; 17 | 18 | namespace CMakeProjectManager::Internal { 19 | 20 | CMakeSpecificSettings &settings() 21 | { 22 | static CMakeSpecificSettings theSettings; 23 | return theSettings; 24 | } 25 | 26 | CMakeSpecificSettings::CMakeSpecificSettings() 27 | { 28 | setLayouter([this] { 29 | using namespace Layouting; 30 | return Column { 31 | autorunCMake, 32 | packageManagerAutoSetup, 33 | askBeforeReConfigureInitialParams, 34 | askBeforePresetsReload, 35 | showSourceSubFolders, 36 | showAdvancedOptionsByDefault, 37 | st 38 | }; 39 | }); 40 | 41 | // TODO: fixup of QTCREATORBUG-26289 , remove in Qt Creator 7 or so 42 | Core::ICore::settings()->remove("CMakeSpecificSettings/NinjaPath"); 43 | 44 | setSettingsGroup("CMakeSpecificSettings"); 45 | setAutoApply(false); 46 | 47 | autorunCMake.setSettingsKey("AutorunCMake"); 48 | autorunCMake.setDefaultValue(true); 49 | autorunCMake.setLabelText(::CMakeProjectManager::Tr::tr("Autorun CMake")); 50 | autorunCMake.setToolTip(::CMakeProjectManager::Tr::tr( 51 | "Automatically run CMake after changes to CMake project files.")); 52 | 53 | ninjaPath.setSettingsKey("NinjaPath"); 54 | // never save this to the settings: 55 | ninjaPath.setToSettingsTransformation( 56 | [](const QVariant &) { return QVariant::fromValue(QString()); }); 57 | ninjaPath.setFromSettingsTransformation([](const QVariant &from) { 58 | // Sometimes the installer appends the same ninja path to the qtcreator.ini file 59 | const QString path = from.canConvert() ? from.toStringList().last() 60 | : from.toString(); 61 | return FilePath::fromUserInput(path).toVariant(); 62 | }); 63 | 64 | packageManagerAutoSetup.setSettingsKey("PackageManagerAutoSetup"); 65 | packageManagerAutoSetup.setDefaultValue(true); 66 | packageManagerAutoSetup.setLabelText(::CMakeProjectManager::Tr::tr("Package manager auto setup")); 67 | packageManagerAutoSetup.setToolTip(::CMakeProjectManager::Tr::tr("Add the CMAKE_PROJECT_INCLUDE_BEFORE variable " 68 | "pointing to a CMake script that will install dependencies from the conanfile.txt, " 69 | "conanfile.py, or vcpkg.json file from the project source directory.")); 70 | 71 | askBeforeReConfigureInitialParams.setSettingsKey("AskReConfigureInitialParams"); 72 | askBeforeReConfigureInitialParams.setDefaultValue(true); 73 | askBeforeReConfigureInitialParams.setLabelText(::CMakeProjectManager::Tr::tr("Ask before re-configuring with " 74 | "initial parameters")); 75 | 76 | askBeforePresetsReload.setSettingsKey("AskBeforePresetsReload"); 77 | askBeforePresetsReload.setDefaultValue(true); 78 | askBeforePresetsReload.setLabelText(::CMakeProjectManager::Tr::tr("Ask before reloading CMake Presets")); 79 | 80 | showSourceSubFolders.setSettingsKey("ShowSourceSubFolders"); 81 | showSourceSubFolders.setDefaultValue(true); 82 | showSourceSubFolders.setLabelText( 83 | ::CMakeProjectManager::Tr::tr("Show subfolders inside source group folders")); 84 | 85 | showAdvancedOptionsByDefault.setSettingsKey("ShowAdvancedOptionsByDefault"); 86 | showAdvancedOptionsByDefault.setDefaultValue(false); 87 | showAdvancedOptionsByDefault.setLabelText( 88 | ::CMakeProjectManager::Tr::tr("Show advanced options by default")); 89 | 90 | readSettings(); 91 | } 92 | 93 | class CMakeSpecificSettingsPage final : public Core::IOptionsPage 94 | { 95 | public: 96 | CMakeSpecificSettingsPage() 97 | { 98 | setId(Constants::Settings::GENERAL_ID); 99 | setDisplayName(::CMakeProjectManager::Tr::tr("General")); 100 | setDisplayCategory("CMake"); 101 | setCategory(Constants::Settings::CATEGORY); 102 | setCategoryIconPath(Constants::Icons::SETTINGS_CATEGORY); 103 | setSettingsProvider([] { return &settings(); }); 104 | } 105 | }; 106 | 107 | const CMakeSpecificSettingsPage settingsPage; 108 | 109 | } // CMakeProjectManager::Internal 110 | -------------------------------------------------------------------------------- /cmakespecificsettings.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace CMakeProjectManager::Internal { 9 | 10 | class CMakeSpecificSettings final : public Utils::AspectContainer 11 | { 12 | public: 13 | CMakeSpecificSettings(); 14 | 15 | Utils::BoolAspect autorunCMake{this}; 16 | Utils::FilePathAspect ninjaPath{this}; 17 | Utils::BoolAspect packageManagerAutoSetup{this}; 18 | Utils::BoolAspect askBeforeReConfigureInitialParams{this}; 19 | Utils::BoolAspect askBeforePresetsReload{this}; 20 | Utils::BoolAspect showSourceSubFolders{this}; 21 | Utils::BoolAspect showAdvancedOptionsByDefault{this}; 22 | }; 23 | 24 | CMakeSpecificSettings &settings(); 25 | 26 | } // CMakeProjectManager::Internal 27 | -------------------------------------------------------------------------------- /cmaketool.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmake_global.h" 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | namespace Utils { class Process; } 17 | 18 | namespace CMakeProjectManager { 19 | 20 | namespace Internal { class IntrospectionData; } 21 | 22 | struct CMAKE_EXPORT CMakeKeywords 23 | { 24 | QMap variables; 25 | QMap functions; 26 | QMap properties; 27 | QSet generatorExpressions; 28 | QMap environmentVariables; 29 | QMap directoryProperties; 30 | QMap sourceProperties; 31 | QMap targetProperties; 32 | QMap testProperties; 33 | QMap includeStandardModules; 34 | QMap findModules; 35 | QMap policies; 36 | QMap functionArgs; 37 | }; 38 | 39 | class CMAKE_EXPORT CMakeTool 40 | { 41 | public: 42 | enum Detection { ManualDetection, AutoDetection }; 43 | 44 | enum ReaderType { FileApi }; 45 | 46 | struct Version 47 | { 48 | int major = 0; 49 | int minor = 0; 50 | int patch = 0; 51 | QByteArray fullVersion; 52 | }; 53 | 54 | class Generator 55 | { 56 | public: 57 | Generator(const QString &n, const QStringList &eg, bool pl = true, bool ts = true) : 58 | name(n), extraGenerators(eg), supportsPlatform(pl), supportsToolset(ts) 59 | { } 60 | 61 | QString name; 62 | QStringList extraGenerators; 63 | bool supportsPlatform = true; 64 | bool supportsToolset = true; 65 | 66 | bool matches(const QString &n) const; 67 | }; 68 | 69 | using PathMapper = std::function; 70 | 71 | explicit CMakeTool(Detection d, const Utils::Id &id); 72 | explicit CMakeTool(const Utils::Store &map, bool fromSdk); 73 | ~CMakeTool(); 74 | 75 | static Utils::Id createId(); 76 | 77 | bool isValid(bool ignoreCache = false) const; 78 | 79 | Utils::Id id() const { return m_id; } 80 | Utils::Store toMap () const; 81 | 82 | void setAutorun(bool autoRun) { m_isAutoRun = autoRun; } 83 | 84 | void setFilePath(const Utils::FilePath &executable); 85 | Utils::FilePath filePath() const; 86 | Utils::FilePath cmakeExecutable() const; 87 | void setQchFilePath(const Utils::FilePath &path); 88 | Utils::FilePath qchFilePath() const; 89 | static Utils::FilePath cmakeExecutable(const Utils::FilePath &path); 90 | bool isAutoRun() const; 91 | bool autoCreateBuildDirectory() const; 92 | QList supportedGenerators() const; 93 | CMakeKeywords keywords(); 94 | bool hasFileApi(bool ignoreCache = false) const; 95 | Version version() const; 96 | QString versionDisplay() const; 97 | 98 | bool isAutoDetected() const; 99 | QString displayName() const; 100 | void setDisplayName(const QString &displayName); 101 | 102 | void setPathMapper(const PathMapper &includePathMapper); 103 | PathMapper pathMapper() const; 104 | 105 | std::optional readerType() const; 106 | 107 | static Utils::FilePath searchQchFile(const Utils::FilePath &executable); 108 | 109 | QString detectionSource() const { return m_detectionSource; } 110 | void setDetectionSource(const QString &source) { m_detectionSource = source; } 111 | 112 | static QString documentationUrl(const Version &version, bool online); 113 | static void openCMakeHelpUrl(const CMakeTool *tool, const QString &linkUrl); 114 | 115 | private: 116 | void readInformation(bool ignoreCache = false) const; 117 | 118 | void runCMake(Utils::Process &proc, const QStringList &args, int timeoutS = 1) const; 119 | void parseFunctionDetailsOutput(const QString &output); 120 | QStringList parseVariableOutput(const QString &output); 121 | QStringList parseSyntaxHighlightingXml(); 122 | 123 | void fetchFromCapabilities(bool ignoreCache = false) const; 124 | void parseFromCapabilities(const QString &input) const; 125 | 126 | // Note: New items here need also be handled in CMakeToolItemModel::apply() 127 | // FIXME: Use a saner approach. 128 | Utils::Id m_id; 129 | QString m_displayName; 130 | Utils::FilePath m_executable; 131 | Utils::FilePath m_qchFilePath; 132 | 133 | bool m_isAutoRun = true; 134 | bool m_isAutoDetected = false; 135 | QString m_detectionSource; 136 | bool m_autoCreateBuildDirectory = false; 137 | 138 | std::optional m_readerType; 139 | 140 | std::unique_ptr m_introspection; 141 | 142 | PathMapper m_pathMapper; 143 | }; 144 | 145 | } // namespace CMakeProjectManager 146 | -------------------------------------------------------------------------------- /cmaketoolmanager.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Canonical Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmake_global.h" 7 | 8 | #include "cmaketool.h" 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | namespace CMakeProjectManager { 18 | 19 | class CMAKE_EXPORT CMakeToolManager : public QObject 20 | { 21 | Q_OBJECT 22 | public: 23 | CMakeToolManager(); 24 | ~CMakeToolManager(); 25 | 26 | static CMakeToolManager *instance(); 27 | 28 | static QList cmakeTools(); 29 | 30 | static bool registerCMakeTool(std::unique_ptr &&tool); 31 | static void deregisterCMakeTool(const Utils::Id &id); 32 | 33 | static CMakeTool *defaultProjectOrDefaultCMakeTool(); 34 | 35 | static CMakeTool *defaultCMakeTool(); 36 | static void setDefaultCMakeTool(const Utils::Id &id); 37 | static CMakeTool *findByCommand(const Utils::FilePath &command); 38 | static CMakeTool *findById(const Utils::Id &id); 39 | 40 | static void notifyAboutUpdate(CMakeTool *); 41 | static void restoreCMakeTools(); 42 | 43 | static void updateDocumentation(); 44 | 45 | static QString toolTipForRstHelpFile(const Utils::FilePath &helpFile); 46 | 47 | public slots: 48 | QList autoDetectCMakeForDevice(const Utils::FilePaths &searchPaths, 49 | const QString &detectionSource, 50 | QString *logMessage); 51 | Utils::Id registerCMakeByPath(const Utils::FilePath &cmakePath, 52 | const QString &detectionSource); 53 | void removeDetectedCMake(const QString &detectionSource, QString *logMessage); 54 | void listDetectedCMake(const QString &detectionSource, QString *logMessage); 55 | 56 | signals: 57 | void cmakeAdded (const Utils::Id &id); 58 | void cmakeRemoved (const Utils::Id &id); 59 | void cmakeUpdated (const Utils::Id &id); 60 | void cmakeToolsChanged (); 61 | void cmakeToolsLoaded (); 62 | void defaultCMakeChanged (); 63 | 64 | private: 65 | static void saveCMakeTools(); 66 | static void ensureDefaultCMakeToolIsValid(); 67 | 68 | static CMakeToolManager *m_instance; 69 | }; 70 | 71 | } // namespace CMakeProjectManager 72 | 73 | Q_DECLARE_METATYPE(QString *) 74 | -------------------------------------------------------------------------------- /cmaketoolsettingsaccessor.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace CMakeProjectManager { 11 | 12 | class CMakeTool; 13 | 14 | namespace Internal { 15 | 16 | class CMakeToolSettingsAccessor : public Utils::UpgradingSettingsAccessor 17 | { 18 | public: 19 | CMakeToolSettingsAccessor(); 20 | 21 | struct CMakeTools { 22 | Utils::Id defaultToolId; 23 | std::vector> cmakeTools; 24 | }; 25 | 26 | CMakeTools restoreCMakeTools(QWidget *parent) const; 27 | 28 | void saveCMakeTools(const QList &cmakeTools, 29 | const Utils::Id &defaultId, 30 | QWidget *parent); 31 | 32 | private: 33 | CMakeTools cmakeTools(const Utils::Store &data, bool fromSdk) const; 34 | }; 35 | 36 | } // namespace Internal 37 | } // namespace CMakeProjectManager 38 | -------------------------------------------------------------------------------- /configmodel.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmakeconfigitem.h" 7 | 8 | #include 9 | 10 | namespace CMakeProjectManager::Internal { 11 | 12 | class ConfigModelTreeItem; 13 | 14 | class ConfigModel : public Utils::TreeModel<> 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | enum Roles { 20 | ItemIsAdvancedRole = Qt::UserRole, 21 | ItemIsInitialRole, 22 | ItemIsUserNew, 23 | }; 24 | 25 | struct DataItem { 26 | bool operator==(const DataItem &other) const { 27 | return key == other.key && isInitial == other.isInitial; 28 | } 29 | 30 | DataItem() {} 31 | DataItem(const CMakeConfigItem &cmi); 32 | 33 | void setType(CMakeConfigItem::Type cmt); 34 | 35 | QString typeDisplay() const; 36 | 37 | CMakeConfigItem toCMakeConfigItem() const; 38 | 39 | QString expandedValue(Utils::MacroExpander *expander); 40 | 41 | enum Type { BOOLEAN, FILE, DIRECTORY, STRING, UNKNOWN}; 42 | 43 | QString key; 44 | Type type = STRING; 45 | bool isHidden = false; 46 | bool isAdvanced = false; 47 | bool isInitial = false; 48 | bool inCMakeCache = false; 49 | bool isUnset = false; 50 | QString value; 51 | QString description; 52 | QStringList values; 53 | }; 54 | 55 | explicit ConfigModel(QObject *parent = nullptr); 56 | ~ConfigModel() override; 57 | 58 | QVariant data(const QModelIndex &idx, int role) const final; 59 | bool setData(const QModelIndex &idx, const QVariant &data, int role) final; 60 | 61 | void appendConfiguration(const QString &key, 62 | const QString &value = QString(), 63 | const DataItem::Type type = DataItem::UNKNOWN, 64 | bool isInitial = false, 65 | const QString &description = QString(), 66 | const QStringList &values = QStringList()); 67 | void setConfiguration(const CMakeConfig &config); 68 | void setBatchEditConfiguration(const CMakeConfig &config); 69 | void setInitialParametersConfiguration(const CMakeConfig &config); 70 | void setConfiguration(const QList &config); 71 | 72 | using KitConfiguration = QHash; 73 | void setConfigurationFromKit(const KitConfiguration &kitConfig); 74 | 75 | void flush(); 76 | void resetAllChanges(bool initialParameters = false); 77 | 78 | bool hasChanges(bool initialParameters = false) const; 79 | 80 | bool canForceTo(const QModelIndex &idx, const DataItem::Type type) const; 81 | void forceTo(const QModelIndex &idx, const DataItem::Type type); 82 | 83 | void toggleUnsetFlag(const QModelIndex &idx); 84 | 85 | void applyKitValue(const QModelIndex &idx); 86 | void applyInitialValue(const QModelIndex &idx); 87 | 88 | static DataItem dataItemFromIndex(const QModelIndex &idx); 89 | 90 | QList configurationForCMake() const; 91 | 92 | Utils::MacroExpander *macroExpander() const; 93 | void setMacroExpander(Utils::MacroExpander *newExpander); 94 | 95 | private: 96 | enum class KitOrInitial { Kit, Initial }; 97 | void applyKitOrInitialValue(const QModelIndex &idx, KitOrInitial ki); 98 | 99 | class InternalDataItem : public DataItem 100 | { 101 | public: 102 | InternalDataItem(const DataItem &item); 103 | 104 | QString currentValue() const; 105 | 106 | bool isUserChanged = false; 107 | bool isUserNew = false; 108 | QString newValue; 109 | QString kitValue; 110 | QString initialValue; 111 | }; 112 | 113 | void generateTree(); 114 | 115 | void setConfiguration(const QList &config); 116 | QList m_configuration; 117 | KitConfiguration m_kitConfiguration; 118 | Utils::MacroExpander *m_macroExpander = nullptr; 119 | 120 | friend class Internal::ConfigModelTreeItem; 121 | }; 122 | 123 | class ConfigModelTreeItem : public Utils::TreeItem 124 | { 125 | public: 126 | ConfigModelTreeItem(ConfigModel::InternalDataItem *di = nullptr) : dataItem(di) {} 127 | ~ConfigModelTreeItem() override; 128 | 129 | QVariant data(int column, int role) const final; 130 | bool setData(int column, const QVariant &data, int role) final; 131 | Qt::ItemFlags flags(int column) const final; 132 | 133 | QString toolTip() const; 134 | QString currentValue() const; 135 | 136 | ConfigModel::InternalDataItem *dataItem; 137 | }; 138 | 139 | } // CMakeProjectManager::Internal 140 | -------------------------------------------------------------------------------- /configmodelitemdelegate.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Alexander Drozdov. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #include "configmodelitemdelegate.h" 5 | 6 | #include "configmodel.h" 7 | #include "cmakeprojectmanagertr.h" 8 | 9 | #include 10 | 11 | #include 12 | 13 | using namespace Utils; 14 | 15 | namespace CMakeProjectManager::Internal { 16 | 17 | ConfigModelItemDelegate::ConfigModelItemDelegate(const FilePath &base, QObject* parent) 18 | : QStyledItemDelegate(parent) 19 | , m_base(base) 20 | { } 21 | 22 | QWidget *ConfigModelItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, 23 | const QModelIndex &index) const 24 | 25 | { 26 | if (index.column() == 1) { 27 | ConfigModel::DataItem data = ConfigModel::dataItemFromIndex(index); 28 | if (data.type == ConfigModel::DataItem::FILE || data.type == ConfigModel::DataItem::DIRECTORY) { 29 | auto edit = new PathChooser(parent); 30 | edit->setAttribute(Qt::WA_MacSmallSize); 31 | edit->setFocusPolicy(Qt::StrongFocus); 32 | edit->setBaseDirectory(m_base); 33 | edit->setAutoFillBackground(true); 34 | if (data.type == ConfigModel::DataItem::FILE) { 35 | edit->setExpectedKind(PathChooser::File); 36 | edit->setPromptDialogTitle(Tr::tr("Select a file for %1").arg(data.key)); 37 | } else { 38 | edit->setExpectedKind(PathChooser::Directory); 39 | edit->setPromptDialogTitle(Tr::tr("Select a directory for %1").arg(data.key)); 40 | } 41 | return edit; 42 | } else if (!data.values.isEmpty()) { 43 | auto edit = new QComboBox(parent); 44 | edit->setAttribute(Qt::WA_MacSmallSize); 45 | edit->setFocusPolicy(Qt::StrongFocus); 46 | edit->setAutoFillBackground(true); 47 | for (const QString &s : std::as_const(data.values)) 48 | edit->addItem(s); 49 | return edit; 50 | } else if (data.type == ConfigModel::DataItem::BOOLEAN) { 51 | auto edit = new QCheckBox(parent); 52 | edit->setFocusPolicy(Qt::StrongFocus); 53 | return edit; 54 | } else if (data.type == ConfigModel::DataItem::STRING) { 55 | auto edit = new QLineEdit(parent); 56 | edit->setFocusPolicy(Qt::StrongFocus); 57 | return edit; 58 | } 59 | } 60 | 61 | return QStyledItemDelegate::createEditor(parent, option, index); 62 | } 63 | 64 | void ConfigModelItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const 65 | { 66 | if (index.column() == 1) { 67 | ConfigModel::DataItem data = ConfigModel::dataItemFromIndex(index); 68 | if (data.type == ConfigModel::DataItem::FILE || data.type == ConfigModel::DataItem::DIRECTORY) { 69 | auto edit = static_cast(editor); 70 | edit->setFilePath(FilePath::fromUserInput(data.value)); 71 | return; 72 | } else if (!data.values.isEmpty()) { 73 | auto edit = static_cast(editor); 74 | edit->setCurrentText(data.value); 75 | return; 76 | } else if (data.type == ConfigModel::DataItem::BOOLEAN) { 77 | auto edit = static_cast(editor); 78 | edit->setChecked(index.data(Qt::CheckStateRole).toBool()); 79 | edit->setText(data.value); 80 | return; 81 | } else if (data.type == ConfigModel::DataItem::STRING) { 82 | auto edit = static_cast(editor); 83 | edit->setText(data.value); 84 | return; 85 | } 86 | } 87 | QStyledItemDelegate::setEditorData(editor, index); 88 | } 89 | 90 | void ConfigModelItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, 91 | const QModelIndex &index) const 92 | { 93 | if (index.column() == 1) { 94 | ConfigModel::DataItem data = ConfigModel::dataItemFromIndex(index); 95 | if (data.type == ConfigModel::DataItem::FILE || data.type == ConfigModel::DataItem::DIRECTORY) { 96 | auto edit = static_cast(editor); 97 | if (edit->rawFilePath().toString() != data.value) 98 | model->setData(index, edit->rawFilePath().toString(), Qt::EditRole); 99 | return; 100 | } else if (!data.values.isEmpty()) { 101 | auto edit = static_cast(editor); 102 | model->setData(index, edit->currentText(), Qt::EditRole); 103 | return; 104 | } else if (data.type == ConfigModel::DataItem::BOOLEAN) { 105 | auto edit = static_cast(editor); 106 | model->setData(index, edit->text(), Qt::EditRole); 107 | } else if (data.type == ConfigModel::DataItem::STRING) { 108 | auto edit = static_cast(editor); 109 | model->setData(index, edit->text(), Qt::EditRole); 110 | } 111 | } 112 | QStyledItemDelegate::setModelData(editor, model, index); 113 | } 114 | 115 | QSize ConfigModelItemDelegate::sizeHint(const QStyleOptionViewItem &option, 116 | const QModelIndex &index) const 117 | { 118 | static int height = -1; 119 | if (height < 0) { 120 | const auto setMaxSize = [](const QWidget &w) { 121 | if (w.sizeHint().height() > height) 122 | height = w.sizeHint().height(); 123 | }; 124 | QComboBox box; 125 | box.setAttribute(Qt::WA_MacSmallSize); 126 | QCheckBox check; 127 | setMaxSize(box); 128 | setMaxSize(check); 129 | // Do not take the path chooser into consideration, because that would make the height 130 | // larger on Windows, leading to less items displayed, and the size of PathChooser looks 131 | // "fine enough" as is. 132 | } 133 | Q_UNUSED(option) 134 | Q_UNUSED(index) 135 | return QSize(100, height); 136 | } 137 | 138 | } // CMakeProjectManager::Internal 139 | -------------------------------------------------------------------------------- /configmodelitemdelegate.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Alexander Drozdov. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace CMakeProjectManager::Internal { 12 | 13 | class ConfigModelItemDelegate : public QStyledItemDelegate 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | ConfigModelItemDelegate(const Utils::FilePath &base, QObject *parent = nullptr); 19 | 20 | QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, 21 | const QModelIndex &index) const final; 22 | void setEditorData(QWidget *editor, const QModelIndex &index) const final; 23 | void setModelData(QWidget *editor, QAbstractItemModel *model, 24 | const QModelIndex &index) const final; 25 | QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const final; 26 | 27 | private: 28 | Utils::FilePath m_base; 29 | }; 30 | 31 | } // CMakeProjectManager::Internal 32 | -------------------------------------------------------------------------------- /fileapidataextractor.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmakebuildtarget.h" 7 | #include "cmakeprojectnodes.h" 8 | #include "3rdparty/cmake/cmListFileCache.h" 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | namespace CMakeProjectManager::Internal { 22 | 23 | class FileApiData; 24 | 25 | class CMakeFileInfo 26 | { 27 | public: 28 | bool operator==(const CMakeFileInfo& other) const { return path == other.path; } 29 | friend size_t qHash(const CMakeFileInfo &info, uint seed = 0) { return qHash(info.path, seed); } 30 | 31 | bool operator<(const CMakeFileInfo &other) const { return path < other.path; } 32 | 33 | Utils::FilePath path; 34 | bool isCMake = false; 35 | bool isCMakeListsDotTxt = false; 36 | bool isExternal = false; 37 | bool isGenerated = false; 38 | cmListFile cmakeListFile; 39 | }; 40 | 41 | class FileApiQtcData 42 | { 43 | public: 44 | QString errorMessage; 45 | CMakeConfig cache; 46 | QSet cmakeFiles; 47 | QList buildTargets; 48 | ProjectExplorer::RawProjectParts projectParts; 49 | std::unique_ptr rootProjectNode; 50 | QString ctestPath; 51 | bool isMultiConfig = false; 52 | bool usesAllCapsTargets = false; 53 | }; 54 | 55 | FileApiQtcData extractData(const QFuture &cancelFuture, FileApiData &input, 56 | const Utils::FilePath &sourceDir, const Utils::FilePath &buildDir, 57 | bool plain = false); 58 | 59 | } // CMakeProjectManager::Internal 60 | -------------------------------------------------------------------------------- /fileapiparser.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmakeconfigitem.h" 7 | 8 | #include "fileapidataextractor.h" 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | QT_BEGIN_NAMESPACE 23 | template 24 | class QPromise; 25 | QT_END_NAMESPACE 26 | 27 | namespace CMakeProjectManager::Internal { 28 | 29 | namespace FileApiDetails { 30 | 31 | class ReplyObject 32 | { 33 | public: 34 | QString kind; 35 | QString file; 36 | std::pair version; 37 | }; 38 | 39 | class ReplyFileContents 40 | { 41 | public: 42 | QString generator; 43 | bool isMultiConfig = false; 44 | QString cmakeExecutable; 45 | QString ctestExecutable; 46 | QString cmakeRoot; 47 | 48 | QVector replies; 49 | QVersionNumber cmakeVersion; 50 | 51 | Utils::FilePath jsonFile(const QString &kind, const Utils::FilePath &replyDir) const; 52 | }; 53 | 54 | class Directory 55 | { 56 | public: 57 | QString buildPath; 58 | QString sourcePath; 59 | int parent = -1; 60 | int project = -1; 61 | std::vector children; 62 | std::vector targets; 63 | bool hasInstallRule = false; 64 | }; 65 | 66 | class Project 67 | { 68 | public: 69 | QString name; 70 | int parent = -1; 71 | std::vector children; 72 | std::vector directories; 73 | std::vector targets; 74 | }; 75 | 76 | class Target 77 | { 78 | public: 79 | // From codemodel file: 80 | QString name; 81 | QString id; 82 | int directory = -1; 83 | int project = -1; 84 | QString jsonFile; 85 | }; 86 | 87 | class Configuration 88 | { 89 | public: 90 | QString name; 91 | std::vector directories; 92 | std::vector projects; 93 | std::vector targets; 94 | }; 95 | 96 | class InstallDestination 97 | { 98 | public: 99 | QString path; 100 | int backtrace; 101 | }; 102 | 103 | class FragmentInfo 104 | { 105 | public: 106 | QString fragment; 107 | QString role; 108 | }; 109 | 110 | class LinkInfo 111 | { 112 | public: 113 | QString language; 114 | std::vector fragments; 115 | bool isLto = false; 116 | QString sysroot; 117 | }; 118 | 119 | class ArchiveInfo 120 | { 121 | public: 122 | std::vector fragments; 123 | bool isLto = false; 124 | }; 125 | 126 | class DependencyInfo 127 | { 128 | public: 129 | QString targetId; 130 | int backtrace; 131 | }; 132 | 133 | class SourceInfo 134 | { 135 | public: 136 | QString path; 137 | int compileGroup = -1; 138 | int sourceGroup = -1; 139 | int backtrace = -1; 140 | bool isGenerated = false; 141 | }; 142 | 143 | class IncludeInfo 144 | { 145 | public: 146 | ProjectExplorer::HeaderPath path; 147 | int backtrace; 148 | }; 149 | 150 | class DefineInfo 151 | { 152 | public: 153 | ProjectExplorer::Macro define; 154 | int backtrace; 155 | }; 156 | 157 | class CompileInfo 158 | { 159 | public: 160 | std::vector sources; 161 | QString language; 162 | QStringList fragments; 163 | std::vector includes; 164 | std::vector defines; 165 | QString sysroot; 166 | }; 167 | 168 | class BacktraceNode 169 | { 170 | public: 171 | int file = -1; 172 | int line = -1; 173 | int command = -1; 174 | int parent = -1; 175 | }; 176 | 177 | class BacktraceInfo 178 | { 179 | public: 180 | std::vector commands; 181 | std::vector files; 182 | std::vector nodes; 183 | }; 184 | 185 | class TargetDetails 186 | { 187 | public: 188 | QString name; 189 | QString id; 190 | QString type; 191 | QString folderTargetProperty; 192 | Utils::FilePath sourceDir; 193 | Utils::FilePath buildDir; 194 | int backtrace = -1; 195 | bool isGeneratorProvided = false; 196 | QString nameOnDisk; 197 | QList artifacts; 198 | QString installPrefix; 199 | std::vector installDestination; 200 | std::optional link; 201 | std::optional archive; 202 | std::vector dependencies; 203 | std::vector sources; 204 | std::vector sourceGroups; 205 | std::vector compileGroups; 206 | BacktraceInfo backtraceGraph; 207 | }; 208 | 209 | } // namespace FileApiDetails 210 | 211 | class FileApiData 212 | { 213 | public: 214 | FileApiDetails::ReplyFileContents replyFile; 215 | CMakeConfig cache; 216 | std::vector cmakeFiles; 217 | FileApiDetails::Configuration codemodel; 218 | std::vector targetDetails; 219 | }; 220 | 221 | class FileApiParser 222 | { 223 | public: 224 | static FileApiData parseData(QPromise> &promise, 225 | const Utils::FilePath &replyFilePath, 226 | const QString &cmakeBuildType, 227 | QString &errorMessage); 228 | 229 | static bool setupCMakeFileApi(const Utils::FilePath &buildDirectory); 230 | 231 | static Utils::FilePath cmakeReplyDirectory(const Utils::FilePath &buildDirectory); 232 | static Utils::FilePaths cmakeQueryFilePaths(const Utils::FilePath &buildDirectory); 233 | 234 | static Utils::FilePath scanForCMakeReplyFile(const Utils::FilePath &buildDirectory); 235 | }; 236 | 237 | } // CMakeProjectManager::Internal 238 | -------------------------------------------------------------------------------- /fileapireader.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "builddirparameters.h" 7 | #include "cmakebuildtarget.h" 8 | #include "cmakeprojectnodes.h" 9 | #include "fileapidataextractor.h" 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | namespace ProjectExplorer { class ProjectNode; } 24 | 25 | namespace CMakeProjectManager::Internal { 26 | 27 | class CMakeProcess; 28 | class FileApiQtcData; 29 | 30 | class FileApiReader : public QObject 31 | { 32 | Q_OBJECT 33 | 34 | public: 35 | FileApiReader(); 36 | ~FileApiReader() override; 37 | 38 | void setParameters(const BuildDirParameters &p); 39 | 40 | void resetData(); 41 | void parse(bool forceCMakeRun, 42 | bool forceInitialConfiguration, 43 | bool forceExtraConfiguration, 44 | bool debugging, 45 | bool profiling); 46 | void stop(); 47 | void stopCMakeRun(); 48 | 49 | bool isParsing() const; 50 | 51 | QList takeBuildTargets(QString &errorMessage); 52 | QSet takeCMakeFileInfos(QString &errorMessage); 53 | CMakeConfig takeParsedConfiguration(QString &errorMessage); 54 | QString ctestPath() const; 55 | virtual 56 | ProjectExplorer::RawProjectParts createRawProjectParts(QString &errorMessage); 57 | 58 | bool isMultiConfig() const; 59 | bool usesAllCapsTargets() const; 60 | 61 | int lastCMakeExitCode() const; 62 | 63 | std::unique_ptr rootProjectNode(); 64 | 65 | Utils::FilePath topCmakeFile() const; 66 | 67 | signals: 68 | void configurationStarted() const; 69 | void dataAvailable(bool restoredFromBackup) const; 70 | void dirty() const; 71 | void errorOccurred(const QString &message) const; 72 | void debuggingStarted() const; 73 | 74 | protected: 75 | void startState(); 76 | void endState(const Utils::FilePath &replyFilePath, bool restoredFromBackup); 77 | void startCMakeState(const QStringList &configurationArguments); 78 | void cmakeFinishedState(int exitCode); 79 | 80 | void replyDirectoryHasChanged(const QString &directory) const; 81 | void makeBackupConfiguration(bool store); 82 | 83 | void writeConfigurationIntoBuildDirectory(const QStringList &configuration); 84 | 85 | std::unique_ptr m_cmakeProcess; 86 | 87 | // cmake data: 88 | CMakeConfig m_cache; 89 | QSet m_cmakeFiles; 90 | QList m_buildTargets; 91 | ProjectExplorer::RawProjectParts m_projectParts; 92 | std::unique_ptr m_rootProjectNode; 93 | QString m_ctestPath; 94 | bool m_isMultiConfig = false; 95 | bool m_usesAllCapsTargets = false; 96 | bool m_isPlain = false; 97 | int m_lastCMakeExitCode = 0; 98 | 99 | std::optional>> m_future; 100 | 101 | // Update related: 102 | bool m_isParsing = false; 103 | BuildDirParameters m_parameters; 104 | 105 | // Notification on changes outside of creator: 106 | Utils::FileSystemWatcher m_watcher; 107 | QDateTime m_lastReplyTimestamp; 108 | }; 109 | 110 | } // CMakeProjectManager::Internal 111 | -------------------------------------------------------------------------------- /images/fileoverlay_cmake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/h4tr3d/cmakeprojectmanager2/a1373669b315f1b7206e70969a548993f0bd1ca0/images/fileoverlay_cmake.png -------------------------------------------------------------------------------- /images/fileoverlay_cmake@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/h4tr3d/cmakeprojectmanager2/a1373669b315f1b7206e70969a548993f0bd1ca0/images/fileoverlay_cmake@2x.png -------------------------------------------------------------------------------- /images/settingscategory_cmakeprojectmanager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/h4tr3d/cmakeprojectmanager2/a1373669b315f1b7206e70969a548993f0bd1ca0/images/settingscategory_cmakeprojectmanager.png -------------------------------------------------------------------------------- /images/settingscategory_cmakeprojectmanager@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/h4tr3d/cmakeprojectmanager2/a1373669b315f1b7206e70969a548993f0bd1ca0/images/settingscategory_cmakeprojectmanager@2x.png -------------------------------------------------------------------------------- /mk-cmake-patches.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ ! -f qtcreator.qbs ]; then 4 | echo "This command must be executed from the ROOT folder of Qt Creator source tree" 5 | exit 1 6 | fi 7 | 8 | if [ -z "$1" ]; then 9 | echo "Use $(basename $0) Last-Change-Id" 10 | exit 1 11 | fi 12 | 13 | id=$1 14 | 15 | commit=$(git log | grep '^commit \|Change-Id: ' | awk -v id=$id ' 16 | BEGIN { 17 | commit="" 18 | } 19 | { 20 | if ($1 ~ /^commit/) { 21 | commit=$2; 22 | } 23 | if ($1 ~ /^Change-Id:/ && $2 == id) 24 | { 25 | print commit; 26 | exit; 27 | } 28 | }') 29 | 30 | git format-patch $commit -- src/plugins/cmakeprojectmanager/ 31 | -------------------------------------------------------------------------------- /presetsmacros.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace Utils { 9 | class Environment; 10 | class FilePath; 11 | } 12 | 13 | namespace CMakeProjectManager::Internal { 14 | 15 | namespace PresetsDetails { 16 | class ConfigurePreset; 17 | } 18 | 19 | namespace CMakePresets::Macros { 20 | /** 21 | * Expands the CMakePresets Macros using Utils::Environment as target and source for parent environment values. 22 | * $penv{PATH} is taken from Utils::Environment 23 | */ 24 | template 25 | void expand(const PresetType &preset, 26 | Utils::Environment &env, 27 | const Utils::FilePath &sourceDirectory); 28 | 29 | /** 30 | * Expands the CMakePresets Macros using Utils::Environment as target 31 | * $penv{PATH} is replaced with Qt Creator macros ${PATH} 32 | */ 33 | template 34 | void expand(const PresetType &preset, 35 | Utils::EnvironmentItems &envItems, 36 | const Utils::FilePath &sourceDirectory); 37 | 38 | /** 39 | * Expands the CMakePresets macros inside the @value QString parameter. 40 | */ 41 | template 42 | void expand(const PresetType &preset, 43 | const Utils::Environment &env, 44 | const Utils::FilePath &sourceDirectory, 45 | QString &value); 46 | 47 | /** 48 | * Updates the cacheVariables parameter of the configurePreset with the expandned toolchainFile parameter. 49 | * Including macro expansion and relative paths resolving. 50 | */ 51 | void updateToolchainFile(PresetsDetails::ConfigurePreset &configurePreset, 52 | const Utils::Environment &env, 53 | const Utils::FilePath &sourceDirectory, 54 | const Utils::FilePath &buildDirectory); 55 | 56 | /** 57 | * Updates the cacheVariables parameter of the configurePreset with the expanded installDir parameter. 58 | * Including macro expansion and relative paths resolving. 59 | */ 60 | void updateInstallDir(PresetsDetails::ConfigurePreset &configurePreset, 61 | const Utils::Environment &env, 62 | const Utils::FilePath &sourceDirectory); 63 | 64 | /** 65 | * Updates the cacheVariables parameter of the configurePreset with the expanded prameter values. 66 | * Including macro expansion and relative paths resolving. 67 | */ 68 | void updateCacheVariables(PresetsDetails::ConfigurePreset &configurePreset, 69 | const Utils::Environment &env, 70 | const Utils::FilePath &sourceDirectory); 71 | /** 72 | * Expands the condition values and then evaluates the condition object of the preset and returns 73 | * the boolean result. 74 | */ 75 | template 76 | bool evaluatePresetCondition(const PresetType &preset, const Utils::FilePath &sourceDirectory); 77 | 78 | } // namespace CMakePresets::Macros 79 | 80 | } // namespace CMakeProjectManager::Internal 81 | -------------------------------------------------------------------------------- /presetsparser.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmakeconfigitem.h" 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | namespace CMakeProjectManager::Internal { 15 | 16 | namespace PresetsDetails { 17 | 18 | class ValueStrategyPair { 19 | public: 20 | std::optional value; 21 | enum class Strategy : bool { set, external }; 22 | std::optional strategy; 23 | }; 24 | 25 | class Warnings { 26 | public: 27 | std::optional dev; 28 | std::optional deprecated; 29 | std::optional uninitialized = false; 30 | std::optional unusedCli = true; 31 | std::optional systemVars = false; 32 | }; 33 | 34 | class Errors { 35 | public: 36 | std::optional dev; 37 | std::optional deprecated; 38 | }; 39 | 40 | class Debug { 41 | public: 42 | std::optional output = false; 43 | std::optional tryCompile = false; 44 | std::optional find = false; 45 | }; 46 | 47 | class Condition { 48 | public: 49 | QString type; 50 | 51 | bool isNull() const { return type == "null"; } 52 | bool isConst() const { return type == "const"; } 53 | bool isEquals() const { return type == "equals"; } 54 | bool isNotEquals() const { return type == "notEquals"; } 55 | bool isInList() const { return type == "inList"; } 56 | bool isNotInList() const { return type == "notInList"; } 57 | bool isMatches() const { return type == "matches"; } 58 | bool isNotMatches() const { return type == "notMatches"; } 59 | bool isAnyOf() const { return type == "anyOf"; } 60 | bool isAllOf() const { return type == "allOf"; } 61 | bool isNot() const { return type == "not"; } 62 | 63 | bool evaluate() const; 64 | 65 | // const 66 | std::optional constValue; 67 | 68 | // equals, notEquals 69 | std::optional lhs; 70 | std::optional rhs; 71 | 72 | // inList, notInList 73 | std::optional string; 74 | std::optional list; 75 | 76 | // matches, notMatches 77 | std::optional regex; 78 | 79 | using ConditionPtr = std::shared_ptr; 80 | 81 | // anyOf, allOf 82 | std::optional> conditions; 83 | 84 | // not 85 | std::optional condition; 86 | }; 87 | 88 | class ConfigurePreset { 89 | public: 90 | void inheritFrom(const ConfigurePreset &other); 91 | 92 | QString name; 93 | Utils::FilePath fileDir; 94 | std::optional hidden = false; 95 | std::optional inherits; 96 | std::optional condition; 97 | std::optional> vendor; 98 | std::optional displayName; 99 | std::optional description; 100 | std::optional generator; 101 | std::optional architecture; 102 | std::optional toolset; 103 | std::optional toolchainFile; 104 | std::optional binaryDir; 105 | std::optional installDir; 106 | std::optional cmakeExecutable; 107 | std::optional cacheVariables; 108 | std::optional environment; 109 | std::optional warnings; 110 | std::optional errors; 111 | std::optional debug; 112 | }; 113 | 114 | class BuildPreset { 115 | public: 116 | void inheritFrom(const BuildPreset &other); 117 | 118 | QString name; 119 | Utils::FilePath fileDir; 120 | std::optional hidden = false; 121 | std::optional inherits; 122 | std::optional condition; 123 | std::optional> vendor; 124 | std::optional displayName; 125 | std::optional description; 126 | std::optional environment; 127 | std::optional configurePreset; 128 | std::optional inheritConfigureEnvironment = true; 129 | std::optional jobs; 130 | std::optional targets; 131 | std::optional configuration; 132 | std::optional verbose; 133 | std::optional cleanFirst; 134 | std::optional nativeToolOptions; 135 | }; 136 | 137 | } // namespace PresetsDetails 138 | 139 | class PresetsData 140 | { 141 | public: 142 | int version = 0; 143 | QVersionNumber cmakeMinimimRequired; 144 | QHash vendor; 145 | std::optional include; 146 | Utils::FilePath fileDir; 147 | QList configurePresets; 148 | QList buildPresets; 149 | }; 150 | 151 | class PresetsParser 152 | { 153 | PresetsData m_presetsData; 154 | public: 155 | bool parse(Utils::FilePath const &jsonFile, QString &errorMessage, int &errorLine); 156 | 157 | const PresetsData &presetsData() const; 158 | }; 159 | 160 | } // CMakeProjectManager::Internal 161 | -------------------------------------------------------------------------------- /projecttreehelper.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #include "projecttreehelper.h" 5 | 6 | #include "cmakeproject.h" 7 | #include "cmakeprojectmanagertr.h" 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace ProjectExplorer; 17 | 18 | namespace CMakeProjectManager::Internal { 19 | 20 | std::unique_ptr createCMakeVFolder(const Utils::FilePath &basePath, 21 | int priority, 22 | const QString &displayName, 23 | bool sourcesOrHeaders) 24 | { 25 | auto newFolder = std::make_unique(basePath); 26 | newFolder->setPriority(priority); 27 | newFolder->setDisplayName(displayName); 28 | newFolder->setIsSourcesOrHeaders(sourcesOrHeaders); 29 | return newFolder; 30 | } 31 | 32 | void addCMakeVFolder(FolderNode *base, 33 | const Utils::FilePath &basePath, 34 | int priority, 35 | const QString &displayName, 36 | std::vector> &&files, 37 | bool sourcesOrHeaders) 38 | { 39 | if (files.size() == 0) 40 | return; 41 | FolderNode *folder = base; 42 | if (!displayName.isEmpty()) { 43 | auto newFolder = createCMakeVFolder(basePath, priority, displayName, sourcesOrHeaders); 44 | folder = newFolder.get(); 45 | base->addNode(std::move(newFolder)); 46 | } 47 | folder->addNestedNodes(std::move(files)); 48 | folder->forEachFolderNode([] (FolderNode *fn) { fn->compress(); }); 49 | } 50 | 51 | std::vector> &&removeKnownNodes( 52 | const QSet &knownFiles, std::vector> &&files) 53 | { 54 | Utils::erase(files, [&knownFiles](const std::unique_ptr &n) { 55 | return knownFiles.contains(n->filePath()); 56 | }); 57 | return std::move(files); 58 | } 59 | 60 | void addCMakeInputs(FolderNode *root, 61 | const Utils::FilePath &sourceDir, 62 | const Utils::FilePath &buildDir, 63 | std::vector> &&sourceInputs, 64 | std::vector> &&buildInputs, 65 | std::vector> &&rootInputs) 66 | { 67 | std::unique_ptr cmakeVFolder = std::make_unique(root->filePath()); 68 | 69 | QSet knownFiles; 70 | root->forEachGenericNode([&knownFiles](const Node *n) { 71 | if (n->listInProject()) 72 | knownFiles.insert(n->filePath()); 73 | }); 74 | 75 | addCMakeVFolder(cmakeVFolder.get(), 76 | sourceDir, 77 | 1000, 78 | QString(), 79 | removeKnownNodes(knownFiles, std::move(sourceInputs))); 80 | addCMakeVFolder(cmakeVFolder.get(), 81 | buildDir, 82 | 100, 83 | Tr::tr(""), 84 | removeKnownNodes(knownFiles, std::move(buildInputs))); 85 | addCMakeVFolder(cmakeVFolder.get(), 86 | Utils::FilePath(), 87 | 10, 88 | Tr::tr(""), 89 | removeKnownNodes(knownFiles, std::move(rootInputs))); 90 | 91 | root->addNode(std::move(cmakeVFolder)); 92 | } 93 | 94 | void addCMakePresets(FolderNode *root, const Utils::FilePath &sourceDir) 95 | { 96 | QStringList presetFileNames; 97 | presetFileNames << "CMakePresets.json"; 98 | presetFileNames << "CMakeUserPresets.json"; 99 | 100 | const CMakeProject *cp = static_cast( 101 | ProjectManager::projectForFile(sourceDir.pathAppended("CMakeLists.txt"))); 102 | 103 | if (cp && cp->presetsData().include) 104 | presetFileNames.append(cp->presetsData().include.value()); 105 | 106 | std::vector> presets; 107 | for (const auto &fileName : presetFileNames) { 108 | Utils::FilePath file = sourceDir.pathAppended(fileName); 109 | if (file.exists()) 110 | presets.push_back(std::make_unique(file, Node::fileTypeForFileName(file))); 111 | } 112 | 113 | if (presets.empty()) 114 | return; 115 | 116 | std::unique_ptr cmakeVFolder = std::make_unique(root->filePath()); 117 | addCMakeVFolder(cmakeVFolder.get(), sourceDir, 1000, QString(), std::move(presets)); 118 | 119 | root->addNode(std::move(cmakeVFolder)); 120 | } 121 | 122 | QHash addCMakeLists( 123 | CMakeProjectNode *root, std::vector> &&cmakeLists) 124 | { 125 | QHash cmakeListsNodes; 126 | cmakeListsNodes.insert(root->filePath(), root); 127 | 128 | const QSet cmakeDirs 129 | = Utils::transform(cmakeLists, [](const std::unique_ptr &n) { 130 | return n->filePath().parentDir(); 131 | }); 132 | root->addNestedNodes(std::move(cmakeLists), 133 | Utils::FilePath(), 134 | [&cmakeDirs, &cmakeListsNodes](const Utils::FilePath &fp) 135 | -> std::unique_ptr { 136 | if (cmakeDirs.contains(fp)) { 137 | auto fn = std::make_unique(fp); 138 | cmakeListsNodes.insert(fp, fn.get()); 139 | return fn; 140 | } 141 | 142 | return std::make_unique(fp); 143 | }); 144 | root->compress(); 145 | return cmakeListsNodes; 146 | } 147 | 148 | void createProjectNode(const QHash &cmakeListsNodes, 149 | const Utils::FilePath &dir, 150 | const QString &displayName) 151 | { 152 | ProjectNode *cmln = cmakeListsNodes.value(dir); 153 | QTC_ASSERT(cmln, return ); 154 | 155 | const Utils::FilePath projectName = dir.pathAppended(".project::" + displayName); 156 | 157 | ProjectNode *pn = cmln->projectNode(projectName); 158 | if (!pn) { 159 | auto newNode = std::make_unique(projectName); 160 | pn = newNode.get(); 161 | cmln->addNode(std::move(newNode)); 162 | } 163 | pn->setDisplayName(displayName); 164 | } 165 | 166 | CMakeTargetNode *createTargetNode(const QHash &cmakeListsNodes, 167 | const Utils::FilePath &dir, 168 | const QString &displayName) 169 | { 170 | ProjectNode *cmln = cmakeListsNodes.value(dir); 171 | QTC_ASSERT(cmln, return nullptr); 172 | 173 | QString targetId = displayName; 174 | 175 | CMakeTargetNode *tn = static_cast( 176 | cmln->findNode([&targetId](const Node *n) { return n->buildKey() == targetId; })); 177 | if (!tn) { 178 | auto newNode = std::make_unique(dir, displayName); 179 | tn = newNode.get(); 180 | cmln->addNode(std::move(newNode)); 181 | } 182 | tn->setDisplayName(displayName); 183 | return tn; 184 | } 185 | 186 | template 187 | static std::unique_ptr cloneFolderNode(FolderNode *node) 188 | { 189 | auto folderNode = std::make_unique(node->filePath()); 190 | folderNode->setDisplayName(node->displayName()); 191 | for (Node *node : node->nodes()) { 192 | if (FileNode *fn = node->asFileNode()) { 193 | folderNode->addNode(std::unique_ptr(fn->clone())); 194 | } else if (FolderNode *fn = node->asFolderNode()) { 195 | folderNode->addNode(cloneFolderNode(fn)); 196 | } else { 197 | QTC_CHECK(false); 198 | } 199 | } 200 | return folderNode; 201 | } 202 | 203 | void addFileSystemNodes(ProjectNode *root, const std::shared_ptr &folderNode) 204 | { 205 | QTC_ASSERT(root, return ); 206 | 207 | auto fileSystemNode = cloneFolderNode(folderNode.get()); 208 | // just before special nodes like "CMake Modules" 209 | fileSystemNode->setPriority(Node::DefaultPriority - 6); 210 | fileSystemNode->setDisplayName(Tr::tr("")); 211 | fileSystemNode->setIcon(DirectoryIcon(ProjectExplorer::Constants::FILEOVERLAY_UNKNOWN)); 212 | 213 | if (!fileSystemNode->isEmpty()) { 214 | // make file system nodes less probable to be selected when syncing with the current document 215 | fileSystemNode->forEachGenericNode([](Node *n) { 216 | n->setPriority(n->priority() + Node::DefaultProjectFilePriority + 1); 217 | n->setEnabled(false); 218 | }); 219 | root->addNode(std::move(fileSystemNode)); 220 | } 221 | } 222 | 223 | } // CMakeProjectManager::Internal 224 | -------------------------------------------------------------------------------- /projecttreehelper.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include "cmakeprojectnodes.h" 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace CMakeProjectManager::Internal { 13 | 14 | std::unique_ptr createCMakeVFolder(const Utils::FilePath &basePath, 15 | int priority, 16 | const QString &displayName, 17 | bool sourcesOrHeaders); 18 | 19 | void addCMakeVFolder(ProjectExplorer::FolderNode *base, 20 | const Utils::FilePath &basePath, 21 | int priority, 22 | const QString &displayName, 23 | std::vector> &&files, 24 | bool sourcesOrHeaders = false); 25 | 26 | std::vector> &&removeKnownNodes( 27 | const QSet &knownFiles, 28 | std::vector> &&files); 29 | 30 | void addCMakeInputs(ProjectExplorer::FolderNode *root, 31 | const Utils::FilePath &sourceDir, 32 | const Utils::FilePath &buildDir, 33 | std::vector> &&sourceInputs, 34 | std::vector> &&buildInputs, 35 | std::vector> &&rootInputs); 36 | 37 | void addCMakePresets(ProjectExplorer::FolderNode *root, const Utils::FilePath &sourceDir); 38 | 39 | QHash addCMakeLists( 40 | CMakeProjectNode *root, std::vector> &&cmakeLists); 41 | 42 | void createProjectNode(const QHash &cmakeListsNodes, 43 | const Utils::FilePath &dir, 44 | const QString &displayName); 45 | CMakeTargetNode *createTargetNode( 46 | const QHash &cmakeListsNodes, 47 | const Utils::FilePath &dir, 48 | const QString &displayName); 49 | 50 | void addFileSystemNodes(ProjectExplorer::ProjectNode *root, 51 | const std::shared_ptr &folderNode); 52 | 53 | } // CMakeProjectManager::Internal 54 | -------------------------------------------------------------------------------- /simplefileapireader.cpp: -------------------------------------------------------------------------------- 1 | #include "simplefileapireader.h" 2 | 3 | #include "cmakebuildconfiguration.h" 4 | #include "cmakeprojectconstants.h" 5 | #include "cmakeprojectmanager.h" 6 | #include "fileapidataextractor.h" 7 | #include "fileapiparser.h" 8 | #include "projecttreehelper.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | using namespace ProjectExplorer; 28 | using namespace Utils; 29 | 30 | namespace CMakeProjectManager { 31 | namespace Internal { 32 | 33 | Q_DECLARE_LOGGING_CATEGORY(cmakeFileApiMode); 34 | 35 | // -------------------------------------------------------------------- 36 | // SimpleFileApiReader: 37 | // -------------------------------------------------------------------- 38 | 39 | SimpleFileApiReader::SimpleFileApiReader() 40 | : FileApiReader() 41 | { 42 | m_isPlain = true; 43 | } 44 | 45 | std::unique_ptr SimpleFileApiReader::rootProjectNode( 46 | const ProjectExplorer::TreeScanner::Result &allFiles, bool failedToParse) 47 | { 48 | QSet alreadyListed; 49 | 50 | // Cache is needed to reload tree without CMake run 51 | if (m_rootProjectNode) { 52 | m_topLevelNameCache = m_rootProjectNode->displayName(); 53 | m_filesCache.clear(); 54 | 55 | // Files already added: 56 | qCDebug(cmakeFileApiMode) << "SimpleFileApiReader: fill cache:"; 57 | m_rootProjectNode->forEachGenericNode([&alreadyListed,this] (const Node *node) { 58 | alreadyListed.insert(node->filePath()); 59 | auto fn = dynamic_cast(node); 60 | // Cache only files 61 | if (fn) { 62 | m_filesCache.push_back(std::make_tuple(node->filePath(), fn->fileType(), node->isGenerated())); 63 | qCDebug(cmakeFileApiMode) << " cache:" << node->filePath(); 64 | } 65 | }); 66 | } else { 67 | // Restore from cache 68 | m_rootProjectNode = std::make_unique(m_parameters.sourceDirectory); 69 | m_rootProjectNode->setDisplayName(m_topLevelNameCache); 70 | 71 | std::vector> files; 72 | 73 | files.reserve(m_filesCache.count()); 74 | for (auto it = m_filesCache.begin(); it != m_filesCache.end();) { 75 | //qDebug() << "try:" << std::get<0>(*it) << std::get<0>(*it).exists(); 76 | if (!std::get<0>(*it).exists()) { 77 | it = m_filesCache.erase(it); 78 | continue; 79 | } 80 | 81 | alreadyListed.insert(std::get<0>(*it)); 82 | 83 | auto node = std::make_unique(std::get<0>(*it), std::get<1>(*it)); 84 | node->setIsGenerated(std::get<2>(*it)); 85 | files.emplace_back(std::move(node)); 86 | ++it; 87 | } 88 | 89 | m_rootProjectNode->addNestedNodes(std::move(files), m_parameters.sourceDirectory); 90 | } 91 | 92 | QList added = 93 | Utils::filtered(allFiles.allFiles, [&alreadyListed](const FileNode *fn) -> bool { 94 | const int count = alreadyListed.count(); 95 | alreadyListed.insert(fn->filePath()); 96 | return (alreadyListed.count() != count); 97 | }); 98 | 99 | auto addedNodes = Utils::transform(added, [](const FileNode *fn) { 100 | return std::unique_ptr(fn->clone()); 101 | }); 102 | 103 | // TBD: optimize here with allFiles.folderNode and use just an addNode() 104 | m_rootProjectNode->addNestedNodes(std::move(addedNodes), m_parameters.sourceDirectory); 105 | 106 | return std::exchange(m_rootProjectNode, {}); 107 | } 108 | 109 | RawProjectParts SimpleFileApiReader::createRawProjectParts(QString &errorMessage) 110 | { 111 | Q_UNUSED(errorMessage) 112 | 113 | if (!m_projectParts.empty()) 114 | m_projectPartsCache = std::exchange(m_projectParts, {}); 115 | 116 | return m_projectPartsCache; 117 | } 118 | 119 | 120 | } // namespace Internal 121 | } // namespace CMakeProjectManager 122 | -------------------------------------------------------------------------------- /simplefileapireader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "projectexplorer/projectnodes.h" 4 | #include "fileapireader.h" 5 | 6 | #include 7 | 8 | namespace CMakeProjectManager { 9 | namespace Internal { 10 | 11 | class SimpleFileApiReader : public FileApiReader 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | SimpleFileApiReader(); 17 | 18 | ProjectExplorer::RawProjectParts createRawProjectParts(QString &errorMessage) final; 19 | 20 | // TBD: make virtual? 21 | std::unique_ptr rootProjectNode(const ProjectExplorer::TreeScanner::Result &allFiles, bool failedToParse); 22 | 23 | private: 24 | QList> m_filesCache; 25 | QString m_topLevelNameCache; 26 | ProjectExplorer::RawProjectParts m_projectPartsCache; 27 | }; 28 | 29 | } // namespace Internal 30 | } // namespace CMakeProjectManager 31 | -------------------------------------------------------------------------------- /wizard/cmake2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(%{ProjectName}) 2 | cmake_minimum_required(VERSION 3.14) 3 | 4 | # where to look first for cmake modules, before ${CMAKE_ROOT}/modules/ is checked 5 | set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules) 6 | 7 | # C++ standard: 98, 11, 14, 17, 20 8 | # to use per-terget: https://cmake.org/cmake/help/v3.8/prop_tgt/CXX_STANDARD.html 9 | set(CMAKE_CXX_STANDARD 20) 10 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 11 | #set(CMAKE_CXX_EXTENSIONS OFF) # turn on/off GNU or some other extensions 12 | 13 | # C standard: 90, 99, 11 14 | # to use per-terget: https://cmake.org/cmake/help/v3.8/prop_tgt/C_STANDARD.html 15 | set(CMAKE_C_STANDARD 11) 16 | set(CMAKE_C_STANDARD_REQUIRED ON) 17 | #set(CMAKE_C_EXTENSIONS OFF) # turn on/off GNU or some other extensions 18 | 19 | find_package(Threads) 20 | #find_package(PkgConfig) 21 | 22 | # Warnings 23 | set (WARNING_OPTIONS 24 | $<$,$,$>: 25 | -Wall -Wextra> 26 | $<$: 27 | /W4>) 28 | 29 | aux_source_directory(. SRC_LIST) 30 | 31 | add_executable(${PROJECT_NAME} ${SRC_LIST}) 32 | target_link_libraries(${PROJECT_NAME} Threads::Threads) 33 | target_compile_options(${PROJECT_NAME} PRIVATE ${WARNING_OPTIONS}) 34 | -------------------------------------------------------------------------------- /wizard/cmake2/CMakeLists_qt5.txt: -------------------------------------------------------------------------------- 1 | project(%{ProjectName}) 2 | cmake_minimum_required(VERSION 3.14) 3 | 4 | # Qt5 search 5 | #set(QT_ROOT /opt/Qt5.3.2/5.3/gcc_64) 6 | #set(CMAKE_PREFIX_PATH ${QT_ROOT}) 7 | 8 | # Modules 9 | set(QT_COMPONENTS Core Widgets) 10 | 11 | # where to look first for cmake modules, before ${CMAKE_ROOT}/modules/ is checked 12 | set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules) 13 | 14 | # C++ standard: 98, 11, 14, 17, 20 15 | # to use per-terget: https://cmake.org/cmake/help/v3.8/prop_tgt/CXX_STANDARD.html 16 | set(CMAKE_CXX_STANDARD 17) 17 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 18 | #set(CMAKE_CXX_EXTENSIONS OFF) # turn on/off GNU or some other extensions 19 | 20 | # C standard: 90, 99, 11 21 | # to use per-terget: https://cmake.org/cmake/help/v3.8/prop_tgt/C_STANDARD.html 22 | set(CMAKE_C_STANDARD 11) 23 | set(CMAKE_C_STANDARD_REQUIRED ON) 24 | #set(CMAKE_C_EXTENSIONS OFF) # turn on/off GNU or some other extensions 25 | 26 | # Set up Qt stuff: 27 | set(CMAKE_AUTOMOC ON) 28 | set(CMAKE_AUTORCC ON) 29 | set(CMAKE_AUTOUIC ON) 30 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 31 | 32 | # 33 | # Search Packages 34 | # 35 | find_package(Threads) 36 | #find_package(PkgConfig) 37 | 38 | # Qt 39 | find_package(Qt5 40 | COMPONENTS ${QT_COMPONENTS} REQUIRED 41 | ) 42 | 43 | # Add prefix `Qt5::` to the components 44 | set(QT_COMPONENT_TARGETS) 45 | foreach(l ${QT_COMPONENTS}) 46 | list(APPEND QT_COMPONENT_TARGETS Qt5::${l}) 47 | endforeach() 48 | 49 | # Warnings 50 | set (WARNING_OPTIONS 51 | $<$,$,$>: 52 | -Wall -Wextra> 53 | $<$: 54 | /W4>) 55 | 56 | # Sources 57 | aux_source_directory(. SRC_LIST) 58 | 59 | # Target 60 | add_executable(${PROJECT_NAME} ${SRC_LIST}) 61 | target_link_libraries(${PROJECT_NAME} Threads::Threads ${QT_COMPONENT_TARGETS}) 62 | target_compile_options(${PROJECT_NAME} PRIVATE ${WARNING_OPTIONS}) 63 | -------------------------------------------------------------------------------- /wizard/cmake2/cmake/modules/.dummy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/h4tr3d/cmakeprojectmanager2/a1373669b315f1b7206e70969a548993f0bd1ca0/wizard/cmake2/cmake/modules/.dummy -------------------------------------------------------------------------------- /wizard/cmake2/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | printf("Hello World!\\n"); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /wizard/cmake2/main.cpp: -------------------------------------------------------------------------------- 1 | %{Cpp:LicenseTemplate}\ 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | cout << "Hello World!" << endl; 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /wizard/cmake2/wizard.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "kind": "project", 4 | "id": "S.Plain CXX (CMake)", 5 | "category": "I.Projects", 6 | "trDescription": "Creates a plain C/C++ project using CMake (with optional Qt5 support)", 7 | "trDisplayName": "Plain C/C++ Project (CMake Build)", 8 | "trDisplayCategory": "Non-Qt Project", 9 | "icon": "../../global/consoleapplication.png", 10 | "enabled": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager2') >= 0}", 11 | 12 | "options": 13 | [ 14 | { "key": "ProjectFile", "value": "%{CMakeFile}" }, 15 | { "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" }, 16 | { "key": "CFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-csrc')}" }, 17 | { "key": "CppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" }, 18 | { "key": "IsTopLevelProject", "value": "%{JS: !'%{Exists:ProjectExplorer.Profile.Ids}'}" } 19 | ], 20 | 21 | "pages": 22 | [ 23 | { 24 | "trDisplayName": "Project Location", 25 | "trShortTitle": "Location", 26 | "typeId": "Project" 27 | }, 28 | { 29 | "trDisplayName": "Define Project Language", 30 | "trShortTitle": "Project Language", 31 | "typeId": "Fields", 32 | "data": 33 | [ 34 | { 35 | "name": "ProjectLanguage", 36 | "trDisplayName": "Project Language:", 37 | "type": "ComboBox", 38 | "data": 39 | { 40 | "index": 0, 41 | "items": 42 | [ 43 | { 44 | "trKey": "C++", 45 | "value": "cpp" 46 | }, 47 | { 48 | "trKey": "C", 49 | "value": "plainc" 50 | } 51 | ] 52 | } 53 | } 54 | ] 55 | }, 56 | { 57 | "trDisplayName": "CMake Qt Support", 58 | "trShortName": "CMake Qt Support", 59 | "typeId": "Fields", 60 | "data": 61 | [ 62 | { 63 | "name": "QtVersion", 64 | "trDisplayName": "Qt version support:", 65 | "type": "ComboBox", 66 | "data": 67 | { 68 | "index": 0, 69 | "items": 70 | [ 71 | { 72 | "trKey": "None", 73 | "value": "none" 74 | }, 75 | { 76 | "trKey": "Qt 5", 77 | "value": "qt5", 78 | "condition": "%{JS: '%{ProjectLanguage}' === 'cpp'}" 79 | } 80 | ] 81 | } 82 | } 83 | ] 84 | }, 85 | { 86 | "trDisplayName": "Kit Selection", 87 | "trShortTitle": "Kits", 88 | "typeId": "Kits", 89 | "enabled": "%{IsTopLevelProject}", 90 | "data": { "projectFilePath": "%{ProjectFile}" } 91 | }, 92 | { 93 | "trDisplayName": "Project Management", 94 | "trShortTitle": "Summary", 95 | "typeId": "Summary" 96 | } 97 | ], 98 | "generators": 99 | [ 100 | { 101 | "typeId": "File", 102 | "data": 103 | [ 104 | { 105 | "source": "CMakeLists.txt", 106 | "target": "%{CMakeFile}", 107 | "openAsProject": true, 108 | "condition": "%{JS: '%{QtVersion}' === 'none' || '%{ProjectLanguage}' === 'plainc'}" 109 | }, 110 | { 111 | "source": "CMakeLists_qt5.txt", 112 | "target": "%{CMakeFile}", 113 | "openAsProject": true, 114 | "condition": "%{JS: '%{QtVersion}' === 'qt5'}" 115 | }, 116 | { 117 | "source": "main.c", 118 | "target": "%{CFileName}", 119 | "openInEditor": true, 120 | "condition": "%{JS: '%{ProjectLanguage}' === 'plainc'}" 121 | }, 122 | { 123 | "source": "main.cpp", 124 | "target": "%{CppFileName}", 125 | "openInEditor": true, 126 | "condition": "%{JS: '%{ProjectLanguage}' === 'cpp'}" 127 | }, 128 | { 129 | "source": "../git.ignore", 130 | "target": "%{ProjectDirectory}/.gitignore", 131 | "condition": "%{JS: ! %{IsSubproject} && '%{VersionControl}' === 'G.Git'}" 132 | } 133 | ] 134 | } 135 | ] 136 | } 137 | --------------------------------------------------------------------------------