주요 내용으로 건너뛰기

Multiple developers on a project

여러 명의 개발자가 관여하는 TouchGFX 프로젝트가 많습니다. 동일한 리소스에 액세스 및 수정하는 개발자가 두 명 이상이면 문제가 될 수 있지만, 몇 가지 모범 사례를 따르면 이러한 문제를 줄이고 처리할 수 있습니다.

TouchGFX 버전 4.18 이전에는 모든 텍스트 리소스(번역)를 저장하는 데 Excel 파일이 사용되었습니다. 두 명의 사용자가 모두 텍스트를 추가 또는 변경한 경우에는 Excel 파일을 병합할 수 없기 때문에 여러 개발자가 관여하는 프로젝트의 경우에 문제가 되었습니다. 따라서, 다양한 Excel 시트 간에 텍스트를 수동으로 복사해야 했습니다.

TouchGFX 버전 4.18부터는 텍스트를 보관하는 데 XML 문서가 사용됩니다. 대부분의 경우, 이 XML 파일은 표준 텍스트 도구를 사용해 병합이 가능합니다.

TouchGFX Designer가 UI 디자인을 저장하는 .touchgfx 파일에서도 충돌이 발생할 수 있습니다. 이 파일은 JSON 형식이며, 표준 도구를 사용해 병합할 수도 있습니다.

이 섹션에서는 TouchGFX 파일에서 충돌의 몇 가지 예와 이를 해결하는 방법을 살펴보겠습니다.

다른 충돌 소스로 IAR 또는 Keil 프로젝트 파일이 있지만, 여기서는 논의하지 않겠습니다.

충돌

2명의 개발자가 동일한 리소스를 수정하거나 추가할 때 충돌이 발생할 수 있습니다. 두 변경 사항을 병합할 때 대부분의 도구는 어떤 수정 사항을 유지해야 하는지(일부를 삭제할 예정인 경우), 두 변경 사항의 올바른 순서는 무엇인지(둘 다 유지되는 경우) 알려줄 수 없습니다.

일반적인 상황이 아래 그림에 설명되어 있습니다.

2개의 브랜치 사용

이 예제에서는 메인 브랜치로부터 두 개의 브랜치가 생성됩니다. Feature2 브랜치가 먼저 메인 브랜치에 병합됩니다. 메인 브랜치에서도 작업이 수행되는 경우 병합 충돌이 발생할 수 있습니다. 나중에는 Feature1 브랜치가 메인 브랜치에 병합이 됩니다. 따라서, 두 Feature 브랜치가 동일한 파일을 변경한 경우에 충돌이 발생할 수 있습니다.

TouchGFX 프로젝트에는 4개의 주요 충돌 지점이 있습니다.

  • TouchGFX UI 파일(.touchgfx 파일)
  • TouchGFX Text Database(texts.xml 파일)
  • UI 및 기타 모듈의 일반 C++ 코드
  • IDE용 프로젝트 파일

다음 섹션에서는 TouchGFX 파일에서 충돌 문제를 처리하고 줄이는 방법을 살펴보겠습니다.

TouchGFX 파일

.touchgfx 파일은 TouchGFX Designer가 내부에 생성된 UI의 정의를 저장하는 위치입니다. 즉, 한 프로젝트에 참여하고 있는 두 개발자 모두가 TouchGFX Designer로 작업하고 있는 경우에 두 사람 모두 이 파일을 변경해서 충돌이 발생할 수 있습니다.

.touchgfx 파일은 기본적으로 두 개의 어레이로 이루어져 있습니다. 첫 번째 어레이에는 화면 목록이 포함되어 있습니다. 두 번째 어레이에는 컨테이너 목록입니다.

다음은 TouchGFX Designer를 사용해 생성한 매우 간단한 프로젝트입니다. 이 프로젝트는 "box1"이라는 하나의 Box 위젯이 있는 단일 화면으로 구성되어 있습니다.

단일 화면 프로젝트

.touchgfx 파일의 화면 섹션은 다음과 같습니다.

    "Screens": [
{
"Name": "Screen1",
"Components": [
{
"Type": "Box",
"Name": "box1",
"Width": 800,
"Height": 480,
"Color": {
"Red": 51,
"Green": 255
}
}
],
"Interactions": []
}
],

이러한 화면은 "Screens" 아래에 저장이 되며, 이 경우에는 오직 Screen1이라는 화면 정의만을 포함하고 있습니다. Screen1에 추가된 위젯은 해당 화면 내의 "Components"에서 확인할 수 있습니다. 지금까지 Box1이라는 Box 유형의 위젯 1개를 추가해봤습니다. 너비, 높이, 색상 등 다양한 속성이 Box1에서 설정됩니다. 기본값은 .touchgfx 파일에 기록되지 않기 때문에 값이 0인 box1의 색상 속성의 "Blue" 구성 요소는 명시적으로 지정되지 않습니다.

화면 추가 시 충돌

지금부터 충돌이 발생할 수 있는 이유와 더 많은 화면이 추가되는 시기, 충돌을 해결하는 방법 등을 자세히 살펴보겠습니다.

위의 프로젝트를 개발의 출발점으로 삼겠습니다. 몇 가지 Feature 브랜치를 만들어 보겠습니다.

git checkout -b feature1
git checkout -b feature2

이제 developer1이 브랜치 feature1을 확인하고 Screen2를 추가했다고 가정합니다. .touchgfx 파일에는 Screen1 이후 Screen2에 대한 화면 정의도 포함되어 있습니다.

    "Screens": [
{
"Name": "Screen1",
...
},
{
"Name": "Screen2",
"Components": [
{
"Type": "Box",
"Name": "box1",
"Width": 800,
"Height": 480,
"Color": {
"Red": 255,
"Green": 255,
"Blue": 255
}
}
],
"Interactions": []
}
],

이제, developer2가 feature2를 확인하고 새 화면(Screen3)을 추가한다고 가정합니다. 이 개발자의 .touchgfx 파일은 위의 파일과 매우 유사합니다.

팀이 하려는 다음에 하려는 작업은 두 Feature 브랜치를 병합하는 것입니다(작업을 완료했다고 가정). 먼저 feature1을 병합해 보겠습니다.

feature1 병합

이 병합 작업은 잘 진행되었습니다. 병합된 .touchgfx 파일은 feature1의 파일과 동일합니다. 그러나 feature2에서 병합을 수행할 때는 상황이 그렇게 순조롭지 않습니다.

feature2 병합

feature2 브랜치와 메인 브랜치 모두 .touchgfx 파일을 변경했지만, git가 이러한 변경 사항을 병합할 수 없었습니다. 왜냐하면 두 브랜치가 Screen1 바로 뒤에 화면을 추가했기 때문입니다.

.touchgfx 파일에서의 병합 충돌

WinMerge에 나타난 병합 충돌

이 병합에는 두 가지 문제가 있습니다. 최악의 문제는 git이 두 개의 화면 정의(Screen2 및 Screen3)를 하나로 병합하려고 시도하고 있다는 것입니다. 우리는 두 개의 전체 화면을 차례로 정의하고 싶습니다. 두 번째 문제는 git와 다른 버전 제어 시스템이 사용자가 메인 화면, Screen2 또는 Screen3로 어떤 화면을 먼저 갖고 싶어하는지를 알 수 없다는 것입니다. 이것은 개발자에게 달려 있습니다.

따라서 우리는 .touchgfx 파일의 변경 사항을 수동으로 병합해야 합니다. Screen2 뒤에 Screen3의 전체 정의('{' to '}'에서 나온)를 반드시 삽입해야 합니다.

이 명령을 사용하면 Multiple.touchgfx 파일을 병합을 시작하기 전의 상태로 되돌릴 수 있습니다.

git checkout --ours Multiple.touchgfx

이 명령을 사용해 feature2에서 .touchgfx 파일을 가져올 수 있습니다.

git show feature2:Multiple1.touchgfx > feature2.touchgfx

이제, 선호하는 편집기에서 feature2.touchgfx 및 Multiple1.touchgfx를 열고 feature2.touchgfx에서 Multiple1.touchgfx로 전체 Screen3 정의를 복사합니다. 그 결과는 다음과 같습니다(화면 사이의 쉼표를 기억).

    "Screens": [
{
"Name": "Screen1",
...
},
{
"Name": "Screen2",
...
},
{
"Name": "Screen3",
...
}
],

충돌을 수정한 후에는 병합을 커밋할 수 있습니다.

git commit -m 'Merged feature2'

병합이 진행되는 동안 TouchGFX Designer에서 프로젝트를 열어서는 안 됩니다. TouchGFX Designer에서 코드를 저장 또는 생성(F4)하면 디스크의 .touchgfx 파일이 덮어쓰기가 되어서 충돌을 제거할 수 있습니다!

병합 후에는 TouchGFX Designer에서 .touchgfx 프로젝트를 열고 코드를 생성할 수 있습니다.

속성 추가/변경 시 충돌

두 개발자가 위젯의 동일한 속성을 변경할 때도 충돌이 발생할 수 있습니다. feature3과 feature4라는 Feature 브랜치 2개를 새로 생성하고, 두 브랜치 모두에서 Screen1의 상자 색상을 각기 노란색과 파란색으로 변경한다고 생각해 보십시오.

다시 말하지만 feature3을 메인 브랜치에 병합하는 것에는 문제가 없지만, 다른 Feature 브랜치를 병합할 때는 .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는 값이 "0"이기 때문에 "Color"에서 언급되지 않습니다.

TouchGFX Text Database 파일

TouchGFX Text Database(texts.xml 파일)는 위에서 살펴본 것과 매우 유사한 충돌을 일으킬 수 있습니다. 한 가지 예를 살펴보겠습니다. 먼저, 몇 가지 Feature 브랜치를 생성해보겠습니다.

git checkout -b feature5
git checkout -b feature6

Feature5를 사용해 TextArea 위젯 및 텍스트를 Screen2와 feature6에 추가해서 Screen3에 TextArea를 추가해보겠습니다. 이것은 별도의 화면에서 작업 중인 두 명의 개발자를 시뮬레이션한 것입니다.

이제, developer1이 feature5를 확인하고 TextArea를 추가한다고 가정합니다.

1

Screen2에 TextArea 추가

Designer, Screen2Headline 및 텍스트 내용 "Screen 2"에 의해 TextArea에는 리소스 ID(1)가 지정됩니다. 개발자가 TouchGFX Designer에 프로젝트를 저장하면 디스크에서 2개의 파일이 수정됩니다.

.touchgfx 및 .xml 파일 수정

개발자는 파일과 커밋을 모두 추가합니다. texts.xml의 diff(아래 참조)는 ID가 Screen2Headline인 Text XML 요소와 영어 텍스트가 있는 Translation 요소를 추가했음을 보여줍니다. Text 요소는 새 TextGroup 요소 안에 있습니다. 새 텍스트가 특정 그룹에 배정되지 않았기 때문에 이 요소는 TouchGFX Designer에서 생성되었습니다.

assets/texts/texts.xml 수정

비록 자신의 텍스트가 Screen3Headline이라 불리고 이 텍스트가 "My Headline"이기는 하지만, 다른 개발자도 유사한 변경을 수행합니다.

feature6에서 assets/texts/texts.xml 수정

수정된 Feature는 다시 메인 브랜치에 병합이 되어야 합니다. 첫 번째 브랜치인 feature5에서는 문제가 없지만, feature6을 병합할 때 다시 충돌이 발생합니다. 이번에는 tests.xml에서

feature6에서 병합을 수행할 때 assets/texts/texts.xml 충돌이 발생합니다.

또한 .touchgfx 파일은 브랜치가 생성된 이후로 메인 브랜치와 feature6에서 변경이 되었지만, 이러한 변경 사항이 파일의 별도 위치에 있기 때문에 git가 변경 집합을 병합할 수 있었습니다(같은 화면에서가 아님). 둘 다 "Unsorted" TextGroup 요소의 첫 번째(또는 마지막) 텍스트를 변경했기 때문에 충돌이 발생합니다.

feature6에서 병합을 수행할 때 assets/texts/texts.xml 충돌이 발생합니다.

이러한 충돌에서 텍스트의 순서는 중요하지 않지만, 올바른 XML을 생성하기 위해서는 당연히 필수입니다. 따라서, 두 개의 전체 Text 요소를 얻기 위해 텍스트 파일을 수동으로 병합합니다.

텍스트 충돌 문제가 해결됨

충돌 방지

위에서 살펴 본 충돌 중 일부는 몇 가지 간단한 규칙만 따르면 피할 수 있습니다.

  • 항상 메인 브랜치에서 새 화면을 생성하십시오. 메인 브랜치에서 화면이 생성되면 두 개의 Feature 브랜치에서 .touchgfx 파일의 동일 위치에 새 스크린을 삽입하는 것은 불가능합니다. Screens Screen1, Screen2 등을 호출하지 마십시오. 많은 그룹에서 사용하는 일반적인 방법은 프로젝트 초반에 모든 화면(대부분의 경우 빈 화면)을 생성하는 것입니다. 프로젝트를 시작할 때 대부분 애플리케이션에 대한 그래픽 디자인이 제공된 경우에는 이것이 가능합니다. 나중에 화면을 추가해야 하는 경우에는 논리적으로 연결이 되도록 화면 옆에 추가하는 것이 좋습니다. 단, 마지막 화면일 필요는 없습니다. TouchGFX Designer에서 화면을 추가한 다음, 새 화면을 최종 위치로 드래그하면 화면을 추가할 수 있습니다.

  • 맞춤형 컨테이너에서는 화면과 동일한 충돌이 발생합니다. 화면을 개발하는 동안 커스텀 컨테이너가 필요할 수 있기 때문에 미리 메인 브랜치에 컨테이너를 생성하는 것은 실용적이지 않을 수 있습니다. 메인 브랜치에서 커스텀 컨테이너를 생성하는 방법을 고려하고, Feature 브랜치를 메인 브랜치로 rebase하고, 개발을 계속 진행하는 방법이 있습니다. 또 다른 방법은 Feature 브랜치를 완료하고 메인 브랜치로 rebase하는 것입니다. 여기서 충돌이 발생할 수 있지만, Feature 브랜치에서 마지막으로 커밋을 할 때 전체 컨테이너 블록을 가져오고 메인 브랜치에서의 컨테이너를 변경하지 않고 그대로 둔 상태에서 이를 수동으로 .touchgfx 파일에 배치하는 방법으로 문제를 해결할 수 있습니다. 이제 메인 브랜치에 병합이 됩니다. 메인 브랜치에서는 어떤 충돌도 발생하지 않습니다.

  • 모든 텍스트를 "Unsorted" 그룹에 배치하는 대신, 여러 TextGroup을 사용해서 텍스트 충돌을 줄일 수 있습니다. 여기서는 Screen3용 TextGroup을 생성하고, 이전 텍스트를 이 그룹으로 이동시키고, 새 텍스트(SecondHeadline)를 추가했습니다.

Screen3 텍스트를 위한 별도의 그룹

버전 제어 시스템

여러 개발자가 프로젝트에서 작업을 하는 경우에는 버전 제어 시스템을 사용하는 것이 좋습니다. 위에서 사용한 git이 한 예입니다. 이때 문제는 TouchGFX 프로젝트의 버전 제어 시스템에 어떤 파일을 저장하느냐 입니다.

Tip
도구를 통해 재생성된 버전 제어 시스템에 어떤 파일도 저장하지 않는 것이 일반적인 규칙입니다. 이를 위한 한 가지 방법은 해당 파일 이름을 .gitignore 파일에 추가하는 것입니다.

이는 예를 들어 .touchgfx 파일과 그로부터 생성된 파일이 변경될 때 혼동을 피하기 위함입니다. 수정한 내용이 서로 일치하지 않는 경우에는 어떤 수정 사항을 유지합니까? .touchgfx 파일에서 충돌이 발생하면 생성된 파일에서도 충돌이 발생합니다. 이는 충돌 문제를 해결하기 위해 더 많은 작업이 필요하다는 의미입니다.

TouchGFX Designer 프로젝트에서의 일반적인 프로젝트 루트 레이아웃

폴더내용VCS에 저장
코어초기화를 위한 main.c 및 기타 파일. 이들 파일은 CubeMX에서 재생성되지만, 표시된 "User Sections"에 코드를 추가하는 것은 괜찮습니다.
드라이버STM32 HAL 및 BSP 소프트웨어
EWARMIAR EWARM 프로젝트 파일 컴파일러는 컴파일된 파일과 기타 출력 파일에 대한 하위 디렉토리를 생성합니다. 이러한 디렉토리를 저장해서는 안 됩니다.(Yes)
gccARM gcc makefile 및 링커 스크립트
LIBJPEGLibJPEG 미들웨어가 활성화된 경우 CubeMX에서 생성
MDK-ARMKeil 프로젝트 파일. 하위 디렉토리 저장 금지(Yes)
미들웨어활성화된 모든 미들웨어에 대한 소스 코드 또는 헤더 파일 및 라이브러리. TouchGFX 포함
STM32CubeIDECubeIDE 프로젝트 파일
TouchGFX아래 참조

프로젝트에서 TouchGFX 폴더의 일반적인 레이아웃

폴더내용VCS에 저장
AppCubeMX에서 생성됨. main.c에서 TouchGFX를 시작하는 기능
assetsTouchGFX용 글꼴, 이미지 및 텍스트
buildARM 및 Windows gcc용 컴파일러 출력아니요
configgcc 및 MSVS용 구성 파일
generatedTouchGFX 도구 및 TouchGFX Designer에서 생성되는 파일 user.config 파일에는 TouchGFX 설치 경로가 포함되어 있습니다. 이러한 파일을 추가하면 종종 충돌이 발생합니다.아니요
gui화면용 사용자 코드 누락된 경우 TouchGFX Designer에서 이들 코드가 생성됩니다.
simulator시뮬레이터 고유 코드
targetCubeMX에서 생성된 대상 고유 코드
application.config이미지 및 텍스트 형식의 구성. TouchGFX Designer 및 기타 도구에서 사용됩니다.
ApplicationTemplate.touchgfx.partVarious information about the project. CubeMX에서 생성되고 TouchGFX Designer에서 읽기가 가능합니다.
F746TextureMapper.touchgfxTouchGFX Designer에서 생성된 UI 정의.

CubeMX에서 생성된 모든 파일을 버전 관리 시스템에 저장하는 것이 일반적입니다. 반대로 TouchGFX Designer에서 생성된 파일은 저장하면 안 됩니다. 많은 프로젝트에서 주로 초기에 하드웨어 구성을 생성하는 데 CubeMX가 사용되기 때문입니다. 따라서 버전 제어 시스템에서 업데이트할 때마다 CubeMX를 열고 코드를 생성할 필요가 없습니다. TouchGFX Designer에서 훨씬 더 많은 변경이 이루어지기 때문에 어쨌든 개발자들이 해당 애플리케이션을 열어야 하는 경우가 많습니다. 따라서 TouchGFX Designer 내에서 코드를 재생성하는 것에 대한 부담이 없습니다.

이러한 조언의 타당성은 프로젝트 그룹에 따라 다릅니다. UI로 작업하지 않는 개발자가 일부 있는 경우에는 TouchGFX/생성 폴더를 커밋하여 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에 대한 모든 사용자 설정 파일 및 빌드 출력도 무시됩니다.