1{*************************************************************************** 2 * * 3 * This source is free software; you can redistribute it and/or modify * 4 * it under the terms of the GNU General Public License as published by * 5 * the Free Software Foundation; either version 2 of the License, or * 6 * (at your option) any later version. * 7 * * 8 * This code is distributed in the hope that it will be useful, but * 9 * WITHOUT ANY WARRANTY; without even the implied warranty of * 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 11 * General Public License for more details. * 12 * * 13 * A copy of the GNU General Public License is available on the World * 14 * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also * 15 * obtain it by writing to the Free Software Foundation, * 16 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 17 * * 18 *************************************************************************** 19 20 Command line utility to compile lazarus projects and packages. 21} 22program lazbuild; 23 24 25{$mode objfpc}{$H+} 26 27uses 28 {$IFDEF unix} 29 cthreads, 30 {$ENDIF} 31 Classes, SysUtils, math, CustApp, 32 Interfaces, // this includes the NoGUI widgetset 33 // LazUtils 34 Masks, LConvEncoding, FileUtil, LazFileUtils, LazLoggerBase, LazUtilities, 35 LazUTF8, Laz2_XMLCfg, UITypes, LazStringUtils, 36 // LCL 37 LCLPlatformDef, Forms, 38 // Codetools 39 CodeCache, CodeToolManager, DefineTemplates, FileProcs, 40 // BuildIntf 41 BaseIDEIntf, MacroIntf, PackageIntf, LazMsgWorker, ProjectIntf, IDEExternToolIntf, 42 CompOptsIntf, IDEOptionsIntf, PackageDependencyIntf, 43 // IDE 44 InitialSetupProc, ExtToolsConsole, CompilerOptions, 45 ApplicationBundle, TransferMacros, EnvironmentOpts, IDETranslations, 46 LazarusIDEStrConsts, IDECmdLine, MiscOptions, Project, LazConf, PackageDefs, 47 PackageLinks, PackageSystem, InterPkgConflictFiles, BuildLazDialog, 48 BuildProfileManager, BuildManager, BaseBuildManager, ModeMatrixOpts; 49 50type 51 TPkgAction = ( 52 lpaBuild, // build package, default 53 lpaInstall, // install package 54 lpaAddPkgLinks // register, no build 55 ); 56 57 { TLazBuildApplication } 58 59 TLazBuildApplication = class(TCustomApplication) 60 private 61 FBuildAll: boolean; 62 FBuildIDE: boolean; 63 FBuildIDEOptions: string; 64 FBuildModeOverride: String; 65 FBuildRecursive: boolean; 66 fCompilerInCfg: string; 67 fCompilerOverride: String; 68 fCPUOverride: String; 69 FCreateMakefile: boolean; 70 fInitialized: boolean; 71 fInitResult: boolean; 72 fLazarusDirInCfg: string; 73 fLazarusDirOverride : String; 74 FMaxProcessCount: integer; 75 FNoWriteProject: Boolean; 76 fOSOverride: String; 77 FPackageAction: TPkgAction; 78 FPkgGraphVerbosity: TPkgVerbosityFlags; 79 FSkipDependencies: boolean; 80 fWidgetsetOverride: String; 81 82 // codetools 83 procedure OnCodeBufferDecodeLoaded({%H-}Code: TCodeBuffer; 84 const {%H-}Filename: string; var Source, DiskEncoding, MemEncoding: string); 85 procedure OnCodeBufferEncodeSaving(Code: TCodeBuffer; 86 const {%H-}Filename: string; var Source: string); 87 88 // global package functions 89 procedure GetDependencyOwnerDescription(Dependency: TPkgDependency; 90 out Description: string); 91 procedure GetDependencyOwnerDirectory(Dependency: TPkgDependency; 92 out Directory: string); 93 // Event procedure that adds every package added to the package graph to the (user) package links 94 procedure PackageGraphAddPackage(Pkg: TLazPackage); 95 function PackageGraphCheckInterPkgFiles(IDEObject: TObject; 96 PkgList: TFPList; out FilesChanged: boolean): boolean; 97 98 // project 99 procedure OnProjectChangeInfoFile(TheProject: TProject); 100 101 // dialogs 102 function OnIDEMessageDialog(const aCaption, aMsg: string; 103 {%H-}DlgType: TMsgDlgType; {%H-}Buttons: TMsgDlgButtons; 104 const {%H-}HelpKeyword: string): Integer; 105 function OnIDEQuestionDialog(const aCaption, aMsg: string; 106 {%H-}DlgType: TMsgDlgType; {%H-}Buttons: array of const; 107 const {%H-}HelpKeyword: string): Integer; 108 protected 109 function GetParams(Index: Integer): String; override; 110 function GetParamCount: Integer; override; 111 112 // Builds project or package, depending on extension. 113 // Packages can also be specified by package name if they are known to the IDE. 114 function BuildFile(Filename: string): boolean; 115 116 // packages 117 // Build a package identified by filename and return build result 118 function BuildPackage(const AFilename: string): boolean; 119 // Load package file into loaded packages (package graph), overwriting any package with the same name 120 function LoadPackage(const AFilename: string): TLazPackage; 121 procedure CompilePackage(APackage: TLazPackage; Flags: TPkgCompileFlags); 122 procedure DoCreateMakefile(APackage: TLazPackage); 123 procedure CheckPackageGraphForCompilation(APackage: TLazPackage; 124 FirstDependency: TPkgDependency); 125 126 // projects 127 function BuildProject(const AFilename: string): boolean; 128 function LoadProject(const AFilename: string): TProject; 129 procedure CloseProject(var AProject: TProject); 130 131 // Adding packages to list of to-be-installed packages in the IDE. 132 // The packages can then be installed by recompiling the IDE (because we're using static packages) 133 function AddPackagesToInstallList(const PackageNamesOrFiles: TStringList): boolean; 134 function AddCmdLinePackageLinks(const PackageNamesOrFiles: TStringList): boolean; 135 136 // IDE 137 function BuildLazarusIDE: boolean; 138 function CompileAutoInstallPackages(Clean: boolean): boolean; 139 140 function Init: boolean; 141 procedure LoadEnvironmentOptions; 142 procedure LoadMiscellaneousOptions; 143 procedure SetupMacros; 144 procedure SetupCodetools; 145 procedure SetupPackageSystem; 146 procedure SetupDialogs; 147 procedure StoreBaseSettings; 148 function RepairedCheckOptions(Const ShortOptions : String; 149 Const Longopts : TStrings; Opts,NonOpts : TStrings) : String; 150 public 151 // Files (or package names) passed by the user to Lazbuild: 152 Files: TStringList; 153 constructor Create(TheOwner: TComponent); override; 154 destructor Destroy; override; 155 156 procedure Run; 157 function ParseParameters: boolean; 158 procedure WriteUsage; 159 procedure Error(ErrorCode: Byte; const ErrorMsg: string); 160 161 property PackageAction: TPkgAction read FPackageAction write FPackageAction; 162 property BuildAll: boolean read FBuildAll write FBuildAll;// build all files of project/package 163 property BuildRecursive: boolean read FBuildRecursive // apply BuildAll flag to dependencies 164 write FBuildRecursive; 165 property SkipDependencies: boolean read FSkipDependencies 166 write FSkipDependencies; 167 property BuildIDE: boolean read FBuildIDE write FBuildIDE; // build IDE (as opposed to a project/package etc) 168 property BuildIDEOptions: string read FBuildIDEOptions write FBuildIDEOptions; 169 property CreateMakefile: boolean read FCreateMakefile write FCreateMakefile; 170 property WidgetSetOverride: String read fWidgetsetOverride 171 write fWidgetsetOverride; 172 property OSOverride: String read fOSOverride write fOSOverride; 173 property CPUOverride: String read fCPUOverride write fCPUOverride; 174 property CompilerOverride: String read fCompilerOverride write fCompilerOverride; 175 property LazarusDirOverride: String read fLazarusDirOverride write fLazarusDirOverride; 176 property BuildModeOverride: String read FBuildModeOverride write FBuildModeOverride; 177 property MaxProcessCount: integer read FMaxProcessCount write FMaxProcessCount; 178 property NoWriteProject: boolean read FNoWriteProject write FNoWriteProject; 179 property PkgGraphVerbosity: TPkgVerbosityFlags read FPkgGraphVerbosity write FPkgGraphVerbosity; 180 end; 181 182var 183 LazBuildApp: TLazBuildApplication = nil; 184 185const 186 ErrorFileNotFound = 1; 187 ErrorBuildFailed = 2; 188 ErrorLoadPackageFailed = 3; 189 ErrorPackageNameInvalid = 4; 190 ErrorLoadProjectFailed = 5; 191 VersionStr = {$I version.inc}; 192 193procedure FilterConfigFileContent; 194var 195 l: TStrings; 196 i: Integer; 197begin 198 ResetParamsAndCfg; 199 l := GetCfgFileContent; 200 if l = nil then exit; 201 i := l.Count - 1; 202 while i >= 0 do begin 203 if not( 204 (copy(l[i], 1, 22) = '--primary-config-path=') or 205 (copy(l[i], 1, 24) = '--secondary-config-path=') or 206 (copy(l[i], 1, 6) = '--pcp=') or 207 (copy(l[i], 1, 6) = '--scp=') 208 ) 209 then 210 l.Delete(i); 211 dec(i); 212 end; 213end; 214 215Function ToolParamCount: Integer; 216begin 217 Result := GetParamsAndCfgFile.Count - 1; 218end; 219 220Function ToolParamStr(Param : Integer) : Ansistring; 221begin 222 if Param >= GetParamsAndCfgFile.Count then 223 Result := '' 224 else 225 Result := GetParamsAndCfgFile[Param]; 226end; 227 228procedure GetDescriptionOfDependencyOwner(Dependency: TPkgDependency; 229 out Description: string); 230var 231 DepOwner: TObject; 232begin 233 DepOwner:=Dependency.Owner; 234 if (DepOwner<>nil) then begin 235 if DepOwner is TLazPackage then begin 236 Description:=Format(lisPkgMangPackage, [TLazPackage(DepOwner).IDAsString]); 237 end else if DepOwner is TProject then begin 238 Description:=Format(lisPkgMangProject, 239 [ExtractFileNameOnly(TProject(DepOwner).ProjectInfoFile)]); 240 end else begin 241 Description:=dbgsName(DepOwner) 242 end; 243 end else begin 244 Description:=Format(lisPkgMangDependencyWithoutOwner, [Dependency.AsString]); 245 end; 246end; 247 248procedure GetDirectoryOfDependencyOwner(Dependency: TPkgDependency; 249 out Directory: string); 250var 251 DepOwner: TObject; 252begin 253 DepOwner:=Dependency.Owner; 254 if (DepOwner<>nil) then begin 255 if DepOwner is TLazPackage then begin 256 Directory:=TLazPackage(DepOwner).Directory; 257 end else if DepOwner is TProject then begin 258 Directory:=TProject(DepOwner).Directory; 259 end else begin 260 Directory:='' 261 end; 262 end else begin 263 Directory:='' 264 end; 265end; 266 267{ TLazBuildApplication } 268 269procedure TLazBuildApplication.OnCodeBufferEncodeSaving(Code: TCodeBuffer; 270 const Filename: string; var Source: string); 271begin 272 if (Code.DiskEncoding<>'') and (Code.MemEncoding<>'') 273 and (Code.DiskEncoding<>Code.MemEncoding) then begin 274 {$IFDEF VerboseIDEEncoding} 275 DebugLn(['TLazBuildApplication.OnCodeBufferEncodeSaving Filename=',Code.Filename,' Mem=',Code.MemEncoding,' to Disk=',Code.DiskEncoding]); 276 {$ENDIF} 277 Source:=ConvertEncoding(Source,Code.MemEncoding,Code.DiskEncoding); 278 {$IF FPC_FULLVERSION >= 20701} 279 //SetCodePage(Source,CP_ACP); 280 {$ENDIF} 281 end; 282end; 283 284procedure TLazBuildApplication.OnCodeBufferDecodeLoaded(Code: TCodeBuffer; 285 const Filename: string; var Source, DiskEncoding, MemEncoding: string); 286begin 287 //DebugLn(['TLazBuildApplication.OnCodeBufferDecodeLoaded Filename=',Filename,' Encoding=',GuessEncoding(Source)]); 288 DiskEncoding:=''; 289 if DiskEncoding='' then 290 DiskEncoding:=GuessEncoding(Source); 291 MemEncoding:=EncodingUTF8; 292 if (DiskEncoding<>MemEncoding) then begin 293 {$IFDEF VerboseIDEEncoding} 294 DebugLn(['TLazBuildApplication.OnCodeBufferDecodeLoaded Filename=',Filename,' Disk=',DiskEncoding,' to Mem=',MemEncoding]); 295 {$ENDIF} 296 Source:=ConvertEncoding(Source,DiskEncoding,MemEncoding); 297 //DebugLn(['TLazBuildApplication.OnCodeBufferDecodeLoaded ',Source]); 298 end; 299end; 300 301procedure TLazBuildApplication.GetDependencyOwnerDescription( 302 Dependency: TPkgDependency; out Description: string); 303begin 304 GetDescriptionOfDependencyOwner(Dependency,Description); 305end; 306 307procedure TLazBuildApplication.GetDependencyOwnerDirectory( 308 Dependency: TPkgDependency; out Directory: string); 309begin 310 GetDirectoryOfDependencyOwner(Dependency,Directory); 311end; 312 313procedure TLazBuildApplication.PackageGraphAddPackage(Pkg: TLazPackage); 314begin 315 if FileExistsUTF8(Pkg.FileName) then LazPackageLinks.AddUserLink(Pkg); 316end; 317 318function TLazBuildApplication.PackageGraphCheckInterPkgFiles( 319 IDEObject: TObject; PkgList: TFPList; out FilesChanged: boolean): boolean; 320begin 321 Result:=CheckInterPkgFiles(IDEObject,PkgList,FilesChanged); 322end; 323 324procedure TLazBuildApplication.OnProjectChangeInfoFile(TheProject: TProject); 325begin 326 if TheProject<>Project1 then exit; 327 if TheProject.IsVirtual then 328 CodeToolBoss.SetGlobalValue(ExternalMacroStart+'ProjPath',VirtualDirectory) 329 else 330 CodeToolBoss.SetGlobalValue(ExternalMacroStart+'ProjPath',Project1.Directory) 331end; 332 333function TLazBuildApplication.OnIDEMessageDialog(const aCaption, aMsg: string; 334 DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; const HelpKeyword: string 335 ): Integer; 336begin 337 DumpStack; 338 Error(ErrorBuildFailed, Format(lisLazbuildIsNonInteractiveAbortingNow, [ 339 aCaption, LineEnding, aMsg, LineEnding])); 340 Result:=mrCancel; 341end; 342 343function TLazBuildApplication.OnIDEQuestionDialog(const aCaption, aMsg: string; 344 DlgType: TMsgDlgType; Buttons: array of const; const HelpKeyword: string 345 ): Integer; 346begin 347 DumpStack; 348 Error(ErrorBuildFailed, Format(lisLazbuildIsNonInteractiveAbortingNow, [ 349 aCaption, LineEnding, aMsg, LineEnding])); 350 Result:=mrCancel; 351end; 352 353function TLazBuildApplication.GetParams(Index: Integer): String; 354begin 355 Result := ToolParamStr(Index); 356end; 357 358function TLazBuildApplication.GetParamCount: Integer; 359begin 360 Result := ToolParamCount; 361end; 362 363function TLazBuildApplication.BuildFile(Filename: string): boolean; 364var 365 OriginalFilename: string; 366 Package: TLazPackageLink; 367begin 368 Result:=false; 369 OriginalFilename:=FileName; 370 371 Filename:=CleanAndExpandFilename(Filename); 372 if not FileExistsUTF8(Filename) then 373 begin 374 // File doesn't exist. 375 376 // Check for packages if the specified name is a valid identifier 377 //debugln(['TLazBuildApplication.BuildFile ',OriginalFilename]); 378 if IsValidPkgName(OriginalFileName) then begin 379 if PackageAction=lpaAddPkgLinks then begin 380 Error(ErrorFileNotFound,'lpk file expected, but '+OriginalFilename+' found'); 381 Exit; 382 end; 383 // Initialize package graph with base packages etc: 384 if not Init then exit; 385 // Could be a known but not installed package 386 // so try and get package filename from all other known packages 387 Package:=TLazPackageLink(LazPackageLinks.FindLinkWithPkgName(OriginalFileName)); 388 if Package=nil then begin 389 // Not found after everything we tried 390 if FilenameExtIs(Filename,'lpi', true) then 391 Error(ErrorFileNotFound,'file not found: '+OriginalFilename) 392 else 393 Error(ErrorFileNotFound,'package not found: '+OriginalFilename); 394 end 395 else begin 396 // We found a package link 397 case PackageAction of 398 lpaBuild: 399 begin 400 Result:=BuildPackage(Package.LPKFilename); 401 exit; 402 end; 403 lpaInstall: 404 exit(true); // this is handled in AddPackagesToInstallList 405 end; 406 end; 407 end; 408 409 Error(ErrorFileNotFound, 'file not found: '+OriginalFilename); 410 Exit; 411 end 412 else if DirPathExists(Filename) then 413 begin 414 Error(ErrorFileNotFound,'file "'+Filename+'" is a directory'); 415 Exit; 416 end 417 else begin 418 // File exists: 419 if FilenameExtIs(Filename,'lpk',true) then begin 420 case PackageAction of 421 lpaBuild: Result:=BuildPackage(Filename); 422 lpaInstall: Result:=true; // this is handled in AddPackagesToInstallList 423 lpaAddPkgLinks: Result:=true; 424 end; 425 end else if FilenameExtIs(Filename,'lpi',true) then 426 Result:=BuildProject(Filename) 427 else if FilenameExtIs(Filename,'lpr',true) then begin 428 Filename:=ChangeFileExt(Filename,'.lpi'); 429 if FileExists(Filename) then 430 Result:=BuildProject(Filename) 431 else 432 Error(ErrorFileNotFound,'file not found: '+Filename); 433 end else 434 Error(ErrorBuildFailed,'don''t know how to build: '+Filename); 435 end; 436end; 437 438function TLazBuildApplication.BuildPackage(const AFilename: string): boolean; 439var 440 APackage: TLazPackage; 441 Flags: TPkgCompileFlags; 442begin 443 Result:=false; 444 445 if not Init then exit; 446 447 if ConsoleVerbosity>=0 then 448 debugln(['Hint: (lazarus) compile package "',AFilename,'"']); 449 450 APackage:=LoadPackage(AFilename); 451 if APackage=nil then 452 Error(ErrorLoadPackageFailed, 'unable to load package "'+AFilename+'"'); 453 454 Flags:=[]; 455 if BuildAll then 456 Include(Flags,pcfCleanCompile) 457 else 458 Include(Flags,pcfOnlyIfNeeded); 459 if BuildRecursive and BuildAll then 460 Include(Flags,pcfCompileDependenciesClean); 461 if SkipDependencies then 462 Include(Flags,pcfDoNotCompileDependencies); 463 464 if (Length(OSOverride) <> 0) then 465 APackage.CompilerOptions.TargetOS:=OSOverride; 466 if (Length(CPUOverride) <> 0) then 467 APackage.CompilerOptions.TargetCPU:=CPUOverride; 468 469 if CreateMakefile then 470 DoCreateMakefile(APackage) 471 else 472 CompilePackage(APackage,Flags); 473 474 LazPackageLinks.SaveUserLinks(true); 475 476 Result:=true; 477end; 478 479function TLazBuildApplication.LoadPackage(const AFilename: string): TLazPackage; 480var 481 XMLConfig: TXMLConfig; 482 ConflictPkg: TLazPackage; 483begin 484 // check if package is already loaded 485 Result:=PackageGraph.FindPackageWithFilename(AFilename); 486 if (Result<>nil) then exit; 487 if not FileExistsUTF8(AFilename) then 488 Error(ErrorLoadPackageFailed,'Package file not found "'+AFilename+'"'); 489 490 Result:=TLazPackage.Create; 491 // load the package file 492 XMLConfig:=TXMLConfig.Create(AFilename); 493 try 494 Result.Filename:=AFilename; 495 Result.LoadFromXMLConfig(XMLConfig,'Package/'); 496 finally 497 XMLConfig.Free; 498 end; 499 // check Package Name 500 if not IsValidPkgName(Result.Name) then 501 Error(ErrorPackageNameInvalid, 502 Format(lisPkgMangThePackageNameOfTheFileIsInvalid, 503 [Result.Name, LineEnding, Result.Filename])); 504 // check if Package with same name is already loaded 505 ConflictPkg:=PackageGraph.FindPackageWithName(Result.Name,nil); 506 if ConflictPkg<>nil then begin 507 // replace package 508 PackageGraph.ReplacePackage(ConflictPkg,Result); 509 end else begin 510 // add to graph 511 PackageGraph.AddPackage(Result); 512 end; 513 // save package file links 514 LazPackageLinks.SaveUserLinks; 515end; 516 517function TLazBuildApplication.BuildLazarusIDE: boolean; 518var 519 Flags: TBuildLazarusFlags; 520 CurResult: TModalResult; 521 BuildLazProfiles: TBuildLazarusProfiles; 522 CurProf: TBuildLazarusProfile; 523 InheritedOptionStrings: TInheritedCompOptsStrings; 524 TargetDir: String; 525 i: Integer; 526 s: String; 527 Builder: TLazarusBuilder; 528begin 529 Result:=false; 530 if not Init then exit; 531 532 LoadMiscellaneousOptions; 533 BuildLazProfiles:=MiscellaneousOptions.BuildLazProfiles; 534 CurProf:=BuildLazProfiles.Current; 535 if BuildModeOverride<>'' then 536 begin 537 i:=BuildLazProfiles.IndexByName(BuildModeOverride); 538 if i<0 then 539 begin 540 debugln(['Error: (lazarus) IDE build mode "'+BuildModeOverride+'" not found']); 541 if ConsoleVerbosity>=-2 then begin 542 debugln; 543 debugln('Available IDE build modes:'); 544 for i:=0 to BuildLazProfiles.Count-1 do 545 begin 546 if BuildLazProfiles[i]=CurProf then 547 dbgout('* ') 548 else 549 dbgout(' '); 550 debugln(BuildLazProfiles[i].Name); 551 end; 552 debugln; 553 end; 554 Halt(ErrorBuildFailed); 555 end; 556 CurProf:=BuildLazProfiles[i]; 557 BuildLazProfiles.CurrentIndex:=i; 558 end; 559 if ConsoleVerbosity>=0 then 560 debugln(['Hint: (lazarus) Building Lazarus IDE with profile "',CurProf.Name,'"']); 561 562 if (Length(OSOverride) <> 0) then 563 CurProf.TargetOS:=OSOverride; 564 if (Length(CPUOverride) <> 0) then 565 CurProf.TargetCPU:=CPUOverride; 566 567 if WidgetSetOverride<>'' then 568 CurProf.TargetPlatform:=DirNameToLCLPlatform(WidgetSetOverride) 569 else 570 CurProf.TargetPlatform:=GetBuildLCLWidgetType; 571 if BuildIDEOptions<>'' then 572 begin 573 s:=CurProf.ExtraOptions; 574 if s<>'' then 575 s+=' '; 576 s+=BuildIDEOptions; 577 CurProf.ExtraOptions:=s; 578 end; 579 if BuildAll then 580 CurProf.IdeBuildMode:=bmCleanAllBuild; 581 MainBuildBoss.SetBuildTargetIDE; 582 Flags:=[]; 583 584 // try loading install packages 585 PackageGraph.LoadAutoInstallPackages(BuildLazProfiles.StaticAutoInstallPackages); 586 587 // create target directory 588 TargetDir:=CurProf.TargetDirectory; 589 IDEMacros.SubstituteMacros(TargetDir); 590 if not ForceDirectory(TargetDir) then begin 591 if ConsoleVerbosity>=-1 then 592 DebugLn('Warning: (lazarus) failed creating IDE target directory "',TargetDir,'" (TLazBuildApplication.BuildLazarusIDE)'); 593 exit; 594 end; 595 596 // clean 597 Builder:=TLazarusBuilder.Create; 598 try 599 Builder.ProfileChanged:=false; 600 601 if BuildLazProfiles.Current.IdeBuildMode=bmCleanAllBuild then begin 602 Builder.PackageOptions:=''; 603 CurResult:=Builder.MakeLazarus(BuildLazProfiles.Current, 604 Flags+[blfDontBuild]); 605 if CurResult<>mrOk then begin 606 if ConsoleVerbosity>=-1 then 607 DebugLn('Error: (lazarus) Building IDE: Clean all failed.'); 608 exit; 609 end; 610 end; 611 612 // save list of install packages 613 CurResult:=PackageGraph.SaveAutoInstallConfig; 614 if CurResult<>mrOk then begin 615 if ConsoleVerbosity>=-1 then 616 DebugLn('Error: (lazarus) Building IDE: failed saving IDE make config files.'); 617 exit; 618 end; 619 620 // compile auto install static packages 621 if not CompileAutoInstallPackages(BuildLazProfiles.Current.IdeBuildMode<>bmBuild) 622 then begin 623 if ConsoleVerbosity>=-1 then 624 DebugLn('Error: (lazarus) Building IDE: Compile AutoInstall Packages failed.'); 625 exit; 626 end; 627 628 // create inherited compiler options 629 Builder.PackageOptions:=PackageGraph.GetIDEInstallPackageOptions(InheritedOptionStrings{%H-}); 630 631 // save idemake.cfg 632 CurResult:=Builder.SaveIDEMakeOptions(BuildLazProfiles.Current,Flags+[blfBackupOldExe]); 633 if CurResult<>mrOk then begin 634 if ConsoleVerbosity>=-1 then 635 DebugLn('Error: (lazarus) Building IDE: failed saving idemake.cfg'); 636 exit; 637 end; 638 639 // compile IDE 640 CurResult:=Builder.MakeLazarus(BuildLazProfiles.Current, 641 Flags+[blfUseMakeIDECfg,blfOnlyIDE]); 642 if CurResult<>mrOk then begin 643 if ConsoleVerbosity>=-1 then 644 DebugLn('Error: (lazarus) Building IDE: Building IDE failed.'); 645 exit; 646 end; 647 648 Result:=true; 649 finally 650 Builder.Free; 651 end; 652end; 653 654function TLazBuildApplication.CompileAutoInstallPackages(Clean: boolean): boolean; 655var 656 Dependency: TPkgDependency; 657 OldDependency: TPkgDependency; 658 CurResult: TModalResult; 659 CompilePolicy: TPackageUpdatePolicy; 660begin 661 Result:=false; 662 PackageGraph.BeginUpdate(false); 663 try 664 Dependency:=PackageGraph.FirstAutoInstallDependency; 665 while Dependency<>nil do begin 666 OldDependency:=Dependency; 667 Dependency:=Dependency.NextRequiresDependency; 668 if OldDependency.LoadPackageResult<>lprSuccess then begin 669 raise Exception.Create(Format( 670 lisPkgMangThePackageIsMarkedForInstallationButCanNotBeFound, [ 671 OldDependency.AsString, LineEnding])); 672 end; 673 end; 674 675 // check consistency 676 CheckPackageGraphForCompilation(nil, 677 PackageGraph.FirstAutoInstallDependency); 678 679 // compile all auto install dependencies 680 CompilePolicy:=pupAsNeeded; 681 if (BuildRecursive and BuildAll) or Clean then 682 CompilePolicy:=pupOnRebuildingAll; 683 CurResult:=PackageGraph.CompileRequiredPackages(nil, 684 PackageGraph.FirstAutoInstallDependency,false,CompilePolicy); 685 if CurResult<>mrOk then exit; 686 687 finally 688 PackageGraph.EndUpdate; 689 end; 690 Result:=true; 691end; 692 693procedure TLazBuildApplication.CompilePackage(APackage: TLazPackage; 694 Flags: TPkgCompileFlags); 695begin 696 if APackage.Missing then 697 Error(ErrorBuildFailed,APackage.IDAsString+' lpk file missing'); 698 699 // check graph for circles and broken dependencies 700 if not (pcfDoNotCompileDependencies in Flags) then begin 701 CheckPackageGraphForCompilation(APackage,nil); 702 end; 703 704 if PackageGraph.CompilePackage(APackage,Flags,false)<>mrOk then 705 Error(ErrorBuildFailed,APackage.IDAsString+' compilation failed'); 706end; 707 708procedure TLazBuildApplication.DoCreateMakefile(APackage: TLazPackage); 709begin 710 if ConsoleVerbosity>0 then 711 debugln(['Hint: (lazarus) [TLazBuildApplication.DoCreateMakefile] ',APackage.Filename]); 712 PackageGraph.WriteMakeFile(APackage); 713end; 714 715procedure TLazBuildApplication.CheckPackageGraphForCompilation( 716 APackage: TLazPackage; FirstDependency: TPkgDependency); 717 718 function PathListToString(PathList: TFPList): string; 719 var 720 i: Integer; 721 Item: TObject; 722 begin 723 Result:=''; 724 for i:=0 to PathList.Count-1 do begin 725 Item:=TObject(PathList[i]); 726 if Result<>'' then 727 Result:=Result+'->'; 728 if Item is TPkgDependency then begin 729 Result:=Result+TPkgDependency(Item).AsString; 730 end else if Item is TProject then begin 731 Result:=Result 732 +'Project:'+ExtractFileNameOnly(TProject(Item).ProjectInfoFile); 733 end else if Item is TLazPackage then begin 734 Result:=Result+TLazPackage(Item).IDAsString; 735 end else begin 736 Result:=Result+'Unknown:'+dbgsName(Item); 737 end; 738 end; 739 end; 740 741var 742 PathList: TFPList; 743begin 744 PathList:=nil; 745 try 746 // check for broken dependencies 747 PathList:=PackageGraph.FindBrokenDependencyPath(APackage,FirstDependency); 748 if PathList<>nil then 749 Error(ErrorLoadPackageFailed,'Broken dependency: '+PathListToString(PathList)); 750 751 // check for circle dependencies 752 PathList:=PackageGraph.FindCycleDependencyPath(APackage,FirstDependency); 753 if PathList<>nil then 754 Error(ErrorLoadPackageFailed,'Circle dependency: '+PathListToString(PathList)); 755 finally 756 PathList.Free; 757 end; 758end; 759 760function TLazBuildApplication.BuildProject(const AFilename: string): boolean; 761var 762 CompilerFilename: String; 763 WorkingDir: String; 764 SrcFilename: String; 765 CompilerParams: String; 766 ToolBefore: TProjectCompilationToolOptions; 767 ToolAfter: TProjectCompilationToolOptions; 768 UnitOutputDirectory: String; 769 TargetExeName: String; 770 TargetExeDir: String; 771 CompilePolicy: TPackageUpdatePolicy; 772 i,MatchCount: Integer; 773 CompileHint: String; 774 CompReason: TCompileReason; 775 NeedBuildAllFlag: Boolean; 776 MatrixOption: TBuildMatrixOption; 777 ModeMask: TMask; 778 CurResult: Boolean; 779 780 function StartBuilding : boolean; 781 begin 782 Result := false; 783 784 // then override specific options 785 if (OSOverride<>'') then 786 Project1.CompilerOptions.TargetOS:=OSOverride; 787 if (CPUOverride<>'') then 788 Project1.CompilerOptions.TargetCPU:=CPUOverride; 789 if (WidgetSetOverride<>'') then begin 790 MatrixOption:=Project1.BuildModes.SessionMatrixOptions.Add(bmotIDEMacro); 791 MatrixOption.Modes:=Project1.ActiveBuildMode.Identifier; 792 MatrixOption.MacroName:='LCLWidgetType'; 793 MatrixOption.Value:=WidgetSetOverride; 794 end; 795 // apply options 796 MainBuildBoss.SetBuildTargetProject1(true,smsfsSkip); 797 798 try 799 if not SkipDependencies then 800 begin 801 // compile required packages 802 CheckPackageGraphForCompilation(nil,Project1.FirstRequiredDependency); 803 PackageGraph.BeginUpdate(false); 804 // automatically compile required packages 805 CompilePolicy:=pupAsNeeded; 806 if BuildRecursive and BuildAll then 807 CompilePolicy:=pupOnRebuildingAll; 808 if PackageGraph.CompileRequiredPackages(nil,Project1.FirstRequiredDependency, 809 not (pfUseDesignTimePackages in Project1.Flags), 810 CompilePolicy)<>mrOk 811 then 812 Error(ErrorBuildFailed,'Project dependencies of '+AFilename); 813 end; 814 815 WorkingDir:=Project1.Directory; 816 SrcFilename:=CreateRelativePath(Project1.MainUnitInfo.Filename,WorkingDir); 817 818 NeedBuildAllFlag:=false; 819 CompileHint:=''; 820 if (CompReason in Project1.CompilerOptions.CompileReasons) then begin 821 // only check if NeedBuildAllFlag will be set 822 MainBuildBoss.DoCheckIfProjectNeedsCompilation(Project1, NeedBuildAllFlag,CompileHint); 823 end; 824 825 // execute compilation tool 'Before' 826 ToolBefore:=TProjectCompilationToolOptions(Project1.CompilerOptions.ExecuteBefore); 827 if (CompReason in ToolBefore.CompileReasons) then begin 828 if ToolBefore.Execute(Project1.Directory, 829 lisProject2+lisExecutingCommandBefore, CompileHint)<>mrOk 830 then 831 Error(ErrorBuildFailed,'failed "tool before" of project '+AFilename); 832 end; 833 834 // create unit output directory 835 UnitOutputDirectory:=Project1.CompilerOptions.GetUnitOutPath(false); 836 if not ForceDirectory(UnitOutputDirectory) then 837 Error(ErrorBuildFailed,'Unable to create project unit output directory '+UnitOutputDirectory); 838 839 // create target output directory 840 TargetExeName := Project1.CompilerOptions.CreateTargetFilename; 841 TargetExeDir := ExtractFilePath(TargetExeName); 842 if not ForceDirectory(TargetExeDir) then 843 Error(ErrorBuildFailed,'Unable to create project target directory '+TargetExeDir); 844 845 // create LazBuildApp bundle 846 if Project1.UseAppBundle and (Project1.MainUnitID>=0) 847 and ((MainBuildBoss.GetLCLWidgetType=LCLPlatformDirNames[lpCarbon]) 848 or (MainBuildBoss.GetLCLWidgetType=LCLPlatformDirNames[lpCocoa])) 849 then begin 850 if not (CreateApplicationBundle(TargetExeName, Project1.Title) in [mrOk,mrIgnore]) then 851 Error(ErrorBuildFailed,'Unable to create application bundle for '+TargetExeName); 852 if not (CreateAppBundleSymbolicLink(TargetExeName) in [mrOk,mrIgnore]) then 853 Error(ErrorBuildFailed,'Unable to create application bundle symbolic link for '+TargetExeName); 854 end; 855 856 // update all lrs files 857 MainBuildBoss.UpdateProjectAutomaticFiles(''); 858 859 // regenerate resources 860 if not Project1.ProjResources.Regenerate(SrcFileName, False, True, '') then 861 begin 862 if ConsoleVerbosity>=-1 then 863 DebugLn('Error: (lazarus) Project1.Resources.Regenerate failed of ',SrcFilename); 864 end; 865 866 // get compiler parameters 867 if CompilerOverride <> '' then 868 CompilerFilename := CompilerOverride 869 else 870 CompilerFilename:=Project1.GetCompilerFilename; 871 //DebugLn(['TLazBuildApplication.BuildProject CompilerFilename="',CompilerFilename,'" CompilerPath="',Project1.CompilerOptions.CompilerPath,'"']); 872 // CompileHint: use absolute paths, same as TBuildManager.DoCheckIfProjectNeedsCompilation 873 CompilerParams:=Project1.CompilerOptions.MakeOptionsString([ccloAbsolutePaths]) 874 +' '+PrepareCmdLineOption(SrcFilename); 875 876 if (CompReason in Project1.CompilerOptions.CompileReasons) then begin 877 // compile 878 879 // write state file to avoid building clean every time 880 if Project1.SaveStateFile(CompilerFilename,CompilerParams,false)<>mrOk then 881 Error(ErrorBuildFailed,'failed saving statefile of project '+AFilename); 882 if TheCompiler.Compile(Project1,WorkingDir,CompilerFilename,CompilerParams, 883 BuildAll or NeedBuildAllFlag,false,false,false, 884 CompileHint)<>mrOk 885 then 886 Error(ErrorBuildFailed,'failed compiling of project '+AFilename); 887 // compilation succeded -> write state file 888 if Project1.SaveStateFile(CompilerFilename,CompilerParams,true)<>mrOk then 889 Error(ErrorBuildFailed,'failed saving statefile of project '+AFilename); 890 end; 891 892 // execute compilation tool 'After' 893 ToolAfter:=TProjectCompilationToolOptions(Project1.CompilerOptions.ExecuteAfter); 894 if (CompReason in ToolAfter.CompileReasons) then begin 895 if ToolAfter.Execute(Project1.Directory, 896 lisProject2+lisExecutingCommandAfter,CompileHint)<>mrOk 897 then 898 Error(ErrorBuildFailed,'failed "tool after" of project '+AFilename); 899 end; 900 901 // no need to check for mrOk, we are exit if it wasn't 902 Result:=true; 903 finally 904 if not SkipDependencies then 905 PackageGraph.EndUpdate; 906 end; 907 end; 908 909begin 910 Result:=false; 911 CloseProject(Project1); 912 913 if not Init then exit; 914 915 Project1:=LoadProject(AFilename); 916 917 if Project1.MainUnitInfo=nil then 918 Error(ErrorBuildFailed,'project has no main unit'); 919 920 if BuildAll then 921 CompReason:= crBuild 922 else 923 CompReason:= crCompile; 924 925 // first override build mode 926 if (BuildModeOverride<>'') then 927 begin 928 CurResult := true; 929 930 MatchCount := 0; 931 ModeMask := TMask.Create(BuildModeOverride,[]); 932 for i := 0 to Project1.BuildModes.Count-1 do 933 begin 934 if ModeMask.Matches(Project1.BuildModes[i].Identifier) then 935 begin 936 inc(MatchCount); 937 Project1.ActiveBuildMode := Project1.BuildModes[i]; 938 CurResult := CurResult and StartBuilding; 939 end; 940 end; 941 ModeMask.Free; 942 943 if MatchCount=0 then // No matches 944 begin 945 debugln([Format(lisERRORInvalidBuildMode, [BuildModeOverride])]); 946 if ConsoleVerbosity>=0 then 947 begin 948 debugln; 949 if Project1.BuildModes.Count>1 then 950 begin 951 debugln(lisAvailableProjectBuildModes); 952 for i:=0 to Project1.BuildModes.Count-1 do 953 begin 954 if Project1.BuildModes[i]=Project1.ActiveBuildMode then 955 dbgout('* ') 956 else 957 dbgout(' '); 958 debugln(Project1.BuildModes[i].Identifier); 959 end; 960 end else begin 961 debugln(lisThisProjectHasOnlyTheDefaultBuildMode); 962 end; 963 debugln; 964 end; 965 Halt(ErrorBuildFailed); 966 end; 967 968 Result := CurResult; 969 end 970 else 971 Result := StartBuilding; 972 973 // Auto increment build number 974 if Result and not NoWriteProject 975 and Project1.ProjResources.VersionInfo.UseVersionInfo 976 and Project1.ProjResources.VersionInfo.AutoIncrementBuild 977 then begin 978 if FileIsWritable(AFilename) then 979 begin 980 Project1.ProjResources.DoAfterBuild(CompReason, Project1.IsVirtual); 981 Project1.WriteProject(Project1.PublishOptions.WriteFlags,AFileName,EnvironmentOptions.BuildMatrixOptions) 982 end 983 else 984 begin 985 if ConsoleVerbosity>=-1 then 986 DebugLn('Error: (lazarus) Project1.WriteProject skipped for read-only ',SrcFilename); 987 end; 988 end; 989end; 990 991function TLazBuildApplication.LoadProject(const AFilename: string): TProject; 992var 993 ProjectDesc: TProjectDescriptor; 994begin 995 ProjectDesc:=TProjectDescriptor.Create; 996 try 997 Result:=TProject.Create(ProjectDesc); 998 // custom initialization 999 Result.BeginUpdate(true); 1000 if ProjectDesc.InitProject(Result)<>mrOk then begin 1001 Result.EndUpdate; 1002 Result.Free; 1003 Result:=nil; 1004 end; 1005 Result.EndUpdate; 1006 1007 Result.MainProject:=true; 1008 Result.OnFileBackup:=@BuildBoss.BackupFileForWrite; 1009 Result.OnChangeProjectInfoFile:=@OnProjectChangeInfoFile; 1010 1011 finally 1012 ProjectDesc.Free; 1013 end; 1014 1015 Result.BeginUpdate(true); 1016 try 1017 // read project info file 1018 if Result.ReadProject(AFilename,EnvironmentOptions.BuildMatrixOptions)<>mrOk then 1019 Error(ErrorLoadProjectFailed,'Project '+AFilename); 1020 //BuildBoss.RescanCompilerDefines(true); 1021 1022 // load required packages 1023 PackageGraph.OpenRequiredDependencyList(Result.FirstRequiredDependency); 1024 finally 1025 Result.EndUpdate; 1026 end; 1027 IncreaseCompilerParseStamp; 1028end; 1029 1030procedure TLazBuildApplication.CloseProject(var AProject: TProject); 1031begin 1032 // free project, if it is still there 1033 FreeThenNil(AProject); 1034end; 1035 1036function TLazBuildApplication.AddPackagesToInstallList( 1037 const PackageNamesOrFiles: TStringList): boolean; 1038var 1039 i: integer; 1040 Package: TLazPackage; 1041 PackageLink: TLazPackageLink; 1042 PackageName: String; 1043 PkgFilename: String; 1044 ErrorMsg: String; 1045 ErrCode: Byte; 1046begin 1047 Result:=false; 1048 if not Init then exit; 1049 1050 LoadMiscellaneousOptions; 1051 1052 ErrorMsg:=''; 1053 ErrCode:=ErrorPackageNameInvalid; 1054 for i:=0 to PackageNamesOrFiles.Count -1 do 1055 begin 1056 // Look for package name in all known packages 1057 PackageName:=''; 1058 PkgFilename:=''; 1059 if pvPkgSearch in fPkgGraphVerbosity then 1060 debugln(['Info: (lazarus) [TLazBuildApplication.AddPackagesToInstallList] "',PackageNamesOrFiles[i],'"']); 1061 if FilenameExtIs(PackageNamesOrFiles[i],'lpk',true) then 1062 PkgFilename:=ExpandFileNameUTF8(PackageNamesOrFiles[i]) 1063 else if IsValidPkgName(PackageNamesOrFiles[i]) then begin 1064 PackageLink:=TLazPackageLink(LazPackageLinks.FindLinkWithPkgName(PackageNamesOrFiles[i])); 1065 if PackageLink=nil then 1066 begin 1067 ErrorMsg+='Can not find package '+PackageNamesOrFiles[i]+', so it is not marked for installation.'+LineEnding; 1068 continue; 1069 end; 1070 PkgFilename:=PackageLink.LPKFilename; 1071 end else begin 1072 ErrorMsg+=PackageNamesOrFiles[i]+' is not a package, so it is not marked for installation.'+LineEnding; 1073 continue; 1074 end; 1075 Package:=LoadPackage(PkgFilename); 1076 if Package=nil then 1077 begin 1078 ErrorMsg+='Could not load '+PackageNamesOrFiles[i]+', so it is not marked for installation.'+LineEnding; 1079 ErrCode:=ErrorLoadPackageFailed; 1080 continue; 1081 end; 1082 if Package.PackageType in [lptRunTime,lptRunTimeOnly] then 1083 begin 1084 ErrorMsg+='Package '+PackageNamesOrFiles[i]+' is only for runtime.'+LineEnding; 1085 continue; 1086 end; 1087 PackageName:=Package.Name; 1088 // set it as (static) autoinstall: select for installation 1089 if ConsoleVerbosity>=0 then 1090 debugln(['Hint: (lazarus) adding package "'+PkgFilename+'" to install list of IDE']); 1091 if MiscellaneousOptions.BuildLazProfiles.StaticAutoInstallPackages.IndexOf(PackageName)<0 then 1092 MiscellaneousOptions.BuildLazProfiles.StaticAutoInstallPackages.Add(PackageName); 1093 end; 1094 if ErrorMsg<>'' then begin 1095 ErrorMsg:=UTF8Trim(ErrorMsg); 1096 Error(ErrCode,ErrorMsg); 1097 exit; 1098 end; 1099 // save list 1100 MiscellaneousOptions.Save; 1101 LazPackageLinks.SaveUserLinks(true); 1102 1103 Result:=true; 1104end; 1105 1106function TLazBuildApplication.AddCmdLinePackageLinks( 1107 const PackageNamesOrFiles: TStringList): boolean; 1108var 1109 ErrorMsg, PkgFilename: String; 1110 i, ErrCode: Integer; 1111 Package: TLazPackage; 1112begin 1113 Result:=false; 1114 if not Init then exit; 1115 1116 ErrorMsg:=''; 1117 ErrCode:=ErrorLoadPackageFailed; 1118 for i:=0 to PackageNamesOrFiles.Count -1 do 1119 begin 1120 // Look for package name in all known packages 1121 PkgFilename:=PackageNamesOrFiles[i]; 1122 if not FilenameExtIs(PkgFilename,'lpk',true) then begin 1123 ErrorMsg+=PkgFilename+' is not a package (.lpk), so it is not registered.'+LineEnding; 1124 continue; 1125 end; 1126 PkgFilename:=ExpandFileNameUTF8(PkgFilename); 1127 1128 Package:=LoadPackage(PkgFilename); 1129 if Package=nil then 1130 begin 1131 ErrorMsg+='Could not load '+PkgFilename+', so it is not registered.'+LineEnding; 1132 continue; 1133 end; 1134 if ConsoleVerbosity>=0 then 1135 debugln(['Hint: (lazarus) registering package link "'+PkgFilename+'".']); 1136 LazPackageLinks.AddUserLink(Package); 1137 end; 1138 if ErrorMsg<>'' then begin 1139 ErrorMsg:=UTF8Trim(ErrorMsg); 1140 Error(ErrCode,ErrorMsg); 1141 exit; 1142 end; 1143 1144 LazPackageLinks.SaveUserLinks(true); 1145 Result:=true; 1146end; 1147 1148function TLazBuildApplication.Init: boolean; 1149begin 1150 if fInitialized then exit(fInitResult); 1151 fInitResult:=false; 1152 fInitialized:=true; 1153 1154 if ConsoleVerbosity>=0 then 1155 debugln(['Hint: (lazarus) primary config path: ',GetPrimaryConfigPath]); 1156 CreatePrimaryConfigPath; 1157 1158 MainBuildBoss:=TBuildManager.Create(nil); 1159 SetupMacros; 1160 LoadEnvironmentOptions; 1161 if Terminated then exit(false); 1162 LoadMiscellaneousOptions; 1163 SetupLazarusDirectory; 1164 SetupCodetools; 1165 SetupFPCExeFilename; 1166 SetupPackageSystem; 1167 MainBuildBoss.SetupExternalTools(TExternalToolsConsole); 1168 ExtToolConsole:=TLazExtToolConsole.Create(nil); 1169 MainBuildBoss.SetupCompilerInterface; 1170 1171 StoreBaseSettings; 1172 1173 // load static base packages 1174 PackageGraph.LoadStaticBasePackages; 1175 1176 MainBuildBoss.SetBuildTarget(OSOverride,CPUOverride,WidgetSetOverride,smsfsSkip,true); 1177 1178 fInitResult:=true; 1179 Result:=fInitResult; 1180end; 1181 1182procedure TLazBuildApplication.LoadEnvironmentOptions; 1183var 1184 Note: string; 1185begin 1186 with EnvironmentOptions do begin 1187 CreateConfig; 1188 Load(false); 1189 fCompilerInCfg:=CompilerFilename; 1190 fLazarusDirInCfg:=LazarusDirectory; 1191 1192 if LazBuildApp.HasOption('language') then begin 1193 if ConsoleVerbosity>=0 then 1194 debugln('Note: (lazarus) overriding language with command line: ', 1195 LazBuildApp.GetOptionValue('language')); 1196 EnvironmentOptions.LanguageID:=LazBuildApp.GetOptionValue('language'); 1197 end; 1198 TranslateResourceStrings(EnvironmentOptions.GetParsedLazarusDirectory, 1199 EnvironmentOptions.LanguageID); 1200 if CompilerOverride<>'' then 1201 CompilerFilename:=CompilerOverride; 1202 //debugln(['TLazBuildApplication.LoadEnvironmentOptions LazarusDirectory="',LazarusDirectory,'"']); 1203 if LazarusDirOverride<>'' then 1204 LazarusDirectory:=CleanAndExpandDirectory(LazarusDirOverride); 1205 if MaxProcessCount>=0 then 1206 // set command line override 1207 MaxExtToolsInParallel:=MaxProcessCount; 1208 end; 1209 if not FileExistsUTF8(EnvironmentOptions.GetParsedLazarusDirectory 1210 +GetForcedPathDelims('packager/registration/fcl.lpk')) 1211 then begin 1212 CheckLazarusDirectoryQuality(EnvironmentOptions.GetParsedLazarusDirectory,Note); 1213 if ConsoleVerbosity>=-1 then 1214 debugln(['Error: (lazarus) invalid Lazarus directory "'+EnvironmentOptions.LazarusDirectory+'": '+Note]); 1215 Terminate; 1216 end; 1217end; 1218 1219procedure TLazBuildApplication.LoadMiscellaneousOptions; 1220begin 1221 if MiscellaneousOptions<>nil then exit; 1222 MiscellaneousOptions:=TMiscellaneousOptions.Create; 1223 MiscellaneousOptions.Load; 1224end; 1225 1226procedure TLazBuildApplication.SetupMacros; 1227begin 1228 MainBuildBoss.SetupTransferMacros; 1229end; 1230 1231procedure TLazBuildApplication.SetupCodetools; 1232begin 1233 // create a test unit needed to get from the compiler all macros and search paths 1234 CodeToolBoss.CompilerDefinesCache.TestFilename:=CreateCompilerTestPascalFilename; 1235 CodeToolBoss.SourceCache.OnEncodeSaving:=@OnCodeBufferEncodeSaving; 1236 CodeToolBoss.SourceCache.OnDecodeLoaded:=@OnCodeBufferDecodeLoaded; 1237 CodeToolBoss.SourceCache.DefaultEncoding:=EncodingUTF8; 1238 1239 MainBuildBoss.LoadCompilerDefinesCaches; 1240 // create a test unit needed to get from the compiler all macros and search paths 1241 CodeToolBoss.CompilerDefinesCache.TestFilename:=CreateCompilerTestPascalFilename; 1242end; 1243 1244procedure TLazBuildApplication.SetupPackageSystem; 1245begin 1246 OnGetDependencyOwnerDescription:=@GetDependencyOwnerDescription; 1247 OnGetDependencyOwnerDirectory:=@GetDependencyOwnerDirectory; 1248 1249 // package links 1250 LazPackageLinks:=TLazPackageLinks.Create; 1251 LazPackageLinks.UpdateAll; 1252 1253 // package graph 1254 PackageGraph:=TLazPackageGraph.Create; 1255 PackageGraphInterface:=PackageGraph; 1256 PackageGraph.OnAddPackage:=@PackageGraphAddPackage; 1257 PackageGraph.OnCheckInterPkgFiles:=@PackageGraphCheckInterPkgFiles; 1258 PackageGraph.Verbosity:=PkgGraphVerbosity; 1259end; 1260 1261procedure TLazBuildApplication.SetupDialogs; 1262begin 1263 LazMessageWorker:=@OnIDEMessageDialog; 1264 LazQuestionWorker:=@OnIDEQuestionDialog; 1265end; 1266 1267procedure TLazBuildApplication.StoreBaseSettings; 1268var 1269 StoreLazDir: Boolean; 1270 StoreCompPath: Boolean; 1271 Cfg: TXMLConfig; 1272begin 1273 StoreLazDir:=(fLazarusDirInCfg='') and (EnvironmentOptions.LazarusDirectory<>''); 1274 StoreCompPath:=(fCompilerInCfg='') and (EnvironmentOptions.CompilerFilename<>''); 1275 if (not StoreLazDir) and (not StoreCompPath) then exit; 1276 1277 try 1278 if ConsoleVerbosity>=-1 then 1279 begin 1280 dbgout('Hint: (lazarus) storing'); 1281 if StoreLazDir then 1282 dbgout(' Lazarus directory "',EnvironmentOptions.LazarusDirectory,'"'); 1283 if StoreCompPath then 1284 dbgout(' Compiler path "',EnvironmentOptions.CompilerFilename,'"'); 1285 debugln(' in "',EnvironmentOptions.Filename,'"'); 1286 end; 1287 Cfg:=TXMLConfig.Create(EnvironmentOptions.Filename); 1288 try 1289 if StoreLazDir then 1290 Cfg.SetValue('EnvironmentOptions/LazarusDirectory/Value', 1291 EnvironmentOptions.LazarusDirectory); 1292 if StoreCompPath then 1293 Cfg.SetValue('EnvironmentOptions/CompilerFilename/Value', 1294 EnvironmentOptions.CompilerFilename); 1295 Cfg.Flush; 1296 finally 1297 Cfg.Free; 1298 end; 1299 except 1300 on E: Exception do 1301 debugln(['Error: (lazarus) unable to edit file ',EnvironmentOptions.Filename]); 1302 end; 1303end; 1304 1305function TLazBuildApplication.RepairedCheckOptions(const ShortOptions: String; 1306 const Longopts: TStrings; Opts, NonOpts: TStrings): String; 1307 1308Var 1309 I,J,L,P : Integer; 1310 O,OV : String; 1311 HaveArg : Boolean; 1312 NeedArg: Boolean; 1313 1314 Function FindLongOpt(S : String) : boolean; 1315 Var 1316 I : integer; 1317 begin 1318 If CaseSensitiveOptions then 1319 begin 1320 I:=LongOpts.Count-1; 1321 While (I>=0) and (LongOpts[i]<>S) do 1322 Dec(i); 1323 end 1324 else 1325 begin 1326 S:=UpperCase(S); 1327 I:=LongOpts.Count-1; 1328 While (I>=0) and (UpperCase(LongOpts[i])<>S) do 1329 Dec(i); 1330 end; 1331 Result:=(I<>-1); 1332 end; 1333 1334begin 1335 Result:=''; 1336 I:=1; 1337 While (I<=ToolParamCount) and (Result='') do 1338 begin 1339 O:=ToolParamStr(I); 1340 If (Length(O)=0) or (O[1]<>OptionChar) then 1341 begin 1342 If Assigned(NonOpts) then 1343 NonOpts.Add(O) 1344 end 1345 else 1346 begin 1347 If (Length(O)<2) then 1348 Result:=Format(lisErrInvalidOption,[i,O]) 1349 else 1350 begin 1351 HaveArg:=False; 1352 OV:=''; 1353 // Long option ? 1354 If (O[2]=OptionChar) then 1355 begin 1356 Delete(O,1,2); 1357 J:=Pos('=',O); 1358 If J<>0 then 1359 begin 1360 HaveArg:=true; 1361 OV:=O; 1362 Delete(OV,1,J); 1363 O:=Copy(O,1,J-1); 1364 end; 1365 // Switch Option 1366 If FindLongopt(O) then 1367 begin 1368 If HaveArg then 1369 Result:=Format(lisErrNoOptionAllowed,[I,O]); 1370 end 1371 else 1372 begin // Required argument 1373 If FindLongOpt(O+':') then 1374 begin 1375 If Not HaveArg then 1376 Result:=Format(lisErrOptionNeeded,[I,O]); 1377 end 1378 else 1379 begin // Optional Argument. 1380 If not FindLongOpt(O+'::') then 1381 Result:=Format(lisErrInvalidOption,[I,O]); 1382 end; 1383 end; 1384 end 1385 else // Short Option. 1386 begin 1387 HaveArg:=(I<ToolParamCount) and (Length(ToolParamStr(I+1))>0) 1388 and (ToolParamStr(I+1)[i]<>OptionChar); 1389 If HaveArg then 1390 OV:=ToolParamStr(I+1); 1391 If Not CaseSensitiveOptions then 1392 O:=LowerCase(O); 1393 L:=Length(O); 1394 J:=2; 1395 NeedArg:=false; 1396 While (result='') and (J<=L) do 1397 begin 1398 P:=Pos(O[J],ShortOptions); 1399 If (P=0) or (O[j]=':') then 1400 Result:=Format(lisErrInvalidOption,[I,O[J]]) 1401 else 1402 begin 1403 If (P<Length(ShortOptions)) and (Shortoptions[P+1]=':') then 1404 begin 1405 // Required argument 1406 NeedArg:=true; 1407 if ConsoleVerbosity>0 then 1408 debugln(['P ',P,' J ',J,' ',O[J],' ',l,' Havearg ',HaveArg]); 1409 If ((P+1)=Length(ShortOptions)) or (Shortoptions[P+2]<>':') Then 1410 If (J<L) or not haveArg then // Must be last in multi-opt !! 1411 Result:=Format(lisErrOptionNeeded,[I,O[J]]); 1412 O:=O[j]; // O is added to arguments. 1413 end; 1414 end; 1415 Inc(J); 1416 end; 1417 if not NeedArg then HaveArg:=false; 1418 If HaveArg then 1419 begin 1420 Inc(I); // Skip argument. 1421 O:=O[Length(O)]; // O is added to arguments ! 1422 end; 1423 end; 1424 If HaveArg and (Result='') then 1425 If Assigned(Opts) then 1426 Opts.Add(O+'='+OV); 1427 end; 1428 end; 1429 Inc(I); 1430 end; 1431end; 1432 1433constructor TLazBuildApplication.Create(TheOwner: TComponent); 1434begin 1435 inherited Create(TheOwner); 1436 SetupDialogs; 1437 Files:=TStringList.Create; 1438 fMaxProcessCount:=-1; 1439end; 1440 1441destructor TLazBuildApplication.Destroy; 1442begin 1443 CloseProject(Project1); 1444 1445 if Assigned(PackageGraph) then 1446 begin 1447 PackageGraph.FreeAutoInstallDependencies; 1448 FreeThenNil(PackageGraph); 1449 end; 1450 1451 FreeThenNil(LazPackageLinks); 1452 FreeThenNil(TheCompiler); 1453 FreeAndNil(ExtToolConsole); 1454 FreeThenNil(GlobalMacroList); 1455 FreeThenNil(IDEMacros); 1456 FreeThenNil(MiscellaneousOptions); 1457 FreeThenNil(EnvironmentOptions); 1458 FreeThenNil(MainBuildBoss); 1459 1460 FreeAndNil(Files); 1461 inherited Destroy; 1462end; 1463 1464procedure TLazBuildApplication.Run; 1465var 1466 i: Integer; 1467begin 1468 if not ParseParameters then exit; 1469 1470 // Build all projects/packages specified by the user... 1471 // except packages to be added the IDE install list. 1472 for i:=0 to Files.Count-1 do begin 1473 if not BuildFile(Files[i]) then begin 1474 if ConsoleVerbosity>=-1 then 1475 debugln('Error: (lazarus) Building failed: ',Files[i]); 1476 ExitCode := ErrorBuildFailed; 1477 exit; 1478 end; 1479 end; 1480 1481 // Add user-requested packages to IDE install list: 1482 case PackageAction of 1483 lpaInstall: 1484 if not AddPackagesToInstallList(Files) then begin 1485 if ConsoleVerbosity>=-1 then 1486 debugln('Error: (lazarus) Installing package(s) failed: ',Files.Text); 1487 ExitCode := ErrorBuildFailed; 1488 exit; 1489 end; 1490 lpaAddPkgLinks: 1491 if not AddCmdLinePackageLinks(Files) then begin 1492 if ConsoleVerbosity>=-1 then 1493 debugln('Error: (lazarus) Adding package(s) links failed: ',Files.Text); 1494 ExitCode := ErrorBuildFailed; 1495 exit; 1496 end; 1497 end; 1498 1499 if BuildIDE then begin 1500 if not BuildLazarusIDE then begin 1501 ExitCode := ErrorBuildFailed; 1502 exit; 1503 end; 1504 end; 1505end; 1506 1507function TLazBuildApplication.ParseParameters: boolean; 1508var 1509 Options: TStringList; 1510 NonOptions: TStringList; 1511 ErrorMsg: String; 1512 LongOptions: TStringList; 1513 i: Integer; 1514 p: String; 1515 FilesNeeded: Boolean; 1516begin 1517 Result:=false; 1518 if (ToolParamCount<=0) 1519 or (CompareText(ToolParamStr(1),'--help')=0) 1520 or (CompareText(ToolParamStr(1),'-help')=0) 1521 or (CompareText(ToolParamStr(1),'-?')=0) 1522 or (CompareText(ToolParamStr(1),'-h')=0) 1523 then begin 1524 WriteUsage; 1525 exit; 1526 end; 1527 if HasOption('h','help') or HasOption('?') then begin 1528 WriteUsage; 1529 exit; 1530 end; 1531 if HasOption('v','version') then begin 1532 writeln(VersionStr); 1533 exit; 1534 end; 1535 1536 // ConsoleVerbosity 1537 for i:=1 to ToolParamCount do begin 1538 p:=ToolParamStr(i); 1539 if p='--verbose' then 1540 ConsoleVerbosity:=Max(1,ConsoleVerbosity+1) 1541 else if (p='-q') or (p='--quiet') then 1542 ConsoleVerbosity:=Min(0,ConsoleVerbosity-1); 1543 end; 1544 CTConsoleVerbosity:=ConsoleVerbosity; 1545 1546 Options:=TStringList.Create; 1547 NonOptions:=TStringList.Create; 1548 LongOptions:=TStringList.Create; 1549 try 1550 LongOptions.Add('quiet'); 1551 LongOptions.Add('verbose'); 1552 LongOptions.Add('verbose-pkgsearch'); 1553 LongOptions.Add('primary-config-path:'); 1554 LongOptions.Add('pcp:'); 1555 LongOptions.Add('secondary-config-path:'); 1556 LongOptions.Add('scp:'); 1557 LongOptions.Add('language:'); 1558 LongOptions.Add('add-package'); 1559 LongOptions.Add('add-package-link'); 1560 LongOptions.Add('build-all'); 1561 LongOptions.Add('build-ide:'); 1562 LongOptions.Add('recursive'); 1563 LongOptions.Add('skip-dependencies'); 1564 LongOptions.Add('widgetset:'); 1565 LongOptions.Add('ws:'); 1566 LongOptions.Add('operating-system:'); 1567 LongOptions.Add('os:'); 1568 LongOptions.Add('cpu:'); 1569 LongOptions.Add('bm:'); 1570 LongOptions.Add('build-mode:'); 1571 LongOptions.Add('compiler:'); 1572 LongOptions.Add('lazarusdir:'); 1573 LongOptions.Add('create-makefile'); 1574 LongOptions.Add('max-process-count:'); 1575 LongOptions.Add('no-write-project'); 1576 ErrorMsg:=RepairedCheckOptions('lBrdq',LongOptions,Options,NonOptions); 1577 if ErrorMsg<>'' then begin 1578 writeln(ErrorMsg); 1579 writeln(''); 1580 exit; 1581 end; 1582 1583 FilesNeeded:=true; 1584 1585 if HasOption('verbose-pkgsearch') then 1586 Include(fPkgGraphVerbosity,pvPkgSearch); 1587 1588 // PackageAction: register lpk files 1589 if HasOption('add-package-link') then begin 1590 if ConsoleVerbosity>=0 then 1591 writeln('Parameter: add-package-link'); 1592 if PackageAction<>lpaBuild then begin 1593 writeln('Error: invalid combination of package actions'); 1594 WriteUsage; 1595 exit; 1596 end; 1597 FilesNeeded:=false; 1598 PackageAction:=lpaAddPkgLinks; 1599 end; 1600 1601 // PackageAction: install lpk files 1602 if HasOption('add-package') then begin 1603 if ConsoleVerbosity>=0 then 1604 writeln('Parameter: add-package'); 1605 if PackageAction<>lpaBuild then begin 1606 writeln('Error: invalid combination of package actions'); 1607 WriteUsage; 1608 exit; 1609 end; 1610 PackageAction:=lpaInstall; 1611 FilesNeeded:=false; 1612 end; 1613 1614 // building IDE 1615 if HasOption('build-ide') then begin 1616 BuildIDE:=true; 1617 BuildIDEOptions:=GetOptionValue('build-ide'); 1618 FilesNeeded:=false; 1619 if ConsoleVerbosity>=0 then 1620 writeln('Parameter: build-ide=',BuildIDEOptions); 1621 end; 1622 1623 // files 1624 Files.Assign(NonOptions); 1625 if FilesNeeded and (Files.Count=0) then begin 1626 writeln('Error: missing file'); 1627 WriteUsage; 1628 exit; 1629 end; 1630 1631 // primary config path 1632 if HasOption('primary-config-path') then begin 1633 SetPrimaryConfigPath(GetOptionValue('primary-config-path')); 1634 if ConsoleVerbosity>=0 then 1635 writeln('Parameter: primary-config-path=',GetPrimaryConfigPath); 1636 end else if HasOption('pcp') then begin 1637 SetPrimaryConfigPath(GetOptionValue('pcp')); 1638 if ConsoleVerbosity>=0 then 1639 writeln('Parameter: pcp=',GetPrimaryConfigPath); 1640 end; 1641 1642 // secondary config path 1643 if HasOption('secondary-config-path') then begin 1644 SetPrimaryConfigPath(GetOptionValue('secondary-config-path')); 1645 if ConsoleVerbosity>=0 then 1646 writeln('Parameter: secondary-config-path=',GetSecondaryConfigPath); 1647 end else if HasOption('scp') then begin 1648 SetSecondaryConfigPath(GetOptionValue('scp')); 1649 if ConsoleVerbosity>=0 then 1650 writeln('Parameter: scp=',GetSecondaryConfigPath); 1651 end; 1652 1653 // build all 1654 if HasOption('B','build-all') then begin 1655 BuildAll:=true; 1656 if ConsoleVerbosity>=0 then 1657 writeln('Parameter: build-all'); 1658 end; 1659 if HasOption('r','recursive') then begin 1660 BuildAll:=true; 1661 BuildRecursive:=true; 1662 if ConsoleVerbosity>=0 then 1663 writeln('Parameter: recursive'); 1664 end; 1665 if HasOption('d','skip-dependencies') then begin 1666 SkipDependencies:=true; 1667 if ConsoleVerbosity>=0 then 1668 writeln('Parameter: skip-dependencies'); 1669 end; 1670 if BuildRecursive and SkipDependencies then begin 1671 writeln('Error: --recursive and --skip-dependencies. You have to make up your mind.'); 1672 WriteUsage; 1673 exit; 1674 end; 1675 1676 // overides 1677 // widgetset 1678 if HasOption('ws') then begin 1679 WidgetSetOverride := GetOptionValue('ws'); 1680 if ConsoleVerbosity>=0 then 1681 writeln('Parameter: ws=',WidgetSetOverride); 1682 end else if HasOption('widgetset') then begin 1683 WidgetSetOverride := GetOptionValue('widgetset'); 1684 if ConsoleVerbosity>=0 then 1685 writeln('Parameter: widgetset=',WidgetSetOverride); 1686 end; 1687 1688 // operating system 1689 if HasOption('os') then begin 1690 OSOverride := GetOptionValue('os'); 1691 if ConsoleVerbosity>=0 then 1692 writeln('Parameter: os=',OSOverride); 1693 end else if HasOption('operating-system') then begin 1694 OSOverride := GetOptionValue('operating-system'); 1695 if ConsoleVerbosity>=0 then 1696 writeln('Parameter: operating-system=',OSOverride); 1697 end; 1698 1699 // cpu 1700 if HasOption('cpu') then begin 1701 CPUOverride := GetOptionValue('cpu'); 1702 if ConsoleVerbosity>=0 then 1703 writeln('Parameter: cpu=',CPUOverride); 1704 end; 1705 1706 // build mode 1707 if HasOption('bm') then begin 1708 BuildModeOverride := GetOptionValue('bm'); 1709 if ConsoleVerbosity>=0 then 1710 writeln('Parameter: bm=',BuildModeOverride); 1711 end else if HasOption('build-mode') then begin 1712 BuildModeOverride := GetOptionValue('build-mode'); 1713 if ConsoleVerbosity>=0 then 1714 writeln('Parameter: build-mode=',BuildModeOverride); 1715 end; 1716 1717 // compiler 1718 if HasOption('compiler') then begin 1719 CompilerOverride := GetOptionValue('compiler'); 1720 if ConsoleVerbosity>=0 then 1721 writeln('Parameter: compiler=',CompilerOverride); 1722 end; 1723 1724 // lazarusdir 1725 if HasOption('lazarusdir') then begin 1726 LazarusDirOverride := GetOptionValue('lazarusdir'); 1727 if ConsoleVerbosity>=0 then 1728 writeln('Parameter: lazarusdir=',LazarusDirOverride); 1729 end; 1730 1731 // max-process-count 1732 if HasOption('max-process-count') then begin 1733 MaxProcessCount:=StrToInt(GetOptionValue('max-process-count')); 1734 if ConsoleVerbosity>=0 then 1735 writeln('Parameter: max-process-count=',MaxProcessCount); 1736 end; 1737 1738 if HasOption('no-write-project') then 1739 begin 1740 NoWriteProject := true; 1741 if ConsoleVerbosity>=0 then 1742 writeln('Parameter: no-write-project'); 1743 end; 1744 1745 if HasOption('create-makefile') then 1746 begin 1747 CreateMakefile := true; 1748 if ConsoleVerbosity>=0 then 1749 writeln('Parameter: create-makefile'); 1750 if PackageAction<>lpaBuild then 1751 Error(ErrorPackageNameInvalid,'You can not combine --create-makefile and --add-package'); 1752 end; 1753 finally 1754 Options.Free; 1755 NonOptions.Free; 1756 LongOptions.Free; 1757 end; 1758 Result:=true; 1759end; 1760 1761procedure TLazBuildApplication.WriteUsage; 1762const 1763 space = ' '; 1764 1765 function LongToConsole(s: string): string; 1766 begin 1767 Result:=UTF8ToConsole(BreakString(s,75, length(space))) 1768 end; 1769 1770 procedure w(Msg: string); 1771 begin 1772 writeln(LongToConsole(Msg)); 1773 end; 1774 1775begin 1776 TranslateResourceStrings(ProgramDirectoryWithBundle,''); 1777 writeln(''); 1778 writeln('lazbuild [options] <project/package filename or package name>'); 1779 writeln(''); 1780 w(lisEdtExtToolParameters); 1781 writeln(''); 1782 writeln('--help or -?'); 1783 w(space+listhisHelpMessage); 1784 writeln('-B or --build-all'); 1785 w(space+lisBuildAllFilesOfProjectPackageIDE); 1786 writeln('-r or --recursive'); 1787 w(space+lisApplyBuildFlagsBToDependenciesToo); 1788 writeln('-d or --skip-dependencies'); 1789 w(space+lisDoNotCompileDependencies); 1790 writeln('--build-ide=<options>'); 1791 w(space+lisBuildIDEWithPackages); 1792 writeln('-v or --version'); 1793 w(space+lisShowVersionAndExit); 1794 writeln('-q or --quiet'); 1795 w(space+lisBeLessVerboseCanBeGivenMultipleTimes); 1796 w(space+'Passing quiet two times, will pass -vw-n-h-i-l-d-u-t-p-c-x- to the compiler'); 1797 writeln('--verbose'); 1798 w(space+lisBeMoreVerboseCanBeGivenMultipleTimes); 1799 writeln('--verbose-pkgsearch'); 1800 w(space+'Write what package files are searched and found'); 1801 writeln(''); 1802 1803 writeln('--add-package'); 1804 w(space+lisAddPackageSToListOfInstalledPackagesCombineWithBui); 1805 writeln('--add-package-link=<.lpk file>'); 1806 w(space+lisOnlyRegisterTheLazarusPackageFilesLpkDoNotBuild); 1807 writeln('--create-makefile'); 1808 w(space+lisInsteadOfCompilePackageCreateASimpleMakefile); 1809 writeln(''); 1810 1811 writeln(PrimaryConfPathOptLong,'<path>'); 1812 writeln('or ',PrimaryConfPathOptShort,'<path>'); 1813 w(space+lisprimaryConfigDirectoryWhereLazarusStoresItsConfig+LazConf.GetPrimaryConfigPath); 1814 writeln(''); 1815 writeln(SecondaryConfPathOptLong,'<path>'); 1816 writeln('or ',SecondaryConfPathOptShort,'<path>'); 1817 w(space+lissecondaryConfigDirectoryWhereLazarusSearchesFor+LazConf.GetSecondaryConfigPath); 1818 writeln(''); 1819 writeln('--operating-system=<operating-system>'); 1820 writeln('or --os=<operating-system>'); 1821 writeln(LongToConsole(Format( 1822 lisOverrideTheProjectOperatingSystemEGWin32LinuxDefau, [space, 1823 GetCompiledTargetOS]))); 1824 writeln(''); 1825 writeln('--widgetset=<widgetset>'); 1826 writeln('or --ws=<widgetset>'); 1827 writeln(LongToConsole(Format( 1828 lisOverrideTheProjectWidgetsetEGGtkGtk2QtWin32CarbonD, [space, 1829 LCLPlatformDirNames[GetBuildLCLWidgetType]]))); 1830 writeln(''); 1831 writeln('--cpu=<cpu>'); 1832 writeln(LongToConsole(Format( 1833 lisOverrideTheProjectCpuEGI386X86_64PowerpcPowerpc_64, [space, 1834 GetCompiledTargetCPU]))); 1835 writeln(''); 1836 writeln('--build-mode=<project/ide build mode>'); 1837 writeln('or --bm=<project/ide build mode>'); 1838 writeln(LongToConsole(Format(lisOverrideTheProjectBuildMode,[space]))); 1839 writeln(''); 1840 writeln('--compiler=<ppcXXX>'); 1841 writeln(LongToConsole(Format( 1842 lisOverrideTheDefaultCompilerEGPpc386Ppcx64PpcppcEtcD, [space]))); 1843 writeln(''); 1844 writeln(LanguageOpt); 1845 w(space+lisOverrideLanguage); 1846 writeln(''); 1847 writeln('--lazarusdir=<Lazarus directory>'); 1848 w(space+lisLazarusDirOverride); 1849 writeln(''); 1850 writeln('--max-process-count=<count>'); 1851 w(space+lisMaximumNumberOfThreadsForCompilingInParallelDefaul); 1852 writeln(''); 1853 writeln('--no-write-project'); 1854 w(space+lisDoNotWriteUpdatedProjectInfoAfterBuild); 1855 writeln(''); 1856end; 1857 1858procedure TLazBuildApplication.Error(ErrorCode: Byte; const ErrorMsg: string); 1859begin 1860 writeln('Error: (lazbuild) ',LineBreaksToSystemLineBreaks(ErrorMsg)); 1861 Halt(ErrorCode); 1862end; 1863 1864begin 1865 // When quick rebuilding lazbuild, FPC rebuilds only the lazbuild.lpr, so any 1866 // flag that should work with quick build must be set here. 1867 // At the moment there is no flag 1868 1869 HasGUI:=false; 1870 ConsoleVerbosity:=-1; 1871 FilterConfigFileContent; 1872 // free LCL Application to help debugging nogui issues 1873 Application.Free; 1874 // start our own LazBuildApp 1875 LazBuildApp:=TLazBuildApplication.Create(nil); 1876 LazBuildApp.Run; 1877 LazBuildApp.Free; 1878end. 1879 1880