요즘은 모바일 게임을 많이 개발합니다. 특히 Cocos2d-x를 많이 사용하는데요. 오픈소스라서 추가 비용이 발생하지 않는 장점이 있지만 사용하기가 좀 까다롭습니다.

특히 ADT, NDK가 엮여 있어서 자동화하기가 쉽지 않습니다.

오늘은 안드로이드용 Cocos2d-x 게임을 위한 빌드 스크립트를 소개하겠습니다.

CruiseControl.NET은 최신 버전을 사용하면 됩니다. 저는 버전 관리 시스템으로 Git을 사용했고, <CronTrigger>로 매시 20분에 빌드되도록 설정하였습니다.

ccnet.config

<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
  <queue name="HelloGame" />

  <project name="HelloGame Android" description="HelloGame Android Client" queue="HelloGame">
    
    <state type="state" directory="C:\CCNet\State" />
    <artifactDirectory>C:\CCNet\BuildArtifacts\HelloGame Android</artifactDirectory>
    <workingDirectory>C:\CCNet\WorkingDirectory\HelloGame Android</workingDirectory>

    <labeller type="dateLabeller" />

    <triggers>
      <cronTrigger>
        <cronExpression>20 * * * *</cronExpression>
        <buildCondition>IfModificationExists</buildCondition>
      </cronTrigger>
    </triggers>

    <sourcecontrol type="git">
      <repository>git@bitbucket.org:pyrasis/examplegame.git</repository>
      <autoGetSource>false</autoGetSource>
      <fetchSubmodules>true</fetchSubmodules>
      <workingDirectory>$(ExampleGame)</workingDirectory>
    </sourcecontrol>

    <tasks>
      <exec>
        <executable>git.exe</executable>
        <baseDirectory>$(ExampleGame)</baseDirectory>
        <buildArgs>pull origin master</buildArgs>
      </exec>

      <powershell>
        <script>build_native.ps1</script>
        <scriptsDirectory>$(ExampleGame)\build</scriptsDirectory>
        <buildArgs>$(ExampleGame)\ExampleGame\proj.android\build_native.sh</buildArgs>
        <buildTimeoutSeconds>600000</buildTimeoutSeconds>
      </powershell>

      <exec>
        <executable>ant.bat</executable>
        <baseDirectory>$(ExampleGame)\ExampleGame\proj.android</baseDirectory>
        <buildArgs>clean release</buildArgs>
        <buildTimeoutSeconds>600000</buildTimeoutSeconds>
      </exec>
    </tasks>

    <publishers>
      <xmllogger />
      <artifactcleanup cleanUpMethod="KeepLastXBuilds" cleanUpValue="50" />

      <buildpublisher>
        <sourceDir>$(ExampleGame)\ExampleGame\proj.android\bin</sourceDir>
        <publishDir>C:\Release\Android</publishDir>
        <useLabelSubDirectory>true</useLabelSubDirectory>
        <alwaysPublish>false</alwaysPublish>
        <cleanUpMethod>KeepLastXBuilds</cleanUpMethod>
        <cleanUpValue>5</cleanUpValue>
      </buildpublisher>

      <powershell>
        <script>clean-android.ps1</script>
        <scriptsDirectory>$(ExampleGame)\build</scriptsDirectory>
      </powershell>
    </publishers>

  </project>
</cruisecontrol>

게임 프로젝트 이름은 ExampleGame입니다. 그리고 윈도우 환경 변수에서 ExampleGame을 만들고 프로젝트의 디렉터리를 지정합니다. $()는 CruiseControl.NET에서 환경 변수를 가져오는 문법입니다.

이제 프로젝트 디렉터리에 build라는 디렉터리를 생성하고, 아래 내용으로 build_native.ps1 파일을 생성합니다.

프로젝트 디렉터리\build\build_native.ps1

$output = & python.exe $args[0] 2>&1
$output -match "[Ee]rror"

CruiseControl.NET에서 안드로이드용으로 Cocos2d-x Native 빌드를 하면 Cygwin이 stderr로 에러를 뿌리기 때문에 빌드에 실패합니다. 이때는 build_native.ps1에서 stderr을 stdout으로 리다이렉션하면 됩니다. $output -match "[Ee]rror"는 stdout에서 에러 메시지를 잡아냅니다.

Native 빌드가 끝났으면 ant로 .apk 파일을 생성합니다. ant는 따로 설치해도 되고, Eclipse 안에 들어있는 것을 사용해도 됩니다.

clean-android.ps1 스크립트로 .apk 파일을 제외한 기타 파일들은 깔끔하게 지워줍니다.

프로젝트 디렉터리\build\clean-android.ps1

Get-ChildItem -Path C:\Release\Android -Recurse -File -Exclude *.apk | Remove-Item
try
{
    (Get-ChildItem C:\Release\Android -Recurse | Where-Object {$_.PSIsContainer -eq $True}) | Where-Object {$_.GetFiles().Count -eq 0} | Remove-Item -Recurse
}
catch
{
}

Remove-Item으로는 하위 파일만 삭제할 수 있습니다. 그래서 빈 디렉터리까지 모두 삭제하기 위해 좀 복잡해보이는 코드를 사용합니다.

Where-Object {$_.PSIsContainer -eq $True}로 디렉터리인지 판별하고, Where-Object {$_.GetFiles().Count -eq 0}로 디렉터리가 비어 있는지 판별한 뒤 해당 디렉터리를 모두 삭제합니다.

이미 삭제된 디렉터리를 순회하다가 예외가 발생하기 때문에 반드시 try {} catch {}로 감싸주어야 합니다. 그렇지 않으면 CruiseControl.NET에서 에러로 간주하고 빌드에 실패합니다.


저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.