跳轉到主要內容

多位開發人員處理一項專案

許多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:

合併feature1

合併操作順利進行, 產生的.touchgfx檔案與feature1中的檔案相同。 不過我們在feature2嘗試合併時,就沒有這麼順利:

合併feature2

feature2分支及主分支都變更了.touchgfx檔案,而git無法合併變更。 這是因為兩個分支都是在Screen1之後新增螢幕:

.touchgfx檔案中的合併衝突

於WinMerge顯示的合併衝突

此項合併有兩個問題。 其中最糟糕的問題,就是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檔案中相同的程式行:

合併feature4

.touchgfx檔案中的合併衝突

這個問題的解決方案,就是決定(與開發人員談話)是否需要feature3或feature4的屬性(亦即色彩); 但當然不可能兩者都要。 此外可能也不應該混合(提供白色)。 所以請在編輯器或最喜愛的git合併工具中開啟.touchgfx檔案,選擇您需要處理的程式行。 這裡我們選擇feature3的屬性獲得:

        "Name": "Screen1",
"Components": [
{
"Type": "Box",
"Name": "box1",
"Width": 800,
"Height": 480,
"Color": {
"Red": 255,
"Green": 255
}
}
...
Note
TouchGFX Designer並沒有包含具有預設值的JSON檔案屬性。 這代表在以上範例中,Blue (藍色)並沒有在「Color」(色彩)之下提到,且其值為「0」。

TouchGFX文字資料庫檔案

TouchGFX文字資料庫(texts.xml檔案)可能會出現與前述範例非常類似的衝突。 以下將透過範例加以瞭解。 我們一開始建立兩個特徵分支:

git checkout -b feature5
git checkout -b feature6

我們將使用feature5新增TextArea小工具及文字至Screen2,並以feature6新增TextArea至Screen3。 這樣可以模擬兩位開發人員在處理不同螢幕。

現在假設開發人員1查看feature5,並新增了TextArea。

1

新增TextArea至Screen2

Designer、Screen2Headline及文字內容「Screen 2」會向TextArea提供資源ID (1)。 開發人員在TouchGFX Designer儲存專案時,會在磁碟修改兩個檔案:

修改.touchgfx及.xml檔案

開發人員會新增兩個檔案並確認。 texts.xml的diff (如下)顯示我們新增了包含ID Screen2Headline的Text XML元素,以及包含英文文字的Translation元素。 Text元素位於TextGroup元素內部。 此元素是由Designer建立,因為我們並未將新文字置於特定群組之中:

修改至assets/texts/texts.xml

另一位開發人員執行類似變更,不過他的文字叫做Screen3Headline,而文字則為「My Headline」:

修改至feature6中的assets/texts/texts.xml

特徵完成時一樣也必須合併至主分支。 這對第一個分支feature5而言沒有問題,不過合併feature6時就會出現衝突。 這次在tests.xml之中:

於feature6合併時在assets/texts/texts.xml發生衝突

分支建立時,.touchgfx檔案也在主分支和feature6變更,但git能夠合併變更集,因為這些變更位在檔案的不同位置(不在相同螢幕中)。 發生衝突的原因,是兩人都在「未排序」的TextGroup元素中變更了第一個(或最後一個)文字:

於feature6合併時在assets/texts/texts.xml發生衝突

對此衝突而言,文字順序並不重要,但卻是產生正確XML的必要條件,所以我們手動合併文字檔案,以產生兩個完整的Text元素:

文字衝突已解決

避免衝突

以上所見的部分衝突,可遵循幾項簡單原則加以避免。

  • 一定要在主分支建立新螢幕。 在主分支建立螢幕時,兩個特徵分支就不可能將新螢幕插入至.touchgfx檔案的相同位置。 不要以Screen1、Screen2等名稱為螢幕命名。 許多團隊都會在專案初期建立所有螢幕(大部分為空白)。 如果專案開始時,您就獲得大部分應用程式的圖形設計,就有可能這樣處理。 如果您之後需要新增螢幕,請考慮將螢幕新增在具有邏輯關聯的螢幕旁邊,不一定要新增為最後一個螢幕。 如果要這樣處理,可以在Designer中新增螢幕,然後將新螢幕往上拖動到最終位置。

  • 客製容器會產生和螢幕相同的衝突。 由於客製容器需求是在開發螢幕期間產生,事先在主分支建立容器或許並不可行。 請考慮在主分支建立客製容器、將特徵分支重訂基底至主分支,然後繼續開發。 另一種方式則是完成特徵分支,然後重訂基底至主分支。 其中可能會產生衝突,解決方法是將整個容器區塊在特徵分支中最後確認,手動放置於.touchgfx檔案,並且不變更主分支的容器。 現在合併至主分支。 主分支將不會出現任何衝突。

  • 如果要減少文字衝突,可以使用多個TextGroup,而不是將所有文字都置於「未排序」群組中。 我們在此為Screen3建立TextGroup,將舊文字移往此群組,並新增了新文字(SecondHeadline):

Screen3文字的另一個群組

版本控制系統

如果有多位開發人員處理一個專案,使用版本控制系統會比較好, 例如在之前範例中使用的git。 這裡產生的問題,就是要將哪些檔案儲存在TouchGFX專案中的版本控制系統?

Tip
一般規則:不要將工具重新產生的任何檔案儲存在版本控制系統中。 這樣做的方法之一,就是將這類檔案的名稱新增至.gitignore檔案中。

這是為了避免混淆,例如.touchgfx檔案及其產生的檔案變更時。 如果其他人不同意,您要保留哪些修改的部分。 如果在.touchgfx檔案出現衝突,則在產生的檔案中也會出現衝突。 這表示需要處理更多工作以解決任何衝突。

TouchGFX Designer專案典型的專案根目錄配置

資料夾內容儲存於VCS
Core用於初始化的main.c及其他檔案。 這些檔案是由CubeMX重新產生,但是將程式碼新增至標示的「使用者區段」並沒有問題
DriversSTM32 HAL及BSP軟體
EWARMIAR EWARM專案檔案。 編譯器會為編譯的檔案及其他輸出檔案建立子目錄。 這些子目錄不應儲存。(是)
gccARM gcc Makefile及連結器指令碼
LIBJPEG如果啟用LibJPEG中介軟體,就會由CubeMX產生
MDK-ARMKeil專案檔案。 請勿儲存任何子目錄(是)
Middlewares任何已啟用中介軟體的原始程式碼或標頭檔案及程式庫。 包括TouchGFX
STM32CubeIDECubeIDE專案檔案
TouchGFX請參閱下方資訊

專案中TouchGFX資料夾的典型配置

資料夾內容儲存於VCS
App由CubeMX產生。 由main.c啟動TouchGFX的函數
assetsTouchGFX的字型、圖像及文字
buildARM及Windows gcc的編譯器輸出
configgcc及MSVS的設定檔案
generatedTouchGFX工具及Designer產生的檔案。 user.config檔案包含TouchGFX安裝路徑。 如果新增這些檔案,通常會造成衝突。
gui螢幕的使用者程式碼。 如果遺失會由TouchGFX Designer產生。
simulator模擬器專屬程式碼
targetCubeMX產生的目標專屬程式碼
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檔案及任何編譯檔案。 We also ignore any user settings files and build output for IAR.