AppleWatchアプリをXcodeGenで構築したので、project.ymlを大雑把に置いておきます
困ったこと
- AppleWatchでのXcodeGenの文献が少なかった
開発環境と構成
- Xcode11.X~
- 構成
- iOSAppTarget
- WatchKit App
- WatchKit Extension
- iOS13.X
- WatchOS6.X
- ツール系
- Mint: 0.13.0(Mintfile)
- XcodeGen: 2.15.1(project.yml)
- SwiftPM
- SwiftPMに対応しているライブラリがあれば優先的に
- SwiftLint: 0.39.2
- Carthage: 0.34.0(Cartfile)
- SwiftPMに対応してないが、Carthageに対応しているライブラリがあれば優先的に
- Bundler: 2.1.3(Gemfile)
- Cocoapods: 1.9.1(Podfile)
- SwiftPMにもCarthageにも対応してないライブラリ(Firebaseとか)
- Fastlane: 2.144.0(Fastfile)
- いろいろ
- Cocoapods: 1.9.1(Podfile)
- Mint: 0.13.0(Mintfile)
XcodeGenはMintで管理
- Mintを使って XcodeGen / SwiftLint / Carthage のバージョンを管理しました
- ライブラリはなるべくSwiftPMに対応していればそれを優先的に利用し、Carthage->CocoaPodsの順で優先度を割り振りました
XcodeGenのproject.yml
project.yml
attributes:
LastSwiftUpdateCheck: 1130
LastUpgradeCheck: 1130
ORGANIZATIONNAME: inc.noplan
settings:
base:
CURRENT_PROJECT_VERSION: 1
MARKETING_VERSION: "0.0.26"
configs:
Debug: debug
Release: release
name: [アプリ名]
packages:
Nuke:
url: https://github.com/kean/Nuke.git
from: 8.4.1
[SwiftPMで使用するライブラリたち]
options:
groupSortPosition: bottom
transitivelyLinkDependencies: false
settingGroups:
Debug:
ALWAYS_SEARCH_USER_PATHS: NO
CLANG_ANALYZER_NONNULL: YES
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION: YES_AGGRESSIVE
CLANG_CXX_LANGUAGE_STANDARD: gnu++14
CLANG_CXX_LIBRARY: libc++
CLANG_ENABLE_MODULES: YES
CLANG_ENABLE_OBJC_ARC: YES
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING: YES
CLANG_WARN_BOOL_CONVERSION: YES
CLANG_WARN_COMMA: YES
CLANG_WARN_CONSTANT_CONVERSION: YES
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS: YES
CLANG_WARN_DIRECT_OBJC_ISA_USAGE: YES_ERROR
CLANG_WARN_DOCUMENTATION_COMMENTS: YES
CLANG_WARN_EMPTY_BODY: YES
CLANG_WARN_ENUM_CONVERSION: YES
CLANG_WARN_INFINITE_RECURSION: YES
CLANG_WARN_INT_CONVERSION: YES
CLANG_WARN_NON_LITERAL_NULL_CONVERSION: YES
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF: YES
CLANG_WARN_OBJC_LITERAL_CONVERSION: YES
CLANG_WARN_OBJC_ROOT_CLASS: YES_ERROR
CLANG_WARN_RANGE_LOOP_ANALYSIS: YES
CLANG_WARN_STRICT_PROTOTYPES: YES
CLANG_WARN_SUSPICIOUS_MOVE: YES
CLANG_WARN_UNGUARDED_AVAILABILITY: YES_AGGRESSIVE
CLANG_WARN_UNREACHABLE_CODE: YES
CLANG_WARN__DUPLICATE_METHOD_MATCH: YES
COPY_PHASE_STRIP: NO
DEBUG_INFORMATION_FORMAT: dwarf
ENABLE_STRICT_OBJC_MSGSEND: YES
ENABLE_TESTABILITY: YES
GCC_C_LANGUAGE_STANDARD: gnu11
GCC_DYNAMIC_NO_PIC: NO
GCC_NO_COMMON_BLOCKS: YES
GCC_OPTIMIZATION_LEVEL: 0
GCC_PREPROCESSOR_DEFINITIONS:
- $(inherited)
- DEBUG=1
GCC_WARN_64_TO_32_BIT_CONVERSION: YES
GCC_WARN_ABOUT_RETURN_TYPE: YES_ERROR
GCC_WARN_UNDECLARED_SELECTOR: YES
GCC_WARN_UNINITIALIZED_AUTOS: YES_AGGRESSIVE
GCC_WARN_UNUSED_FUNCTION: YES
GCC_WARN_UNUSED_VARIABLE: YES
MTL_ENABLE_DEBUG_INFO: YES
ONLY_ACTIVE_ARCH: YES
PRODUCT_NAME: $(TARGET_NAME)
SDKROOT: iphoneos
SWIFT_ACTIVE_COMPILATION_CONDITIONS: DEBUG
SWIFT_OPTIMIZATION_LEVEL: -Onone
SWIFT_VERSION: 5.0
Staging:
[割愛]
Release:
[割愛]
schemes:
\[scheme名]:
build:
targets:
[iOSのターゲット名]: all
run:
config: Debug
test:
config: Debug
profile:
config: Debug
analyze:
config: Debug
archive:
config: Release
\[いろいろiOSのscheme]:
\[WatchOSのscheme名 WatchKit App]:
build:
targets:
[WatchOSのターゲット名 WatchKit App]: all
run:
config: Debug
test:
config: Debug
profile:
config: Debug
analyze:
config: Debug
archive:
config: Release
\[WatchOSのscheme名 WatchKit Extension]:
build:
targets:
[WatchOSのターゲット名 WatchKit Extension]: all
run:
config: Debug
test:
config: Debug
profile:
config: Debug
analyze:
config: Debug
archive:
config: Release
targets:
\[iOSのターゲット名]:
dependencies:
- target: [WatchOSのターゲット WatchKit App]
- {embed: false, framework: Pods_[iOSのターゲット].framework}
- {embed: false, framework: StoreKit.framework}
- package: SDWebImageSwiftUI
- package: SwiftUIX
- carthage: SwiftyStoreKit
- carthage: SwiftDate
- carthage: ObjectMapper
platform: iOS
postbuildScripts:
- inputFiles:
- ${PODS_PODFILE_DIR_PATH}/Podfile.lock
- ${PODS_ROOT}/Manifest.lock
name: '[CP] Check Pods Manifest.lock'
outputFiles:
- $(DERIVED_FILE_DIR)/Pods-[プロジェクト]-checkManifestLockResult.txt
runOnlyWhenInstalling: false
script: "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\"
> /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo
\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install'
or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output
is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\"
> \"${SCRIPT_OUTPUT_FILE_0}\"\n"
shell: /bin/sh
showEnvVars: false
- inputFileLists:
- ${PODS_ROOT}/Target Support Files/Pods-{iOSのターゲット}/Pods-{iOSのターゲット}-frameworks-${CONFIGURATION}-input-files.xcfilelist
name: '[CP] Embed Pods Frameworks'
outputFileLists:
- ${PODS_ROOT}/Target Support Files/Pods-{iOSのターゲット}/Pods-{iOSのターゲット}-frameworks-${CONFIGURATION}-output-files.xcfilelist
runOnlyWhenInstalling: false
script: '"${PODS_ROOT}/Target Support Files/Pods-{iOSのターゲット}/Pods-{iOSのターゲット}-frameworks.sh"'
shell: /bin/sh
showEnvVars: false
prebuildScripts:
- name: run swiftlint
script: |
if mint which swiftlint >/dev/null; then
mint run swiftlint autocorrect --format
mint run swiftlint
else
echo "warning: mint install swiftlint"
fi
- name: linence plist
script: |
${PODS_ROOT}/LicensePlist/license-plist --output-path $PRODUCT_NAME/Settings.bundle --config-path $PRODUCT_NAME/license_plist.yml
/usr/libexec/PlistBuddy -c "Set :PreferenceSpecifiers:2:DefaultValue ${MARKETING_VERSION}" "$PRODUCT_NAME/Settings.bundle/Root.plist"
/usr/libexec/PlistBuddy -c "Set :PreferenceSpecifiers:3:DefaultValue ${CURRENT_PROJECT_VERSION}" "$PRODUCT_NAME/Settings.bundle/Root.plist"
settings:
configs:
Debug:
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
CLANG_ENABLE_MODULES: YES
CODE_SIGN_ENTITLEMENTS: [ENTITLEMENTSのpath].entitlements
CODE_SIGN_IDENTITY: iPhone Developer
CODE_SIGN_STYLE: Automatic
DEVELOPMENT_ASSET_PATHS: '"[DEVELOPMENT_ASSETのpath]/Preview Content"'
DEVELOPMENT_TEAM: [TEAMをどうぞ]
ENABLE_PREVIEWS: YES
FRAMEWORK_SEARCH_PATHS:
- $(inherited)
- '"."'
INFOPLIST_FILE: [plistのpath]/Info.plist
LD_RUNPATH_SEARCH_PATHS:
- $(inherited)
- '@executable_path/Frameworks'
PRODUCT_BUNDLE_IDENTIFIER: [PRODUCTのBUNDLE_IDENTIFIER]
PRODUCT_NAME: $(TARGET_NAME)
SDKROOT: iphoneos
SWIFT_OBJC_BRIDGING_HEADER: [Bridging-Headerのpath/Bridging-Header.h]
SWIFT_OPTIMIZATION_LEVEL: -Onone
SWIFT_VERSION: 5.0
TARGETED_DEVICE_FAMILY: 1,2
Staging:
[割愛]
Release:
[割愛]
sources:
- [デフォルトだとtarget名がフォルダ名と同じになってる]
- name: GoogleService-Info.plist
path: GoogleService-Info.plist
group: [ファイルはrootにあるけどまとめたいのでフォルダを指定する]
type: application
deploymentTarget: "13.0"
attributes:
SystemCapabilities:
com.apple.Push:
enabled: 1
com.apple.InAppPurchase:
enabled: 1
\[WatchOSのプロジェクト WatchKit App]:
dependencies:
- target: [WatchOSのtarget名 WatchKit Extension]
- {embed: false, framework: Pods_[プロジェクト]_WatchKit_App.framework}
platform: watchOS
postbuildScripts:
- inputFiles:
- ${PODS_PODFILE_DIR_PATH}/Podfile.lock
- ${PODS_ROOT}/Manifest.lock
name: '[CP] Check Pods Manifest.lock'
outputFiles:
- $(DERIVED_FILE_DIR)/Pods-[プロジェクト] WatchKit App-checkManifestLockResult.txt
runOnlyWhenInstalling: false
script: "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\"
> /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo
\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install'
or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output
is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\"
> \"${SCRIPT_OUTPUT_FILE_0}\"\n"
shell: /bin/sh
showEnvVars: false
settings:
configs:
Debug:
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES: YES
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
CODE_SIGN_STYLE: Automatic
DEVELOPMENT_TEAM: [チーム]
FRAMEWORK_SEARCH_PATHS:
- $(inherited)
- '"."'
IBSC_MODULE: [IBSC_MODULE]_WatchKit_Extension
INFOPLIST_FILE: [プロジェクト] WatchKit App/Info.plist
LD_RUNPATH_SEARCH_PATHS:
- $(inherited)
- '@executable_path/Frameworks'
PRODUCT_BUNDLE_IDENTIFIER: [アプリのBUNDLE_IDENTIFIER].watchkitapp
PRODUCT_NAME: $(TARGET_NAME)
SDKROOT: watchos
SKIP_INSTALL: YES
SWIFT_VERSION: 5.0
TARGETED_DEVICE_FAMILY: 4
WATCHOS_DEPLOYMENT_TARGET: 6.1
Stating:
[割愛]
Release:
[割愛]
sources:
- name: [デフォルトだとtarget名がフォルダ名と同じになってるやつ] WatchKit App
type: application.watchapp2
deploymentTarget: "6.0"
\[WatchOSのプロジェクト] WatchKit Extension:
dependencies:
- {embed: false, framework: Pods_[プロジェクト]_WatchKit_Extension.framework}
- carthage: ObjectMapper
- package: Nuke
platform: watchOS
postbuildScripts:
- inputFiles:
- ${PODS_PODFILE_DIR_PATH}/Podfile.lock
- ${PODS_ROOT}/Manifest.lock
name: '[CP] Check Pods Manifest.lock'
outputFiles:
- $(DERIVED_FILE_DIR)/Pods-[プロジェクト] WatchKit Extension-checkManifestLockResult.txt
runOnlyWhenInstalling: false
script: "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\"
> /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo
\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install'
or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output
is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\"
> \"${SCRIPT_OUTPUT_FILE_0}\"\n"
shell: /bin/sh
showEnvVars: false
settings:
configs:
Debug:
ASSETCATALOG_COMPILER_COMPLICATION_NAME: Complication
CODE_SIGN_STYLE: Automatic
DEVELOPMENT_ASSET_PATHS: '"[プロジェクト] WatchKit Extension/Preview Content"'
DEVELOPMENT_TEAM: 83GH78U9V5
ENABLE_PREVIEWS: YES
FRAMEWORK_SEARCH_PATHS:
- $(inherited)
- '"."'
INFOPLIST_FILE: [プロジェクト] WatchKit Extension/Info.plist
LD_RUNPATH_SEARCH_PATHS:
- $(inherited)
- '@executable_path/Frameworks'
- '@executable_path/../../Frameworks'
PRODUCT_BUNDLE_IDENTIFIER: [アプリのBUNDLE_IDENTIFIER].watchkitapp.watchkitextension
PRODUCT_NAME: ${TARGET_NAME}
SDKROOT: watchos
SKIP_INSTALL: YES
SWIFT_VERSION: 5.0
TARGETED_DEVICE_FAMILY: 4
WATCHOS_DEPLOYMENT_TARGET: 6.1
Staging:
[割愛]
Release:
[割愛]
sources:
- [デフォルトだとtarget名がフォルダ名と同じになってるやつ] WatchKit Extension
- name: [iOSでもWatchOSでも使いたいファイル].swift
path: [path/to/ファイルの所在地].swift
group: [置いておきたいpath/to/DataModel]
type: watchkit2-extension
deploymentTarget: "6.0"