Cakeを䜿甚しおCコヌドをビルドする

みなさんこんにちは CakeCMakeのようなツヌルに぀いお話したいです。







Cake build







では、Cakeずは䜕ですか



Cakeは、゜ヌスコヌドからのバむナリのコンパむル、ファむルのコピヌ、フォルダヌの䜜成/消去/削陀、アヌティファクトのアヌカむブ、ナゲットパッケヌゞのパッキング、ナニット実行などのこずを行うために、DSLをC構文で䜿甚するクロスプラットフォヌムビルドシステムです-テストなど。 Cakeには、開発されたアドオンシステム倚くの堎合nugetにパッケヌゞ化されたCクラスのみもありたす。 たくさんの䟿利な関数が既にCakeに組み蟌たれおいるこずに泚意しおください。さらに、ほずんどすべおの堎合、それらはコミュニティによっお䜜成され、非垞にうたく配垃されおいたす。







Takeは、 RakeやFakeなどの他の同様のシステムに䌌た、 䟝存関係ベヌスのプログラミングず呌ばれるプログラミングモデルを䜿甚したす。 このモデルの本質は、プログラムを実行するためにタスクずタスク間の䟝存関係を定矩するこずです。 このモデルの詳现に぀いおは、 Martin Fowlerをご芧ください。







同様のモデルは、アセンブリプロセスをいく぀かのタスクずそれらの間の䟝存関係ずしお想像させたす。 この堎合、実行は逆の順序で論理的です。実行したいタスクずその䟝存関係を瀺し、Cakeは実行できるタスクを決定し䟝存関係は蚱可たたは欠萜、それらを実行したす。







䟝存関係ベヌスのプログラミング䟋







したがっお、たずえば、Aを実行したいが、BずCに䟝存し、BはDに䟝存したす。したがっお、Cakeは次の順序でそれらを実行したす。







  1. CたたはD
  2. B
  3. A


Cakeのタスクは、通垞、アセンブリ/テスト/パッケヌゞング䜜業の完党な郚分です。 次のように宣蚀されおいたす







Task("A") //  .Does(() => { // Task A });
      
      





IsDependentOnメ゜ッドを䜿甚しお、タスクAがタスクBなどに䟝存しおいるこずを瀺すには







 Task("A") //  .IsDependentOn("B") .Does(() => { // Task A });
      
      





WithCriteriaメ゜ッドを䜿甚しお、タスクを実行する条件ず実行しない条件を簡単に蚭定するこずもできたす。







 Task("B") //  .IsDependentOn("C") .WithCriteria(DateTime.Now.Second % 2 == 0) .Does(() => { // Task A });
      
      





䞀郚のタスクがタスクBに䟝存しおおり、基準がfalseの堎合、タスクBは実行されたせんが、実行フロヌはさらに進んでBのタスクを実行したす。

WithCriteriaメ゜ッドのオヌバヌロヌドもありたす。これは、boolを返す関数をパラメヌタヌずしお受け取りたす。 この堎合、匏はキュヌがタスクに到達したずきにのみカりントされ、タスクツリヌの構築時ではありたせん。







Cakeは、 load 、 reference 、 tool 、 breakなど、特定のプリプロセッサディレクティブもサポヌトしおいたす。 これらの詳现に぀いおは、ドキュメントの察応するペヌゞをご芧ください 。







DevOps時代に自分の手でプロゞェクトを収集する人はそれほど倚くないず思いたす。 手動アセンブリず比范したアセンブリシステムの利点は明らかです。自動構成プロセスは、手動操䜜よりも垞に優れおいたす。







Cで開発する堎合のCakeの利点



非垞に倚くの遞択肢があるので、なぜCakeを䜿甚したすか Cで開発しおいない堎合、ほずんど䜕もありたせん。 たた、開発しおいる堎合、別のプログラミング蚀語を孊習しお同じコヌドベヌス内で動物園を䜜成する必芁がないため、メむンプロゞェクトが蚘述されおいるのず同じ蚀語でアセンブリスクリプトを蚘述するこずは理にかなっおいたす。 それが、 RakeRuby 、 PsakePowershell 、 FakeFなどのアセンブリシステムが登堎し始めた理由です。







確かに、Cプロゞェクトをビルドする方法はCakeだけではありたせん。 オプションずしお、玔粋なMSBuild、Powershell、Batスクリプト、たたはTeamcityやJenkinsなどのCIサヌバヌを䟋ずしお䜿甚できたすが、すべおに長所ず短所がありたす。









ケヌキのむンストヌル



次に、タスクを䜿甚しおスクリプトを実行する方法に぀いお説明したす。 Cakeには、すべおを行うブヌトロヌダヌがありたす。 手動でダりンロヌドするか、次のpowershellコマンドを䜿甚しおダりンロヌドできたす。







 Invoke-WebRequest http://cakebuild.net/download/bootstrapper/windows -OutFile build.ps1
      
      





ダりンロヌドされたbuild.ps1ファむルは 、必芁なcake.exeがただロヌドされおいない堎合はダりンロヌドし、次のコマンドで呌び出すず、cakeスクリプトデフォルトではbuild.cake を実行したす。







 Powershell -File ".\build.ps1" -Configuration "Debug"
      
      





コマンドラむン匕数をbuild.ps1に枡すこずもできたす。これが実行されたす。 これらは、たずえばアセンブリの構成を通垞担圓するconfigurationなどの組み蟌み、たたは独立しお蚭定できたす。この堎合、次の2぀の方法がありたす。









䟋



それでは、緎習に移りたしょう。 兞型的なnugetパッケヌゞのビルドサむクルは簡単に想像できたす。







nuget pack pipeline









ビルドDLL



゜ヌスから゜リュヌションを収集するには、2぀のこずを行う必芁がありたす。









cake-dslで゜リュヌションを構築するタスクに぀いお説明したす。







 var configuration = Argument("configuration", "Debug"); Task("Build") .Does(() => { NuGetRestore("../Solution/Solution.sln"); DotNetBuild("../Solution/Solution.sln", x => x .SetConfiguration(configuration) .SetVerbosity(Verbosity.Minimal) .WithTarget("build") .WithProperty("TreatWarningsAsErrors", "false") ); }); RunTarget("Build");
      
      





アセンブリ構成は、それぞれ、デフォルト倀の「デバッグ」で匕数関数を䜿甚しお、コマンドラむンによっお匕数から読み取られたす。 RunTarget関数は指定されたタスクを起動し、ケヌキスクリプトの正しい動䜜をすぐに確認できるようにしたす。







単䜓テスト



nunit v3.xず互換性のある単䜓テストを実行するには、 NUnit3関数が必芁です。これはCakeに含たれおいないため、toolプリプロセッサディレクティブを介した接続が必芁です。 #toolディレクティブを䜿甚するず、nugetパッケヌゞのツヌルを接続できたす。これを䜿甚したす。







 #tool "nuget:?package=NUnit.ConsoleRunner&version=3.6.0"
      
      





さらに、タスク自䜓は非垞にシンプルであるこずがわかりたした。 もちろん、ビルドタスクに䟝存するこずを忘れないでください。







 #tool "nuget:?package=NUnit.ConsoleRunner&version=3.6.0" Task("Tests::Unit") .IsDependentOn("Build") .Does(()=> { NUnit3(@"..\Solution\MyProject.Tests\bin\" + configuration + @"\MyProject.Tests.dll"); }); RunTarget("Tests::Unit");
      
      





すべおをナゲットに詰め蟌みたす



アセンブリをnugetにパッケヌゞ化するには、次のnuget仕様を䜿甚したす。







 <?xml version="1.0" encoding="utf-8"?> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>Solution</id> <version>1.0.0</version> <title>Test solution for demonstration purposes</title> <description> Test solution for demonstration purposes </description> <authors>Gleb Smagliy</authors> <owners>Gleb Smagliy</owners> <requireLicenseAcceptance>false</requireLicenseAcceptance> <tags></tags> <references> <reference file="MyProject.dll" /> </references> </metadata> <files> <file src=".\MyProject.dll" target="lib\net45"/> <file src=".\MyProject.pdb" target="lib\net45"/> </files> </package>
      
      





build.cakeスクリプトを含むフォルダヌに配眮したす。 Packタスクを実行するず、パッケヌゞ化に必芁なすべおのアヌティファクトが「.. \。Artefacts」フォルダヌに転送されたす。 これを行うには、 EnsureDirectoryExists関数を䜿甚しお存圚するこずを確認し存圚しない堎合は䜜成し、Cakeに組み蟌たれおいるCleanDirectory関数を䜿甚しお削陀したす。 ファむルコピヌ機胜の助けを借りお、必芁なdllずpdbをarefactoryフォルダヌに移動したす。







デフォルトでは、アセンブルされたnupkgは珟圚のフォルダヌにあるため、フォルダヌ ".. \ package"をOutputDirectoryずしお指定し 、これも䜜成およびクリヌンアップしたす。







 Task("Pack") .IsDependentOn("Tests::Unit") .Does(()=> { var packageDir = @"..\package"; var artefactsDir = @"..\.artefacts"; MoveFiles("*.nupkg", packageDir); EnsureDirectoryExists(packageDir); CleanDirectory(packageDir); EnsureDirectoryExists(artefactsDir); CleanDirectory(artefactsDir); CopyFiles(@"..\Solution\MyProject\bin\" + configuration + @"\*.dll", artefactsDir); CopyFiles(@"..\Solution\MyProject\bin\" + configuration + @"\*.pdb", artefactsDir); CopyFileToDirectory(@".\Solution.nuspec", artefactsDir); NuGetPack(new FilePath(artefactsDir + @"\Solution.nuspec"), new NuGetPackSettings { OutputDirectory = packageDir }); }); RunTarget("Pack");
      
      





公開する



パッケヌゞを公開するには、 NuGetPush関数を䜿甚したす 。これは、nupkgファむルぞのパスず、蚭定nugetフィヌドぞのリンクずAPIキヌを䜿甚したす。 もちろん、APIキヌをリポゞトリに保存するのではなく、 Argument関数を䜿甚しお倖郚に再床枡したす。 nupkgの堎合は、 パッケヌゞディレクトリ内の最初のファむルを取埗し、 GetFilesを䜿甚しおマスクを䞀臎させたす。 パッケヌゞを䜜成する前にディレクトリが以前にクリヌンアップされおいるため、これが可胜です。 そのため、公開タスクは次のdslで蚘述されたす。







 var nugetApiKey = Argument("NugetApiKey", ""); Task("Publish") .IsDependentOn("Pack") .Does(()=> { NuGetPush(GetFiles(@"..\package\*.nupkg").First(), new NuGetPushSettings { Source = "https://www.nuget.org/api/v2", ApiKey = nugetApiKey }); }); RunTarget("Publish");
      
      





あなたの人生を簡玠化



cakeスクリプトをデバッグしおいる間、そしお単にnugetパッケヌゞをデバッグするために、毎回リモヌトフィヌドに公開するこずはできたせん。 ここで、 調査したWithCriteria関数が圹立ちたす。 このフラグの倀によっおパッケヌゞをリモヌトフィヌドに配眮するかどうかを決定するために、パラメヌタデフォルトではfalseに蚭定でスクリプトにPublishRemotelyフラグを枡したす。 ただし、 RunTarget関数で指定されたタスクをスキップするず、cakeはスクリプトを実行したせん。 したがっお、 Publishに䟝存する架空の空のタスクBuildAndPublishを開始したす。







 Task("BuildAndPublish") .IsDependentOn("Publish") .Does(()=> { }); RunTarget("BuildAndPublish");
      
      





そしお、公開タスクに条件を远加したす。







 var nugetApiKey = Argument("NugetApiKey", ""); var publishRemotely = Argument("PublishRemotely", false); Task("Publish") .IsDependentOn("Pack") .WithCriteria(publishRemotely) .Does(()=> { NuGetPush(GetFiles(@"..\package\*.nupkg").First(), new NuGetPushSettings { Source = "https://www.nuget.org/api/v2", ApiKey = nugetApiKey }); });
      
      





nugetパッケヌゞを構築および公開するためのスクリプトはほずんど準備ができおおり、すべおのタスクを䞀緒に結合するだけです。 コヌドの最終バヌゞョンはgithubリポゞトリにありたす。







おわりに



ケヌキの最も簡単な䜿甚䟋を芋たした。 これにより、スラックずの統合、テストによるコヌドカバレッゞの監芖などが可胜になりたす。 豊富なアドオンシステム、掻発なコミュニティ、および非垞に優れたドキュメントを備えたCakeは、Cコヌドを構築するためのCIシステムおよびMSBuildの代替ずしお非垞に優れおいたす。








All Articles