بناء آلي لتطبيق دلفي

في كثير من الأحيان ، صادفت حقيقة أن مطوري دلفي (يمكن للمرء أن يقول تقليديًا) يجمعون تطبيقاتهم باستخدام "أقلام" ، وهي بعيدة عن حل الإنتاج ، ولكن من الخارج تبدو مثل فرك و "تفعل ذلك على الركبة" ، على الرغم من أن المنتجات خطيرة للغاية وقابلة للبيع . ربما يرجع ذلك إلى الوقت الذي كانت فيه الأتمتة بحاجة إلى التوصل إلى ملفات دفعية خاصة بها والتي بدأت مترجم سطر الأوامر dcc32بالمعلمات الضرورية. حتى أن البعض صنع "الناشر" الخاص بهم - خبير دلفي ، الذي يقوم بعمل خادم التجميع: يجمع المشروع (على الرغم من أنه مفتوح في IDE) ، ويكشفه برقم إصدار متزايد مأخوذ من بعض قواعد البيانات ، ويكتب نوعًا من التغيير وينسخه في مكان ما إلى دليل الشبكة .


لن أخوض في رحلة تاريخية كما كانت من قبل . سأخبرك الآن كيف تأكل / تستطيع الآن ، وكيف تستخدمها لزيادة كفاءة عملي.


ملف مشروع النسخة الحديثة من دلفي هو .dprojملف (فيما يلي سوف أركز على دلفي 10 ريو ، ولكن مع اختلافات طفيفة هذا ينطبق على جميع الإصدارات السابقة من دلفي ، ابتداء من عام 2007). يقوم بتخزين جميع إعدادات المشروع ، والتي عادة ما يتم تغييرها في 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 ، لكنني أقترح أن يتقن القارئ أساسياته من تلقاء نفسه . ماذا يعطينا هذا؟ هذا يسمح لنا ببناء مشروع دلفي من سطر الأوامر مع سطر واحد ( والذي بدوره يسمح لنا بأتمتة تجميع المشروع )


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-, , . . ...


. , (, ). , ConfigDebug, — — Release, , -, (, DCC_ExeOutput ( — )), -, , ( , MSBuild- ).


...>msbuild /t:build DelphiAutomatedBuild.dproj /p:DCC_ExeOutput=binaries

. ? !
Build. - , IDE ( ; , MMX: DProjNormalizer, DProjSplitterProjectMagician.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- , , , , , , . , ( ), .



  1. ( FixInsight, !)
  2. unit- Delphi (, ))). )
  3. "" Delphi- GitLab CI
  4. وكذلك كيفية استخدام مصحح أخطاء WinDbg ، على سبيل المثال ، للعثور على أسباب أعطال / أعطال التطبيق بسبب المكتبات المكتوبة في دلفي (بالطبع ، بالطبع ، كيفية دمج تشكيل ملفات PDB اللازمة لهذا في التجميع التلقائي)

Z.Y. يسعدني الرد على أي أسئلة ، بما في ذلك في برقية ، سواء في PM أو في Delphi_Lazarus و DelphiCommunity دردشات


All Articles