我经常碰到一个事实,Delphi开发人员(传统上可以说)使用“ pens”来编译应用程序,这远非生产解决方案,但从外部看起来像是“擦洗”并“在膝盖上做”,尽管这些产品非常认真且可出售。这可能可以追溯到自动化的时代,当时有必要提出自己的批处理文件,dcc32
以必要的参数启动命令行编译器。一些人甚至创建了自己的“发布者”-Delphi-expert,它负责组装服务器的工作:编译项目(尽管在IDE中打开),使用从某个数据库获取的递增版本号进行公开,编写某种变更日志并将其复制到某个地方网络目录。
我将不会像以前那样进行历史考察。我将告诉您现在如何吃/可以吃,以及如何使用它来提高工作效率。
现代版本的Delphi的项目文件是一个.dproj
文件(以下我将重点介绍Delphi 10 Rio,但从2007年开始,对于所有早期版本的Delphi都是如此)。它存储所有项目设置,通常在IDE中更改它们(菜单Project - Options (Ctrl+Shift+F11)
)。在本文中,我将重点介绍演示通用原则所需的“核心”要素:这Config
是配置,Platform
平台,OutputDirectory
输出文件的路径和ConditionalDefines
(条件编译指令)。其余设置(如果需要在组装过程中进行任何更改),我建议您确定自己的身份。.dproj
如果使用常规文本编辑器查看该文件,则此文件只不过是MSBuild构建脚本(让我们创建一个简单的控制台应用程序并将其命名为DelphiAutomatedBuild):
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{6880AD8E-6CB3-47B9-B8E3-7304CF6E9735}</ProjectGuid>
<ProjectVersion>18.1</ProjectVersion>
<FrameworkType>None</FrameworkType>
<MainSource>DelphiAutomatedBuild.dpr</MainSource>
<Base>True</Base>
<Config Condition="'$(Config)'==''">Debug</Config>
<Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms>
<AppType>Console</AppType>
</PropertyGroup>
...
MSBuild构建脚本还用于描述项目,例如Visual Studio。我将详细介绍MSBuild的一些细节,但是我建议读者自己掌握其基础知识。这给了我们什么?这样一来,我们就可以在命令行中用一行来构建一个Delphi项目(这反过来又可以使我们自动进行项目的组装)
msbuild /t:build DelphiAutomatedBuild.dproj
MSBuild? Delphi, MSBuild , Delphi . , %WINDIR%\Microsoft.Net\Framework\v3.5
, .Net 4.0/4.5/4.6. Microsoft. MSBuild 4.0, ,
(hint: , () IDE — Show in Explorer, — ), :
...>msbuild /t:build DelphiAutomatedBuild.dproj
"msbuild"
, .
. , MSBuild- PATH
. :
set PATH=%WINDIR%\Microsoft.Net\Framework\v3.5;%PATH%
:
...>msbuild /t:build DelphiAutomatedBuild.dproj
Microsoft (R) Build Engine 12.0.21005.1
[Microsoft .NET Framework 4.0.30319.42000]
(C) (Microsoft Corporation). .
24.11.2018 0:12:14.
"Z:\habr\delphi-automate-build\DelphiAutomatedBuild.dproj" 1 ( build).
Z:\habr\delphi-automate-build\DelphiAutomatedBuild.dproj : error MSB4057: "build".
"Z:\habr\delphi-automate-build\DelphiAutomatedBuild.dproj" ( build) .
.
"Z:\habr\delphi-automate-build\DelphiAutomatedBuild.dproj" ( build ) (1) ->
Z:\habr\delphi-automate-build\DelphiAutomatedBuild.dproj : error MSB4057: "build".
: 0
: 1
: 00:00:00.04
, . ? build
?
.dproj
-, :
...
<Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
...
Delphi
c:\Program Files\Embarcadero\Studio\20.0\Bin\CodeGear.Delphi.Targets
, MSBuild-, Build
:
<Target Name="Build"...
.. BDS
($(VAR)
MSBuild (Property) VAR
, , ), Delphi, (-, Delphi, BDS
). $(BDS)
, .Targets
Delphi Build
.
:
set BDS=c:\Program Files\Embarcadero\Studio\20.0
...>msbuild /t:build DelphiAutomatedBuild.dproj
Microsoft (R) Build Engine 12.0.21005.1
[Microsoft .NET Framework 4.0.30319.42000]
(C) (Microsoft Corporation). .
24.11.2018 0:20:40.
"Z:\habr\delphi-automate-build\DelphiAutomatedBuild.dproj" 1 ( build).
CreateProjectDirectories:
".\Win32\Debug".
BuildVersionResource:
C:\Program Files\Embarcadero\Studio\20.0\bin\cgrc.exe -c65001 DelphiAutomatedBuild.vrc -foDelphiAutomatedBuild.res
CodeGear Resource Compiler/Binder
Version 1.2.2 Copyright (c) 2008-2012 Embarcadero Technologies Inc.
Microsoft (R) Windows (R) Resource Compiler Version 6.0.5724.0
Copyright (C) Microsoft Corporation. All rights reserved.
"DelphiAutomatedBuild.vrc" .
_PasCoreCompile:
C:\Program Files\Embarcadero\Studio\20.0\bin\dcc32.exe -$O- -$W+ --no-config -B -Q -TX.exe -AGenerics.Collections=System.Generics.Collections;Generics.Defaults=System.Generics.Defaults;WinTypes=Winapi.Windows;WinProcs=Winapi.Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE -DDEBUG -E.\Win32\Debug -I"c:\program files\embarcadero\studio\20.0\lib\Win32\debug";"c:\program files\embarcadero\studio\20.0\lib\Win32\release";C:\Users\USER\Documents\Embarcadero\Studio\20.0\Imports;"C:\Program Files\Embarcadero\Studio\20.0\Imports";"C:\Users\Public\Documents\RAD Studio\5.0\Dcp";"C:\Program Files\Embarcadero\Studio\20.0\include";C:\Users\USER\AppData\Local\Programs\TestInsight\Source -LE"C:\Users\Public\Documents\RAD Studio\5.0\Bpl" -LN"C:\Users\Public\Documents\RAD Studio\5.0\Dcp" -NU.\Win32\Debug -NSWinapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;System;Xml;Data;Datasnap;Web;Soap; -O"c:\program files\embarcadero\studio\20.0\lib\Win32\release";C:\Users\USER\Documents\Embarcadero\Studio\20.0\Imports;"C:\Program Files\Embarcadero\Studio\20.0\Imports";"C:\Users\Public\Documents\RAD Studio\5.0\Dcp";"C:\Program Files\Embarcadero\Studio\20.0\include";C:\Users\USER\AppData\Local\Programs\TestInsight\Source -R"c:\program files\embarcadero\studio\20.0\lib\Win32\release";C:\Users\USER\Documents\Embarcadero\Studio\20.0\Imports;"C:\Program Files\Embarcadero\Studio\20.0\Imports";"C:\Users\Public\Documents\RAD Studio\5.0\Dcp";"C:\Program Files\Embarcadero\Studio\20.0\include";C:\Users\USER\AppData\Local\Programs\TestInsight\Source -U"c:\program files\embarcadero\studio\20.0\lib\Win32\debug";"c:\program files\embarcadero\studio\20.0\lib\Win32\release";C:\Users\USER\Documents\Embarcadero\Studio\20.0\Imports;"C:\Program Files\Embarcadero\Studio\20.0\Imports";"C:\Users\Public\Documents\RAD Studio\5.0\Dcp";"C:\Program Files\Embarcadero\Studio\20.0\include";C:\Users\USER\AppData\Local\Programs\TestInsight\Source -CC -V -VN -NB"C:\Users\Public\Documents\RAD Studio\5.0\Dcp" -NH"C:\Users\Public\Documents\RAD Studio\5.0\hpp\Win32" -NO.\Win32\Debug DelphiAutomatedBuild.dpr
Embarcadero Delphi for Win32 compiler version 30.0
Copyright (c) 1983,2015 Embarcadero Technologies, Inc.
19 lines, 0.27 seconds, 100748 bytes code, 26044 bytes data.
"Z:\habr\delphi-automate-build\DelphiAutomatedBuild.dproj" ( build).
.
: 0
: 0
: 00:00:01.32
-! . Win32\Debug
DelphiAutomatedBuild.exe
.
( , Debug-), Release- ( ). IDE , , , , . .dproj
-,
...
<Config Condition="'$(Config)'==''">Debug</Config>
...
, , / Config
, , Debug
. , IDE ( IDE Release —
...
<Config Condition="'$(Config)'==''">Release</Config>
...
:
{$IFDEF RELEASE}
WriteLn('This is RELEASE build');
{$ENDIF RELEASE}
{$IFDEF DEBUG}
WriteLn('This is DEBUG build');
{$ENDIF DEBUG}
, conditional defines Release Debug- RELEASE DEBUG,
Config
, :
...>msbuild /t:build DelphiAutomatedBuild.dproj /p:Config=Release
Microsoft (R) Build Engine 12.0.21005.1
[Microsoft .NET Framework 4.0.30319.42000]
(C) (Microsoft Corporation). .
24.11.2018 0:48:30.
"Z:\habr\delphi-automate-build\DelphiAutomatedBuild.dproj" 1 ( build).
CreateProjectDirectories:
".\Win32\Release".
...
...>Win32\Debug\DelphiAutomatedBuild.exe
This is DEBUG build
...>Win32\Release\DelphiAutomatedBuild.exe
This is RELEASE build
!
( ) - , , , — - . , . .dproj
:
...
<DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
...
? ( ), , ?
...>msbuild /t:build DelphiAutomatedBuild.dproj /p:DCC_ExeOutput=binaries
-! binaries
, — DelphiAutomatedBuild.exe
. ? , MSBuild
, , , MSBuild
-, , . . ...
. , (, ). , Config
— Debug
, — — Release
, , -, (, DCC_ExeOutput
( — )), -, , ( , MSBuild- ).
...>msbuild /t:build DelphiAutomatedBuild.dproj /p:DCC_ExeOutput=binaries
. ? !
Build
. - , IDE ( ; , MMX: DProjNormalizer, DProjSplitter — ProjectMagician — .dproj
-), . DAB.ciproj (CI-project, CI — Continuous Integration):
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build">
<MSBuild Projects="DelphiAutomatedBuild.dproj"
Targets="Build"
Properties="Config=Debug"/>
<MSBuild Projects="DelphiAutomatedBuild.dproj"
Targets="Build"
Properties="Config=Release"/>
</Target>
</Project>
...>msbuild /t:build DAB.ciproj /p:DCC_ExeOutput=binaries
… DelphiAutomatedBuild.exe
binaries
, , :
...>binaries\DelphiAutomatedBuild.exe
This is RELEASE build
DCC_Exeoutput
MSBuild — , . :
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build">
<MSBuild Projects="DelphiAutomatedBuild.dproj"
Targets="Build"
Properties="Config=Debug;DCC_Exeoutput=$(DCC_ExeOutput)\Debug"/>
<MSBuild Projects="DelphiAutomatedBuild.dproj"
Targets="Build"
Properties="Config=Release;DCC_Exeoutput=$(DCC_ExeOutput)\Release"/>
</Target>
</Project>
...>msbuild /t:build DAB.ciproj /p:DCC_ExeOutput=binaries
binaries\Debug\DelphiAutomatedBuild.exe
binaries\Release\DelphiAutomatedBuild.exe
.
...>binaries\Debug\DelphiAutomatedBuild.exe
This is DEBUG build
...>binaries\Release\DelphiAutomatedBuild.exe
This is RELEASE build
, / conditional define (, -, , TRIAL )
-
{$IFDEF TRIAL}
WriteLn('This is TRIAL version');
{$ENDIF TRIAL}
Debug- conditional define TRIAL , .dproj:
<DCC_Define>DEBUG;TRIAL;$(DCC_Define)</DCC_Define>
, .. /p:DCC_Define=TRIAL,
...>msbuild /t:build DAB.ciproj /p:DCC_ExeOutput=binaries /p:DCC_Define=TRIAL
...>binaries\Debug\DelphiAutomatedBuild.exe
This is TRIAL version
...>binaries\Release\DelphiAutomatedBuild.exe
This is TRIAL version
, - , - DEBUG RELEASE, , .. define-.
, , . .
DCC_Define
:
...>set DCC_Define=TRIAL
...>msbuild /t:build DAB.ciproj /p:DCC_ExeOutput=binaries
...
...>binaries\Debug\DelphiAutomatedBuild.exe
This is DEBUG build
This is TRIAL version
...>binaries\Release\DelphiAutomatedBuild.exe
This is RELEASE build
This is TRIAL version
, , ( Git, SVN ) , , , , .
, . ? , , — - "-", , ( " " — ).
Windows/Delphi- Major.Minor.Release.Build
, , , Release
, , , . , , .dproj-
<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
, . FileVersion=0.0.0.0
, , FileVersion=$(Version)
, Version
— , , , IDE — , .. "" . . , , — CSV-, .
, . MSBuild 4.0 C#, ( , PATH ).
Delphi.Version.Targets<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' ToolsVersion="12.0">
<UsingTask TaskName="__SetFileVersion" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
<ParameterGroup>
<VerInfoKeys ParameterType="System.String" Required="true" />
<VerInfoProperties ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<Out ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs"><![CDATA[
// split values as CSV (by ";")
String[] verInfoKeysList = VerInfoKeys.Split(';');
Dictionary<String, String> d = new Dictionary<String, String>();
foreach (String verInfoValue in verInfoKeysList) {
// split values as "key=value"
if (! String.IsNullOrEmpty(verInfoValue)) {
String[] kv = verInfoValue.Split('=');
d.Add(kv[0], kv[1]);
}
}
if (VerInfoProperties.Length > 0) {
foreach (ITaskItem item in VerInfoProperties) {
String value = item.GetMetadata("Value");
if (value.Length > 0) {
Log.LogMessage("{0}: {1}", item.ItemSpec, value);
d.Remove(item.ItemSpec);
d.Add(item.ItemSpec, value);
}
}
}
List<String> L = new List<String>();
foreach (KeyValuePair<String, String> kv in d) {
L.Add(kv.Key + "=" + kv.Value);
}
_Out = String.Join(";", L.ToArray());
]]></Code>
</Task>
</UsingTask>
<Target Name='_SetVersionCode_Name'>
<Message Text="$(VerInfo_Keys)" />
<ItemGroup>
<VerInfoProperties Include="FileVersion">
<Value>$(FileVersion)</Value>
</VerInfoProperties>
</ItemGroup>
<__SetFileVersion VerInfoKeys="$(VerInfo_Keys)" VerInfoProperties="@(VerInfoProperties)">
<Output PropertyName="VerInfo_Keys" TaskParameter="Out" />
</__SetFileVersion>
<Message Text="$(VerInfo_Keys)" />
</Target>
<Target Name='_SetFileVersion' BeforeTargets="_BuildRCFile"
Condition="'$(FileVersion)' != ''">
<CallTarget Targets='_SetVersionCode_Name'/>
</Target>
</Project>
.
DelphiAutomatedBuild.dproj
...
<Import Project="Delphi.Version.Targets" Condition="$(MSBuildToolsVersion) >= 4.0" />
...
( "$(MSBuildToolsVersion) >= 4.0" , IDE, , , MSBuild 3.5, UsingTask)
, _SetFileVersion
, _BuildRCFile
( : , — . $(BDS)\bin\Codegear.Common.Targets
), FileVersion
. CSV- VerInfo_Keys
, -, , VerInfo_Keys
.
"Include version information in project" ( ), :
...>msbuild /t:build DAB.ciproj /p:DCC_ExeOutput=binaries /p:FileVersion=4.3.2.1
...>binaries\Debug\DelphiAutomatedBuild.exe
This is RELEASE build
This is TRIAL version
This file version is 4.3.2.1
...>binaries\Release\DelphiAutomatedBuild.exe
This is DEBUG build
This is TRIAL version
This file version is 4.3.2.1
Profit!
Delphi- , , , , , , . , ( ), .
- ( FixInsight, !)
- unit- Delphi (, ))). )
- "" Delphi- GitLab CI
- 以及如何使用WinDbg调试器,例如,查找因Delphi编写的库而导致应用程序崩溃/崩溃的原因(当然,如何将为此所需的PDB文件格式集成到自动组装中)
Z.Y. 我将很乐意在PM以及@Delphi_Lazarus和@DelphiCommunity中回答任何问题,包括电报