多位開發人員處理一項專案
許多TouchGFX專案都有多位開發人員參與其中。 如果有兩位以上開發人員存取及修改相同資源,可能會產生問題,但如果您遵循最佳實務,就可減少及處理這類問題。
TouchGFX 4.18版之前的版本使用Excel檔案儲存所有文字資源(翻譯)。 這在有多位開發人員參與的專案中會造成問題,因為如果有兩位使用者都新增或變更文字,Excel檔案無法合併。 您必須在不同的Excel工作表之間手動複製文字。
自TouchGFX 4.18版起開始使用XML文件儲存文字。 XML檔案在大部分情況下,都可利用標準文字工具加以合併。
TouchGFX Designer儲存UI設計的.touchgfx檔案也可能產生衝突。 此檔案為JSON格式,也可利用標準工具加以合併。
本節將介紹TouchGFX檔案的衝突範例,並說明如何解決。
其他衝突來源為IAR或Keil專案檔案,我們在此不會討論這些問題。
衝突
如果有兩位開發人員修改或新增相同資源,就可能產生衝突。 在合併兩項變更時,大部分工具並無法辨別應該保留哪一項修改(是否需要刪除部分修改),或是兩者的正確順序(是否都應該保留)。
下圖顯示一般情況:
在此範例中,由主分支建立了兩個分支。 Feature2分支先合併至主分支之中。 如果也在主分支進行工作,這就可能會產生合併衝突。 稍後Feature1分支合併至主分支。 如果兩個特徵分支對相同檔案進行變更,就可能會產生衝突。
TouchGFX專案有四個主要的衝突點:
- TouchGFX UI檔案(.touchgfx檔案)
- TouchGFX文字資料庫(texts.xml檔案)
- UI及其他模組的原始C++程式碼
- IDE專案檔案
下節將介紹如何處理及減少TouchGFX檔案衝突的各項問題。
TouchGFX檔案
TouchGFX Designer將其中建立的UI定義儲存在.touchgfx檔案之中。 這表示如果有兩位參與專案的開發人員都使用TouchGFX Designer,都會對此檔案進行變更,可能會造成衝突。
.touchgfx檔案基本上是由兩個陣列組成。 第一個陣列包含螢幕清單, 第二個陣列則為容器清單。
以下這個非常簡單的專案是使用TouchGFX Designer所建立。 其中包含一個螢幕,以及一個名為「box1」的方框小工具:
.touchgfx檔案的螢幕區段如下:
"Screens": [
{
"Name": "Screen1",
"Components": [
{
"Type": "Box",
"Name": "box1",
"Width": 800,
"Height": 480,
"Color": {
"Red": 51,
"Green": 255
}
}
],
"Interactions": []
}
],
螢幕儲存在「Screens」之下,在此範例中有一個名為Screen1的螢幕定義。 新增至Screen1的小工具位在「Screen」內部的「Components」(元件)。 目前我們僅新增了一個名為Box1的方框類小工具。 您可在Box1設定各種屬性,例如寬度、高度及色彩。 請注意預設值並未寫入.touchgfx檔案,因此並未明確表示box1色彩屬性的「Blue」(藍色)元件為零。
新增螢幕時的衝突
以下將詳細說明新增更多螢幕時為何會產生衝突,以及如何解決衝突問題。
我們利用以上專案作為開發起點, 製作兩個特徵分支:
git checkout -b feature1
git checkout -b feature2
現在假設開發人員1查看分支feature1,並新增了Screen2。 .touchgfx檔案現在也包含Screen2的螢幕定義,就在Screen1之後:
"Screens": [
{
"Name": "Screen1",
...
},
{
"Name": "Screen2",
"Components": [
{
"Type": "Box",
"Name": "box1",
"Width": 800,
"Height": 480,
"Color": {
"Red": 255,
"Green": 255,
"Blue": 255
}
}
],
"Interactions": []
}
],
現在假設開發人員2查看feature2,也新增了一個新螢幕(Screen3)。 他的.touchgfx檔案和上方檔案非常相似。
團隊要做的下一件事,就是合併兩個特徵分支(假設均已完成工作)。 首先來合併feature1:
合併操作順利進行, 產生的.touchgfx檔案與feature1中的檔案相同。 不過我們在feature2嘗試合併時,就沒有這麼順利:
feature2分支及主分支都變更了.touchgfx檔案,而git無法合併變更。 這是因為兩個分支都是在Screen1之後新增螢幕:
此項合併有兩個問題。 其中最糟糕的問題,就是git嘗試將兩個螢幕定義(Screen2及Screen3)合而為一。 我們需要兩個完整螢幕定義, 一前一後。 第二個問題是git(以及任何其他的版本控制系統)無法得知您在主分支、Screen2或Screen3要以哪個螢幕為優先; 這取決於開發人員。
因此我們需要在.touchgfx檔案中手動合併變更。 請務必將Screen3的完整定義(從'{' to '}')插入至Screen2之後。
您可利用以下指令,讓Multiple.touchgfx檔案回到開始合併之前的狀態:
git checkout --ours Multiple.touchgfx
您可利用以下指令取得feature2的.touchgfx檔案:
git show feature2:Multiple1.touchgfx > feature2.touchgfx
現在從您最喜愛的編輯器開啟feature2.touchgfx及Multiple1.touchgfx,然後由feature2.touchgfx將完整的Screen3定義複製到Multiple1.touchgfx。 現在就會變成以下所示(請記得在螢幕之間的逗號):
"Screens": [
{
"Name": "Screen1",
...
},
{
"Name": "Screen2",
...
},
{
"Name": "Screen3",
...
}
],
修正衝突後,我們就可以進行合併:
git commit -m 'Merged feature2'
請注意合併時TouchGFX Designer中不要有開啟的專案。 如果您由Designer儲存或產生程式碼(F4),就會覆寫磁碟上的.touchgfx檔案(並移除衝突)!
合併之後,您就可以在TouchGFX Designer開啟.touchgfx專案並產生程式碼。
新增變更屬性時的衝突
如果兩位開發人員變更小工具的同一項屬性,也可能會產生衝突。 想像一下我們建立了兩個新的特徵分支feature3及feature4,並在Screen1於兩個分支中將方框色彩分別變更為黃色及藍色。
將feature3合併至主分支一樣沒問題,不過在合併其他功能分支時就會出現衝突,原因是修改了.touchgfx檔案中相同的程式行:
這個問題的解決方案,就是決定(與開發人員談話)是否需要feature3或feature4的屬性(亦即色彩); 但當然不可能兩者都要。 此外可能也不應該混合(提供白色)。 所以請在編輯器或最喜愛的git合併工具中開啟.touchgfx檔案,選擇您需要處理的程式行。 這裡我們選擇feature3的屬性獲得:
"Name": "Screen1",
"Components": [
{
"Type": "Box",
"Name": "box1",
"Width": 800,
"Height": 480,
"Color": {
"Red": 255,
"Green": 255
}
}
...
Note
TouchGFX文字資料庫檔案
TouchGFX文字資料庫(texts.xml檔案)可能會出現與前述範例非常類似的衝突。 以下將透過範例加以瞭解。 我們一開始建立兩個特徵分支:
git checkout -b feature5
git checkout -b feature6
我們將使用feature5新增TextArea小工具及文字至Screen2,並以feature6新增TextArea至Screen3。 這樣可以模擬兩位開發人員在處理不同螢幕。
現在假設開發人員1查看feature5,並新增了TextArea。
Designer、Screen2Headline及文字內容「Screen 2」會向TextArea提供資源ID (1)。 開發人員在TouchGFX Designer儲存專案時,會在磁碟修改兩個檔案:
開發人員會新增兩個檔案並確認。 texts.xml的diff (如下)顯示我們新增了包含ID Screen2Headline的Text XML元素,以及包含英文文字的Translation元素。 Text元素位於TextGroup元素內部。 此元素是由Designer建立,因為我們並未將新文字置於特定群組之中:
另一位開發人員執行類似變更,不過他的文字叫做Screen3Headline,而文字則為「My Headline」:
特徵完成時一樣也必須合併至主分支。 這對第一個分支feature5而言沒有問題,不過合併feature6時就會出現衝突。 這次在tests.xml之中:
分支建立時,.touchgfx檔案也在主分支和feature6變更,但git能夠合併變更集,因為這些變更位在檔案的不同位置(不在相同螢幕中)。 發生衝突的原因,是兩人都在「未排序」的TextGroup元素中變更了第一個(或最後一個)文字:
對此衝突而言,文字順序並不重要,但卻是產生正確XML的必要條件,所以我們手動合併文字檔案,以產生兩個完整的Text元素:
避免衝突
以上所見的部分衝突,可遵循幾項簡單原則加以避免。
一定要在主分支建立新螢幕。 在主分支建立螢幕時,兩個特徵分支就不可能將新螢幕插入至.touchgfx檔案的相同位置。 不要以Screen1、Screen2等名稱為螢幕命名。 許多團隊都會在專案初期建立所有螢幕(大部分為空白)。 如果專案開始時,您就獲得大部分應用程式的圖形設計,就有可能這樣處理。 如果您之後需要新增螢幕,請考慮將螢幕新增在具有邏輯關聯的螢幕旁邊,不一定要新增為最後一個螢幕。 如果要這樣處理,可以在Designer中新增螢幕,然後將新螢幕往上拖動到最終位置。
客製容器會產生和螢幕相同的衝突。 由於客製容器需求是在開發螢幕期間產生,事先在主分支建立容器或許並不可行。 請考慮在主分支建立客製容器、將特徵分支重訂基底至主分支,然後繼續開發。 另一種方式則是完成特徵分支,然後重訂基底至主分支。 其中可能會產生衝突,解決方法是將整個容器區塊在特徵分支中最後確認,手動放置於.touchgfx檔案,並且不變更主分支的容器。 現在合併至主分支。 主分支將不會出現任何衝突。
如果要減少文字衝突,可以使用多個TextGroup,而不是將所有文字都置於「未排序」群組中。 我們在此為Screen3建立TextGroup,將舊文字移往此群組,並新增了新文字(SecondHeadline):
版本控制系統
如果有多位開發人員處理一個專案,使用版本控制系統會比較好, 例如在之前範例中使用的git。 這裡產生的問題,就是要將哪些檔案儲存在TouchGFX專案中的版本控制系統?
Tip
這是為了避免混淆,例如.touchgfx檔案及其產生的檔案變更時。 如果其他人不同意,您要保留哪些修改的部分。 如果在.touchgfx檔案出現衝突,則在產生的檔案中也會出現衝突。 這表示需要處理更多工作以解決任何衝突。
資料夾 | 內容 | 儲存於VCS |
---|---|---|
Core | 用於初始化的main.c及其他檔案。 這些檔案是由CubeMX重新產生,但是將程式碼新增至標示的「使用者區段」並沒有問題 | 是 |
Drivers | STM32 HAL及BSP軟體 | 是 |
EWARM | IAR EWARM專案檔案。 編譯器會為編譯的檔案及其他輸出檔案建立子目錄。 這些子目錄不應儲存。 | (是) |
gcc | ARM gcc Makefile及連結器指令碼 | 是 |
LIBJPEG | 如果啟用LibJPEG中介軟體,就會由CubeMX產生 | 是 |
MDK-ARM | Keil專案檔案。 請勿儲存任何子目錄 | (是) |
Middlewares | 任何已啟用中介軟體的原始程式碼或標頭檔案及程式庫。 包括TouchGFX | 是 |
STM32CubeIDE | CubeIDE專案檔案 | 是 |
TouchGFX | 請參閱下方資訊 |
資料夾 | 內容 | 儲存於VCS |
---|---|---|
App | 由CubeMX產生。 由main.c啟動TouchGFX的函數 | 是 |
assets | TouchGFX的字型、圖像及文字 | 是 |
build | ARM及Windows gcc的編譯器輸出 | 否 |
config | gcc及MSVS的設定檔案 | 是 |
generated | TouchGFX工具及Designer產生的檔案。 user.config檔案包含TouchGFX安裝路徑。 如果新增這些檔案,通常會造成衝突。 | 否 |
gui | 螢幕的使用者程式碼。 如果遺失會由TouchGFX Designer產生。 | 是 |
simulator | 模擬器專屬程式碼 | 是 |
target | CubeMX產生的目標專屬程式碼 | 是 |
application.config | 圖像及文字格式設定。 由TouchGFX Designer及其他工具使用。 | 是 |
ApplicationTemplate.touchgfx.part | 有關專案的各種資訊。 由CubeMX產生,由TouchGFX Designer讀取。 | 是 |
F746TextureMapper.touchgfx | 以TouchGFX Designer建立的UI定義。 | 是 |
標準建議是將CubeMX產生的所有檔案儲存在版本控制系統中。 相反地,TouchGFX Designer產生的檔案則不應儲存。 這是因為在許多專案中,CubeMX主要是在一開始用於建立硬體設定。 因此您在版本控制系統每次進行更新後,最好不要開啟CubeMX及產生程式碼。 還有許多變更是在TouchGFX Designer進行,所以許多開發人員無論如何都需要開啟該應用程式。 因此在TouchGFX Designer中重新產生程式碼並沒有負擔。
這項建議是否有效,需視您的專案群組而定。 如果您有一些開發人員並沒有處理UI,最好也一同交付TouchGFX/generated資料夾,讓他們可直接在VCS處理更完整的專案。
由命令列產生TouchGFX程式碼
您可由命令列重新產生TouchGFX程式碼。 典型的使用案例就是建置伺服器或任何其他CI設定。
命令列介面是由TouchGFX安裝的tgfx.exe工具提供。 如要為以上專案重新產生程式碼,請執行以下指令:
d:/TouchGFX/4.20.0/designer/tgfx.exe generate -p TouchGFX/F746TextureMapper.touchgfx
執行此指令相當於在TouchGFX Designer內部產生程式碼(F4)。 如果您在建置的伺服器使用此指令,就可避免檢查產生的檔案。
忽略特定檔案
許多版本控制系統可設定忽略特定檔案名稱及資料夾。
以下是TouchGFX專案典型的.gitignore:
TouchGFX/build/
TouchGFX/generated/
EWARM/settings/
EWARM/STM32F746/
此項忽略清單可讓git忽略產生的TouchGFX檔案及任何編譯檔案。 我們也忽略任何使用者設定檔案,以及IAR的建置輸出。