多位開發人員處理一項專案
許多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檔案
The .touchgfx file is where TouchGFX Designer saves the definition of the UI created in TouchGFX Designer. This means that if two developers in a project both work with TouchGFX Designer, they will both make changes to this file, and conflicts can occur.
.touchgfx檔案基本上是由兩個陣列組成。 第一個陣列包含螢幕清單, 第二個陣列則為容器清單。
Here is a very simple project created using 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'
Avoid having the project opened in TouchGFX Designer while merging. If you Save or Generate code (F4) from TouchGFX Designer it will overwrite the .touchgfx file on the disk (and remove your conflict)!
合併之後,您就可以在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。
The TextArea is given a resource ID (1) by TouchGFX Designer, Screen2Headline, and the text content "Screen 2". 開發人員在TouchGFX Designer儲存專案時,會在磁碟修改兩個檔案:
開發人員會新增兩個檔案並確認。 texts.xml的diff (如下)顯示我們新增了包含ID Screen2Headline的Text XML元素,以及包含英文文字的Translation元素。 Text元素位於TextGroup元素內部。 This element was created by TouchGFX Designer because we did not put our new text in a specific group:
另一位開發人員執行類似變更,不過他的文字叫做Screen3Headline,而文字則為「My Headline」:
特徵完成時一樣也必須合併至主分支。 這對第一個分支feature5而言沒有問題,不過合併feature6時就會出現衝突。 這次在tests.xml之中:
分支建立時,.touchgfx檔案也在主分支和feature6變更,但git能夠合併變更集,因為這些變更位在檔案的不同位置(不在相同螢幕中)。 發生衝突的原因,是兩人都在「未排序」的TextGroup元素中變更了第一個(或最後一個)文字:
對此衝突而言,文字順序並不重要,但卻是產生正確XML的必要條件,所以我們手動合併文字檔案,以產生兩個完整的Text元素:
避免衝突
以上所見的部分衝突,可遵循幾項簡單原則加以避免。
一定要在主分支建立新螢幕。 在主分支建立螢幕時,兩個特徵分支就不可能將新螢幕插入至.touchgfx檔案的相同位置。 不要以Screen1、Screen2等名稱為螢幕命名。 許多團隊都會在專案初期建立所有螢幕(大部分為空白)。 如果專案開始時,您就獲得大部分應用程式的圖形設計,就有可能這樣處理。 如果您之後需要新增螢幕,請考慮將螢幕新增在具有邏輯關聯的螢幕旁邊,不一定要新增為最後一個螢幕。 This is done by adding the Screen in TouchGFX Designer and then drag the new screen upwards to its final location.
客製容器會產生和螢幕相同的衝突。 由於客製容器需求是在開發螢幕期間產生,事先在主分支建立容器或許並不可行。 請考慮在主分支建立客製容器、將特徵分支重訂基底至主分支,然後繼續開發。 另一種方式則是完成特徵分支,然後重訂基底至主分支。 其中可能會產生衝突,解決方法是將整個容器區塊在特徵分支中最後確認,手動放置於.touchgfx檔案,並且不變更主分支的容器。 現在合併至主分支。 主分支將不會出現任何衝突。
如果要減少文字衝突,可以使用多個TextGroup,而不是將所有文字都置於「未排序」群組中。 我們在此為Screen3建立TextGroup,將舊文字移往此群組,並新增了新文字(SecondHeadline):
版本控制系統
如果有多位開發人員處理一個專案,使用版本控制系統會比較好, 例如在之前範例中使用的git。 這裡產生的問題,就是要將哪些檔案儲存在TouchGFX專案中的版本控制系統?
Tip
這是為了避免混淆,例如.touchgfx檔案及其產生的檔案變更時。 如果其他人不同意,您要保留哪些修改的部分。 如果在.touchgfx檔案出現衝突,則在產生的檔案中也會出現衝突。 這表示需要處理更多工作以解決任何衝突。
資料夾 | 內容 | 儲存於VCS |
---|---|---|
Core | 用於初始化的main.c及其他檔案。 These are regenerated by STM32CubeMX, but it is fine to add code to the marked "User Sections" | 是 |
Drivers | STM32 HAL及BSP軟體 | 是 |
EWARM | IAR EWARM專案檔案。 編譯器會為編譯的檔案及其他輸出檔案建立子目錄。 這些子目錄不應儲存。 | (是) |
gcc | ARM gcc Makefile及連結器指令碼 | 是 |
LIBJPEG | Generated by STM32CubeMX if the LibJPEG middleware is enabled | 是 |
MDK-ARM | Keil專案檔案。 請勿儲存任何子目錄 | (是) |
Middlewares | 任何已啟用中介軟體的原始程式碼或標頭檔案及程式庫。 包括TouchGFX | 是 |
STM32CubeIDE | CubeIDE專案檔案 | 是 |
TouchGFX | 請參閱下方資訊 |
資料夾 | 內容 | 儲存於VCS |
---|---|---|
App | Generated by STM32CubeMX. 由main.c啟動TouchGFX的函數 | 是 |
assets | TouchGFX的字型、圖像及文字 | 是 |
build | ARM及Windows gcc的編譯器輸出 | 否 |
config | gcc及MSVS的設定檔案 | 是 |
generated | TouchGFX工具及Designer產生的檔案。 user.config檔案包含TouchGFX安裝路徑。 如果新增這些檔案,通常會造成衝突。 | 否 |
gui | 螢幕的使用者程式碼。 These are generated by TouchGFX Designer if they are missing. | 是 |
simulator | 模擬器專屬程式碼 | 是 |
target | Target specific code generated by STM32CubeMX | 是 |
application.config | 圖像及文字格式設定。 Used by TouchGFX Designer and other tools. | 是 |
ApplicationTemplate.touchgfx.part | 有關專案的各種資訊。 Generated by STM32CubeMX and read by TouchGFX Designer. | 是 |
F746TextureMapper.touchgfx | 以TouchGFX Designer建立的UI定義。 | 是 |
The standard advice is to save all files generated by STM32CubeMX in your version control system. The files generated by TouchGFX Designer in contrast should not be saved. The reason for this is that in many projects STM32CubeMX is used mainly in the beginning to create a hardware configuration. It is therefore preferable, that you do not need to open STM32CubeMX and generate code after each update from the version control system. 還有許多變更是在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的建置輸出。