빌드 스크립트 정리

젠킨스를 위해서 자동 빌드 스크립트들을 정리해 두었다.

그간 미뤘다가 대강이라도 지금 정리하는 이유는 아는 분이 부탁했기 때문이기도 한다.

이렇게 해둔 이유는 젠킨스 사용 시에 편하게 쓰기 위함이고 .

내가 해온 삽질이 누군가에게 의미가 있었음 좋겠다.

시간 되면 또 다듬어봐야지 .

이게 선처리 빌드 스크립트다.

    using UnityEditor;
    using UnityEditor.Build; // 꼭 필요함 . 
    using UnityEngine;
    class PreBuilder : IPreprocessBuild {
        public void OnPreprocessBuild (BuildTarget target, string path) 
        {
        // 빌드 전에 꼭 해야할 처리들을 해줍니다. 
        }
    
    }

이게 본 빌드 스크립트다 . ( 젠킨스에서 호출하는 ).

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using UnityEditor;
    using UnityEditor.Build;
    using UnityEngine;
    public class AutoBuilder : ScriptableObject {
        static string[] SCENES = FindEnabledEditorScenes ();
        static string APP_NAME = "앱 이름";
        static string TARGET_DIR;
        [MenuItem ("CI/Build For Android")]
        public static void PerformBuildAOS () {
            //  PlayerSettings.Android.bundleVersionCode = 동적으로 버전 코드 설정
            // PlayerSettings.bundleVersion = 동적으로 번들 버전 설정 
            APP_NAME = "앱이름" + PlayerSettings.Android.bundleVersionCode + ".apk";
    				// 맘대로 하셔도 별 지장 없지만, 저는 분간을 위해서 이렇게 합니다. 
            TARGET_DIR = ProjectPath + "/" + "Output";
            Directory.CreateDirectory (TARGET_DIR); // 혹시 없을까봐 디렉토리 만들어줌 
            //PlayerSettings.Android.keyaliasName = 환경 변수로 세팅하길 추천합니다. 
            //PlayerSettings.Android.keystoreName = 환경 변수로 세팅하길 추천합니다. 
            // PlayerSettings.Android.keyaliasPass = 환경 변수로 세팅하길 추천합니다. 
    	      // PlayerSettings.Android.keystorePass = 환경 변수로 세팅하길 추천합니다. 
            PlayerSettings.SetScriptingBackend (BuildTargetGroup.Android, ScriptingImplementation.IL2CPP);
            // 대략 설정해줍니다. 본인 필요에 맞춰서요 .
            PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64 | AndroidArchitecture.ARMv7;
    				// 이넘이니 여러개를 중첩할 수 있습니다. 
            EditorUserBuildSettings.androidBuildSystem = AndroidBuildSystem.Gradle; //저는 그래들로 합니다. 인터널로 하실 수도 있어요 
            EditorUserBuildSettings.androidBuildType = AndroidBuildType.Release; // 디벨롭이 필요하시면 디벨롭으로 하시면 됩니다. 
            BuildAndroid (SCENES, TARGET_DIR + "/" + APP_NAME, BuildTargetGroup.Android, BuildTarget.Android,  BuildOptions.CompressWithLz4HC | BuildOptions.Il2CPP );
            // 이것도 필요하시면 커스텀 ! 
        }
    
    
        
        private static void BuildAndroid (string[] scenes, string app_target, BuildTargetGroup build_target_group, BuildTarget build_target, BuildOptions build_options) {
    				if (EditorUserBuildSettings.activeBuildTarget != BuildTarget.Android)
    		       EditorUserBuildSettings.SwitchActiveBuildTarget (BuildTargetGroup.Android, BuildTarget.Android);
            //현 세팅이 안드로이드 아니면 안드로이드로 바꿔줍니다. 만약 다시 원상태로 돌아오고 싶으면 PostBuild 활용하세요
            BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions ();
            buildPlayerOptions.scenes = scenes;
            buildPlayerOptions.locationPathName = app_target;
            buildPlayerOptions.target = BuildTarget.Android;
            buildPlayerOptions.options = build_options;
            var report = BuildPipeline.BuildPlayer (buildPlayerOptions);
        }
    
    		private static string[] FindEnabledEditorScenes () 
    		{
            List<string> EditorScenes = new List<string> ();
    
            foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes) {
                if (!scene.enabled) continue;
                EditorScenes.Add (scene.path);
            }
    
            return EditorScenes.ToArray ();
        }
    
        static string ProjectPath {
            get { return Application.dataPath.Substring (0, Application.dataPath.LastIndexOf ('/')); }
        } // 귀찮고 시간 없어서 대강 만들어서 쓰고 있는 중인 함수 
    
        [MenuItem ("CI/Build iOS")]
        public static void PerformBuildIOS () {
            BuildOptions opt = BuildOptions.Il2CPP; // 기본이 cpp
            PlayerSettings.iOS.sdkVersion = iOSSdkVersion.DeviceSDK; // 시뮬레이터에서 돌리시려면 시뮬레이터 sdk 로 
            //PlayerSettings.bundleVersion = GetArg ("-BUNDLE_VERSION"); //todo
            //PlayerSettings.iOS.buildNumber = (GetArg ("-VERSION_CODE")); //todo
            char sep = Path.DirectorySeparatorChar;
            string BUILD_TARGET_PATH = ProjectPath + "/ios"; //ios 폴더로 뱉습니다. 
            Directory.CreateDirectory (BUILD_TARGET_PATH);
            PlayerSettings.SetScriptingBackend (BuildTargetGroup.iOS, ScriptingImplementation.IL2CPP);
            try {
                BuildIOS (SCENES, BUILD_TARGET_PATH, BuildTarget.iOS, opt);
            } catch (System.Exception e) {
                Debug.Log (e.Message);
            }
        }
    
        static void BuildIOS (string[] scenes, string target_path,
            BuildTarget build_target, BuildOptions build_options) {
            EditorUserBuildSettings.SwitchActiveBuildTarget (BuildTargetGroup.iOS, build_target);
            string res = BuildPipeline.BuildPlayer (scenes, target_path, build_target, build_options);
            if (res.Length > 0) { throw new Exception ("BuildPlayer failure: " + res); }
        }
    
    }

이게 후처리 빌드 스크립트이다.

    #if UNITY_IOS
    using System.IO;
    using UnityEditor;
    using UnityEditor.Build;
    using UnityEditor.iOS.Xcode;
    using UnityEngine;
    // ios 유니티 빌드는 먼저 엑스코드용으로 빼준다음에 다시 시작되니. 빌드후 이렇게 후처리 해주고 엑스코드 에서 아카이빙 해주면 끝이납니다. 이부분은 젠킨스 파트에서 더 설명할게요 . 
    class PostBuilder : IPostprocessBuild
    {
        public int callbackOrder { get { return 0; } }
    
        static string ProjectPath
        {
            get { return Application.dataPath.Substring(0, Application.dataPath.LastIndexOf('/')); }
        }
        public void OnPostprocessBuild(BuildTarget buildTarget, string pathToBuiltProject)
        {
            // Stop processing if targe is NOT iOS 
            if (buildTarget != BuildTarget.iOS) return;
            // Initialize PbxProject 
            var projectPath = pathToBuiltProject + "/Unity-iPhone.xcodeproj/project.pbxproj";
            PBXProject pbxProject = new PBXProject();
            pbxProject.ReadFromFile(projectPath);
            string targetGuid = pbxProject.TargetGuidByName("Unity-iPhone");
            pbxProject.AddCapability(targetGuid, PBXCapabilityType.InAppPurchase);
            pbxProject.AddCapability(targetGuid, PBXCapabilityType.iCloud);
            pbxProject.AddCapability(targetGuid, PBXCapabilityType.GameCenter);
            pbxProject.AddCapability(targetGuid, PBXCapabilityType.PushNotifications);
    //이런 식으로 권한 추가해주면 되는데, 특이하게 푸시나 아이클라우드는 추가로 더 해줘야합니다.  (다음에 나옴 ) 
    
            pbxProject.SetBuildProperty(targetGuid, "DEVELOPMENT_TEAM", "애플 개발자 팀 아이디 ");
            var guid = pbxProject.FindFileGuidByProjectPath("Classes/UI/Keyboard.mm");
            var flags = pbxProject.GetCompileFlagsForFile(targetGuid, guid);
            flags.Add("-fno-objc-arc");
            pbxProject.SetCompileFlagsForFile(targetGuid, guid, flags);
            pbxProject.AddFrameworkToProject(targetGuid, "CloudKit.framework", false);
    
            // Apply settings 
            File.WriteAllText(projectPath, pbxProject.WriteToString());
            // Samlpe of editing Info.plist 
            var plistPath = Path.Combine(pathToBuiltProject, "Info.plist");
            var plist = new PlistDocument();
            plist.ReadFromFile(plistPath);
            // Add string setting 
            plist.root.SetBoolean("ITSAppUsesNonExemptEncryption", false); // 앱이 암호화를 쓰는지 제출하는 건데, 안하면 귀찮게 바로 테스트플라이트가 안올라가고 의미없는 설문을 더 해야하니 . 암호화를 특별나게 쓰고 있지만 않다면 이렇게 합시다. 
            // Add URL Scheme\
            // Apply editing settings to Info.plist
            var cap = plist.root.CreateArray("UIRequiredDeviceCapabilities");
            cap.AddString("gamekit");
            plist.WriteToFile(plistPath);
    
    
            //-----
    
            var file_name = "unity.entitlements"; // 이거없으면 푸시 안됩니다 
            var proj_path = projectPath;
            var proj = new PBXProject();
            proj.ReadFromFile(proj_path);
    
    
            // target_name = "Unity-iPhone"
            var target_name = PBXProject.GetUnityTargetName();
            var target_guid = proj.TargetGuidByName(target_name);
            var dst = pathToBuiltProject + "/" + target_name + "/" + file_name;
            try
            {
                File.WriteAllText(dst, entitlements);
                proj.AddFile(target_name + "/" + file_name, file_name);
                proj.AddBuildProperty(target_guid, "CODE_SIGN_ENTITLEMENTS", target_name + "/" + file_name);
                proj.WriteToFile(proj_path);
            }
            catch (IOException e)
            {
                Debug.Log("Could not copy entitlements. Probably already exists. " + e);
            }
    
            UnityEditor.iOS.Xcode.ProjectCapabilityManager pcm = new UnityEditor.iOS.Xcode.ProjectCapabilityManager(proj_path, dst, target_name);
            pcm.AddPushNotifications(false);
    
        }
    // 슬픈 하드코딩 타자가 길어서 슬픈 짐승이여 
    
        private const string entitlements = @"
         <?xml version=""1.0"" encoding=""UTF-8\""?>
         <!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd"">
         <plist version=""1.0"">
             <dict>
                 <key>aps-environment</key>
                 <string>production</string>
             </dict>
         </plist>";
    
    }
    #endif

개발자 공부 방향 잡기

Published on November 24, 2023

git branch name on windows and linux

Published on November 19, 2023