Browse Source

* split options in globaloptions and compileroptions
* use compileroptions to load settings for compiling fpmake
* simple version check in config files

git-svn-id: trunk@9256 -

peter 17 years ago
parent
commit
269d8ecf51

+ 28 - 20
utils/fppkg/fppkg.pp

@@ -74,20 +74,20 @@ begin
   GeneratedConfig:=false;
   // Load file or create new default configuration
   if FileExists(cfgfile) then
-    Options.LoadGlobalFromFile(cfgfile)
+    GlobalOptions.LoadGlobalFromFile(cfgfile)
   else
     begin
       ForceDirectories(ExtractFilePath(cfgfile));
-      Options.SaveGlobalToFile(cfgfile);
+      GlobalOptions.SaveGlobalToFile(cfgfile);
       GeneratedConfig:=true;
     end;
   // Load default verbosity from config
   SL:=TStringList.Create;
-  SL.CommaText:=Options.DefaultVerbosity;
+  SL.CommaText:=GlobalOptions.DefaultVerbosity;
   for i:=0 to SL.Count-1 do
     Include(Verbosity,StringToVerbosity(SL[i]));
   SL.Free;
-  Options.CurrentCompilerConfig:=Options.DefaultCompilerConfig;
+  GlobalOptions.CompilerConfig:=GlobalOptions.DefaultCompilerConfig;
   // Tracing of what we've done above, need to be done after the verbosity is set
   if GeneratedConfig then
     Log(vDebug,SLogGeneratingGlobalConfig,[cfgfile])
@@ -98,9 +98,9 @@ end;
 
 procedure TMakeTool.MaybeCreateLocalDirs;
 begin
-  ForceDirectories(Options.BuildDir);
-  ForceDirectories(Options.PackagesDir);
-  ForceDirectories(Options.CompilerConfigDir);
+  ForceDirectories(GlobalOptions.BuildDir);
+  ForceDirectories(GlobalOptions.PackagesDir);
+  ForceDirectories(GlobalOptions.CompilerConfigDir);
 end;
 
 
@@ -108,24 +108,34 @@ procedure TMakeTool.LoadCompilerDefaults;
 var
   S : String;
 begin
-  S:=Options.CompilerConfigDir+Options.CurrentCompilerConfig;
+  // Load default compiler config
+  S:=GlobalOptions.CompilerConfigDir+GlobalOptions.CompilerConfig;
   if FileExists(S) then
     begin
       Log(vDebug,SLogLoadingCompilerConfig,[S]);
-      Options.LoadCompilerFromFile(S)
+      CompilerOptions.LoadCompilerFromFile(S)
     end
   else
     begin
       // Generate a default configuration if it doesn't exists
-      if Options.CurrentCompilerConfig='default' then
+      if GlobalOptions.CompilerConfig='default' then
         begin
           Log(vDebug,SLogGeneratingCompilerConfig,[S]);
-          Options.InitCompilerDefaults;
-          Options.SaveCompilerToFile(S);
+          CompilerOptions.InitCompilerDefaults;
+          CompilerOptions.SaveCompilerToFile(S);
         end
       else
         Error(SErrMissingCompilerConfig,[S]);
     end;
+  // Load FPMake compiler config, this is normally the same config as above
+  S:=GlobalOptions.CompilerConfigDir+GlobalOptions.FPMakeCompilerConfig;
+  if FileExists(S) then
+    begin
+      Log(vDebug,SLogLoadingFPMakeCompilerConfig,[S]);
+      FPMakeCompilerOptions.LoadCompilerFromFile(S)
+    end
+  else
+    Error(SErrMissingCompilerConfig,[S]);
 end;
 
 
@@ -136,18 +146,18 @@ begin
   Writeln('  -c --config        Set compiler configuration to use');
   Writeln('  -h --help          This help');
   Writeln('  -v --verbose       Set verbosity');
-  Writeln('  -b --bootstrap     Special bootstrapping mode');
   Writeln('  -g --global        Force installation to global (system-wide) directory');
   Writeln('  -f --force         Force installation also if the package is already installed');
   Writeln('Actions:');
   Writeln('  update             Update packages list');
   Writeln('  avail              List available packages');
   Writeln('  build              Build package');
+  Writeln('  compile            Compile package');
   Writeln('  install            Install package');
   Writeln('  archive            Create archive of package');
   Writeln('  download           Download package');
   Writeln('  convertmk          Convert Makefile.fpc to fpmake.pp');
-  Writeln('  addconfig          Add a compiler configuration for the supplied compiler');
+//  Writeln('  addconfig          Add a compiler configuration for the supplied compiler');
   Halt(0);
 end;
 
@@ -217,13 +227,11 @@ begin
       Inc(I);
       // Check options.
       if CheckOption(I,'c','config') then
-        Options.CurrentCompilerConfig:=OptionArg(I)
+        GlobalOptions.CompilerConfig:=OptionArg(I)
       else if CheckOption(I,'v','verbose') then
         Include(Verbosity,StringToVerbosity(OptionArg(I)))
-      else if CheckOption(I,'b','bootstrap') then
-        Options.BootStrap:=true
       else if CheckOption(I,'g','global') then
-        Options.InstallGlobal:=true
+        GlobalOptions.InstallGlobal:=true
       else if CheckOption(I,'h','help') then
         begin
           ShowUsage;
@@ -256,14 +264,14 @@ var
   i      : Integer;
 begin
   OldCurrDir:=GetCurrentDir;
-  LoadGlobalDefaults;
   Try
+    LoadGlobalDefaults;
     ProcessCommandLine;
     MaybeCreateLocalDirs;
     LoadCompilerDefaults;
 
     // Load local repository, update first if this is a new installation
-    if not FileExists(Options.LocalPackagesFile) then
+    if not FileExists(GlobalOptions.LocalPackagesFile) then
       pkghandler.ExecuteAction(nil,'update');
     LoadLocalRepository;
     LoadLocalStatus;

+ 2 - 2
utils/fppkg/pkgcommands.pp

@@ -117,8 +117,8 @@ end;
 
 function TCommandUpdate.Execute(const Args:TActionArgs):boolean;
 begin
-  Log(vCommands,SLogDownloading,[Options.RemotePackagesFile,Options.LocalPackagesFile]);
-  DownloadFile(Options.RemotePackagesFile,Options.LocalPackagesFile);
+  Log(vCommands,SLogDownloading,[GlobalOptions.RemotePackagesFile,GlobalOptions.LocalPackagesFile]);
+  DownloadFile(GlobalOptions.RemotePackagesFile,GlobalOptions.LocalPackagesFile);
   // Read the repository again
   LoadLocalRepository;
   LoadLocalStatus;

+ 0 - 10
utils/fppkg/pkgdownload.pp

@@ -15,7 +15,6 @@ Type
   Private
     FBackupFile : Boolean;
   Protected
-    Procedure BackupFile(Const FileName : String);
     // Needs overriding.
     Procedure FTPDownload(Const URL : String; Dest : TStream); Virtual;
     Procedure HTTPDownload(Const URL : String; Dest : TStream); Virtual;
@@ -61,15 +60,6 @@ end;
 
 { TBaseDownloader }
 
-procedure TBaseDownloader.BackupFile(const FileName: String);
-Var
-  BFN : String;
-begin
-  BFN:=FileName+'.bak';
-  If not RenameFile(FileName,BFN) then
-    Error(SErrBackupFailed,[FileName,BFN]);
-end;
-
 procedure TBaseDownloader.FTPDownload(const URL: String; Dest: TStream);
 begin
   Error(SErrNoFTPDownload);

+ 15 - 17
utils/fppkg/pkgfpmake.pp

@@ -118,16 +118,16 @@ Procedure TFPMakeCompiler.CompileFPMake;
   function CheckUnitDir(const AUnitName:string;Out AUnitDir:string):boolean;
   begin
     Result:=false;
-    if Options.FPMakeLocalUnitDir<>'' then
+    if FPMakeCompilerOptions.LocalUnitDir<>'' then
       begin
-        AUnitDir:=IncludeTrailingPathDelimiter(Options.FPMakeLocalUnitDir+AUnitName);
+        AUnitDir:=IncludeTrailingPathDelimiter(FPMakeCompilerOptions.LocalUnitDir+AUnitName);
         if DirectoryExistsLog(AUnitDir) then
           begin
             Result:=true;
             exit;
           end;
       end;
-    AUnitDir:=IncludeTrailingPathDelimiter(Options.FPMakeGlobalUnitDir+AUnitName);
+    AUnitDir:=IncludeTrailingPathDelimiter(FPMakeCompilerOptions.GlobalUnitDir+AUnitName);
     if DirectoryExistsLog(AUnitDir) then
       begin
         Result:=true;
@@ -149,7 +149,7 @@ Var
   HaveFpmake : boolean;
 begin
   SetCurrentDir(PackageBuildPath);
-  { Check for fpmake source }
+  // Check for fpmake source
   FPMakeBin:='fpmake'+ExeExt;
   FPMakeSrc:='fpmake.pp';
   HaveFpmake:=FileExists(FPMakeSrc);
@@ -159,7 +159,7 @@ begin
       If HaveFPMake then
         FPMakeSrc:='fpmake.pas';
     end;
-  { Need to compile fpmake executable? }
+  // Need to compile fpmake executable?
   if not FileExists(FPMakeBin) or
      (FileAge(FPMakeBin)<FileAge(FPMakeSrc)) then
     begin
@@ -233,7 +233,7 @@ begin
       if NeedFPMKUnitSource then
         CreateFPMKUnitSource(TempBuildDir+PathDelim+'fpmkunit.pp');
       // Call compiler
-      If ExecuteProcess(Options.FPMakeCompiler,OOptions+' '+FPmakeSrc)<>0 then
+      If ExecuteProcess(FPMakeCompilerOptions.Compiler,OOptions+' '+FPmakeSrc)<>0 then
         Error(SErrFailedToCompileFPCMake);
       // Cleanup units
       DeleteDir(TempBuildDir);
@@ -264,18 +264,16 @@ begin
   OOptions:=' --nofpccfg';
   if vInfo in Verbosity then
     OOptions:=OOptions+' --verbose';
-  OOptions:=OOptions+' --compiler='+Options.Compiler;
-  OOptions:=OOptions+' --CPU='+CPUToString(Options.CompilerCPU);
-  OOptions:=OOptions+' --OS='+OSToString(Options.CompilerOS);
-  if IsSuperUser or Options.InstallGlobal then
-    OOptions:=OOptions+' --baseinstalldir='+Options.GlobalInstallDir
+  OOptions:=OOptions+' --compiler='+CompilerOptions.Compiler;
+  OOptions:=OOptions+' --CPU='+CPUToString(CompilerOptions.CompilerCPU);
+  OOptions:=OOptions+' --OS='+OSToString(CompilerOptions.CompilerOS);
+  if IsSuperUser or GlobalOptions.InstallGlobal then
+    OOptions:=OOptions+' --baseinstalldir='+CompilerOptions.GlobalInstallDir
   else
-    OOptions:=OOptions+' --baseinstalldir='+Options.LocalInstallDir;
-  if Options.LocalInstallDir<>'' then
-    OOptions:=OOptions+' --localunitdir='+Options.LocalInstallDir+
-        'units'+PathDelim+MakeTargetString(Options.CompilerCPU,Options.CompilerOS);
-  OOptions:=OOptions+' --globalunitdir='+Options.GlobalInstallDir+
-      'units'+PathDelim+MakeTargetString(Options.CompilerCPU,Options.CompilerOS);
+    OOptions:=OOptions+' --baseinstalldir='+CompilerOptions.LocalInstallDir;
+  if CompilerOptions.LocalInstallDir<>'' then
+    OOptions:=OOptions+' --localunitdir='+CompilerOptions.LocalUnitDir;
+  OOptions:=OOptions+' --globalunitdir='+CompilerOptions.GlobalUnitDir;
   { Run FPMake }
   FPMakeBin:='fpmake'+ExeExt;
   SetCurrentDir(PackageBuildPath);

+ 12 - 0
utils/fppkg/pkgglobals.pp

@@ -39,6 +39,7 @@ function maybequoted(const s:string):string;
 Function FixPath(const S : String) : string;
 Function DirectoryExistsLog(const ADir:string):Boolean;
 Function FileExistsLog(const AFileName:string):Boolean;
+procedure BackupFile(const AFileName: String);
 Procedure DeleteDir(const ADir:string);
 Procedure SearchFiles(SL:TStringList;const APattern:string);
 Function GetCompilerInfo(const ACompiler,AOptions:string):string;
@@ -203,6 +204,17 @@ begin
 end;
 
 
+procedure BackupFile(const AFileName: String);
+Var
+  BFN : String;
+begin
+  BFN:=AFileName+'.bak';
+  Log(vDebug,SDbgBackupFile,[BFN]);
+  If not RenameFile(AFileName,BFN) then
+    Error(SErrBackupFailed,[AFileName,BFN]);
+end;
+
+
 Procedure DeleteDir(const ADir:string);
 var
   Info : TSearchRec;

+ 3 - 3
utils/fppkg/pkghandler.pp

@@ -167,7 +167,7 @@ begin
   if CurrentPackage=nil then
     Result:='.'
   else
-    Result:=Options.BuildDir+CurrentPackage.Name;
+    Result:=GlobalOptions.BuildDir+CurrentPackage.Name;
 end;
 
 function TPackageHandler.PackageRemoteArchive: String;
@@ -177,14 +177,14 @@ begin
   if CurrentPackage.ExternalURL<>'' then
     Result:=CurrentPackage.ExternalURL
   else
-    Result:=Options.RemoteRepository+CurrentPackage.FileName;
+    Result:=GlobalOptions.RemoteRepository+CurrentPackage.FileName;
 end;
 
 function TPackageHandler.PackageLocalArchive: String;
 begin
   if not assigned(CurrentPackage) then
     Error(SErrNoPackageSpecified);
-  Result:=Options.PackagesDir+CurrentPackage.FileName;
+  Result:=GlobalOptions.PackagesDir+CurrentPackage.FileName;
 end;
 
 

+ 2 - 1
utils/fppkg/pkgmessages.pp

@@ -43,7 +43,6 @@ Resourcestring
   SErrCWDFailed              = 'FTP CWD "%s" command failed.';
   SErrGETFailed              = 'FTP GET "%s" command failed.';
 
-  SWarnFPMKUnitDirNotFound   = 'Unit directory for package "%s" is not found, compiling fpmake may file';
   SWarnFPMKUnitNotFound      = 'Package "fpmkunit" is not found, using internal bootstrap procedure';
 
   SLogGeneratingFPMake       = 'Generating fpmake.pp';
@@ -57,6 +56,7 @@ Resourcestring
   SLogZippping               = 'Zipping "%s"';
   SLogLoadingGlobalConfig    = 'Loading global configuration from "%s"';
   SLogLoadingCompilerConfig  = 'Loading compiler configuration from "%s"';
+  SLogLoadingFPMakeCompilerConfig = 'Loading compiler configuration for fpmake building from "%s"';
   SLogGeneratingGlobalConfig = 'Generating default global configuration in "%s"';
   SLogDetectedCompiler       = 'Detected compiler "%s" (version %s for %s)';
   SLogDetectedFPCDIR         = 'Detected %s FPCDIR "%s"';
@@ -69,6 +69,7 @@ Resourcestring
   SDbgNotFound               = 'Not Found';
   SDbgDirectoryExists        = 'Directory "%s" %s';
   SDbgFileExists             = 'File "%s" %s';
+  SDbgBackupFile             = 'Creating Backup File "%s"';
 
 
 implementation

+ 262 - 192
utils/fppkg/pkgoptions.pp

@@ -20,86 +20,102 @@ uses Classes, Sysutils, Inifiles, fprepos;
 
 Const
   DefaultManifestFile      = 'manifest.xml';
+  CurrentConfigVersion     = '0.1';
 
 Type
 
-  { TPackagerOptions }
+  { TGlobalOptions }
 
-  TPackagerOptions = Class(TPersistent)
+  TGlobalOptions = Class(TPersistent)
   private
-    FDirty: Boolean;
-    // Global options
-    FRemoteMirrorsLocation : String;
-    FLocalMirrorsLocation : String;
-    FRemoteRepository : String;
-    FLocalRepository : String;
+    FDirty : Boolean;
+    FConfigVersion,
+    FRemoteMirrorsLocation,
+    FLocalMirrorsLocation,
+    FRemoteRepository,
+    FLocalRepository,
     FCompilerConfigDir,
     FPackagesDir,
-    FBuildDir : String;
+    FBuildDir,
     FDefaultVerbosity,
-    FCurrentCompilerConfig,
-    FDefaultCompilerConfig : String;
-    // Compiler specific options
-    FCompiler : String;
-    FCompilerCPU: TCPU;
-    FCompilerOS: TOS;
-    FCompilerVersion : String;
-    FLocalInstallDir,
-    FGlobalInstallDir : String;
-    // Compiler settings for compiling FPMake.pp
-    FFPMakeCompiler,
-    FFPMakeLocalUnitDir,
-    FFPMakeGlobalUnitDir : String;
+    FDefaultCompilerConfig,
+    FFPMakeCompilerConfig : String;
     // Parameter options
-    FBootStrap : Boolean;
-    FInstallGlobal : Boolean;
-    function GetOptString(Index: integer): String;
+    FCompilerConfig : String;
+    FInstallGlobal  : Boolean;
+    function  GetOptString(Index: integer): String;
     procedure SetOptString(Index: integer; const AValue: String);
-    procedure SetCompilerCPU(const AValue: TCPU);
-    procedure SetCompilerOS(const AValue: TOS);
   Public
     Constructor Create;
     Procedure InitGlobalDefaults;
     Procedure LoadGlobalFromIni(Ini : TCustomIniFile); virtual;
     Procedure SaveGlobalToIni(Ini : TCustomIniFile); virtual;
-    Procedure LoadGlobalFromFile(FileName : String);
-    Procedure SaveGlobalToFile(FileName : String);
-    Procedure InitCompilerDefaults;
-    Procedure LoadCompilerFromIni(Ini : TCustomIniFile); virtual;
-    Procedure SaveCompilerToIni(Ini : TCustomIniFile); virtual;
-    Procedure LoadCompilerFromFile(FileName : String);
-    Procedure SaveCompilerToFile(FileName : String);
+    Procedure LoadGlobalFromFile(const AFileName : String);
+    Procedure SaveGlobalToFile(const AFileName : String);
     Property Dirty : Boolean Read FDirty;
+    Property ConfigVersion : String read FConfigVersion;
     function RemotePackagesFile:string;
     function LocalPackagesFile:string;
-    function LocalVersionsFile(CompilerConfig:String):string;
+    function LocalVersionsFile(const ACompilerConfig:String):string;
   Published
     Property RemoteMirrorsLocation : String Index 0 Read GetOptString Write SetOptString;
     Property LocalMirrorsLocation : String Index 1 Read GetOptString Write SetOptString;
     Property RemoteRepository : String Index 2 Read GetOptString Write SetOptString;
     Property LocalRepository : String Index 3 Read GetOptString Write SetOptString;
-    Property BuildDir : String Index 5 Read GetOptString Write SetOptString;
-    Property Compiler : String Index 6 Read GetOptString Write SetOptString;
-    Property CompilerTarget : String Index 7 Read GetOptString Write SetOptString;
+    Property BuildDir : String Index 4 Read GetOptString Write SetOptString;
+    Property PackagesDir : String Index 5 Read GetOptString Write SetOptString;
+    Property CompilerConfigDir : String Index 6 Read GetOptString Write SetOptString;
+    Property DefaultVerbosity : String Index 7 Read GetOptString Write SetOptString;
     Property DefaultCompilerConfig : String Index 8 Read GetOptString Write SetOptString;
-    Property CompilerVersion : String Index 9 Read GetOptString Write SetOptString;
-    Property GlobalInstallDir : String Index 10 Read GetOptString Write SetOptString;
-    Property LocalInstallDir : String Index 11 Read GetOptString Write SetOptString;
-    Property DefaultVerbosity : String Index 12 Read GetOptString Write SetOptString;
-    Property PackagesDir : String Index 13 Read GetOptString Write SetOptString;
-    Property CompilerConfigDir : String Index 14 Read GetOptString Write SetOptString;
-    Property FPMakeCompiler : String Index 15 Read GetOptString Write SetOptString;
-    Property FPMakeGlobalUnitDir : String Index 16 Read GetOptString Write SetOptString;
-    Property FPMakeLocalUnitDir : String Index 17 Read GetOptString Write SetOptString;
-    Property CurrentCompilerConfig : String Index 18 Read GetOptString Write SetOptString;
+    Property FPMakeCompilerConfig : String Index 9 Read GetOptString Write SetOptString;
+    // Parameters
+    Property CompilerConfig : String Read FCompilerConfig Write FCompilerConfig;
+    Property InstallGlobal : Boolean Read FInstallGlobal Write FInstallGlobal;
+  end;
+
+
+  { TCompilerOptions }
+
+  TCompilerOptions = Class(TPersistent)
+  private
+    FDirty: Boolean;
+    FConfigVersion,
+    FCompiler,
+    FCompilerVersion,
+    FLocalInstallDir,
+    FGlobalInstallDir : String;
+    FCompilerCPU: TCPU;
+    FCompilerOS: TOS;
+    function GetOptString(Index: integer): String;
+    procedure SetOptString(Index: integer; const AValue: String);
+    procedure SetCompilerCPU(const AValue: TCPU);
+    procedure SetCompilerOS(const AValue: TOS);
+  Public
+    Constructor Create;
+    Procedure InitCompilerDefaults;
+    Procedure LoadCompilerFromIni(Ini : TCustomIniFile); virtual;
+    Procedure SaveCompilerToIni(Ini : TCustomIniFile); virtual;
+    Procedure LoadCompilerFromFile(const AFileName : String);
+    Procedure SaveCompilerToFile(const AFileName : String);
+    Property Dirty : Boolean Read FDirty;
+    Property ConfigVersion : String read FConfigVersion;
+    Function LocalUnitDir:string;
+    Function GlobalUnitDir:string;
+  Published
+    Property Compiler : String Index 1 Read GetOptString Write SetOptString;
+    Property CompilerTarget : String Index 2 Read GetOptString Write SetOptString;
+    Property CompilerVersion : String Index 3 Read GetOptString Write SetOptString;
+    Property GlobalInstallDir : String Index 4 Read GetOptString Write SetOptString;
+    Property LocalInstallDir : String Index 5 Read GetOptString Write SetOptString;
     Property CompilerOS : TOS Read FCompilerOS Write SetCompilerOS;
     Property CompilerCPU : TCPU Read FCompilerCPU Write SetCompilerCPU;
-    Property BootStrap : Boolean Read FBootStrap Write FBootStrap;
-    Property InstallGlobal : Boolean Read FInstallGlobal Write FInstallGlobal;
   end;
 
 var
-  Options : TPackagerOptions;
+  GlobalOptions : TGlobalOptions;
+  CompilerOptions : TCompilerOptions;
+  FPMakeCompilerOptions : TCompilerOptions;
+
 
 Implementation
 
@@ -122,16 +138,21 @@ Const
   // ini file keys
   SDefaults = 'Defaults';
 
+  // All configs
+  KeyConfigVersion         = 'ConfigVersion';
+
   // Global config
   KeyLocalMirrorsLocation  = 'LocalMirrors';
   KeyRemoteMirrorsLocation = 'RemoteMirrors';
   KeyRemoteRepository      = 'RemoteRepository';
   KeyLocalRepository       = 'LocalRepository';
-  KeyCompilerConfigDir     = 'CompilerConfigDir';
   KeyPackagesDir           = 'PackagesDir';
   KeyBuildDir              = 'BuildDir';
-  KeyCompilerConfig        = 'CompilerConfig';
+  KeyCompilerConfigDir     = 'CompilerConfigDir';
   KeyVerbosity             = 'Verbosity';
+  KeyCompilerConfig        = 'CompilerConfig';
+  KeyFPMakeCompilerConfig  = 'FPMakeCompilerConfig';
+
   // Compiler dependent config
   KeyGlobalInstallDir      = 'GlobalInstallDir';
   KeyLocalInstallDir       = 'LocalInstallDir';
@@ -139,44 +160,37 @@ Const
   KeyCompilerOS            = 'OS';
   KeyCompilerCPU           = 'CPU';
   KeyCompilerVersion       = 'Version';
-  KeyFPMakeCompiler        = 'FPMakeCompiler';
-  KeyFPMakeGlobalUnitDir   = 'FPMakeGlobalUnitDir';
-  KeyFPMakeLocalUnitDir    = 'FPMakeLocalUnitDir';
 
 
-{ TPackagerOptions }
+{*****************************************************************************
+                           TGlobalOptions
+*****************************************************************************}
 
-constructor TPackagerOptions.Create;
+constructor TGlobalOptions.Create;
 begin
   InitGlobalDefaults;
 end;
 
 
-function TPackagerOptions.GetOptString(Index: integer): String;
+function TGlobalOptions.GetOptString(Index: integer): String;
 begin
   Case Index of
     0 : Result:=FRemoteMirrorsLocation;
     1 : Result:=FLocalMirrorsLocation;
     2 : Result:=FRemoteRepository;
     3 : Result:=FLocalRepository;
-    5 : Result:=FBuildDir;
-    6 : Result:=FCompiler;
-    7 : Result:=MakeTargetString(CompilerCPU,CompilerOS);
+    4 : Result:=FBuildDir;
+    5 : Result:=FPackagesDir;
+    6 : Result:=FCompilerConfigDir;
+    7 : Result:=FDefaultVerbosity;
     8 : Result:=FDefaultCompilerConfig;
-    9 : Result:=FCompilerVersion;
-   10 : Result:=FGlobalInstallDir;
-   11 : Result:=FLocalInstallDir;
-   12 : Result:=FDefaultVerbosity;
-   13 : Result:=FPackagesDir;
-   14 : Result:=FCompilerConfigDir;
-   15 : Result:=FFPMakeCompiler;
-   16 : Result:=FFPMakeGlobalUnitDir;
-   17 : Result:=FFPMakeLocalUnitDir;
-   18 : Result:=FCurrentCompilerConfig;
+    9 : Result:=FFPMakeCompilerConfig;
+    else
+      Error('Unknown option');
   end;
 end;
 
-procedure TPackagerOptions.SetOptString(Index: integer; const AValue: String);
+procedure TGlobalOptions.SetOptString(Index: integer; const AValue: String);
 begin
   If AValue=GetOptString(Index) then
     Exit;
@@ -185,64 +199,42 @@ begin
     1 : FRemoteMirrorsLocation:=AValue;
     2 : FRemoteRepository:=AValue;
     3 : FLocalRepository:=AValue;
-    5 : FBuildDir:=FixPath(AValue);
-    6 : FCompiler:=AValue;
-    7 : StringToCPUOS(AValue,FCompilerCPU,FCompilerOS);
+    4 : FBuildDir:=FixPath(AValue);
+    5 : FPackagesDir:=FixPath(AValue);
+    6 : FCompilerConfigDir:=FixPath(AValue);
+    7 : FDefaultVerbosity:=AValue;
     8 : FDefaultCompilerConfig:=AValue;
-    9 : FCompilerVersion:=AValue;
-   10 : FGlobalInstallDir:=FixPath(AValue);
-   11 : FLocalInstallDir:=FixPath(AValue);
-   12 : FDefaultVerbosity:=AValue;
-   13 : FPackagesDir:=FixPath(AValue);
-   14 : FCompilerConfigDir:=FixPath(AValue);
-   15 : FFPMakeCompiler:=AValue;
-   16 : FFPMakeGlobalUnitDir:=FixPath(AValue);
-   17 : FFPMakeLocalUnitDir:=FixPath(AValue);
-   18 : FCurrentCompilerConfig:=AValue;
+    9 : FFPMakeCompilerConfig:=AValue;
+    else
+      Error('Unknown option');
   end;
   FDirty:=True;
 end;
 
 
-procedure TPackagerOptions.SetCompilerCPU(const AValue: TCPU);
-begin
-  if FCompilerCPU=AValue then
-    exit;
-  FCompilerCPU:=AValue;
-  FDirty:=True;
-end;
-
-
-procedure TPackagerOptions.SetCompilerOS(const AValue: TOS);
-begin
-  if FCompilerOS=AValue then
-    exit;
-  FCompilerOS:=AValue;
-  FDirty:=True;
-end;
-
-
-function TPackagerOptions.RemotePackagesFile:string;
+function TGlobalOptions.RemotePackagesFile:string;
 begin
   Result:=FRemoteRepository+DefaultPackagesFile;
 end;
 
 
-function TPackagerOptions.LocalPackagesFile:string;
+function TGlobalOptions.LocalPackagesFile:string;
 begin
   Result:=FLocalRepository+DefaultPackagesFile;
 end;
 
 
-function TPackagerOptions.LocalVersionsFile(CompilerConfig:String):string;
+function TGlobalOptions.LocalVersionsFile(const ACompilerConfig:String):string;
 begin
-  Result:=FLocalRepository+Format(DefaultVersionsFile,[CompilerConfig]);
+  Result:=FLocalRepository+Format(DefaultVersionsFile,[ACompilerConfig]);
 end;
 
-Procedure TPackagerOptions.InitGlobalDefaults;
+
+Procedure TGlobalOptions.InitGlobalDefaults;
 var
   LocalDir : String;
 begin
+  FConfigVersion:=CurrentConfigVersion;
   // Retrieve Local fppkg directory
 {$ifdef unix}
   if IsSuperUser then
@@ -268,76 +260,22 @@ begin
   FRemoteMirrorsLocation:=DefaultMirrorsLocation;
   FRemoteRepository:=DefaultRemoteRepository;
   // Other config
-  FDefaultCompilerConfig:='default';
-  FCurrentCompilerConfig:=FDefaultCompilerConfig;
   FDefaultVerbosity:='error,warning,info,debug,commands';
-  FBootStrap:=False;
+  FDefaultCompilerConfig:='default';
+  FFPMakeCompilerConfig:='default';
+  // Parameter defaults
+  FCompilerConfig:=FDefaultCompilerConfig;
   FInstallGlobal:=False;
 end;
 
 
-Procedure TPackagerOptions.InitCompilerDefaults;
-var
-  infoSL : TStringList;
-  i : Integer;
-begin
-  FCompiler:=FileSearch('fpc'+ExeExt,GetEnvironmentVariable('PATH'));
-  if FCompiler='' then
-    Raise EPackagerError.Create(SErrMissingFPC);
-  // Detect compiler version/target from -i option
-  infosl:=TStringList.Create;
-  infosl.Delimiter:=' ';
-  infosl.DelimitedText:=GetCompilerInfo(FCompiler,'-iVTPTO');
-  if infosl.Count<>3 then
-    Raise EPackagerError.Create(SErrInvalidFPCInfo);
-  FCompilerVersion:=infosl[0];
-  FCompilerCPU:=StringToCPU(infosl[1]);
-  FCompilerOS:=StringToOS(infosl[2]);
-  Log(vDebug,SLogDetectedCompiler,[FCompiler,FCompilerVersion,MakeTargetString(FCompilerCPU,FCompilerOS)]);
-  // Use the same algorithm as the compiler, see options.pas
-{$ifdef Unix}
-  FGlobalInstallDir:=FixPath(GetEnvironmentVariable('FPCDIR'));
-  if FGlobalInstallDir='' then
-    begin
-      FGlobalInstallDir:='/usr/local/lib/fpc/'+FCompilerVersion+'/';
-      if not DirectoryExists(FGlobalInstallDir) and
-         DirectoryExists('/usr/lib/fpc/'+FCompilerVersion) then
-        FGlobalInstallDir:='/usr/lib/fpc/'+FCompilerVersion+'/';
-    end;
-{$else unix}
-  FGlobalInstallDir:=FixPath(GetEnvironmentVariable('FPCDIR'));
-  if FGlobalInstallDir='' then
-    begin
-      FGlobalInstallDir:=ExtractFilePath(FCompiler)+'../';
-      if not(DirectoryExists(FGlobalInstallDir+'/units')) and
-         not(DirectoryExists(FGlobalInstallDir+'/rtl')) then
-        FGlobalInstallDir:=FGlobalInstallDir+'../';
-    end;
-{$endif unix}
-  Log(vDebug,SLogDetectedFPCDIR,['global',FGlobalInstallDir]);
-  // User writable install directory
-  if not IsSuperUser then
-    begin
-      FLocalInstallDir:=FLocalRepository+'lib'+PathDelim+FCompilerVersion+PathDelim;
-      Log(vDebug,SLogDetectedFPCDIR,['local',FLocalInstallDir]);
-    end;
-  // Detect directory where fpmake units are located
-  FFPMakeCompiler:=FCompiler;
-  FFPMakeGlobalUnitDir:=FGlobalInstallDir+'units'+PathDelim+CompilerTarget+PathDelim;
-  FFPMakeLocalUnitDir:=FLocalInstallDir+'units'+PathDelim+CompilerTarget+PathDelim;
-  for i:=low(FPMKUnitDeps) to high(FPMKUnitDeps) do
-    begin
-      if not DirectoryExistsLog(FFPMakeGlobalUnitDir+FPMKUnitDeps[i]+PathDelim) and
-         not DirectoryExistsLog(FFPMakeLocalUnitDir+FPMKUnitDeps[i]+PathDelim) then
-        Log(vWarning,SWarnFPMKUnitDirNotFound,[FPMKUnitDeps[i]]);
-    end;
-end;
-
-
-procedure TPackagerOptions.LoadGlobalFromIni(Ini: TCustomIniFile);
+procedure TGlobalOptions.LoadGlobalFromIni(Ini: TCustomIniFile);
 begin
  With Ini do
    begin
+     FConfigVersion:=ReadString(SDefaults,KeyConfigVersion,'');
+     if FConfigVersion<>CurrentConfigVersion then
+       Error('Old configuration found, please delete manual');
      FLocalMirrorsLocation:=ReadString(SDefaults,KeyLocalMirrorsLocation,FLocalMirrorsLocation);
      FRemoteMirrorsLocation:=ReadString(SDefaults,KeyRemoteMirrorsLocation,FRemoteMirrorsLocation);
      FRemoteRepository:=ReadString(SDefaults,KeyRemoteRepository,FRemoteRepository);
@@ -345,16 +283,18 @@ begin
      FBuildDir:=FixPath(ReadString(SDefaults,KeyBuildDir,FBuildDir));
      FPackagesDir:=FixPath(ReadString(SDefaults,KeyPackagesDir,FPackagesDir));
      FCompilerConfigDir:=FixPath(ReadString(SDefaults,KeyCompilerConfigDir,FCompilerConfigDir));
-     FDefaultCompilerConfig:=ReadString(SDefaults,KeyCompilerConfig,FDefaultCompilerConfig);
      FDefaultVerbosity:=ReadString(SDefaults,KeyVerbosity,FDefaultVerbosity);
+     FDefaultCompilerConfig:=ReadString(SDefaults,KeyCompilerConfig,FDefaultCompilerConfig);
+     FFPMakeCompilerConfig:=ReadString(SDefaults,KeyFPMakeCompilerConfig,FFPMakeCompilerConfig);
    end;
 end;
 
 
-procedure TPackagerOptions.SaveGlobalToIni(Ini: TCustomIniFile);
+procedure TGlobalOptions.SaveGlobalToIni(Ini: TCustomIniFile);
 begin
  With Ini do
    begin
+     WriteString(SDefaults,KeyConfigVersion,FConfigVersion);
      WriteString(SDefaults,KeyBuildDir,FBuildDir);
      WriteString(SDefaults,KeyPackagesDir,FPackagesDir);
      WriteString(SDefaults,KeyCompilerConfigDir,FCompilerConfigDir);
@@ -362,17 +302,18 @@ begin
      WriteString(SDefaults,KeyLocalMirrorsLocation,FLocalMirrorsLocation);
      WriteString(SDefaults,KeyRemoteMirrorsLocation,FRemoteMirrorsLocation);
      WriteString(SDefaults,KeyRemoteRepository,FRemoteRepository);
-     WriteString(SDefaults,KeyCompilerConfig,FDefaultCompilerConfig);
      WriteString(SDefaults,KeyVerbosity,FDefaultVerbosity);
+     WriteString(SDefaults,KeyCompilerConfig,FDefaultCompilerConfig);
+     WriteString(SDefaults,KeyFPMakeCompilerConfig,FFPMakeCompilerConfig);
    end;
 end;
 
 
-procedure TPackagerOptions.LoadGlobalFromFile(FileName: String);
+procedure TGlobalOptions.LoadGlobalFromFile(const AFileName: String);
 Var
   Ini : TMemIniFile;
 begin
-  Ini:=TMemIniFile.Create(FileName);
+  Ini:=TMemIniFile.Create(AFileName);
   try
     LoadGlobalFromIni(Ini);
   finally
@@ -381,11 +322,13 @@ begin
 end;
 
 
-procedure TPackagerOptions.SaveGlobalToFile(FileName: String);
+procedure TGlobalOptions.SaveGlobalToFile(const AFileName: String);
 Var
   Ini : TIniFile;
 begin
-  Ini:=TIniFile.Create(FileName);
+  if FileExists(AFileName) then
+    BackupFile(AFileName);
+  Ini:=TIniFile.Create(AFileName);
   try
     SaveGlobalToIni(Ini);
     Ini.UpdateFile;
@@ -395,45 +338,166 @@ begin
 end;
 
 
-procedure TPackagerOptions.LoadCompilerFromIni(Ini: TCustomIniFile);
+{*****************************************************************************
+                           TCompilerOptions
+*****************************************************************************}
+
+constructor TCompilerOptions.Create;
+begin
+end;
+
+
+function TCompilerOptions.GetOptString(Index: integer): String;
+begin
+  Case Index of
+    1 : Result:=FCompiler;
+    2 : Result:=MakeTargetString(CompilerCPU,CompilerOS);
+    3 : Result:=FCompilerVersion;
+    4 : Result:=FGlobalInstallDir;
+    5 : Result:=FLocalInstallDir;
+    else
+      Error('Unknown option');
+  end;
+end;
+
+procedure TCompilerOptions.SetOptString(Index: integer; const AValue: String);
+begin
+  If AValue=GetOptString(Index) then
+    Exit;
+  Case Index of
+    1 : FCompiler:=AValue;
+    2 : StringToCPUOS(AValue,FCompilerCPU,FCompilerOS);
+    3 : FCompilerVersion:=AValue;
+    4 : FGlobalInstallDir:=FixPath(AValue);
+    5 : FLocalInstallDir:=FixPath(AValue);
+    else
+      Error('Unknown option');
+  end;
+  FDirty:=True;
+end;
+
+
+procedure TCompilerOptions.SetCompilerCPU(const AValue: TCPU);
+begin
+  if FCompilerCPU=AValue then
+    exit;
+  FCompilerCPU:=AValue;
+  FDirty:=True;
+end;
+
+
+procedure TCompilerOptions.SetCompilerOS(const AValue: TOS);
+begin
+  if FCompilerOS=AValue then
+    exit;
+  FCompilerOS:=AValue;
+  FDirty:=True;
+end;
+
+
+function TCompilerOptions.LocalUnitDir:string;
+begin
+  if FLocalInstallDir<>'' then
+    result:=FLocalInstallDir+'units'+PathDelim+CompilerTarget+PathDelim
+  else
+    result:='';
+end;
+
+
+function TCompilerOptions.GlobalUnitDir:string;
+begin
+  if FGlobalInstallDir<>'' then
+    result:=FGlobalInstallDir+'units'+PathDelim+CompilerTarget+PathDelim
+  else
+    result:='';
+end;
+
+
+procedure TCompilerOptions.InitCompilerDefaults;
+var
+  infoSL : TStringList;
+begin
+  FConfigVersion:=CurrentConfigVersion;
+  FCompiler:=FileSearch('fpc'+ExeExt,GetEnvironmentVariable('PATH'));
+  if FCompiler='' then
+    Raise EPackagerError.Create(SErrMissingFPC);
+  // Detect compiler version/target from -i option
+  infosl:=TStringList.Create;
+  infosl.Delimiter:=' ';
+  infosl.DelimitedText:=GetCompilerInfo(FCompiler,'-iVTPTO');
+  if infosl.Count<>3 then
+    Raise EPackagerError.Create(SErrInvalidFPCInfo);
+  FCompilerVersion:=infosl[0];
+  FCompilerCPU:=StringToCPU(infosl[1]);
+  FCompilerOS:=StringToOS(infosl[2]);
+  Log(vDebug,SLogDetectedCompiler,[FCompiler,FCompilerVersion,MakeTargetString(FCompilerCPU,FCompilerOS)]);
+  // Use the same algorithm as the compiler, see options.pas
+{$ifdef Unix}
+  FGlobalInstallDir:=FixPath(GetEnvironmentVariable('FPCDIR'));
+  if FGlobalInstallDir='' then
+    begin
+      FGlobalInstallDir:='/usr/local/lib/fpc/'+FCompilerVersion+'/';
+      if not DirectoryExists(FGlobalInstallDir) and
+         DirectoryExists('/usr/lib/fpc/'+FCompilerVersion) then
+        FGlobalInstallDir:='/usr/lib/fpc/'+FCompilerVersion+'/';
+    end;
+{$else unix}
+  FGlobalInstallDir:=FixPath(GetEnvironmentVariable('FPCDIR'));
+  if FGlobalInstallDir='' then
+    begin
+      FGlobalInstallDir:=ExtractFilePath(FCompiler)+'../';
+      if not(DirectoryExists(FGlobalInstallDir+'/units')) and
+         not(DirectoryExists(FGlobalInstallDir+'/rtl')) then
+        FGlobalInstallDir:=FGlobalInstallDir+'../';
+    end;
+{$endif unix}
+  Log(vDebug,SLogDetectedFPCDIR,['global',FGlobalInstallDir]);
+  // User writable install directory
+  if not IsSuperUser then
+    begin
+      FLocalInstallDir:=GlobalOptions.LocalRepository+'lib'+PathDelim+FCompilerVersion+PathDelim;
+      Log(vDebug,SLogDetectedFPCDIR,['local',FLocalInstallDir]);
+    end;
+ end;
+
+
+procedure TCompilerOptions.LoadCompilerFromIni(Ini: TCustomIniFile);
 begin
  With Ini do
    begin
+     FConfigVersion:=ReadString(SDefaults,KeyConfigVersion,'');
+     if FConfigVersion<>CurrentConfigVersion then
+       Error('Old configuration found, please delete manual');
      FGlobalInstallDir:=FixPath(ReadString(SDefaults,KeyGlobalInstallDir,FGlobalInstallDir));
      FLocalInstallDir:=FixPath(ReadString(SDefaults,KeyLocalInstallDir,FLocalInstallDir));
      FCompiler:=ReadString(SDefaults,KeyCompiler,FCompiler);
      FCompilerOS:=StringToOS(ReadString(SDefaults,KeyCompilerOS,OSToString(CompilerOS)));
      FCompilerCPU:=StringToCPU(ReadString(SDefaults,KeyCompilerCPU,CPUtoString(CompilerCPU)));
      FCompilerVersion:=ReadString(SDefaults,KeyCompilerVersion,FCompilerVersion);
-     FFPMakeCompiler:=ReadString(SDefaults,KeyFPMakeCompiler,FFPMakeCompiler);
-     FFPMakeGlobalUnitDir:=FixPath(ReadString(SDefaults,KeyFPMakeGlobalUnitDir,FFPMakeGlobalUnitDir));
-     FFPMakeLocalUnitDir:=FixPath(ReadString(SDefaults,KeyFPMakeLocalUnitDir,FFPMakeLocalUnitDir));
    end;
 end;
 
 
-procedure TPackagerOptions.SaveCompilerToIni(Ini: TCustomIniFile);
+procedure TCompilerOptions.SaveCompilerToIni(Ini: TCustomIniFile);
 begin
  With Ini do
    begin
+     WriteString(SDefaults,KeyConfigVersion,FConfigVersion);
      WriteString(SDefaults,KeyGlobalInstallDir,FGlobalInstallDir);
      WriteString(SDefaults,KeyLocalInstallDir,FLocalInstallDir);
      WriteString(SDefaults,KeyCompiler,FCompiler);
      WriteString(SDefaults,KeyCompilerOS,OSToString(CompilerOS));
      WriteString(SDefaults,KeyCompilerCPU,CPUtoString(CompilerCPU));
      WriteString(SDefaults,KeyCompilerVersion,FCompilerVersion);
-     WriteString(SDefaults,KeyFPMakeCompiler,FFPMakeCompiler);
-     WriteString(SDefaults,KeyFPMakeGlobalUnitDir,FFPMakeGlobalUnitDir);
-     WriteString(SDefaults,KeyFPMakeLocalUnitDir,FFPMakeLocalUnitDir);
    end;
 end;
 
 
-procedure TPackagerOptions.LoadCompilerFromFile(FileName: String);
+procedure TCompilerOptions.LoadCompilerFromFile(const AFileName: String);
 Var
   Ini : TMemIniFile;
 begin
-  Ini:=TMemIniFile.Create(FileName);
+  Ini:=TMemIniFile.Create(AFileName);
   try
     LoadCompilerFromIni(Ini);
   finally
@@ -442,11 +506,13 @@ begin
 end;
 
 
-procedure TPackagerOptions.SaveCompilerToFile(FileName: String);
+procedure TCompilerOptions.SaveCompilerToFile(const AFileName: String);
 Var
   Ini : TIniFile;
 begin
-  Ini:=TIniFile.Create(FileName);
+  if FileExists(AFileName) then
+    BackupFile(AFileName);
+  Ini:=TIniFile.Create(AFileName);
   try
     SaveCompilerToIni(Ini);
     Ini.UpdateFile;
@@ -457,7 +523,11 @@ end;
 
 
 initialization
-  Options:=TPackagerOptions.Create;
+  GlobalOptions:=TGlobalOptions.Create;
+  CompilerOptions:=TCompilerOptions.Create;
+  FPMakeCompilerOptions:=TCompilerOptions.Create;
 finalization
-  FreeAndNil(Options);
+  FreeAndNil(GlobalOptions);
+  FreeAndNil(CompilerOptions);
+  FreeAndNil(FPMakeCompilerOptions);
 end.

+ 7 - 6
utils/fppkg/pkgrepos.pp

@@ -43,14 +43,15 @@ begin
     CurrentRepository.Free;
   CurrentRepository:=TFPRepository.Create(Nil);
   // Repository
-  Log(vDebug,SLogLoadingPackagesFile,[Options.LocalPackagesFile]);
-  if not FileExists(Options.LocalPackagesFile) then
+  S:=GlobalOptions.LocalPackagesFile;
+  Log(vDebug,SLogLoadingPackagesFile,[S]);
+  if not FileExists(S) then
     exit;
   try
     X:=TFPXMLRepositoryHandler.Create;
     With X do
       try
-        LoadFromXml(CurrentRepository,Options.LocalPackagesFile);
+        LoadFromXml(CurrentRepository,S);
       finally
         Free;
       end;
@@ -58,7 +59,7 @@ begin
     on E : Exception do
       begin
         Log(vError,E.Message);
-        Error(SErrCorruptPackagesFile,[Options.LocalPackagesFile]);
+        Error(SErrCorruptPackagesFile,[S]);
       end;
   end;
 end;
@@ -68,7 +69,7 @@ procedure LoadLocalStatus;
 var
   S : String;
 begin
-  S:=Options.LocalVersionsFile(Options.CurrentCompilerConfig);
+  S:=GlobalOptions.LocalVersionsFile(GlobalOptions.CompilerConfig);
   Log(vDebug,SLogLoadingStatusFile,[S]);
   if FileExists(S) then
     CurrentRepository.LoadStatusFromFile(S);
@@ -79,7 +80,7 @@ procedure SaveLocalStatus;
 var
   S : String;
 begin
-  S:=Options.LocalVersionsFile(Options.CurrentCompilerConfig);
+  S:=GlobalOptions.LocalVersionsFile(GlobalOptions.CompilerConfig);
   Log(vDebug,SLogSavingStatusFile,[S]);
   CurrentRepository.SaveStatusToFile(S);
 end;