Build Server Scripting

(Zurück zu: Infos)

  1. Einleitung
    1. Ziele
  2. Windows Server Implementierung
    1. Docker Setup
    2. Source Build Script
    3. Server Build Script

Einleitung

Während früher ein Entwickler auf seiner eigenen Maschine nur zur Mond- oder Sonnenwende ein neues Software-Kompilat erzeugen wollte, spricht man heute von Continuous Integration und Continous Delivery (kurz CI und CD) und meint damit meist, dass zu jeder Zeit ein Softwarestand lieferfertig gemacht werden können soll.

Azure-DevOps oder Team-Foundation Server, TeamCity, Jenkins, GitLab … so heißen einige der bekannten Build-Server, mit denen man automatisiert das Kompilieren von Quellcodes anstoßen kann. Sie alle bringen ihre Vorteile am Einsatzort zum Tragen und helfen dabei, die Auslieferung von Software zu automatisieren und auch zu standardisieren.

Ich möchte aber für meine Sourcen auf meinen minimalistischen Systemen keine aufwändigen Dienste wie Datenbanken und Webserver installieren, und suche daher eine Möglichkeit, Builds ohne Zusatztools automatisch anzustarten.

Ziele

  • Ein Docker Image stellt eine Build-Umgebung mit allen nötigen Tools bereit
  • Ein Script lädt Quellcodes per GIT am Host-System herunter.
  • Der Docker Container erhält Zugriff auf die Sourcen am Host und startet ein individuelles Build-Script
  • Ein Script sammelt die Build-Ergebnisse ein und legt sie komprimiert in einem Unterverzeichnis ab.
graph LR S[Start
Server
Script] subgraph Shared Folder between Host and Docker G(GIT
Download) SS((Source
Build
Script)) D(Docker
Container) A(Store
Artifacts) end F[Finish
Server
Script] S --> G G --> D D --> A A --> F D --> SS SS --> D

Windows Server Implementierung

Voraussetzungen

Die Build-Automations-Scripts können auf einem Windows Server mit Docker Unterstützung mitlaufen. Das Beispiel sollte allerdings auch mit Docker Desktop funktionieren.

Wir brauchen dafür eine Docker-kompatible Visual Studio Umgebung für C++ Projekte. Natürlich sind auch andere Umgebungen möglich, auf diese wird aber hier nicht eingegangen.

Dann muss GIT für Windows auf dem Server installiert werden.

Und am Ende benötigen wir einen Ordner, in dem die Projekte heruntergeladen und gebaut werden können.

Docker Setup

Ab Visual Studio 2017 ist das Bauen in Docker offiziell unterstützt. Die Installation wird vom VS-Build-Tools Installer eingeleitet, der unter folgenden Adressen verfügbar ist:

Dem Installer kann per Kommandazeile aufgetragen werden, welche Teilkomponenten er laden und installieren soll.
Für VC++ sind die Workload-Pakete Microsoft.VisualStudio.Workload.MSBuildTools und Microsoft.VisualStudio.Workload.VCTools erforderlich. Zusätzlich wollen wir, dass auch “empfohlene” Zusatzpakete installiert werden, womit wir die Windows SDK und CMake erhalten.

Das Dockerfile hierfür sieht wie folgt aus:

 1# escape=`
 2
 3# Select the required Windows Server Release:
 4#FROM mcr.microsoft.com/windows/servercore:ltsc2016
 5#FROM mcr.microsoft.com/windows/servercore:ltsc2019
 6FROM mcr.microsoft.com/windows/servercore:ltsc2022
 7
 8SHELL ["cmd", "/S", "/C"]
 9
10RUN `
11  curl -SL --output vs_buildtools.exe `
12    https://aka.ms/vs/15/release/vs_buildtools.exe `
13  && (start /w `
14    vs_buildtools.exe --quiet --wait --norestart --nocache `
15    --installPath `
16      "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\BuildTools" `
17    --add Microsoft.VisualStudio.Workload.MSBuildTools `
18    --add Microsoft.VisualStudio.Workload.VCTools `
19    --includeRecommended `
20  || IF "%ERRORLEVEL%"=="3010" EXIT 0) `
21  && del /q vs_buildtools.exe
22
23ENTRYPOINT [ `
24"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\Common7\\Tools\\VsDevCmd.bat", `
25"&&", "cmd.exe", "/S", "/C"]

Mit dem Aufruf von
docker build -t msvc-build:2017 -f Dockerfile . im Verzeichnis der Datei wird das Docker-Image erstellt und mit dem TAG msvc-build:2017 abgelegt.

Dockerfile lädt den Visual Studio 2017 Installer herunter, startet ihn über das start Kommando und wartet bis die Installation fertig ist.

Als ENTRYPOINT wird das Visual Studio-Environment Script geladen, damit alle notwendigen Tools in die Environment-Variablen geladen werden.

Source Build Script

Den zu bauenden Quellcodes sollte ein Script beiliegen, das den gesamten Kompiliervorgang verwalten kann.
Wichtig ist dabei zu wissen, wo das Build-Script am Ende seine Daten ablegt, denn von der Stelle muss das Folgescript die fertigen Binaries abholen können.

Am einfachsten ist es, im Stammverzeichnis des Projektes eine Datei namens build.bat abzulegen.

Beispiel Visual Studio Solution

Wer eine Visual Studio Solution (*.sln) mit den Quellen in GIT eingecheckt hat, braucht nur msbuild in der Batch Datei aufzurufen.

1msbuild .\my-project.sln /t:Rebuild /p:configuration=release /p:platform=x64 /m

Die Binärdateien sollten dann in .\x64\Release ausgegeben werden.

Im Falle von 32-Bit Kompilaten, liegen sie in .\Release, wenn sie wie folgt erzeugt werden:

1msbuild .\my-project.sln /t:Rebuild /p:configuration=release /p:platform=win32 /m

Beispiel CMAKE

In CMakeLists.txt lässt sich per Variable definieren, wohin Binaries am Ende geschrieben werden sollen:

1set(MY_OUTPUT_PATH  "${CMAKE_BINARY_DIR}/output" )
2
3set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${MY_OUTPUT_PATH}" 
4    CACHE PATH "Shared library target directory")
5set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${MY_OUTPUT_PATH}" 
6    CACHE PATH "Static library target directory")
7set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${MY_OUTPUT_PATH}" 
8    CACHE PATH "Executable target directory")

Wenn wir CMake im Unterverzeichnis build des Source-Verzeichnis arbeiten lassen, werden dann die finalen Binärdateien in .\build\output\ zu finden sein.

1SET SOURCE_DIR=%~dp0
2SET BUILD_DIR=%SOURCE_DIR%\build
3CHDIR /d %SOURCE_DIR%
4RMDIR /s /q %BUILD_DIR%
5MKDIR %BUILD_DIR%
6CHDIR %BUILD_DIR%
7cmake -A x64 ..
8msbuild gate.sln /t:Rebuild /p:configuration=Release /p:platform=x64

Server Build Script

Auf dem Windows Server wird nun für jedes Projekt ein Server-Build Script angelegt, das wie folgt vorgeht:

  • Es legt ein temporäres Verzeichnis an
  • Die Quellcodes werden per GIT in das temporäre Verzeichnis geladen
  • Der Docker Container startet und bekommt das temporäre Verzeichnis als Austauschordner eingebunden.
  • Im Docker Container wird das Source-Build-Script ausgeführt, das alle Quellen zu Binärdateien übersetzt, die im mit dem Host geteilten temporärer Verzeichnis liegen.
  • Am Ende werden die erzeugten Binärdateien in ein Archiv gesichert und an einem dafür vorgesehenem Ort abgelegt.

Mein Beispiel Script sieht wie folgt aus:

 1SET GIT_URL=https://user:password@git-server.tld/path-to/project.git
 2SET DOCKER_IMAGE=msvc-build:2017
 3SET WORKDIR=%CD%
 4SET BUILD_ID=%RANDOM%
 5SET BUILD_DIR=%WORKDIR%\%BUILD_ID%
 6SET OUTPUT_ID=%DATE:~-4%-%DATE:~-10,2%-%DATE:~-7,2%_%TIME:~0,2%-%TIME:~3,2%-%TIME:~6,2%_%BUILD_ID%
 7SET OUTPUT_BASE=%WORKDIR%\artifacts
 8SET OUTPUT_DIR="%OUTPUT_BASE%\%OUTPUT_ID%"
 9DEL /F /S /Q %BUILD_DIR%
10MKDIR %BUILD_DIR%
11MKDIR %OUTPUT_BASE%
12MKDIR %OUTPUT_DIR%
13CHDIR %BUILD_DIR%
14
15git clone %GIT_URL% .
16
17docker run -v %BUILD_DIR%:c:\build %DOCKER_IMAGE% c:\build\build.bat
18
19tar -czvf %OUTPUT_DIR%\artifacts.tgz -C %BUILD_DIR%\build\output ./*.*
20
21CHDIR ..
22DEL /F /S /Q %BUILD_DIR%

Fortsetzung folgt


(Zurück zu: Infos)

Meine Dokus über:
 
Weitere externe Links zu:
Alle extern verlinkten Webseiten stehen nicht in Zusammenhang mit opengate.at.
Für deren Inhalt wird keine Haftung übernommen.



Wenn sich eine triviale Erkenntnis mit Dummheit in der Interpretation paart, dann gibt es in der Regel Kollateralschäden in der Anwendung.
frei zitiert nach A. Van der Bellen
... also dann paaren wir mal eine komplexe Erkenntnis mit Klugheit in der Interpretation!