فهرست منبع

Merged revision(s) 28904-28905, 29038-29044 from branches/svenbarth/packages:
Don't try to export generic symbols.

pkgutil.pas:
* exportabstractrecordsymproc: do not export generic type symbols or their nested symbols
........
Ensure that the correct name is used for the PCP file.

proc_package:
* use current_module.modulename instead of module_name for the base filename of the PCP file
........
Add a possibility to track if a unit was loaded from a package.

fmodule.pas, tmodule:
+ new field "package" which is Nil if the unit is not (yet) part of a package or a reference to the package this unit was loaded from
fppu.pas, tppumodule:
* loadfrompackage: set the "package" field of the module to the package it's loaded from.

........
Ensure that units loaded from a package are not recompiled if the source files should happen to be available.

fppu.pas, tppumodule:
loadppu: set the state to ms_compiled instead of ms_load if the unit was loaded from a package (additionally close the PPU file as it's no longer needed)

........
Add support for reading/writing required packages from/to the PCP file

fpcp.pas, tpcppackage:
+ new methods writerequiredpackages and readrequiredpackages
* loadpcp: use readrequiredpackages
* savepcp: use writerequiredpackages
pcp.pas:
* increase PCP version

........
When compiling a package, handle only those units that are not yet part of a package.

pmodules.pas, proc_package:
* only export units that are part of the package
* only add units to the package if they are really part of the package
* don't rewrite the PPU if the unit is not part of the package
* don't link the unit's files if it is not part of the package

........
Add support for parsing required packages.

pkgutil.pas:
+ new function add_package to add a package to the list of available packages with the possibility to check for duplicates
* load_packages: also load all required packages
pmodules.pas, proc_package:
* create the tpcppackage instance earlier (and use the module name as read from the source file as package name)
* clear the list of packages in case the user passed any using -FPxxx
* parse the "requires" section like a list of units and add each full identifier as a package to load
* before parsing the "contains" section load all packages, so that all units can be correctly resolved

........
Correctly create import libraries for packages as well.

pkgutil.pas, createimportlibfromexternals:
* instead of processing units without the uf_in_library flag, only process those that don't have a package reference set (thus becoming part of the program/library or the package)
- remove unneeded "pkg" parameter
pmodules.pas:
+ proc_package: create the import library if the package requires other packages
* proc_program: adjust call to createimportlibfromexternals

........
Ensure that the reference to the System unit is correctly set up for packages. Among other things this is needed to compile a package with the -gl option (though debug information doesn't work yet).

pmodules.pas:
* convert AddUnit to a function and let it return the newly loaded module
* proc_package: when parsing the contained units ensure that we correctly set up the System unit reference if we are to contain the System unit
* proc_package: also set up the System unit reference once all units are loaded and this hasn't happened yet (because all contained units are already compiled)

........

git-svn-id: trunk@33502 -

svenbarth 9 سال پیش
والد
کامیت
f55123ce92
6فایلهای تغییر یافته به همراه155 افزوده شده و 37 حذف شده
  1. 2 1
      compiler/fmodule.pas
  2. 41 2
      compiler/fpcp.pas
  3. 9 1
      compiler/fppu.pas
  4. 1 1
      compiler/pcp.pas
  5. 38 20
      compiler/pkgutil.pas
  6. 64 12
      compiler/pmodules.pas

+ 2 - 1
compiler/fmodule.pas

@@ -43,7 +43,7 @@ interface
 
     uses
        cutils,cclasses,cfileutl,
-       globtype,finput,ogbase,
+       globtype,finput,ogbase,fpkg,
        symbase,symconst,symsym,
        wpobase,
        aasmbase,aasmtai,aasmdata;
@@ -172,6 +172,7 @@ interface
         linkotherstaticlibs,
         linkotherframeworks  : tlinkcontainer;
         mainname      : pshortstring; { alternate name for "main" procedure }
+        package       : tpackage;
 
         used_units           : tlinkedlist;
         dependent_units      : tlinkedlist;

+ 41 - 2
compiler/fpcp.pas

@@ -42,8 +42,10 @@ interface
       procedure setfilename(const fn:string;allowoutput:boolean);
       procedure writecontainernames;
       procedure writecontainedunits;
+      procedure writerequiredpackages;
       procedure readcontainernames;
       procedure readcontainedunits;
+      procedure readrequiredpackages;
     public
       constructor create(const pn:string);
       destructor destroy; override;
@@ -250,6 +252,19 @@ implementation
       pcpfile.writeentry(ibendcontained);
     end;
 
+  procedure tpcppackage.writerequiredpackages;
+    var
+      i : longint;
+    begin
+      pcpfile.putlongint(requiredpackages.count);
+      pcpfile.writeentry(ibstartrequireds);
+      for i:=0 to requiredpackages.count-1 do
+        begin
+          pcpfile.putstring(requiredpackages.NameOfIndex(i));
+        end;
+      pcpfile.writeentry(ibendrequireds);
+    end;
+
   procedure tpcppackage.readcontainernames;
     begin
       if pcpfile.readentry<>ibpackagefiles then
@@ -291,6 +306,30 @@ implementation
         end;
     end;
 
+  procedure tpcppackage.readrequiredpackages;
+    var
+      cnt,i : longint;
+      name : string;
+    begin
+      if pcpfile.readentry<>ibstartrequireds then
+        begin
+          Writeln('Error reading pcp file');
+          internalerror(2014110901);
+        end;
+      cnt:=pcpfile.getlongint;
+      if pcpfile.readentry<>ibendrequireds then
+        begin
+          Writeln('Error reading pcp file');
+          internalerror(2014110902);
+        end;
+      for i:=0 to cnt-1 do
+        begin
+          name:=pcpfile.getstring;
+          requiredpackages.add(name,nil);
+          Writeln('Found required package ',name);
+        end;
+    end;
+
     constructor tpcppackage.create(const pn: string);
     begin
       inherited create(pn);
@@ -329,7 +368,7 @@ implementation
 
       readcontainernames;
 
-      //readrequiredpackages
+      readrequiredpackages;
 
       readcontainedunits;
     end;
@@ -346,7 +385,7 @@ implementation
 
       writecontainernames;
 
-      //writerequiredpackages;
+      writerequiredpackages;
 
       writecontainedunits;
 

+ 9 - 1
compiler/fppu.pas

@@ -583,6 +583,7 @@ var
                 filename:=pkgunit^.ppufile;
                 if not SearchPathList(unitsearchpath) then
                   exit;
+                package:=pkg^.package;
 
                 { now load the unit and all used units }
                 load_interface;
@@ -1775,7 +1776,14 @@ var
           begin
             do_load:=false;
             do_reload:=false;
-            state:=ms_load;
+            state:=ms_compiled;
+            { PPU is not needed anymore }
+            if assigned(ppufile) then
+             begin
+                ppufile.closefile;
+                ppufile.free;
+                ppufile:=nil;
+             end;
             { add the unit to the used units list of the program }
             usedunits.concat(tused_unit.create(self,true,false,nil));
           end;

+ 1 - 1
compiler/pcp.pas

@@ -29,7 +29,7 @@ interface
     cstreams,entfile;
 
   const
-    CurrentPCPVersion=1;
+    CurrentPCPVersion=2;
 
   { unit flags }
     //uf_init                = $000001; { unit has initialization section }

+ 38 - 20
compiler/pkgutil.pas

@@ -29,10 +29,11 @@ interface
   uses
     fmodule,fpkg;
 
-  procedure createimportlibfromexternals(pkg:tpackage);
+  procedure createimportlibfromexternals;
   Function RewritePPU(const PPUFn,PPLFn:String):Boolean;
   procedure export_unit(u:tmodule);
   procedure load_packages;
+  procedure add_package(const name:string;ignoreduplicates:boolean);
 
 implementation
 
@@ -98,6 +99,9 @@ implementation
               recorddef:
                 begin
                   def:=tabstractrecorddef(ttypesym(sym).typedef);
+                  { don't export generics or their nested types }
+                  if df_generic in def.defoptions then
+                    exit;
                   def.symtable.symlist.foreachcall(@exportabstractrecordsymproc,def.symtable);
                 end;
             end;
@@ -406,7 +410,28 @@ implementation
     end;
 
 
-  procedure createimportlibfromexternals(pkg:tpackage);
+  procedure add_package(const name:string;ignoreduplicates:boolean);
+    var
+      entry : ppackageentry;
+      i : longint;
+    begin
+      for i:=0 to packagelist.count-1 do
+        begin
+          if packagelist.nameofindex(i)=name then
+            begin
+              if not ignoreduplicates then
+                Message1(package_e_duplicate_package,name);
+              exit;
+            end;
+        end;
+      new(entry);
+      entry^.package:=nil;
+      entry^.realpkgname:=name;
+      packagelist.add(name,entry);
+    end;
+
+
+  procedure createimportlibfromexternals;
     var
       alreadyloaded : tfpobjectlist;
 
@@ -499,26 +524,19 @@ implementation
       { check each external asm symbol of each unit of the package whether it is
         contained in the unit of a loaded package (and thus an import entry
         is needed) }
-      if assigned(pkg) then
-        begin
-          { ToDo }
-        end
-      else
-        begin
-          alreadyloaded:=tfpobjectlist.create(false);
-          { we were called from a program/library }
+      alreadyloaded:=tfpobjectlist.create(false);
 
-          module:=tmodule(loaded_units.first);
-          while assigned(module) do
-            begin
-              //if not assigned(module.package) then
-              if (uf_in_library and module.flags)=0 then
-                processimportedsyms(module.unitimportsyms);
-              module:=tmodule(module.next);
-            end;
-
-          alreadyloaded.free;
+      { first pass to find all symbols that were not loaded by asm name }
+      module:=tmodule(loaded_units.first);
+      while assigned(module) do
+        begin
+          //if not assigned(module.package) then
+          if (uf_in_library and module.flags)=0 then
+            processimportedsyms(module.unitimportsyms);
+          module:=tmodule(module.next);
         end;
+
+      alreadyloaded.free;
     end;
 
 

+ 64 - 12
compiler/pmodules.pas

@@ -35,13 +35,13 @@ implementation
        SysUtils,
        globtype,version,systems,tokens,
        cutils,cfileutl,cclasses,comphook,
-       globals,verbose,fmodule,finput,fppu,globstat,
+       globals,verbose,fmodule,finput,fppu,globstat,fpcp,fpkg,
        symconst,symbase,symtype,symdef,symsym,symtable,symcreat,
        wpoinfo,
        aasmtai,aasmdata,aasmcpu,aasmbase,
        cgbase,cgobj,ngenutil,
        nbas,nutils,ncgutil,
-       link,assemble,import,export,gendef,entfile,ppu,comprsrc,dbgbase,fpcp,
+       link,assemble,import,export,gendef,entfile,ppu,comprsrc,dbgbase,
        cresstr,procinfo,
        pexports,
        objcgutl,
@@ -1437,6 +1437,7 @@ type
          current_module.setmodulename(module_name);
          current_module.ispackage:=true;
          exportlib.preparelib(module_name);
+         pkg:=tpcppackage.create(module_name);
 
          if tf_library_needs_pic in target_info.flags then
            include(current_settings.moduleswitches,cs_create_pic);
@@ -1459,11 +1460,42 @@ type
          { of the program                                             }
          current_module.localsymtable:=tstaticsymtable.create(current_module.modulename^,current_module.moduleid);
 
-         {Load the units used by the program we compile.}
-         if token=_REQUIRES then
+         { ensure that no packages are picked up from the options }
+         packagelist.clear;
+
+         {Read the packages used by the package we compile.}
+         if (token=_ID) and (idtoken=_REQUIRES) then
            begin
+             { consume _REQUIRES word }
+             consume(_ID);
+             while true do
+               begin
+                 if token=_ID then
+                   begin
+                     module_name:=orgpattern;
+                     consume(_ID);
+                     while token=_POINT do
+                       begin
+                         consume(_POINT);
+                         module_name:=module_name+'.'+orgpattern;
+                         consume(_ID);
+                       end;
+                     add_package(module_name,false);
+                   end
+                 else
+                   consume(_ID);
+                 if token=_COMMA then
+                   consume(_COMMA)
+                 else
+                   break;
+               end;
+             consume(_SEMICOLON);
            end;
 
+         { now load all packages, so that we can determine whether a unit is
+           already provided by one of the loaded packages }
+         load_packages;
+
          {Load the units used by the program we compile.}
          if (token=_ID) and (idtoken=_CONTAINS) then
            begin
@@ -1481,7 +1513,12 @@ type
                          module_name:=module_name+'.'+orgpattern;
                          consume(_ID);
                        end;
-                     AddUnit(module_name);
+                     hp:=AddUnit(module_name);
+                     if (hp.modulename^='SYSTEM') and not assigned(systemunit) then
+                       begin
+                         systemunit:=tglobalsymtable(hp.globalsymtable);
+                         load_intern_types;
+                       end;
                    end
                  else
                    consume(_ID);
@@ -1552,6 +1589,7 @@ type
            begin
              Message1(unit_f_errors_in_unit,tostr(Errorcount));
              status.skip_error:=true;
+             pkg.free;
              exit;
            end;
 
@@ -1573,7 +1611,13 @@ type
          uu:=tused_unit(usedunits.first);
          while assigned(uu) do
            begin
-             export_unit(uu.u);
+             if not assigned(systemunit) and (uu.u.modulename^='SYSTEM') then
+               begin
+                 systemunit:=tglobalsymtable(uu.u.globalsymtable);
+                 load_intern_types;
+               end;
+             if not assigned(uu.u.package) then
+               export_unit(uu.u);
 
              uu:=tused_unit(uu.next);
            end;
@@ -1593,6 +1637,10 @@ type
 
          exportlib.ignoreduplicates:=false;
 
+         { create import libraries for all packages }
+         if packagelist.count>0 then
+           createimportlibfromexternals;
+
          { generate imports }
          if current_module.ImportLibraryList.Count>0 then
            importlib.generatelib;
@@ -1620,6 +1668,7 @@ type
           begin
             Message1(unit_f_errors_in_unit,tostr(Errorcount));
             status.skip_error:=true;
+            pkg.free;
             exit;
           end;
 
@@ -1627,11 +1676,11 @@ type
            begin
              { add all contained units to the package }
              { TODO : handle implicitly imported units }
-             pkg:=tpcppackage.create(module_name);
              uu:=tused_unit(current_module.used_units.first);
              while assigned(uu) do
                begin
-                 pkg.addunit(uu.u);
+                 if not assigned(uu.u.package) then
+                   pkg.addunit(uu.u);
                  uu:=tused_unit(uu.next);
                end;
 
@@ -1641,7 +1690,8 @@ type
              uu:=tused_unit(usedunits.first);
              while assigned(uu) do
                begin
-                 RewritePPU(uu.u.ppufilename,uu.u.ppufilename);
+                 if not assigned(uu.u.package) then
+                   RewritePPU(uu.u.ppufilename,uu.u.ppufilename);
                  uu:=tused_unit(uu.next);
                end;
 
@@ -1663,8 +1713,10 @@ type
                  hp:=tmodule(loaded_units.first);
                  while assigned(hp) do
                   begin
-                    { the package itself contains no code so far }
-                    linker.AddModuleFiles(hp);
+                    { only link in those units which should become part of this
+                      package }
+                    if not assigned(hp.package) then
+                      linker.AddModuleFiles(hp);
                     hp2:=tmodule(hp.next);
                     if (hp<>current_module) and
                        (not needsymbolinfo) then
@@ -2124,7 +2176,7 @@ type
 
          { create import library for all packages }
          if packagelist.count>0 then
-           createimportlibfromexternals(nil);
+           createimportlibfromexternals;
 
          { generate imports }
          if current_module.ImportLibraryList.Count>0 then