+ when compiling for Darwin/ARM, pass the subarchitecture to the linker.

The old linker option to accept object files from all subarchitecture
    types no longer works.
  + support for subarchitectures in fcl-res/fpcres

git-svn-id: trunk@18070 -
This commit is contained in:
Jonas Maebe 2011-08-02 20:41:39 +00:00
parent da056da20f
commit ec8c7b4888
10 changed files with 220 additions and 45 deletions

View File

@ -75,7 +75,7 @@ implementation
uses
SysUtils,
cutils,cfileutl,cclasses,
Globtype,Globals,Verbose,Fmodule, comphook;
Globtype,Globals,Verbose,Fmodule, comphook,cpuinfo;
{****************************************************************************
TRESOURCEFILE
@ -237,7 +237,8 @@ var
srcfilepath,
preprocessorbin,
s : TCmdStr;
arch : ansistring;
arch,
subarch: ansistring;
function WindresFileName(filename: TCmdStr): TCmdStr;
// to be on the safe side, for files that are passed to the preprocessor,
@ -271,11 +272,18 @@ begin
else
ObjUsed:=(pos('$OBJ',s)>0);
Replace(s,'$OBJ',maybequoted(OutName));
subarch:='all';
arch:=cpu2str[target_cpu];
//Differentiate between arm and armeb
if (source_info.cpu=cpu_arm) and (source_info.endian=endian_big) then
arch:=arch+'eb';
if (source_info.cpu=systems.cpu_arm) then
begin
//Differentiate between arm and armeb
if (source_info.endian=endian_big) then
arch:=arch+'eb';
end;
Replace(s,'$ARCH',arch);
if target_info.system=system_arm_darwin then
subarch:=lower(cputypestr[current_settings.cputype]);
Replace(s,'$SUBARCH',subarch);
case target_info.endian of
endian_little : Replace(s,'$ENDIAN','littleendian');
endian_big : Replace(s,'$ENDIAN','bigendian');

View File

@ -37,7 +37,7 @@ unit i_bsd;
(
id : res_macho;
resbin : 'fpcres';
rescmd : '-o $OBJ -a $ARCH -of mach-o $DBG';
rescmd : '-o $OBJ -a $ARCH -s $SUBARCH -of mach-o $DBG';
rcbin : 'windres';
rccmd : '--include $INC -O res -o $RES $RC';
resourcefileclass : nil;

View File

@ -341,9 +341,9 @@ begin
system_x86_64_darwin:
LinkRes.Add('x86_64');
system_arm_darwin:
{ don't specify architecture subtype, because then CPU_SUBTYPE_ALL
files, such as compiled resources, are rejected }
LinkRes.Add('arm');
{ current versions of the linker require the sub-architecture type
to be specified }
LinkRes.Add(lower(cputypestr[current_settings.cputype]));
end;
end;
end;

View File

@ -56,6 +56,11 @@ const
CPU_SUBTYPE_X86_64_ALL = CPU_SUBTYPE_I386_ALL;
CPU_SUBTYPE_POWERPC_ALL = 0;
CPU_SUBTYPE_ARM_ALL = 0;
CPU_SUBTYPE_ARM_V4T = 5;
CPU_SUBTYPE_ARM_V6 = 6;
CPU_SUBTYPE_ARM_V5TEJ = 7;
CPU_SUBTYPE_ARM_XSCALE = 8;
CPU_SUBTYPE_ARM_V7 = 9;
//Mach-O object types
MH_OBJECT = $1; // relocatable object file

View File

@ -37,7 +37,8 @@ type
procedure FixResHeader(aStream : TStream); override;
public
constructor Create(aParent : TMachOResourceWriter; const aMachineType
: TMachOMachineType; const aOppositeEndianess : boolean); override;
: TMachOMachineType; const aSubMachineType: TMachoSubMachineType;
const aOppositeEndianess : boolean); override;
end;
{ _TMachOSymbolTable_ }
@ -336,9 +337,9 @@ begin
end;
constructor _TMachOSubWriter_.Create(aParent : TMachOResourceWriter;
const aMachineType : TMachOMachineType; const aOppositeEndianess : boolean);
const aMachineType : TMachOMachineType; const aSubMachineType: TMachoSubMachineType; const aOppositeEndianess : boolean);
begin
inherited Create(aParent, aMachineType,aOppositeEndianess);
inherited Create(aParent,aMachineType,aSubMachineType,aOppositeEndianess);
fSymbolTable:=_TMachOSymbolTable_.Create(fMachOStringTable);
fSymbolTable.OppositeEndianess:=fOppositeEndianess;
{$IF _TMachOSubWriter_=TMachO32SubWriter}

View File

@ -21,6 +21,11 @@ interface
type
TMachOMachineType = (mmtpowerpc, mmtpowerpc64, mmti386, mmtx86_64, mmtarm);
TMachOSubMachineTypePowerPC = (msmppc_all);
TMachOSubMachineTypePowerPC64 = (msmppc64_all);
TMachOSubMachineType386 = (msm386_all);
TMachOSubMachineTypex64 = (msmx64_all);
TMachOSubMachineTypeArm = (msmarm_all,msmarm_v4t,msmarm_v6,msmarm_v5tej,msmarm_xscale,msmarm_v7);
TSegSectName = array[0..15] of char;
type

View File

@ -30,6 +30,15 @@ type
{ TMachOResourceWriter }
TMachoSubMachineType = record
case TMachOMachineType of
msmppc_all: (fPpcSubType: TMachOSubMachineTypePowerPC);
msmppc64_all: (fPpc64SubType: TMachOSubMachineTypePowerPC64);
msm386_all: (f386SubType: TMachOSubMachineType386);
msmx64_all: (fX64SubType: TMachOSubMachineTypex64);
mmtarm: (fArmSubType: TMachOSubMachineTypeArm);
end;
TMachOResourceWriter = class(TAbstractResourceWriter)
private
fExtensions : string;
@ -38,10 +47,12 @@ type
fEndianess : integer;
fOppositeEndianess : boolean;
fMachineType : TMachOMachineType;
fSubMachineType : TMachoSubMachineType;
fBits : integer;
procedure SetDefaultTarget;
procedure SetMachineType(const aMachineType : TMachOMachineType);
procedure SetSubMachineType(const aSubMachineType: TMachoSubMachineType);
protected
function GetExtensions : string; override;
function GetDescription : string; override;
@ -50,6 +61,7 @@ type
constructor Create; override;
destructor Destroy; override;
property MachineType : TMachOMachineType read fMachineType write SetMachineType;
property SubMachineType : TMachOSubMachineType read fSubMachineType write SetSubMachineType;
end;
implementation
@ -115,6 +127,7 @@ type
fParent : TMachOResourceWriter;
fOppositeEndianess : boolean;
fMachineType : TMachOMachineType;
fSubMachineType: TMachoSubMachineType;
fDataAlignment : integer;
fSectAlignment : integer;
fSegType : longword;
@ -154,7 +167,8 @@ type
procedure Write(aResources: TResources; aStream: TStream);
public
constructor Create(aParent : TMachOResourceWriter; const aMachineType
: TMachOMachineType; const aOppositeEndianess : boolean); virtual;
: TMachOMachineType; const aSubMachineType: TMachoSubMachineType;
const aOppositeEndianess : boolean); virtual;
destructor Destroy; override;
end;
@ -469,33 +483,41 @@ begin
end;
procedure TAbstractMachOSubWriter.FixHeader(aStream: TStream);
const
ppcsm2int: array[TMachOSubMachineTypePowerPC] of longint = (CPU_SUBTYPE_POWERPC_ALL);
ppc64sm2int: array[TMachOSubMachineTypePowerPC64] of longint = (CPU_SUBTYPE_POWERPC_ALL);
i386sm2int: array[TMachOSubMachineType386] of longint = (CPU_SUBTYPE_I386_ALL);
x86_64sm2int: array[TMachOSubMachineTypex64] of longint = (CPU_SUBTYPE_X86_64_ALL);
armsm2int: array[TMachOSubMachineTypeArm] of longint = (CPU_SUBTYPE_ARM_ALL,
CPU_SUBTYPE_ARM_V4T,CPU_SUBTYPE_ARM_V6,CPU_SUBTYPE_ARM_V5TEJ,
CPU_SUBTYPE_ARM_XSCALE,CPU_SUBTYPE_ARM_V7);
begin
aStream.Position:=0;
case fMachineType of
mmtpowerpc : begin
fHeader.magic:=MH_MAGIC;
fHeader.cputype:=CPU_TYPE_POWERPC;
fHeader.cpusubtype:=CPU_SUBTYPE_POWERPC_ALL;
fHeader.cpusubtype:=ppcsm2int[fSubMachineType.fPpcSubType];
end;
mmtpowerpc64 : begin
fHeader.magic:=MH_MAGIC_64;
fHeader.cputype:=CPU_TYPE_POWERPC64;
fHeader.cpusubtype:=CPU_SUBTYPE_POWERPC_ALL;
fHeader.cpusubtype:=ppc64sm2int[fSubMachineType.fPpc64SubType];
end;
mmti386 : begin
fHeader.magic:=MH_MAGIC;
fHeader.cputype:=CPU_TYPE_I386;
fHeader.cpusubtype:=CPU_SUBTYPE_I386_ALL;
fHeader.cpusubtype:=i386sm2int[fSubMachineType.f386SubType];
end;
mmtx86_64 : begin
fHeader.magic:=MH_MAGIC_64;
fHeader.cputype:=CPU_TYPE_X86_64;
fHeader.cpusubtype:=CPU_SUBTYPE_X86_64_ALL;
fHeader.cpusubtype:=x86_64sm2int[fSubMachineType.fX64SubType];
end;
mmtarm : begin
fHeader.magic:=MH_MAGIC;
fHeader.cputype:=CPU_TYPE_ARM;
fHeader.cpusubtype:=CPU_SUBTYPE_ARM_ALL;
fHeader.cpusubtype:=armsm2int[fSubMachineType.fArmSubType];
end;
end;
fHeader.filetype:=MH_OBJECT;
@ -541,10 +563,12 @@ begin
end;
constructor TAbstractMachOSubWriter.Create(aParent : TMachOResourceWriter;
const aMachineType : TMachOMachineType; const aOppositeEndianess : boolean);
const aMachineType : TMachOMachineType; const aSubMachineType:
TMachoSubMachineType; const aOppositeEndianess : boolean);
begin
fParent:=aParent;
fMachineType:=aMachineType;
fSubMachineType:=aSubMachineType;
fOppositeEndianess:=aOppositeEndianess;
fRoot:=nil;
fMachOStringTable:=TObjectStringTable.Create(nil,0);
@ -570,8 +594,7 @@ begin
{$INCLUDE machodefaulttarget.inc}
end;
procedure TMachOResourceWriter.SetMachineType(
const aMachineType: TMachOMachineType);
procedure TMachOResourceWriter.SetMachineType(const aMachineType: TMachOMachineType);
begin
case aMachineType of
mmtpowerpc : begin fBits:=MACH_32BIT; fEndianess:=MACH_BIG_ENDIAN; end;
@ -584,6 +607,11 @@ begin
fOppositeEndianess:=fNativeEndianess<>fEndianess;
end;
procedure TMachOResourceWriter.SetSubMachineType(const aSubMachineType: TMachoSubMachineType);
begin
fSubMachineType:=aSubMachineType;
end;
function TMachOResourceWriter.GetExtensions: string;
begin
Result:=fExtensions;
@ -598,8 +626,8 @@ procedure TMachOResourceWriter.Write(aResources: TResources; aStream: TStream);
var subwriter : TAbstractMachOSubWriter;
begin
case fBits of
MACH_32BIT : subwriter:=TMachO32SubWriter.Create(self,fMachineType,fOppositeEndianess);
MACH_64BIT : subwriter:=TMachO64SubWriter.Create(self,fMachineType,fOppositeEndianess)
MACH_32BIT : subwriter:=TMachO32SubWriter.Create(self,fMachineType,fSubMachineType,fOppositeEndianess);
MACH_64BIT : subwriter:=TMachO64SubWriter.Create(self,fMachineType,fSubMachineType,fOppositeEndianess)
else
raise EMachOResourceWriterUnknownBitSizeException.Create('');
end;

View File

@ -62,20 +62,23 @@ begin
writeln('Syntax: '+progname+' [options] <inputfile> [<inputfile>...] [-o <outputfile>]');
writeln;
writeln('Options:');
writeln(' --help, -h, -? Show this screen.');
writeln(' --version, -V Show program version.');
writeln(' --verbose, -v Be verbose.');
writeln(' --input, -i <x> Ignored for compatibility.');
writeln(' --output, -o <x> Set the output file name.');
writeln(' -of <format> Set the output file format. Supported formats:');
writeln(' res, elf, coff, mach-o, external');
writeln(' --arch, -a <name> Set object file architecture. Supported architectures:');
writeln(' i386, x86_64, arm (coff)');
writeln(' i386, x86_64, powerpc, powerpc64, arm, armeb, m68k,');
writeln(' sparc, alpha, ia64 (elf)');
writeln(' i386, x86_64, powerpc, powerpc64 (mach-o)');
writeln(' bigendian, littleendian (external)');
writeln(' @<file> Read more options from file <file>');
writeln(' --help, -h, -? Show this screen.');
writeln(' --version, -V Show program version.');
writeln(' --verbose, -v Be verbose.');
writeln(' --input, -i <x> Ignored for compatibility.');
writeln(' --output, -o <x> Set the output file name.');
writeln(' -of <format> Set the output file format. Supported formats:');
writeln(' res, elf, coff, mach-o, external');
writeln(' --arch, -a <name> Set object file architecture. Supported architectures:');
writeln(' i386, x86_64, arm, arm (coff)');
writeln(' i386, x86_64, powerpc, powerpc64, arm, armeb, m68k,');
writeln(' sparc, alpha, ia64 (elf)');
writeln(' i386, x86_64, powerpc, powerpc64 (mach-o)');
writeln(' bigendian, littleendian (external)');
writeln(' --subarch, -s <name> Set object file sub-architecture. Supported values:');
writeln(' arm: all, v4t, v6, v5tej, xscale, v7');
writeln(' other architectures: all');
writeln(' @<file> Read more options from file <file>');
writeln('Default output target: '+TargetToStr(currenttarget));
end;
@ -112,9 +115,16 @@ begin
if params.Target.machine=mtNone then
begin
if not (CurrentTarget.machine in ObjFormats[CurrentTarget.objformat].machines) then
CurrentTarget.machine:=GetDefaultMachineForFormat(CurrentTarget.objformat);
begin
CurrentTarget.machine:=GetDefaultMachineForFormat(CurrentTarget.objformat);
CurrentTarget.submachine:=GetDefaultSubMachineForMachine(currentTarget.machine);
end
end
else CurrentTarget.machine:=params.Target.machine;
else
begin
CurrentTarget.machine:=params.Target.machine;
CurrentTarget.submachine:=params.Target.submachine;
end;
if not (CurrentTarget.machine in ObjFormats[CurrentTarget.objformat].machines) then
begin
@ -255,16 +265,42 @@ begin
end;
function SetUpMachOWriter : TMachOResourceWriter;
const
ArmSubMachine2MachOSubMachine: array[TSubMachineTypeArm] of TMachOSubMachineTypeArm =
(msmarm_all,msmarm_v4t,msmarm_v6,msmarm_v5tej,msmarm_xscale,msmarm_v7);
var
MachOSubMachineType: TMachoSubMachineType;
begin
Result:=TMachOResourceWriter.Create;
case CurrentTarget.machine of
// mtnone :
mti386 : Result.MachineType:=mmti386;
mtx86_64 : Result.MachineType:=mmtx86_64;
mtppc : Result.MachineType:=mmtpowerpc;
mtppc64 : Result.MachineType:=mmtpowerpc64;
mtarm : Result.MachineType:=mmtarm;
mti386 :
begin
Result.MachineType:=mmti386;
MachOSubMachineType.f386SubType:=msm386_all;
end;
mtx86_64 :
begin
Result.MachineType:=mmtx86_64;
MachOSubMachineType.fX64SubType:=msmx64_all;
end;
mtppc :
begin
Result.MachineType:=mmtpowerpc;
MachOSubMachineType.fPpcSubType:=msmppc_all;
end;
mtppc64 :
begin
Result.MachineType:=mmtpowerpc64;
MachOSubMachineType.fPpc64SubType:=msmppc64_all;
end;
mtarm :
begin
Result.MachineType:=mmtarm;
MachOSubMachineType.fArmSubType:=ArmSubMachine2MachOSubMachine[CurrentTarget.submachine.subarm];
end;
end;
Result.SubMachineType:=MachOSubMachineType;
end;

View File

@ -30,6 +30,7 @@ type
EArgumentMissingException = class(EParametersException);
EUnknownObjFormatException = class(EParametersException);
EUnknownMachineException = class(EParametersException);
EUnknownSubMachineException = class(EParametersException);
ECannotReadConfFile = class(EParametersException);
type
@ -49,6 +50,7 @@ type
procedure ParseOutputFile(aList : TStringList; var index : integer; const parname : string);
procedure ParseOutputFormat(aList : TStringList; var index : integer; const parname : string);
procedure ParseArchitecture(aList : TStringList; var index : integer; const parname : string);
procedure ParseSubArchitecture(aList : TStringList; var index : integer; const parname : string);
procedure ParseConfigFile(aList : TStringList; var index : integer; const parname : string);
function DoOptionalArgument(aList : TStringList; const i : integer) : string;
function DoMandatoryArgument(aList : TStringList; const i : integer) : string;
@ -242,6 +244,7 @@ begin
if Machines[aMachine].name=tmp then
begin
fTarget.machine:=aMachine;
fTarget.submachine:=GetDefaultSubMachineForMachine(fTarget.machine);
exit;
end;
end;
@ -250,6 +253,37 @@ begin
end;
procedure TParameters.ParseSubArchitecture(aList: TStringList; var index: integer; const parname: string);
var tmp : string;
aSubMachineArm : TSubMachineTypeArm;
aSubMachineGeneric : TSubMachineTypeGeneric;
begin
inc(index);
tmp:=DoMandatoryArgument(aList,index);
if tmp='' then
raise EArgumentMissingException.Create(parname);
case fTarget.machine of
mtarm,mtarmeb:
for aSubMachineArm:=low(TSubMachineTypeArm) to high(TSubMachineTypeArm) do
if SubMachinesArm[aSubMachineArm]=tmp then
begin
ftarget.submachine.subarm:=aSubMachineArm;
exit;
end;
else
for aSubMachineGeneric:=low(TSubMachineTypeGeneric) to high(TSubMachineTypeGeneric) do
if SubMachinesGen[aSubMachineGeneric]=tmp then
begin
ftarget.submachine.subgen:=aSubMachineGeneric;
exit;
end;
end;
raise EUnknownSubMachineException.Create(tmp);
end;
procedure TParameters.ParseConfigFile(aList: TStringList; var index: integer;
const parname : string);
var tmp : string;
@ -333,6 +367,8 @@ begin
ParseOutputFormat(fList,i,tmp)
else if ((tmp='-a') or (tmp='--arch')) then
ParseArchitecture(fList,i,tmp)
else if ((tmp='-s') or (tmp='--subarch')) then
ParseSubArchitecture(fList,i,tmp)
else
raise EUnknownParameterException.Create(tmp);
end
@ -356,6 +392,7 @@ begin
fInputFiles:=TStringList.Create;
fOutputFile:='';
fTarget.machine:=mtnone;
GetDefaultSubMachineForMachine(fTarget.machine);
fTarget.objformat:=ofnone;
end;

View File

@ -25,6 +25,18 @@ type
mtsparc,mtalpha,mtia64,mtBigEndian,mtLittleEndian);
TMachineTypes = set of TMachineType;
TSubMachineTypeArm = (smtarm_all,smtarm_v4t,smtarm_v6,smtarm_v5tej,smtarm_xscale,smtarm_v7);
TSubMachineTypeGeneric = (smtgen_all);
TSubMachineType = record
case TMachineType of
mtarm,mtarmeb:
(subarm: TSubMachineTypeArm);
mtnone, mti386,mtx86_64,mtppc,mtppc64,mtm68k,
mtsparc,mtalpha,mtia64,mtBigEndian,mtLittleEndian:
(subgen: TSubMachineTypeGeneric);
end;
TObjFormat = (ofNone, ofRes, ofElf, ofCoff, ofMachO, ofExt);
TObjFormats = set of TObjFormat;
@ -42,10 +54,12 @@ type
TResTarget = record
machine : TMachineType;
submachine : TSubMachineType;
objformat : TObjFormat;
end;
function GetDefaultMachineForFormat(aFormat : TObjFormat) : TMachineType;
function GetDefaultSubMachineForMachine(aMachine: TMachineType) : TSubMachineType;
function TargetToStr(const aTarget : TResTarget) : string;
function MachineToStr(const aMachine : TMachineType) : string;
function ObjFormatToStr(const aFormat : TObjFormat) : string;
@ -67,6 +81,11 @@ var
(name : 'bigendian'; formats : [ofExt]), //mtBigEndian
(name : 'littleendian'; formats : [ofExt]) //mtLittleEndian
);
SubMachinesArm: array[TSubMachineTypeArm] of string[8] =
('all','armv4','armv6','armv5tej','xscale','armv7');
SubMachinesGen: array[TSubMachineTypeGeneric] of string[3] =
('all');
ObjFormats : array[TObjFormat] of TFormatInfo =
(
@ -87,36 +106,47 @@ var
(
{$IFDEF CPUI386}
machine : mti386;
submachine : (subgen: smtgen_all);
{$ELSE}
{$IFDEF CPUX86_64}
machine : mtx86_64;
submachine : (subgen: smtgen_all);
{$ELSE}
{$IFDEF CPUPOWERPC32}
machine : mtppc;
submachine : (subgen: smtgen_all);
{$ELSE}
{$IFDEF CPUPOWERPC64}
machine : mtppc64;
submachine : (subgen: smtgen_all);
{$ELSE}
{$IFDEF CPUARM}
{$IFDEF ENDIAN_LITTLE}
machine : mtarm;
submachine : (subarm: smtarm_all);
{$ELSE}
machine : mtarmeb;
submachine : (subarm: smtarm_all);
{$ENDIF}
{$ELSE}
{$IFDEF CPU68K}
machine : mtm68k;
submachine : (subgen: smtgen_all);
{$ELSE}
{$IFDEF CPUSPARC}
machine : mtsparc;
submachine : (subgen: smtgen_all);
{$ELSE}
{$IFDEF CPUALPHA}
machine : mtalpha;
submachine : (subgen: smtgen_all);
{$ELSE}
{$IFDEF CPUIA64}
machine : mtia64;
submachine : (subgen: smtgen_all);
{$ELSE}
machine : mti386; //default i386
submachine : (subgen: smtgen_all);
{$ENDIF}
{$ENDIF}
{$ENDIF}
@ -162,18 +192,43 @@ begin
Result:=Machines[aMachine].name;
end;
function SubMachineToStr(const aMachine : TMachineType; const aSubMachine : TSubMachineType) : string;
begin
case aMachine of
mtarm,mtarmeb:
result:=SubMachinesArm[aSubMachine.subarm];
else
// no need to confuse people with the "all" suffix, it doesn't do
// anything anyway
result:='';
end;
end;
function ObjFormatToStr(const aFormat : TObjFormat) : string;
begin
Result:=ObjFormats[aFormat].name;
end;
function GetDefaultSubMachineForMachine(aMachine: TMachineType): TSubMachineType;
begin
case aMachine of
mtarm,mtarmeb:
result.subarm:=smtarm_all;
else
result.subgen:=smtgen_all;
end;
end;
function TargetToStr(const aTarget : TResTarget) : string;
var s1, s2 : string;
var s1, s2, s3 : string;
begin
s1:=MachineToStr(aTarget.machine);
s2:=ObjFormatToStr(aTarget.objformat);
s3:=SubMachineToStr(aTarget.Machine,aTarget.submachine);
if (s1='') or (s2='') then Result:=s1+s2
else Result:=s1+' - '+s2;
if s3<>'' then
Result:=Result+'-'+s3;
end;
end.