之前已經在《GitLab 簡單的 C++ 專案腳本範例》這篇文章裡面,大概整理了一下 Heresy 這邊針對自己的 C++ 專案、撰寫出來的 GitLab CI 自動建置的腳本了。
不過,當時在 Windows 平台下,Heresy 是使用「Windows Batch」(CMD)這個 shell 來進行操作的。
但是,GitLab 官方其實有說,從 11.11 開始,就將「Windows Batch executor」設定為棄用(deprecated),並將於 13.0 時移除(預計時間是 2020/06/22);而取而代之的,GitLab 將使用 PowerShell 來作為 Windows 上預設的 shell。(參考)
而這篇記錄,就是簡單地記錄一下 Heresy 把之前 cmd 的 script、改寫成 PowerShell 版本的紀錄。
<!–more–>
Runner
理論上,Windows 上如果用最新版的 GitLab Runner 來設定一台新的 GitLab Runner,在選擇 shell 模式的情況下,預設就會是使用 PowerShell 來執行了。
而針對既有的 GitLab Runner 呢,則就需要手動去修改設定了。
修改的方法,基本上就是以純文字檔編輯器去開啟「config.toml」(在 Windows 環境應該會跟 gitlab-runner.exe 在一起),然後找到「runners」的區段,加入「shell」的設定了。
在官方文件中,也有提供對應的範例:
... [[runners]] name = "shell executor runner" executor = "shell" shell = "powershell" ...
在修改完後,只要再讓 GitLab Runner 重新執行,就可以讓修改生效了。
要重新執行 gitlab-runner.exe 的話,只要用系統管理者權限,執行
.gitlab-runner.exe restart
就可以了。
.gitlab-ci.yml
在 yaml 腳本的部分,由於流程沒有變,所以大致上都可以沿用之前的腳本。
但是,有兩個地方必須要針對更換 shell 做對應的修改:
- 切換字碼
- 設定 Visual C++ 的環境
切換字碼
首先,在切換字碼的部分,在使用 cmd 作為 shell 的時候,只要執行「CHCP 65001」就可以了。但是這個指令在 PowerShell 下,似乎不能解決問題。
後來查了一下資料,最後是採用下面的指令:
[System.Console]::OutputEncoding = [System.Console]::InputEncoding =
[System.Text.Encoding]::UTF8
透過這個指令,可以把 console 輸入、輸出的編碼都設定成 UTF-8;如此一來 GitLab 抓到的紀錄就能正常顯示中文了。
(這個指令哪抄來的已經忘了 ^^")
Visual C++ 環境變數
在設定 Visual C++ 需要的環境變數的時候,微軟提供的是一個 batch 檔,所以當使用 cmd 做 shell 的時候,只要執行
'call "c:progra~2MICROS~12017BuildToolsVCAuxiliaryBuildvcvars64.bat"'
就可以了。
但是這樣的指令在 PowerShell 一樣是沒有用的。
後來又找了好一陣子資料,最後是決定參考《How to use vcvars64.bat from Powershell?》這串討論裡面,Tyler Denniston 所提供的腳本:
if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { cmd.exe /c "call `"C:Program FilesMicrosoft SDKsWindowsv7.1BinSetEnv.cmd`" /x64 && call `"C:Program Files (x86)Microsoft Visual Studio 14.0VCvcvarsall.bat`" x86_amd64 && set > %temp%vcvars.txt" } else { cmd.exe /c "call `"C:Program Files (x86)Microsoft Visual Studio2017CommunityVCAuxiliaryBuildvcvars64.bat`" && set > %temp%vcvars.txt" } Get-Content "$env:tempvcvars.txt" | Foreach-Object { if ($_ -match "^(.*?)=(.*)$") { Set-Content "env:$($matches[1])" $matches[2] } }
他的概念就是先把本來 vcvars64.bat 要設定的環境變數,輸出成一個名為 vcvars.txt 的純文字檔,然後再透過 PowerShell 的 script 來讀取他,並透過 Set-Content 來設定環境變數。
這邊針對這個腳本,則可以在簡化一點,把前面判斷的部分拿掉,會更為簡單。
最後,如果只看「build-windows」 這個工作的話,他的腳本就變成:
.powershell_encoding: before_script: - "[System.Console]::OutputEncoding = [System.Console]::InputEncoding = [System.Text.Encoding]::UTF8" # Set as UTF-8 build-windows: stage: build extends: .powershell_encoding variables: GIT_SUBMODULE_STRATEGY: none script: - git submodule sync --recursive - git submodule update --recursive --init --remote external - cmd.exe /c "call `"C:Program Files (x86)Microsoft Visual Studio2017BuildToolsVCAuxiliaryBuildvcvars64.bat`" && set > vcvars.txt" # Generate VC env-settings - Get-Content "vcvars.txt" | Foreach-Object { if ($_ -match "^(.*?)=(.*)$") { Set-Content "env:$($matches[1])" $matches[2] } } # Apply VC env settings - msbuild.exe /m /property:Configuration=Release tags: - msvc
目前這個腳本在 Heresy 這邊是可以正常運作的。
不過,當然他還有很多改善空間。
目前想到之後還可以、或是可能需要修改的地方,包括了:
-
編譯出來的檔案要怎麼傳遞給測試階段。
感覺上,應該比較適合用 cache 來做?(參考) -
目前 Visual C++ 的環境變數設定的 bat 檔是寫死的,但是根據 GitLab Runner 裝的版本的不同,路徑可能會不一樣;所以在有多台不同配置的 runner 的情況下,有可能會出現找不到檔案的問題。
目前想到的解法,是在 Runner 上把路徑設定成一個特別的環境變數,在執行腳本的時候就透過環境變數去取得路徑。 -
在 GitLab 12 的時候,針對 CI/CD 的 job log 加入了折疊/展開的功能(參考)。
他基本上是預設就可以直接用的,但是個人總覺得他的摺起來的方法和想像的不太一樣?這部分還不知道有沒有辦法手動進行控制。