fpc/compiler/fpkg.pas
svenbarth f8e9b33f99 Merge first batch of package handling related revisions from the packages branch
Merged revision(s) 28796, 28837-28845, 28847-28850, 28852, 32135 from branches/svenbarth/packages:
Provide possibility to pass packages and search paths for packages as parameters.

fpkg.pas:
  + new unit which contains the base types related to package files (most importantly "tpackage")
globals.pas:
  + new variable "packagesearchpath" which contains all paths in which package files should be looked for
  + new variable "packagelist" which contains a list of all packages that should be used in a program or library
  * InitGlobals & DoneGlobals: initialize/finalize "packagesearchpath" accordingly ("packagelist" is handled in unit fpkg using a init/done-callback)
options.pas:
  + TOption: new fields "parapackagepath" and "parapackages" to keep track of package search paths and package files passed as parameters
  * TOption.interpret_option: use '-Fp' for package search paths and '-FP' for package files
  * read_arguments: apply the passed package search paths and packages to their respective containers
........
+ add a new unit which will contain basic functions related to handling packages
........
Move package related functions from pmodules to pkgutil.

pmodules.pas => pkgutil.pas:
  * createimportlibfromexports
  * varexport
  * procexport
  * insert_export
  * RewritePPU
........
* adjust indentation
........
Extract the code to export the symbols of a unit to its own function in pkgutil so that less functions need to be exported.

pmodules.pas, proc_package:
  * move code to export the symbols of a unit to new function export_unit
pkgutil.pas:
  + new function export_unit
  - remove exports of procexport, varexport and insert_export
........
Some small fixes for package parsing.

pmodules.pas, proc_package:
  * use orgpattern instead of pattern to build the module name (like is done in uses sections)
  * ignore duplicates when generating exports
  - no need to generate an import library for the package; that is done by the program/library that uses the package
........
+ new unit fpcp of which the class tpcppackage handles the reading and writing of package metadata from/to pcp files (equivalant to tppumodule).
........
+ add unit which contains representation of a PCP file (tpcpfile) like tppufile is for units.
........
Improve export generation.

pkgutil.pas:
  + new function exportprocsym to correctly export a procedure with all its aliases
  + new function exportabstractrecordsymproc to export the members of structured types 
  * insert_export: handle also namespacesym and propertsym (by ignoring them)
  * insert_export: correctly export classes, record and objects
  * insert_export: use new exportprocsym function to export a procsym
  * insert_export: only export public variables of a static symtable


........
+ add entry constants for the name of the package and the package file names, both used by a PCP file
........
* use messages to get rid of most writelns related to package loading
........
Add additional entry types for PCP files

entfile.pas:
  + new entries ibstartrequireds and ibendrequireds to store the list of required packages
  + new entries ibstartcontained and ibendcontained to store the list of contained units
  + new entries ibstartppus and ibendppus to store the list of contained PPU files
........
Generate the PCP file once the package file and the used units were compiled correctly.

pmodules.pas:
  * proc_package: generate the PCP file upon successful compilation
........
Add the possibility to load all packages supplied as parameters.

pkgutil.pas:
  + new function load_packages to load all packages supplied as parameters
pmodules.pas, proc_program:
  * use load_packages to load all packages before any unit is loaded
........
Add code which tries to load a unit from a package first and only then as usual.

fppu.pas, tppumodule:
  + new method loadfrompackage which searches all available packages for the unit and loads it from there if found
  * loadppu: first try to load the unit from a package if any are available
........
Don't link objects files of a unit that is provided by a package.

pmodules.pas, proc_program:
  * if a unit has uf_in_library set we must not include it in the units we link against
........

git-svn-id: trunk@33452 -
2016-04-08 15:40:27 +00:00

132 lines
3.1 KiB
ObjectPascal

{
Copyright (c) 2013-2016 by Free Pascal Development Team
This unit implements basic parts of the package system
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
unit fpkg;
{$i fpcdefs.inc}
interface
uses
cclasses,
globtype,
finput;
type
tcontainedunit=record
module:tmodulebase;
ppufile:tpathstr;
end;
pcontainedunit=^tcontainedunit;
tpackage=class
public
realpackagename,
packagename : pshortstring;
containedmodules : TFPHashList;
requiredpackages : TFPHashObjectList;
pcpfilename,
ppafilename,
pplfilename : tpathstr;
constructor create(const pn:string);
destructor destroy;override;
end;
tpackageentry=record
package : tpackage;
realpkgname : string;
end;
ppackageentry=^tpackageentry;
procedure addpackage(list:tfphashlist;const pn:string);
implementation
uses
cutils,globals;
procedure addpackage(list: tfphashlist;const pn:string);
var
pkgentry : ppackageentry;
begin
new(pkgentry);
pkgentry^.realpkgname:=pn;
pkgentry^.package:=nil;
list.add(upper(pn),pkgentry);
end;
{ tpackage }
constructor tpackage.create(const pn: string);
begin
realpackagename:=stringdup(pn);
packagename:=stringdup(upper(pn));
containedmodules:=TFPHashList.Create;
requiredpackages:=TFPHashObjectList.Create(false);
end;
destructor tpackage.destroy;
var
p : pcontainedunit;
i : longint;
begin
if assigned(containedmodules) then
for i:=0 to containedmodules.count-1 do
begin
p:=pcontainedunit(containedmodules[i]);
dispose(p);
end;
containedmodules.free;
requiredpackages.free;
inherited destroy;
end;
procedure packageinit;
begin
packagelist:=TFPHashList.Create;
end;
procedure packagedone;
var
i : longint;
pkgentry : ppackageentry;
begin
if assigned(packagelist) then
begin
for i:=0 to packagelist.count-1 do
begin
pkgentry:=ppackageentry(packagelist[i]);
pkgentry^.package.free;
dispose(pkgentry);
end;
end;
packagelist.Free;
packagelist:=nil;
end;
initialization
register_initdone_proc(@packageinit,@packagedone);
end.