1 /* 2 * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3 3 * http://www.gnu.org/licenses/lgpl-3.0.html 4 */ 5 6 #ifndef COMPILER_H 7 #define COMPILER_H 8 9 #include <vector> 10 #include <map> 11 12 #include <wx/string.h> 13 #include <wx/filename.h> 14 #include <wx/dynarray.h> 15 #include <wx/regex.h> 16 #include "compileoptionsbase.h" 17 #include "compileroptions.h" 18 19 class CompilerCommandGenerator; 20 class cbProject; 21 class ProjectBuildTarget; 22 class ProjectFile; 23 class wxXmlNode; 24 25 /* 26 Macros used in command specs: 27 (keep in sync with `src/plugins/compilergcc/resources/advanced_compiler_options.xrc`) 28 29 Compiler executable: $compiler 30 Resource compiler executable: $rescomp 31 Linker executable: $linker 32 Linker executable for static libs: $lib_linker 33 Compiler flags: $options 34 Resource compiler flags: $res_options 35 Linker flags: $link_options 36 Compiler include paths: $includes 37 Resource include paths: $res_includes 38 Linker include paths: $libdirs 39 Link libraries: $libs 40 Source file (full name): $file 41 Source file dir (no name, no ext.): $file_dir 42 Source file name (no path, no ext.): $file_name 43 Source file extension: $file_ext 44 Object file: $object 45 Dependency result: $dep_object 46 All *linkable* object files: $link_objects 47 All *linkable* flat object files: $link_flat_objects 48 All *linkable* resource object files: $link_resobjects 49 Executable output file (full name): $exe_output 50 Executable dir (no name, no ext): $exe_dir 51 Executable name (no path, no ext): $exe_name 52 Executable extension: $exe_ext 53 Static library output file: $static_output 54 Dynamic library output file: $exe_output 55 Dynamic library DEF output file: $def_output 56 Resources output file: $resource_output 57 Objects output dir: $objects_output_dir 58 59 Usual special chars apply: \t, \n, etc. 60 The command output should be ready for inclusion 61 in a Makefile (properly tab aligned but *no* tabs at the start of the string) 62 The macro substitution happens in compiler's MakefileGenerator. 63 */ 64 65 /// Enum categorizing compiler's output line as warning/error/info/normal 66 enum CompilerLineType 67 { 68 cltNormal = 0, 69 cltWarning, 70 cltError, 71 cltInfo 72 }; 73 74 // regexes array declaration 75 struct RegExStruct 76 { RegExStructRegExStruct77 RegExStruct() 78 : desc(_("Unknown")), lt(cltError), filename(0), line(0), regex(_T("")), regexCompiled(false) 79 { 80 memset(msg, 0, sizeof(msg)); 81 } RegExStructRegExStruct82 RegExStruct(const RegExStruct& rhs) 83 : desc(rhs.desc), lt(rhs.lt), filename(rhs.filename), line(rhs.line), regex(rhs.regex), regexCompiled(false) 84 { 85 memcpy(msg, rhs.msg, sizeof(msg)); 86 } 87 RegExStruct(const wxString& _desc, 88 CompilerLineType _lt, 89 const wxString& _regex, 90 int _msg, 91 int _filename = 0, 92 int _line = 0, 93 int _msg2 = 0, 94 int _msg3 = 0) descRegExStruct95 : desc(_desc), lt(_lt), filename(_filename), line(_line), regex(_regex), regexCompiled(false) 96 { 97 msg[0] = _msg; 98 msg[1] = _msg2; 99 msg[2] = _msg3; 100 } 101 RegExStruct& operator=(const RegExStruct &obj) 102 { 103 desc=obj.desc; 104 lt=obj.lt; 105 regex=obj.regex; 106 regexCompiled=false; 107 filename=obj.filename; 108 line=obj.line; 109 memcpy(msg, obj.msg, sizeof(msg)); 110 111 return *this; 112 } 113 114 bool operator!=(const RegExStruct& other) 115 { 116 return !(*this == other); 117 } 118 bool operator==(const RegExStruct& other) 119 { 120 return ( desc == other.desc 121 && lt == other.lt 122 && regex == other.regex 123 && msg[0] == other.msg[0] 124 && msg[1] == other.msg[1] 125 && msg[2] == other.msg[2] 126 && filename == other.filename 127 && line == other.line ); 128 } 129 GetRegExStringRegExStruct130 wxString GetRegExString() const { return regex; } SetRegExStringRegExStruct131 void SetRegExString(const wxString &str) 132 { 133 if (regex != str) 134 { 135 regex = str; 136 regexCompiled = false; 137 } 138 } HasRegExRegExStruct139 bool HasRegEx() const { return !regex.empty(); } GetRegExRegExStruct140 const wxRegEx& GetRegEx() const { CompileRegEx(); return regexObject; } 141 142 wxString desc; // title of this regex 143 CompilerLineType lt; // classify the line, if regex matches 144 int msg[3]; // up-to 3 sub-expression nr for warning/error message 145 int filename; // sub-expression nr for filename 146 int line; // sub-expression nr for line number 147 // if more than one sub-expressions are entered for msg, 148 // they are appended to each other, with one space in between. 149 // Appending takes place in the same order... 150 private: CompileRegExRegExStruct151 void CompileRegEx() const 152 { 153 if (!regex.empty() && !regexCompiled) 154 { 155 regexObject.Compile(regex); 156 regexCompiled=true; 157 } 158 } 159 wxString regex; // the regex to match 160 mutable wxRegEx regexObject; 161 mutable bool regexCompiled; 162 }; 163 typedef std::vector<RegExStruct> RegExArray; 164 165 /// Helper enum to retrieve compiler commands 166 enum CommandType 167 { 168 ctCompileObjectCmd = 0, ///< Compile object command, e.g. "$compiler $options $includes -c $file -o $object" 169 ctGenDependenciesCmd, ///< Generate dependencies command 170 ctCompileResourceCmd, ///< Compile Win32 resources command, e.g. "$rescomp -i $file -J rc -o $resource_output -O coff $includes" 171 ctLinkExeCmd, ///< Link executable command, e.g. "$linker $libdirs -o $exe_output $link_objects $libs -mwindows" 172 ctLinkConsoleExeCmd, ///< Link console executable command, e.g. "$linker $libdirs -o $exe_output $link_objects $libs" 173 ctLinkDynamicCmd, ///< Link dynamic (dll) lib command, e.g. "$linker -shared -Wl,--output-def=$def_output -Wl,--out-implib=$static_output -Wl,--dll $libdirs $link_objects $libs -o $dynamic_output" 174 ctLinkStaticCmd, ///< Link static lib command, e.g. "ar -r $output $link_objects\n\tranlib $static_output" 175 ctLinkNativeCmd, ///< Link native binary command 176 177 ctCount ///< Do NOT use 178 }; 179 180 181 182 /// Helper enum for type of compiler logging 183 enum CompilerLoggingType 184 { 185 clogFull, 186 clogSimple, 187 clogNone 188 }; 189 190 enum AutoDetectResult 191 { 192 adrDetected, 193 adrGuessed 194 }; 195 196 /// Struct to keep programs 197 struct CompilerPrograms 198 { 199 wxString C; // C compiler 200 wxString CPP; // C++ compiler 201 wxString LD; // dynamic libs linker 202 wxString LIB; // static libs linker 203 wxString WINDRES; // resource compiler 204 wxString MAKE; // make 205 wxString DBGconfig; // debugger config name = "debugger_settings_name:config_name" 206 }; 207 208 /// Struct to keep switches 209 struct DLLIMPORT CompilerSwitches 210 { 211 static const CompilerLoggingType defaultLogging = clogFull; 212 wxString includeDirs; // -I 213 wxString libDirs; // -L 214 wxString linkLibs; // -l 215 wxString defines; // -D 216 wxString genericSwitch; // - 217 wxString objectExtension; // o 218 bool forceFwdSlashes; // force use forward slashes in file/path names (used by CompilerCommandGenerator) 219 bool forceLinkerUseQuotes; // use quotes for filenames in linker command line (needed or not)? 220 bool forceCompilerUseQuotes; // use quotes for filenames in compiler command line (needed or not)? 221 bool needDependencies; // true 222 CompilerLoggingType logging; // clogFull 223 wxString libPrefix; // lib 224 wxString libExtension; // a 225 bool linkerNeedsLibPrefix; // when adding a link library, linker needs prefix? 226 bool linkerNeedsLibExtension; // when adding a link library, linker needs extension? 227 bool linkerNeedsPathResolved; // linker does not support libDirs; C::B must resolve file paths 228 bool supportsPCH; // supports pre-compiled headers? 229 wxString PCHExtension; // pre-compiled headers extension 230 bool UseFlatObjects; // Use Flat object file names (no extra subdirs)? 231 bool UseFullSourcePaths; // This is mainly a workaround for the GDB debugger, apparently I doesn't deal 232 // well with relative paths, therefore for GCC it is better to specify the source 233 // full to the compiler in a full path notation, for all other compilers it is 234 // suggested to keep this switch at false 235 bool Use83Paths; // This is mainly a workaround for the resource compiler under Windows, apparently 236 // it doesn't deal well with spaces in the (include) path even if the path is quoted, 237 // therefore use 8.3 notation without spaces on Windows. 238 // However, this will apply to all include path's as other tools might have the 239 // same issue and it won't hurt to apply it to all include directories, if enabled. 240 wxChar includeDirSeparator; // space 241 wxChar libDirSeparator; // space 242 wxChar objectSeparator; // space 243 int statusSuccess; // 0 - treat exit-codes >= 0 and <= statusSuccess as success (do not set negative!) 244 245 CompilerSwitches(); // constructor initializing the members, specific compilers should overrule if needed 246 }; 247 248 /// Struct for compiler/linker commands 249 struct CompilerTool 250 { 251 // extensions string will be converted to array by GetArrayFromString using DEFAULT_ARRAY_SEP (;) 252 // as separator 253 CompilerTool(const wxString& command_in = wxEmptyString, const wxString& extensions_in = wxEmptyString, const wxString& generatedFiles_in = wxEmptyString) commandCompilerTool254 : command(command_in), extensions(GetArrayFromString(extensions_in)), generatedFiles(GetArrayFromString(generatedFiles_in)) 255 {} CompilerToolCompilerTool256 CompilerTool(const CompilerTool& rhs) 257 : command(rhs.command), extensions(rhs.extensions), generatedFiles(rhs.generatedFiles) 258 {} 259 bool operator==(const CompilerTool& rhs) const { return command == rhs.command && extensions == rhs.extensions && generatedFiles == rhs.generatedFiles; } 260 bool operator!=(const CompilerTool& rhs) const { return !(*this == rhs); } 261 262 wxString command; ///< command to execute 263 wxArrayString extensions; ///< file extensions for which the command will be invoked (no leading dot) 264 wxArrayString generatedFiles; ///< the native language files this command generates that should be further compiled 265 }; 266 267 typedef std::vector<CompilerTool> CompilerToolsVector; 268 269 /** 270 * @brief Abstract base class for compilers. 271 * 272 * Create a derived class and add it in compilerfactory.cpp 273 */ 274 class DLLIMPORT Compiler : public CompileOptionsBase 275 { 276 public: 277 static const wxString FilePathWithSpaces; 278 Compiler(const wxString& name, const wxString& ID, const wxString& parentID = wxEmptyString, int weight = 50); 279 ~Compiler() override; 280 281 /** @brief Check if the compiler is actually valid (installed). */ 282 virtual bool IsValid(); 283 284 /** @brief Check if the supplied string is a compiler warning/error */ 285 virtual CompilerLineType CheckForWarningsAndErrors(const wxString& line); 286 /** @brief Returns warning/error filename. Use it after a call to CheckForWarningsAndErrors() */ GetLastErrorFilename()287 virtual wxString GetLastErrorFilename() { return m_ErrorFilename; } 288 /** @brief Returns warning/error line number (as a string). Use it after a call to CheckForWarningsAndErrors() */ GetLastErrorLine()289 virtual wxString GetLastErrorLine() { return m_ErrorLine; } 290 /** @brief Returns warning/error actual string. Use it after a call to CheckForWarningsAndErrors() */ GetLastError()291 virtual wxString GetLastError() { return m_Error; } 292 /** @brief Get the compiler's name */ GetName()293 virtual const wxString& GetName() const { return m_Name; } 294 /** @brief Get the compiler's master path (must contain "bin", "include" and "lib") */ GetMasterPath()295 virtual const wxString& GetMasterPath() const { return m_MasterPath; } 296 /** @brief Get the compiler's extra paths */ GetExtraPaths()297 virtual const wxArrayString& GetExtraPaths() const { return m_ExtraPaths; } 298 /** @brief Get the compiler's programs */ GetPrograms()299 virtual const CompilerPrograms& GetPrograms() const { return m_Programs; } 300 /** @brief Get the compiler's generic switches */ GetSwitches()301 virtual const CompilerSwitches& GetSwitches() const { return m_Switches; } 302 /** @brief Get the compiler's options */ GetOptions()303 virtual const CompilerOptions& GetOptions() const { return m_Options; } 304 /** @brief Get a command based on CommandType 305 * @param ct The command type to process 306 * @param fileExtension the file's extension (no leading dot) 307 */ 308 virtual const wxString& GetCommand(CommandType ct, const wxString& fileExtension = wxEmptyString) const; 309 /** @brief Get a compiler tool based on CommandType */ 310 virtual const CompilerTool* GetCompilerTool(CommandType ct, const wxString& fileExtension = wxEmptyString) const; 311 /** @brief Get a command tool vector based on CommandType (used by advanced compiler dialog) */ GetCommandToolsVector(CommandType ct)312 virtual CompilerToolsVector& GetCommandToolsVector(CommandType ct) { return m_Commands[ct]; } 313 /** @brief Get the array of regexes used in errors/warnings recognition */ GetRegExArray()314 virtual const RegExArray& GetRegExArray(){ return m_RegExes; } 315 /** @brief Load the default (preset) array of regexes used in errors/warnings recognition */ 316 virtual void LoadDefaultRegExArray(bool globalPrecedence = false); 317 318 /** @brief Set the compiler's name */ SetName(const wxString & name)319 virtual void SetName(const wxString& name){ m_Name = name; } 320 /** @brief Set the compiler's master path (must contain "bin", "include" and "lib") */ SetMasterPath(const wxString & path)321 virtual void SetMasterPath(const wxString& path){ m_MasterPath = path; m_NeedValidityCheck = true; } 322 /** @brief Set the compiler's extra paths */ SetExtraPaths(const wxArrayString & paths)323 virtual void SetExtraPaths(const wxArrayString& paths){ m_ExtraPaths = paths; m_NeedValidityCheck = true; } 324 /** @brief Set the compiler's programs */ SetPrograms(const CompilerPrograms & programs)325 virtual void SetPrograms(const CompilerPrograms& programs){ m_Programs = programs; m_NeedValidityCheck = true; } 326 /** @brief Set the compiler's generic switches */ SetSwitches(const CompilerSwitches & switches)327 virtual void SetSwitches(const CompilerSwitches& switches){ m_Switches = switches; } 328 /** @brief Set the compiler's options */ SetOptions(const CompilerOptions & options)329 virtual void SetOptions(const CompilerOptions& options){ m_Options = options; } 330 /** @brief Set the array of regexes used in errors/warnings recognition */ SetRegExArray(const RegExArray & regexes)331 virtual void SetRegExArray(const RegExArray& regexes) { m_RegExes = regexes; } 332 333 334 /** @brief Save settings */ 335 virtual void SaveSettings(const wxString& baseKey); 336 /** @brief Load settings */ 337 virtual void LoadSettings(const wxString& baseKey); 338 /** @brief Reset settings to defaults. 339 * Put initialization code here or leave blank for standard XML loading. 340 * Call this from the default constructor. 341 */ 342 virtual void Reset(); 343 /** @brief Reload option flags (for copied compilers). 344 * Override if not using standard XML loading. 345 */ 346 virtual void ReloadOptions(); 347 /** @brief Try to auto-detect the compiler's installation directory */ 348 virtual AutoDetectResult AutoDetectInstallationDir() = 0; 349 350 /** @brief Get this compiler's unique ID */ GetID()351 const wxString& GetID() const { return m_ID; } 352 /** @brief Get this compiler's parent's unique ID */ GetParentID()353 const wxString& GetParentID() const { return m_ParentID; } 354 355 /** @brief Get the command type descriptions (used in advanced compiler options) */ 356 static wxString CommandTypeDescriptions[ctCount]; 357 358 /** @brief Set the compiler version string. Please override this virtual function 359 * with your own compiler-version detection code if you want to use this. 360 * 361 * By default this function does nothing. */ SetVersionString()362 virtual void SetVersionString() { return; }; 363 364 /** @brief Get the compiler version string */ GetVersionString()365 const wxString GetVersionString() const { return m_VersionString; }; 366 367 /** This is to be overridden, if compiler needs to alter the default 368 * command line generation. 369 */ 370 virtual CompilerCommandGenerator* GetCommandGenerator(cbProject *project); 371 SetCOnlyFlags(const wxString & flags)372 void SetCOnlyFlags(const wxString& flags) { m_SortOptions[0] = flags; }; SetCPPOnlyFlags(const wxString & flags)373 void SetCPPOnlyFlags(const wxString& flags) { m_SortOptions[1] = flags; }; 374 GetCOnlyFlags()375 const wxString& GetCOnlyFlags() { return m_SortOptions[0]; }; GetCPPOnlyFlags()376 const wxString& GetCPPOnlyFlags() { return m_SortOptions[1]; }; 377 378 /** @brief Do compiler writes multi-line messages? */ WithMultiLineMsg()379 bool WithMultiLineMsg() { return m_MultiLineMessages; }; 380 381 /// @brief Returns messages which might be useful to the use for debugging why the 382 /// compiler is invalid. Call only after IsValid returns false. 383 wxString MakeInvalidCompilerMessages() const; 384 protected: 385 friend class CompilerFactory; 386 Compiler(const Compiler& other); // copy ctor to copy everything but update m_ID 387 388 /** @brief Implement this in new compilers, to return a new copy */ 389 virtual Compiler* CreateCopy() = 0; 390 391 // purposely non-virtual IsUniqueID(const wxString & ID)392 bool IsUniqueID(const wxString& ID){ return m_CompilerIDs.Index(ID) == wxNOT_FOUND; } 393 // converts, if needed, m_ID to something that is valid 394 void MakeValidID(); 395 396 // load options from the corresponding options_<name>.xml 397 void LoadDefaultOptions(const wxString& name, int recursion = 0); 398 // load array of regexes from the corresponding options_<name>.xml 399 void LoadRegExArray(const wxString& name, bool globalPrecedence = false, int recursion = 0); 400 401 bool EvalXMLCondition(const wxXmlNode* node); 402 wxString GetExecName(const wxString& name); 403 404 // keeps a copy of current settings (works only the first time it's called) 405 void MirrorCurrentSettings(); 406 407 // set the following members in your class 408 wxString m_Name; 409 wxString m_MasterPath; 410 wxArrayString m_ExtraPaths; 411 CompilerToolsVector m_Commands[ctCount]; 412 CompilerPrograms m_Programs; 413 CompilerSwitches m_Switches; 414 CompilerOptions m_Options; 415 RegExArray m_RegExes; 416 wxString m_ErrorFilename; 417 wxString m_ErrorLine; 418 wxString m_Error; 419 wxString m_VersionString; 420 wxString m_SortOptions[2]; // m_SortOptions[0] == C-only flags; m_SortOptions[1] == C++-only flags 421 422 int m_Weight; // lower means listed sooner (try to keep between 0 and 100) 423 bool m_MultiLineMessages; // true if the compiler writes multi-line error/warning messages 424 private: 425 wxString m_ID; 426 wxString m_ParentID; // -1 for builtin compilers, the builtin compiler's ID to derive from for user compilers... 427 static wxArrayString m_CompilerIDs; // map to guarantee unique IDs 428 bool m_Valid; // 'valid' flag 429 bool m_NeedValidityCheck; // flag to re-check validity (raised when changing compiler paths) 430 431 // "mirror" default settings for comparing when saving (to save only those that differ from defaults) 432 struct MirrorSettings 433 { 434 wxString Name; 435 wxString MasterPath; 436 wxArrayString ExtraPaths; 437 CompilerPrograms Programs; 438 439 // these are the CompileOptionsBase settings that each compiler keeps on a global level 440 wxArrayString CompilerOptions_; 441 wxArrayString ResourceCompilerOptions; 442 wxArrayString LinkerOptions; 443 wxArrayString IncludeDirs; 444 wxArrayString ResIncludeDirs; 445 wxArrayString LibDirs; 446 wxArrayString LinkLibs; 447 wxArrayString CmdsBefore; 448 wxArrayString CmdsAfter; 449 450 // below are the settings that the user is asked to revert to defaults (if defaults have changed) 451 CompilerToolsVector Commands[ctCount]; 452 CompilerSwitches Switches; 453 CompilerOptions Options; 454 RegExArray RegExes; 455 456 wxString SortOptions[2]; 457 }; 458 MirrorSettings m_Mirror; 459 bool m_Mirrored; // flag to only mirror the settings once 460 }; 461 462 #endif // COMPILER_H 463