def codesign(app, mobileprovision=None, identity=None): identity = identity or _authority(app) if not identity: raise RuntimeError('No valid code signing identity') codeSignature = os.path.join(app, '_CodeSignature') if os.path.isdir(codeSignature): shutil.rmtree(codeSignature) if mobileprovision: shutil.copy2(mobileprovision, os.path.join(app, 'embedded.mobileprovision')) entitlementsFile = None handle, entitlementsFile = tempfile.mkstemp() entitlements = _entitlements(mobileprovision) # set the keychain access group to the identifier, # there might be some corner cases where this is not correct... entitlements['keychain-access-groups'] = [entitlements['application-identifier']] plistlib27.writePlist(entitlements, entitlementsFile) # with Xcode 5 the command line tools now install to /usr/bin codesign_allocate = '/usr/bin/codesign_allocate' if not os.path.isfile(codesign_allocate): codesign_allocate = '%s%s' % (XcodePath(), codesign_allocate) if not os.path.isfile(codesign_allocate): raise RuntimeError('Cannot find codesigning command line tools. Please ensure that the Command Line Tools are installed from Xcode') # Needed for Mountain Lion: http://stackoverflow.com/a/11723891/239380 os.putenv('CODESIGN_ALLOCATE', codesign_allocate) codesign = 'codesign --force --sign "%(identity)s" --entitlements "%(entitlementsFile)s" "%(app)s"' if subprocess.call(codesign % locals(), shell=True): if os.path.isfile(entitlementsFile): os.remove(entitlementsFile) raise RuntimeError('Code signing failed') if os.path.isfile(entitlementsFile): os.remove(entitlementsFile)
def codesign(app, mobileprovision=None, identity=None): identity = identity or _authority(app) if not identity: raise RuntimeError('No valid code signing identity') codeSignature = os.path.join(app, '_CodeSignature') if os.path.isdir(codeSignature): shutil.rmtree(codeSignature) if mobileprovision: shutil.copy2(mobileprovision, os.path.join(app, 'embedded.mobileprovision')) entitlementsFile = None handle, entitlementsFile = tempfile.mkstemp() entitlements = _entitlements(mobileprovision) # set the keychain access group to the identifier, # there might be some corner cases where this is not correct... entitlements['keychain-access-groups'] = [entitlements['application-identifier']] if 'com.apple.developer.icloud-services' in entitlements: if 'com.apple.developer.icloud-container-development-container-identifiers' in entitlements: del entitlements['com.apple.developer.icloud-container-development-container-identifiers'] entitlements['com.apple.developer.icloud-container-environment'] = 'Production' entitlements['com.apple.developer.icloud-services'] = ['CloudDocuments'] if 'com.apple.developer.ubiquity-kvstore-identifier' in entitlements: del entitlements['com.apple.developer.ubiquity-kvstore-identifier'] plistlib27.writePlist(entitlements, entitlementsFile) # with Xcode 5 the command line tools now install to /usr/bin codesign_allocate = '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate' if not os.path.isfile(codesign_allocate): codesign_allocate = '%s%s' % (XcodePath(), codesign_allocate) if not os.path.isfile(codesign_allocate): raise RuntimeError('Cannot find codesigning command line tools. Please ensure that the Command Line Tools are installed from Xcode') # Needed for Mountain Lion: http://stackoverflow.com/a/11723891/239380 os.putenv('CODESIGN_ALLOCATE', codesign_allocate) # Codesign frameworks in Frameworks folder frameworksFolder = os.path.join(app, 'Frameworks') if os.path.isdir(frameworksFolder): for framework in os.listdir(frameworksFolder): if framework.endswith(".dylib") or framework.endswith(".framework"): frameworkPath = os.path.join(frameworksFolder, framework) codesignFramework = 'codesign --force --sign "%(identity)s" "%(frameworkPath)s"' if subprocess.call(codesignFramework % locals(), shell=True): raise RuntimeError('Framework code signing failed') codesign = 'codesign --force --sign "%(identity)s" --entitlements "%(entitlementsFile)s" "%(app)s"' if subprocess.call(codesign % locals(), shell=True): if os.path.isfile(entitlementsFile): os.remove(entitlementsFile) raise RuntimeError('Code signing failed') if os.path.isfile(entitlementsFile): os.remove(entitlementsFile)
def archive(app, dsym, appModifyCallback=None): appBase = os.path.basename(app) appName = os.path.splitext(appBase)[0] date = datetime.today().strftime('%m-%d-%y %H.%M %p') archive = os.path.join(tempfile.mkdtemp(), '%(appName)s %(date)s.xcarchive' % locals()) applications = os.path.join(archive, 'Products', 'Applications') archiveApp = os.path.join(applications, appBase) shutil.copytree(app, archiveApp) if appModifyCallback: appModifyCallback(archiveApp) info = plistlib27.readPlist(os.path.join(app, 'Info.plist')) dsyms = os.path.join(archive, 'dSYMs') dsymArchive = os.path.join(dsyms, os.path.basename(dsym)) shutil.copytree(dsym, dsymArchive) updateDsymIdentifier(dsymArchive, info['CFBundleIdentifier']) icons = (os.path.join('Applications', appBase, item) for item in os.listdir(app) if item.startswith('AppIcon') and item.endswith('@2x.png')) plist = { 'ApplicationProperties': { 'ApplicationPath': os.path.join('Applications', appBase), 'CFBundleIdentifier': info['CFBundleIdentifier'], 'CFBundleShortVersionString': info['CFBundleShortVersionString'], 'CFBundleVersion': info['CFBundleVersion'], 'SigningIdentity': _authority(archiveApp) or '', 'IconPaths': list(icons) }, 'ArchiveVersion': 2, 'CreationDate': datetime.utcnow(), 'Name': appName, 'SchemeName': appName } plistlib27.writePlist(plist, os.path.join(archive, 'Info.plist')) # Add SwiftSupport folder xcodePath = subprocess.check_output(["xcode-select", "--print-path"]) xcodePath = xcodePath.rstrip() libraryPath = os.path.join(xcodePath, 'Toolchains', 'XcodeDefault.xctoolchain', 'usr', 'lib', 'swift', 'iphoneos') frameworksFolder = os.path.join(app, 'Frameworks') if os.path.isdir(frameworksFolder): for framework in os.listdir(frameworksFolder): if framework.startswith("libswift"): swiftSupportFolder = os.path.join(archive, 'SwiftSupport') if not os.path.isdir(swiftSupportFolder): os.mkdir(swiftSupportFolder) print 'Added SwiftSupport folder' shutil.copy2(os.path.join(libraryPath, framework), os.path.join(swiftSupportFolder, framework)) return archive
def archive(app, dsym, appModifyCallback=None): appBase = os.path.basename(app) appName = os.path.splitext(appBase)[0] date = datetime.today().strftime('%m-%d-%y %H.%M %p') archive = os.path.join(tempfile.mkdtemp(), '%(appName)s %(date)s.xcarchive' % locals()) applications = os.path.join(archive, 'Products', 'Applications') archiveApp = os.path.join(applications, appBase) shutil.copytree(app, archiveApp) if appModifyCallback: appModifyCallback(archiveApp) info = plistlib27.readPlist(os.path.join(app, 'Info.plist')) dsyms = os.path.join(archive, 'dSYMs') dsymArchive = os.path.join(dsyms, os.path.basename(dsym)) shutil.copytree(dsym, dsymArchive) updateDsymIdentifier(dsymArchive, info['CFBundleIdentifier']) icons = (os.path.join('Applications', appBase, item) for item in os.listdir(app) if item.startswith('Icon') and item.endswith('png')) plist = { 'AppStoreFileSize': _directorySize(archiveApp), 'ApplicationProperties': { 'ApplicationPath': os.path.join('Applications', appBase), 'CFBundleIdentifier': info['CFBundleIdentifier'], 'CFBundleShortVersionString': info['CFBundleShortVersionString'], 'CFBundleVersion': info['CFBundleVersion'], 'SigningIdentity': _authority(archiveApp) or '', 'IconPaths': list(icons) }, 'ArchiveVersion': 2, 'CreationDate': datetime.today().strftime('%Y-%m-%dT%H:%M:%SZ'), 'Name': appName, 'SchemeName': appName } plistlib27.writePlist(plist, os.path.join(archive, 'Info.plist')) return archive
def updateDsymIdentifier(dsym, identifier): path = os.path.join(dsym, 'Contents', 'Info.plist') info = plistlib27.readPlist(path) info['CFBundleIdentifier'] = 'com.apple.xcode.dsym.'+identifier plistlib27.writePlist(info, path)