秋·风

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  278 随笔 :: 0 文章 :: 308 评论 :: 20万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

近日和樵夫交流时发现unidac在aarch64 linux交叉编译UniProvider.pas出错:

UniProvider.pas(1040,1) Error: Compilation raised exception internally

奇怪的是其他CPU类型是正常的。

樵夫的解决办法:
1、修改UniProvider.pas,添加

{$if FPC_FULLVERSION<30301}
复制代码
  TEnumeratorOption = class(TOption)
  private
    FTypeInfo: PTypeInfo;
    FMinValue: integer;
    FMaxValue: integer;
    FInternalType: boolean;
  protected
    procedure InternalGetValuesList(List: TStrings); override;

  public
    procedure SetTypeInfo(typeInfo: PTypeInfo);
    {$if FPC_FULLVERSION<30301}
    constructor Create(const OptionName: string; InternalIndex: integer; InternalClasses: array of TClass;
      DefaultValue: variant; TypeInfo: PTypeInfo);
    {$endif}
    function GetAsString(const Value: variant): string; override;
    function GetAsNative(const Value: string): variant; override;

    function CheckValue(const Value: string): boolean; override;
  end;

  TOptionsList = class(TStringList)
复制代码
复制代码
{$if FPC_FULLVERSION<30301}
constructor TEnumeratorOption.Create(const OptionName: string; InternalIndex: integer;
  InternalClasses: array of TClass; DefaultValue: variant; TypeInfo: PTypeInfo);
var
  TypeData: PTypeData;
  TypeName: string;
begin
  inherited Create(OptionName, InternalIndex, InternalClasses, DefaultValue);

  FTypeInfo := TypeInfo;
  TypeData := GetTypeData(FTypeInfo);
  if TypeData <> nil then begin
    FMinValue := TypeData{$IFNDEF CLR}^{$ENDIF}.MinValue;
    FMaxValue := TypeData{$IFNDEF CLR}^{$ENDIF}.MaxValue;
  end;

{$IFDEF NEXTGEN}
  TypeName := GetTypeName(FTypeInfo);
{$ELSE}
  TypeName := string(FTypeInfo.Name);
{$ENDIF}

  FInternalType := (TypeName <> '') and (TypeName[1] = '_');
end;
{$endif}
复制代码

 修改相应的TxxxUniProvider.pas,添加

{$if FPC_FULLVERSION>=30301}

参考以下方法修改

复制代码
procedure TAccessUniProvider.CreateConnectionOptions;
{$if FPC_FULLVERSION>=30301}
var
   tmpOption: TEnumeratorOption;
{$endif}
begin
  if FConnectionOptions = nil then begin
    FConnectionOptions := TOptionsList.Create(GetProviderName);
    FConnectionOptions.Add(TBooleanOption.Create('ColumnWiseBinding', prColumnWiseBinding, [TAccessConnection], False));
    FConnectionOptions.Add(TIntegerOption.Create('ConnectionTimeout', prConnectionTimeout, [TAccessConnection], 15));
    FConnectionOptions.Add(TBooleanOption.Create('ExclusiveLock', prExclusiveLock, [TAccessConnection], False));
    FConnectionOptions.Add(TBooleanOption.Create('ExtendedAnsiSQL', prExtendedAnsiSQL, [TAccessConnection], False));
    FConnectionOptions.Add(TBooleanOption.Create('ForceCreateDatabase', prForceCreateDatabase, [TAccessConnection], False));
    FConnectionOptions.Add(TStringOption.Create('SystemDatabase', prSystemDatabase, [TAccessConnection], ''));
    FConnectionOptions.Add(TBooleanOption.Create('UseUnicode', prUseUnicode, [TAccessConnection], False));
    {$if FPC_FULLVERSION>=30301}
    tmpOption:=TEnumeratorOption.Create('DriverVersion', prDriverVersion, [TAccessConnection], Variant(dvAuto));
    tmpOption.SetTypeInfo(TypeInfo(TDriverVersion));
    FConnectionOptions.Add(tmpOption);
    {$else}
    FConnectionOptions.Add(TEnumeratorOption.Create('DriverVersion', prDriverVersion, [TAccessConnection], Variant(dvAuto), TypeInfo(TDriverVersion)));
    {$endif}
  end;
end;

procedure TAccessUniProvider.CreateSQLOptions;
begin
  if FSQLOptions = nil then begin
    FSQLOptions := TOptionsList.Create(GetProviderName);
    FSQLOptions.Add(TIntegerOption.Create('CommandTimeout', prCommandTimeout, [TAccessCommand], 0));
  end;
end;

procedure TAccessUniProvider.CreateDataSetOptions;
begin
  if FDataSetOptions = nil then begin
    FDataSetOptions := TOptionsList.Create(GetProviderName);
    FDataSetOptions.Add(TIntegerOption.Create('CommandTimeout', prCommandTimeout, [TAccessRecordSet], 0));
    FDataSetOptions.Add(TBooleanOption.Create('ExtendedFieldsInfo', prExtendedFieldsInfo, [TAccessRecordSet], False));
    FDataSetOptions.Add(TBooleanOption.Create('FetchAll', prFetchAll, [TAccessRecordSet], True));
  end;
end;
复制代码

 相关单元按以上方法修改后就能交叉编译
注意(2024-11-07更新)
unidac 10.3.0及之后的版本UniProvider中的TEnumeratorOption = class(TOption)删除了原来的procedure SetTypeInfo(typeInfo: PTypeInfo),按上述方法编译时会出错。 
添加下面红色代码就可以。

复制代码
  TEnumeratorOption = class(TOption)
  private
    FTypeInfo: PTypeInfo;
    FMinValue: integer;
    FMaxValue: integer;
    FInternalType: boolean;
  protected
    procedure InternalGetValuesList(List: TStrings); override;
  public
    procedure SetTypeInfo(typeInfo: PTypeInfo);
    {$if FPC_FULLVERSION<30301}
    constructor Create(const OptionName: string; InternalIndex: integer; InternalClasses: array of TClass; DefaultValue: variant; TypeInfo: PTypeInfo);
    {$endif}
    function GetAsString(const Value: variant): string; override;
    function GetAsNative(const Value: string): variant; override;

    function CheckValue(const Value: string): boolean; override;
  end;
复制代码
复制代码
procedure TEnumeratorOption.SetTypeInfo(typeInfo: PTypeInfo);
var
  TypeData: PTypeData;
  TypeName: string;
begin
  FTypeInfo := TypeInfo;
  TypeData := GetTypeData(FTypeInfo);
  if TypeData <> nil then begin
    FMinValue := TypeData{$IFNDEF CLR}^{$ENDIF}.MinValue;
    FMaxValue := TypeData{$IFNDEF CLR}^{$ENDIF}.MaxValue;
  end;

{$IFDEF NEXTGEN}
  TypeName := GetTypeName(FTypeInfo);
{$ELSE}
  TypeName := string(FTypeInfo.Name);
{$ENDIF}

  FInternalType := (TypeName <> '') and (TypeName[1] = '_');
end;

{$if FPC_FULLVERSION<30301}
constructor TEnumeratorOption.Create(const OptionName: string; InternalIndex: integer;
  InternalClasses: array of TClass; DefaultValue: variant; TypeInfo: PTypeInfo);
var
  TypeData: PTypeData;
  TypeName: string;
begin

  inherited Create(OptionName, InternalIndex, InternalClasses, DefaultValue);

  FTypeInfo := TypeInfo;
  TypeData := GetTypeData(FTypeInfo);
  if TypeData <> nil then begin
    FMinValue := TypeData{$IFNDEF CLR}^{$ENDIF}.MinValue;
    FMaxValue := TypeData{$IFNDEF CLR}^{$ENDIF}.MaxValue;
  end;

{$IFDEF NEXTGEN}
  TypeName := GetTypeName(FTypeInfo);
{$ELSE}
  TypeName := string(FTypeInfo.Name);
{$ENDIF}

  FInternalType := (TypeName <> '') and (TypeName[1] = '_');
end;
{$endif}
复制代码

 

posted on   秋·风  阅读(487)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示