War*_* P 9 delphi packages delphi-xe6 delphi-xe7
我正在尝试解决此编译错误,仅在Debug配置中发生,并且仅在下面描述的情况下:
[dcc32 Fatal Error] MyIndyTCPChannel.pas(22): F2051 Unit IdIOHandlerSocket was compiled with a different version of IdGlobal.IdDisposeAndNil
Run Code Online (Sandbox Code Playgroud)
我正在开发一个非常大的Delphi代码库,拥有250万行内部代码和300万行组件代码,其中包括几个大型商业Delphi组件套件(Developer Express,TeeChart等),以及大量代码库开源delphi组件,以及一个相当大的内部开发组件集,编号252个包,其中大约140个是设计时+运行时或设计时,其他是运行时包(也被加载到IDE中)在运行时,由其关联的设计时包中的DLL依赖项).
我们的主库路径已经优化到尽可能小,并且它包含Delphi附带的路径作为标准,再加上我们添加的三个,主要的是单个"OurCompanyLibraryDCU"文件夹,其中包含下面的文件夹我们使用的两个平台和两个配置:
c:\dev\OurCompanyLibraryDCU\Win32\Release
c:\dev\OurCompanyLibraryDCU\Win32\Debug
c:\dev\OurCompanyLibraryDCU\Win64\Release
c:\dev\OurCompanyLibraryDCU\Win32\Debug
Run Code Online (Sandbox Code Playgroud)
上述每个文件夹都包含一个文件夹中的BPL,DCP和DCU文件集,用于该平台/配置组合.
在项目选项中使用了如下的宏,因此我们可以更改平台和配置,并正确解析目录:
$(OURCOMPANYLIBRARYDCU)\$(Platform)\$(Config)
OURCOMPANYLIBRARYDCU是一个环境变量,$(X)是在Delphi IDE的上下文中扩展环境变量的语法.
我正在尝试将最重要和最大的VCL应用程序项目(称为BigApp.dproj)构建,以便项目搜索目录仅包含我们的APPLICATION源文件夹,并且不需要项目搜索路径来包含我们所有的第三方组件LIBRARY源代码.为此,我们需要链接调试DCU或释放DCU.
到目前为止,除了可以使用Debug和Release DCU的情况外,我们一切正常.版本DCU位于库路径中,调试DCU位于IDE设置中的Debug DCU路径中.面对这两个库之间的选择,Delphi的链接器似乎失败,每当存在两组DCU时,这种形式的错误,当我单击Build,并且Build Configuration设置为Release时,我得到F2051错误.F2051错误的普通原因是存在多个不兼容的二进制DCU并且都是可访问的,并且链接器无法使其全部工作.但是,如果你想在库路径中同时使用Debug和Release DCU,我认为这种情况不会发生,因为Linker会为你选择调试或释放DCU.
如果我没有构建调试DCU,则不会发生上述问题.我怀疑我的调试DCU是微妙的"无效"或Delphi中的Debug-DCU选择算法不起作用,但不知道为什么,或如何解决这个问题.
多部分问题:
A.每个平台/配置组合都有一个文件夹,在单个文件夹中包含DCU,BPL和DCP,然后添加到已知导致问题的IDE库路径中?我是否需要三个子文件夹,每个平台+ config + filetype共有12个文件夹,或者我可以通过platform + config将它们保存在一起吗?
B.在包编译情况下,是否可以让IDE库路径包含OurCompanyLibraryDCU文件夹,并将该文件夹配置为DCP输出目录,包输出目录和单元输出目录?我担心的是,通过使输入文件夹和输出文件夹相同,有一种情况是编译器可能无法从.pas源重建单元,只是链接先前编译的DCU.

C.如果我发生了这个问题,我应该如何防止每次构建BigApp时从源代码编译超过250万行的组件LIBRARY代码,而只是通过DCU链接它们,并且仍然有调试并释放dcus正常工作?
D.如果我转到Win32\Debug文件夹并删除IdGlobal.dcu,我可以通过原始错误.这告诉我,我的包编译(用于调试配置)正在生成INVALID IdGlobal.dcu.这甚至可能吗?delphi可以默默输出乱码的DCU吗?
注意:我没有使用,也无法使用Runtime Packages来处理应用程序大小问题.
更新:我应该在这里做的第一件事是验证ZERO额外的DCU文件在我的硬盘驱动器上是任何地方,无论如何.这是标准的F2051错误建议.在我处理完这个问题后,我会更新这个问题.似乎Delphi本身可以将DCU从一个地方复制到另一个地方,或者不在CURRENT搜索路径中的虚假DCU可能已经在某个其他项目的搜索路径中.可能会出现一种坏DCU拷贝的桶式旅.一旦我确定发生了什么样的坏DCU代或副本,我就会更新问题.
更新2:我现在保证在构建之前不存在IdGlobal.dcu的额外副本,并且问题仍然存在.因此,问题随后打开了构建IdGlobal.dcu时使用的编译器选项,版本化了在Debug构建中构建BigApp.dproj时使用的编译器选项.
更新3:虽然我的所有程序包编译似乎都没有错误地完成,但是在启动DCC32.exe或MSBUILD.exe来构建程序包期间,它们似乎没有使用正确的库搜索路径.这个库路径不一致问题似乎是核心问题,感谢Rufo爵士指出这一点.
也许我可以对提交给编译器的搜索路径的顺序有所了解,这应该首先解释为什么问题首先发生并且可以通过在该特定位置添加Debug DCU路径来解决(至少在您的情况下) .所有这些观察都是用XE7进行的.
IDE中有几个位置可以指定搜索路径:
当Library语言设置为英语时,这些路径将按照5,1或3,5,1的顺序提供给编译器,具体取决于Use debug .dcus的设置.这已经有点奇怪,因为debug dcu路径优先于项目搜索路径.
因此,为了让编译器找到我们自己的新版Indy版本的dcu文件,我们必须在1和3下的pathes前面放置相应的pathes.
现在,当Library语言被设置为与英语不同的东西时,事情会变得复杂.在这种情况下,翻译的pathes会起作用,导致2,5,1或4,3,2,5,1的顺序,具体取决于Use debug .dcus的设置.
要使用更新的Indy版本制作上述示例,您还必须调整已翻译的广告.
罪魁祸首在于CodeGear.Delphi.Targets,它按照这个顺序放置了pathes.我能够修改这个文件,以便使用pathes的自然顺序:5,2,1或5,4,3,2,1.如果有人能确认我被允许在这里显示这些变化,我会这样做.也许我只能提供补丁.
更新:以下是Mercurial显示的XE7 中CodeGear.Delphi.Targets的更改
@@ -122,20 +122,19 @@
<DcpFilename Condition="'$(DcpFilename)'!='' And !HasTrailingSlash('$(DcpFilename)')">$(DcpFilename)\</DcpFilename>
<DcpFilename Condition="'$(DcpFilename)'!=''">$(DcpFilename)$(MSBuildProjectName).dcp</DcpFilename>
- <UnitSearchPath Condition="'$(DCC_UnitSearchPath)' != ''">$(DCC_UnitSearchPath);$(DelphiLibraryPath)</UnitSearchPath>
- <UnitSearchPath Condition="'$(DCC_UnitSearchPath)' == ''">$(DelphiLibraryPath)</UnitSearchPath>
-
+ <UnitSearchPath>$(DelphiLibraryPath)</UnitSearchPath>
<UnitSearchPath Condition="'$(DCC_TranslatedLibraryPath)' != ''">$(DCC_TranslatedLibraryPath);$(UnitSearchPath)</UnitSearchPath>
<UnitSearchPath Condition="'$(DCC_DebugDCUs)'=='true' And '$(DelphiDebugDCUPath)'!=''">$(DelphiDebugDCUPath);$(UnitSearchPath)</UnitSearchPath>
<UnitSearchPath Condition="'$(DCC_DebugDCUs)'=='true' And '$(DCC_TranslatedDebugLibraryPath)' != ''">$(DCC_TranslatedDebugLibraryPath);$(UnitSearchPath)</UnitSearchPath>
-
+ <UnitSearchPath Condition="'$(DCC_UnitSearchPath)' != ''">$(DCC_UnitSearchPath);$(UnitSearchPath)</UnitSearchPath>
+
<___ResourcePath Condition="'$(DCC_ResourcePath)' != ''">$(DCC_ResourcePath);$(DelphiLibraryPath)</___ResourcePath>
<___ResourcePath Condition="'$(DCC_ResourcePath)' == ''">$(DelphiLibraryPath)</___ResourcePath>
+ <___ResourcePath Condition="'$(DCC_TranslatedResourcePath)' != ''">$(DCC_TranslatedResourcePath);$(___ResourcePath)</___ResourcePath>
<__ResourcePath Condition="'$(DCC_UnitSearchPath)' != ''">$(DCC_UnitSearchPath);$(___ResourcePath)</__ResourcePath>
<__ResourcePath Condition="'$(DCC_UnitSearchPath)' == ''">$(___ResourcePath)</__ResourcePath>
<ResourcePath Condition="'$(BRCC_OutputDir)' != ''">$(BRCC_OutputDir);$(__ResourcePath)</ResourcePath>
<ResourcePath Condition="'$(BRCC_OutputDir)' == ''">$(__ResourcePath)</ResourcePath>
- <ResourcePath Condition="'$(DCC_TranslatedResourcePath)' != ''">$(DCC_TranslatedResourcePath);$(ResourcePath)</ResourcePath>
<NameSpace Condition="'DelphiNamespaceSearchPath'!=''">$(NameSpace);$(DelphiNamespaceSearchPath)</NameSpace>
Run Code Online (Sandbox Code Playgroud)
War*_* P 1
现在我明白了这个问题的根源。请投票支持鲁福爵士,因为他让我想到了解决方案。
是这样的:我调用 DCC32.exe 来编译包(使用 .dpk,但没有 .dproj 文件,并且不调用 msbuild 来编译这些包)。当我构建这些时,我没有将调试 DCU 路径插入到通过-I参数传入的库路径的头部DCC32.exe。
一旦 DCC32.exe 包编译库搜索路径首先具有 Debug DCU 文件夹,它就可以工作。
如果有人对这样的软件包系统感兴趣,我计划开源这个软件包构建系统,作为重新启动最初由 Juancarlo Anez 构建的 WANT 项目的一部分,我可能会用一个新名称来称呼该项目。一旦组件构建系统的工作演示可用,我将更新此答案。
满足我在问题中提出的要求的工作系统的简要概述:
您将需要一个文件(可以是 xml、ini、json 文件)来定义要构建的包列表。
您需要对其中每一个调用 MSBUILD 或 DCC32.exe。您可以编写自己的代码,也可以使用我的代码,我会尽可能将其开源。
仅当调用调试项构建时,您才需要将调试 DCU DPROJ 作为第一项包含到库路径中。
您将需要$(OURCOMPANYLIBRARYDCU)\$(Platform)\$(Config)在项目搜索路径和库路径中使用宏。
在 Delphi IDE 中,您需要将其硬编码$(OURCOMPANYLIBRARYDCU)\$(Platform)\Release为库路径中的路径。
在 Delphi IDE 中,您需要将其硬编码$(OURCOMPANYLIBRARYDCU)\$(Platform)\Debug为 Debug DCU 路径中的路径。