program fpmake; {$coperators on} {$mode objfpc}{$H+} uses fpmkunit, SysUtils, Classes; const AllMyUnixOSes = AllUnixOSes - [Darwin, Haiku]; const CommonComponents: array[1..10] of String = ( 'components\chsdet\chsdet.lpk', 'components\multithreadprocs\multithreadprocslaz.lpk', 'components\kascrypt\kascrypt.lpk', 'components\doublecmd\doublecmd_common.lpk', 'components\Image32\Image32.lpk', 'components\KASToolBar\kascomp.lpk', 'components\viewer\viewerpackage.lpk', 'components\gifview\gifview.lpk', 'components\synunihighlighter\synuni.lpk', 'components\virtualterminal\virtualterminal.lpk' ); CommonPlugins: array[1..9] of String = ( 'plugins/wcx/base64/src/base64wcx.lpi', 'plugins/wcx/deb/src/deb.lpi', 'plugins/wcx/rpm/src/rpm.lpi', 'plugins/wcx/unrar/src/unrar.lpi', 'plugins/wcx/zip/src/Zip.lpi', 'plugins/wdx/rpm_wdx/src/rpm_wdx.lpi', 'plugins/wdx/deb_wdx/src/deb_wdx.lpi', 'plugins/wdx/audioinfo/src/AudioInfo.lpi', 'plugins/wfx/ftp/src/ftp.lpi' ); UnixPlugins: array[1..4] of String = ( 'plugins/wcx/cpio/src/cpio.lpi', 'plugins/wfx/samba/src/samba.lpi', 'plugins/wlx/WlxMplayer/src/wlxMplayer.lpi', 'plugins/dsx/DSXLocate/src/DSXLocate.lpi' ); HaikuPlugins: array[1..1] of String = ( 'plugins/wcx/cpio/src/cpio.lpi' ); DarwinPlugins: array[1..2] of String = ( 'plugins/wcx/cpio/src/cpio.lpi', 'plugins/wlx/MacPreview/src/MacPreview.lpi' ); WindowsPlugins: array[1..4] of String = ( 'plugins\wcx\sevenzip\src\SevenZipWcx.lpi', 'plugins\wlx\richview\src\richview.lpi', 'plugins\wlx\preview\src\preview.lpi', 'plugins\wlx\wmp\src\wmp.lpi' ); DeleteFiles: array[1..6] of String = ( 'doublecmd', 'doublecmd.exe', 'doublecmd.dbg', 'doublecmd.zdli', 'src\doublecmd.res', 'tools\extractdwrflnfo' ); var FLazBuild: String = 'lazbuild'; type { TDCDefaults } TDCDefaults = class(TFPCDefaults) private FWS: String; public procedure CompilerDefaults; override; property WS: String read FWS write FWS; end; { TDCBuildEngine } TDCBuildEngine = class(TBuildEngine) end; { TDCInstaller } TDCInstaller = class(TCustomInstaller) private FLazBuildParams: String; private procedure CleanDirectory(const Directory: String); procedure CleanComponents; procedure BuildComponents; procedure CleanPlugins; procedure BuildPlugins; procedure Clean; overload; procedure Build; function ReadOutputDirectory(const FileName: String): String; procedure CleanOutputDirectory(const FileName: String); protected procedure Clean(AllTargets: boolean); override; public constructor Create(AOwner : TComponent); override; end; { TDCDefaults } procedure TDCDefaults.CompilerDefaults; var AValue: String; begin if Defaults.OS = osNone then begin AValue:= GetEnvironmentVariable('OS_TARGET'); if Length(AValue) > 0 then Defaults.OS:= StringToOS(AValue); end; if Defaults.CPU = cpuNone then begin AValue:= GetEnvironmentVariable('CPU_TARGET'); if Length(AValue) > 0 then Defaults.CPU:= StringToCPU(AValue); end; AValue:= GetEnvironmentVariable('LCL_PLATFORM'); if Length(AValue) > 0 then (Defaults as TDCDefaults).FWS:= AValue; inherited CompilerDefaults; end; procedure TDCInstaller.BuildComponents; var I: Integer; Args : String; begin for I:= Low(CommonComponents) to High(CommonComponents) do begin Args:= SetDirSeparators(CommonComponents[I]) + FLazBuildParams; BuildEngine.ExecuteCommand(FLazBuild, Args); end; end; procedure TDCInstaller.CleanPlugins; var I: Integer; begin for I:= Low(CommonPlugins) to High(CommonPlugins) do begin CleanOutputDirectory(CommonPlugins[I]); end; end; function TDCInstaller.ReadOutputDirectory(const FileName: String): String; var I: Integer; AFile: TStringList; begin try AFile:= TStringList.Create; try AFile.LoadFromFile(SetDirSeparators(FileName)); I:= Pos('UnitOutputDirectory Value', AFile.Text); if I = 0 then Exit; Result:= Copy(AFile.Text, I + 27, MaxInt); I:= Pos('"', Result); if I = 0 then Exit; Result:= ExtractFilePath(FileName) + Copy(Result, 1, I - 1); Result:= StringReplace(Result, '$(TargetOS)', OSToString(Defaults.OS), [rfReplaceAll, rfIgnoreCase]); Result:= StringReplace(Result, '$(TargetCPU)', CPUToString(Defaults.CPU), [rfReplaceAll, rfIgnoreCase]); Result:= SetDirSeparators(Result); finally AFile.Free; end; except Result:= EmptyStr; end; end; procedure TDCInstaller.CleanOutputDirectory(const FileName: String); begin CleanDirectory(ReadOutputDirectory(FileName)); end; procedure TDCInstaller.Clean(AllTargets: boolean); begin // Clean components CleanComponents; // Clean plugins CleanPlugins; // Clean Double Commander Clean; end; constructor TDCInstaller.Create(AOwner: TComponent); begin Defaults:= TDCDefaults.Create; Defaults.IgnoreInvalidOptions:= True; inherited Create(AOwner); end; procedure TDCInstaller.BuildPlugins; var I: Integer; begin for I:= Low(CommonPlugins) to High(CommonPlugins) do BuildEngine.ExecuteCommand(FLazBuild, SetDirSeparators(CommonPlugins[I]) + FLazBuildParams); if Defaults.OS in AllMyUnixOSes then begin for I:= Low(UnixPlugins) to High(UnixPlugins) do BuildEngine.ExecuteCommand(FLazBuild, SetDirSeparators(UnixPlugins[I]) + FLazBuildParams); end; if Defaults.OS = Haiku then begin for I:= Low(HaikuPlugins) to High(HaikuPlugins) do BuildEngine.ExecuteCommand(FLazBuild, SetDirSeparators(HaikuPlugins[I]) + FLazBuildParams); end; if Defaults.OS = Darwin then begin for I:= Low(DarwinPlugins) to High(DarwinPlugins) do BuildEngine.ExecuteCommand(FLazBuild, SetDirSeparators(DarwinPlugins[I]) + FLazBuildParams); end; if Defaults.OS in AllWindowsOSes then begin for I:= Low(WindowsPlugins) to High(WindowsPlugins) do BuildEngine.ExecuteCommand(FLazBuild, SetDirSeparators(WindowsPlugins[I]) + FLazBuildParams); end; end; procedure TDCInstaller.Clean; const OutputPath = 'units' + PathDelim; var I: Integer; AInfo : TSearchRec; begin // Clean output directories if FindFirst(OutputPath + AllFilesMask, faAnyFile - faHidden, AInfo) = 0 then repeat if ((AInfo.Attr and faDirectory) = faDirectory) and (AInfo.Name <> '.') and (AInfo.Name <> '..') then CleanDirectory(OutputPath + AInfo.Name); until FindNext(AInfo) <> 0; FindClose(AInfo); TDCBuildEngine(BuildEngine).SysDeleteTree('tools' + PathDelim + 'lib'); // Clean files for I:= Low(DeleteFiles) to High(DeleteFiles) do TDCBuildEngine(BuildEngine).SysDeleteFile(SetDirSeparators(DeleteFiles[I])); // Clean debug directory if Defaults.OS = Darwin then begin TDCBuildEngine(BuildEngine).SysDeleteTree('doublecmd.dSYM'); end; // Clean fpmake output files TDCBuildEngine(BuildEngine).SysDeleteFile('fpmake.o'); end; procedure TDCInstaller.Build; begin // Build components BuildComponents; // Build plugins BuildPlugins; // Set default build mode if Pos('--bm=', FLazBuildParams) = 0 then FLazBuildParams+= ' --bm=release'; // Build Double Commander BuildEngine.ExecuteCommand(FLazBuild, SetDirSeparators('src/doublecmd.lpi') + FLazBuildParams); if Pos('--bm=release', FLazBuildParams) > 0 then begin // Build Dwarf LineInfo Extractor BuildEngine.ExecuteCommand(FLazBuild, SetDirSeparators('tools/extractdwrflnfo.lpi')); // Extract debug line info if Defaults.OS = Darwin then begin BuildEngine.CmdRenameFile('doublecmd.dSYM/Contents/Resources/DWARF/doublecmd', 'doublecmd.dbg'); end; BuildEngine.ExecuteCommand(SetDirSeparators('tools/extractdwrflnfo'), 'doublecmd.dbg'); end; end; procedure TDCInstaller.CleanDirectory(const Directory: String); var List: TStrings; begin List:= TStringList.Create; try SearchFiles(IncludeTrailingPathDelimiter(Directory) + AllFilesMask, EmptyStr, False, List); BuildEngine.CmdDeleteFiles(List); finally List.Free; end; end; procedure TDCInstaller.CleanComponents; var I: Integer; begin for I:= Low(CommonComponents) to High(CommonComponents) do begin CleanOutputDirectory(CommonComponents[I]); end; end; var I: Integer; var OptArg: String; BuildTarget: String; begin AddCustomFpmakeCommandlineOption('bm', 'Override the project build mode.'); AddCustomFpmakeCommandlineOption('ws', 'Override the project widgetset, e.g. gtk2 qt qt5 win32 cocoa.'); with Installer(TDCInstaller) as TDCInstaller do begin CreateBuildEngine; BuildTarget:= ParamStr(1); FLazBuildParams:= ' --os=' + OSToString(Defaults.OS); FLazBuildParams+= ' --cpu=' + CPUToString(Defaults.CPU); if BuildTarget = 'clean' then begin Clean(True); Exit; end; for I:= 0 to ParamCount do WriteLn(ParamStr(I)); OptArg:= GetCustomFpmakeCommandlineOptionValue('bm'); if Length(OptArg) > 0 then begin FLazBuildParams+= ' --bm=' + OptArg; end; OptArg:= GetCustomFpmakeCommandlineOptionValue('ws'); if Length(OptArg) > 0 then begin FLazBuildParams+= ' --ws=' + OptArg; end; if (Defaults.HaveOptions) then begin FLazBuildParams+= ' ' + TDCDefaults(Defaults).CmdLineOptions; end; if BuildEngine.Verbose then begin FLazBuildParams+= ' --verbose'; end; if (Pos('--ws', FLazBuildParams) = 0) and (Length((Defaults as TDCDefaults).WS) > 0) then FLazBuildParams+= ' --ws=' + (Defaults as TDCDefaults).WS; WriteLn(FLazBuildParams); if BuildTarget = 'components' then BuildComponents else if BuildTarget = 'plugins' then BuildPlugins else Build; end; end.