프로그래밍/예전글

Jenkins에서 Unity 빌드하기

Cat체셔 2015. 1. 26. 16:20

목적 : CI를 통해  Unity빌드를 자동화 한다.


필요한 것

Unity pro

SVN

Jenkins

JDK(jenkins설치시 필요)

Jenkins의  unity build plugin


진행 과정

0. 젠킨스 설치

0-1. jenkins를 다운로드 후, 설치를 하면 Applications(응용 프로그램)/Jenkins/jenkins.war가 생성된다.

0-2. terminal에서 jenkins.war의 디렉터리로 이동 후, $java -jar jenkins.war 명령을 실행한다.

0-3. 사파리에서 localhost:8080으로 접속한다.

 - Default port번호는 8080 변경하고 싶으면 --httpPort=번호 로 바꿔준다.

1. 시스템 설정을 한다.

1-1. JDK Installations

 - mac에서 JAVA_HOME은 JDK설치 후 /usr/libexec/java_home을 실행하면 알 수 있음

1-2 ANT Installations(있으니까 했음, Maven연동은 안한)

1-3 unity build plugin을 설치하면 Maven아래쪽에 Unity3d탭이 생김 Untiy installations를 등록

 - mac에서 발생하는 Not Unity3d home directory /Applications/Unity 에러가 뭔지 모르겠음.

 => 발견 : Installation directory를 /Applications/Unity/Unity.app으로 해야됨

2. Configure Global Security

2-1. Enable security 활성화

2.2. Security Realm의 Access Control에서 Jenkins'own user database 활성화 및 사용자의 가입 허용 활성화

2.3 Autorization에서 Project-based Matrix Authorization Stratgy 활성화

 => 젠킨스 세팅 완료


3. 새로운 Item(Job 등록)

3-1. 새로운 Item클릭 후, Freestyle project 생성

3-2. 소스 코드 관리에서 Subversion선택

 - Unable to access svn://blah.blah.blah.blah/svn/what/what : svn:E200015:No credential to try. Authentication failed(show details) (Mabe you need to enter credential?) 에러 발생시에는 enter credential을 클릭 후, subversion Authentication을 등록하면 된다.

3-3. Build탭에서 Invoke Unity3d Editor에서 Unity3d installation name을 아까 시스템 설정창에서 등록한 유니티로 설정.

3-4. Editor command line arguments을 채움

 - -quit -batchmode -project Path "/Path/path/Path/path/path" -executeMethod className.methodName -output  "%WORKSPACE%\output" -Define PREDEFINES로 했음

- http://docs.unity3d.com/Manual/CommandLineArguments.html 참조


이제 실행시키면 됨.


빌드 시, 문제 발생

해당 빌드 콘솔에서 FAILED TO establish the default connection to the WindowServer가 뜨고 아무것도 안되는 경우,

sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist

sudo mv /Library/LaunchDaemons/org.jenkins-ci.plist /Library/LaunchAgents/

를 입력하면 젠킨스가 종료됩니다. 이후, 젠킨스를 실행해주면 잘 됩니다.



using UnityEngine;

using System;

using System.IO;

using System.Collections;

using System.Collections.Generic;

using UnityEditor;


public class CommandBuild

{

static Dictionary<string, string> arguments = new Dictionary<string, string>();

static void InitCommandLineArgs()

{

string[] commandArgs;

if (editorBuild != null)

commandArgs = editorBuild.Split(' ');

else

commandArgs = Environment.GetCommandLineArgs();


for (int i = 0; i < commandArgs.Length; i++)

{

if (commandArgs[i].Length > 1 && commandArgs[i].StartsWith("-"))

{

string key = commandArgs[i].Substring(1);

if (arguments.ContainsKey(key) == false)

{

string value = null;

if (i + 1 < commandArgs.Length)

value = commandArgs[i + 1];

arguments.Add(key, value);

}

}

}

}

public static void BuildAndroid()

{

InitCommandLineArgs();


string define = GetValue("Define");

if (define != null)

PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, define);


string outputFileName = GetValue("outputFileName");

string savepath = string.Format("{0}/../{1}.apk", Application.dataPath, outputFileName);

PlayerSettings.Android.keystoreName = "keystoreName.keystore";

PlayerSettings.Android.keyaliasName = "keyaliasName";

PlayerSettings.Android.keystorePass = "keystorePass";

PlayerSettings.Android.keyaliasPass = "keyaliasPass";


Build(savepath, BuildTarget.Android);

}


public static void BuildiOS()

{

InitCommandLineArgs();

string define = GetValue("Define");

if (define != null)

PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.iPhone, define);

string outputFileName = GetValue("outputFileName");

string savepath = string.Format("{0}/../"+outputFileName, Application.dataPath);


Build(savepath, BuildTarget.iPhone);

}




이후 발견된 버그

1. 플랫폼 변경이 안된채로 빌드되는 경우

=> 플랫폼 변경하는 코드를 삽입하여도 실질적으로 코드와 연결된 라이브러리들이 변경전 라이브러리들을 보고 있어서 컴파일 에러 발생

해결 : 빌드 과정을 하나 상단에 추가하여 플랫폼 변경을 미리 해준 후, 다음 빌드 과정에서 빌드를 해준다.

2. Definition이 변경 안되는 경우

=> preprocess defininition들을 위의 소스와 같이 변경을 해도 적용이 안되는 버그 발생

해결 : 1번과 같이 prebuild를 만들어 그 안에서 빌드전에 세팅해야할 것들을 미리 세팅한다.