mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-05 01:29:30 +01:00
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 -
189 lines
5.8 KiB
ObjectPascal
189 lines
5.8 KiB
ObjectPascal
{
|
|
Copyright (c) 2013-2016 by Free Pascal development team
|
|
|
|
Routines to read/write pcp files
|
|
|
|
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 pcp;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
cstreams,entfile;
|
|
|
|
const
|
|
CurrentPCPVersion=2;
|
|
|
|
{ unit flags }
|
|
//uf_init = $000001; { unit has initialization section }
|
|
//uf_finalize = $000002; { unit has finalization section }
|
|
pf_big_endian = $000004;
|
|
//uf_has_browser = $000010;
|
|
//uf_in_library = $000020; { is the file in another file than <ppufile>.* ? }
|
|
//uf_smart_linked = $000040; { the ppu can be smartlinked }
|
|
//uf_static_linked = $000080; { the ppu can be linked static }
|
|
//uf_shared_linked = $000100; { the ppu can be linked shared }
|
|
//uf_local_browser = $000200;
|
|
//uf_no_link = $000400; { unit has no .o generated, but can still have external linking! }
|
|
//uf_has_resourcestrings = $000800; { unit has resource string section }
|
|
pf_little_endian = $001000;
|
|
|
|
|
|
type
|
|
tpcpheader=record
|
|
common : tentryheader;
|
|
checksum : cardinal; { checksum for this pcpfile }
|
|
requiredlistsize, { number of entries for required packages }
|
|
ppulistsize : longint; { number of entries for contained PPUs }
|
|
end;
|
|
|
|
tpcpfile=class(tentryfile)
|
|
public
|
|
header : tpcpheader;
|
|
{ crc for the entire package }
|
|
crc : cardinal;
|
|
protected
|
|
function getheadersize:longint;override;
|
|
function getheaderaddr:pentryheader;override;
|
|
procedure newheader;override;
|
|
function readheader:longint;override;
|
|
procedure resetfile;override;
|
|
public
|
|
procedure writeheader;override;
|
|
function checkpcpid:boolean;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ tpcpfile }
|
|
|
|
function tpcpfile.getheadersize: longint;
|
|
begin
|
|
result:=sizeof(tpcpheader);
|
|
end;
|
|
|
|
function tpcpfile.getheaderaddr: pentryheader;
|
|
begin
|
|
result:=@header;
|
|
end;
|
|
|
|
procedure tpcpfile.newheader;
|
|
var
|
|
s : string;
|
|
begin
|
|
fillchar(header,sizeof(tpcpheader),0);
|
|
str(CurrentPCPVersion,s);
|
|
while length(s)<3 do
|
|
s:='0'+s;
|
|
with header.common do
|
|
begin
|
|
id[1]:='P';
|
|
id[2]:='C';
|
|
id[3]:='P';
|
|
ver[1]:=s[1];
|
|
ver[2]:=s[2];
|
|
ver[3]:=s[3];
|
|
end;
|
|
end;
|
|
|
|
function tpcpfile.readheader: longint;
|
|
begin
|
|
if fsize<sizeof(tpcpheader) then
|
|
exit(0);
|
|
result:=f.Read(header,sizeof(tpcpheader));
|
|
{ The header is always stored in little endian order }
|
|
{ therefore swap if on a big endian machine }
|
|
{$IFDEF ENDIAN_BIG}
|
|
header.common.compiler := swapendian(header.common.compiler);
|
|
header.common.cpu := swapendian(header.common.cpu);
|
|
header.common.target := swapendian(header.common.target);
|
|
header.common.flags := swapendian(header.common.flags);
|
|
header.common.size := swapendian(header.common.size);
|
|
header.checksum := swapendian(header.checksum);
|
|
header.requiredlistsize:=swapendian(header.requiredlistsize);
|
|
header.ppulistsize:=swapendian(header.ppulistsize);
|
|
{$ENDIF}
|
|
{ the PPU DATA is stored in native order }
|
|
if (header.common.flags and pf_big_endian) = pf_big_endian then
|
|
Begin
|
|
{$IFDEF ENDIAN_LITTLE}
|
|
change_endian := TRUE;
|
|
{$ELSE}
|
|
change_endian := FALSE;
|
|
{$ENDIF}
|
|
End
|
|
else if (header.common.flags and pf_little_endian) = pf_little_endian then
|
|
Begin
|
|
{$IFDEF ENDIAN_BIG}
|
|
change_endian := TRUE;
|
|
{$ELSE}
|
|
change_endian := FALSE;
|
|
{$ENDIF}
|
|
End;
|
|
end;
|
|
|
|
procedure tpcpfile.resetfile;
|
|
begin
|
|
crc:=0;
|
|
end;
|
|
|
|
|
|
procedure tpcpfile.writeheader;
|
|
var
|
|
opos : integer;
|
|
begin
|
|
{ flush buffer }
|
|
writebuf;
|
|
{ update size (w/o header!) in the header }
|
|
header.common.size:=bufstart-sizeof(tpcpheader);
|
|
{ set the endian flag }
|
|
{$ifndef FPC_BIG_ENDIAN}
|
|
header.common.flags:=header.common.flags or pf_little_endian;
|
|
{$else not FPC_BIG_ENDIAN}
|
|
header.common.flags:=header.common.flags or pf_big_endian;
|
|
{ Now swap the header in the correct endian (always little endian) }
|
|
header.common.compiler:=swapendian(header.common.compiler);
|
|
header.common.cpu:=swapendian(header.common.cpu);
|
|
header.common.target:=swapendian(header.common.target);
|
|
header.common.flags:=swapendian(header.common.flags);
|
|
header.common.size:=swapendian(header.common.size);
|
|
header.checksum:=swapendian(header.checksum);
|
|
header.requiredlistsize:=swapendian(header.requiredlistsize);
|
|
header.ppulistsize:=swapendian(header.ppulistsize);
|
|
{$endif not FPC_BIG_ENDIAN}
|
|
{ write header and restore filepos after it }
|
|
opos:=f.Position;
|
|
f.Position:=0;
|
|
f.Write(header,sizeof(tpcpheader));
|
|
f.Position:=opos;
|
|
end;
|
|
|
|
|
|
function tpcpfile.checkpcpid:boolean;
|
|
begin
|
|
result:=((Header.common.Id[1]='P') and
|
|
(Header.common.Id[2]='C') and
|
|
(Header.common.Id[3]='P'));
|
|
end;
|
|
|
|
|
|
end.
|
|
|