How to solve “Need imported data reference” while building with runtime packages

送分小仙女□ 提交于 2019-12-10 15:06:40

问题


To help us modularize a monolithic application, we are in the process of setting up packages for use in debug builds, while still compiling to a single exe for release builds.

One of our packages (EAUtils) contains a unit that is now producing [DCC Error] E2201 Need imported data reference ($G) to access 'SMsgDlgWarning' from unit 'SystemUtils'.

This happens when building the EAUtils package itself. I am not into building packages that depend on EAUtils yet. EAUtils only depends on rtl/vcl packages and a package I created for the Jedi WinApi units.

This is a result of the lines:

// This is a TaskDialog override, with the same args as the old MessageDlg.
function TaskDialog(const aContent: string; const Icon: HICON = 0; 
  const Buttons: TTaskDialogCommonButtonFlags = TDCBF_OK_BUTTON): Integer;
const
  Captions: array[TMsgDlgType] of Pointer = (@SMsgDlgWarning, @SMsgDlgError, @SMsgDlgInformation, @SMsgDlgConfirm, nil);
var
  aMsgDlgType: TMsgDlgType;
  aTitle: string;
begin
  aMsgDlgType := TaskDialogIconToMsgDlgType(Icon);
  if aMsgDlgType <> mtCustom then
    aTitle := LoadResString(Captions[aMsgDlgType])
  else
    aTitle := Application.Title;

More specifically this is a result of referencing SMsgDlgWarning, SMsgDlgError, SMsgDlgInformation and SMsgDlgConfirm, which are all declared in Vcl.Const.

Please note that this code compiles without error when we are building a single executable.

As a means of optimization, our include file does contain {$IMPORTEDDATA OFF} as this allows for faster access to (global) variables and constants. See http://hallvards.blogspot.com/2006/09/hack13-access-globals-faster.html.

According to the documentation on the error ( http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/cm_package_varref_xml.html ) this is the cause and it says "To alleviate the problem, it is generally easiest to turn on the $IMPORTEDDATA switch and recompile the unit that produces the error."

So, I have set {$IMPORTEDDATA ON} in our include file and made doubly sure by setting the Use imported data references to true in the Delphi Compiler | Compiling | Debugging section of the project options.

Unfortunately, contrary to the documentation, this did not alleviate the problem. Even setting this compiler directive directly above the offending code and rebuilding the package did not remove the errors.

What else do I need to do to solve this E2201 error? Not sure, but it may be significant that SMsgDlgWarning and its friends are resource strings?


回答1:


The error message is, IMHO, misleading, it's Vcl.Consts which has been compiled with $G- and that's causing the problem. As a workaround, you can use something like this:

function Captions(AType: TMsgDlgType): Pointer;
begin
  Result := nil;

  case AType of
    TMsgDlgType.mtWarning:
      Result := @SMsgDlgWarning;
    TMsgDlgType.mtError:
      Result := @SMsgDlgError;
    TMsgDlgType.mtInformation:
      Result := @SMsgDlgInformation;
    TMsgDlgType.mtConfirmation:
      Result := @SMsgDlgConfirm;
  end;
end;

Using a const array of string compiles, too (although it breaks localization):

const
  Captions: array[TMsgDlgType] of string = (SMsgDlgWarning, SMsgDlgError, SMsgDlgInformation, SMsgDlgConfirm, '');

or you could build your own package containing Vcl.* units, with {$G+} and use that instead of the standard vcl package. I prefer the first solution; the latter can potentially create more problems later with deployment (so-called "DLL hell").



来源:https://stackoverflow.com/questions/10512504/how-to-solve-need-imported-data-reference-while-building-with-runtime-packages

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!