diff --git a/build/lib/ios.js b/build/lib/ios.js index 1c1aad31af0..31a6789867a 100644 --- a/build/lib/ios.js +++ b/build/lib/ios.js @@ -88,7 +88,7 @@ class IOS { async copyLegacyHeaders(DEST_IOS) { // Gather all the *.h files in TitaniumKit, create "redirecting" headers in iphone/include that point to the TitaniumKit ones await fs.ensureDir(path.join(DEST_IOS, 'include')); - const subdirs = await fs.readdir(path.join(IOS_ROOT, 'TitaniumKit/build/Release-iphoneuniversal/TitaniumKit.framework/Headers')); + const subdirs = await fs.readdir(path.join(IOS_ROOT, 'TitaniumKit/build/TitaniumKit.xcframework/ios-arm64_armv7/TitaniumKit.framework/Headers')); // create them all in parallel await Promise.all(subdirs.map(file => { // TODO: Inject a deprecation warning if used and remove in SDK 9.0.0? @@ -138,13 +138,13 @@ class IOS { copyFiles(IOS_ROOT, DEST_IOS, [ 'AppledocSettings.plist', 'Classes', 'cli', 'iphone', 'templates' ]), // Copy TitaniumKit - copyFiles(path.join(IOS_ROOT, 'TitaniumKit/build/Release-iphoneuniversal'), path.join(DEST_IOS, 'Frameworks'), [ 'TitaniumKit.framework' ]), + fs.copySync(path.join(IOS_ROOT, 'TitaniumKit/build/TitaniumKit.xcframework'), path.join(DEST_IOS, 'Frameworks/TitaniumKit.xcframework')), // Copy and inject values for special source files this.injectSDKConstants(path.join(DEST_IOS, 'main.m')), - // Copy Ti.Verify - copyFiles(IOS_LIB, DEST_IOS, [ 'libtiverify.a' ]), + // Copy tiverify.xcframework + copyFiles(IOS_LIB, path.join(DEST_IOS, 'Frameworks'), [ 'tiverify.xcframework' ]), // Copy iphone/package.json, but replace __VERSION__ with our version! copyAndModifyFile(IOS_ROOT, DEST_IOS, 'package.json', { __VERSION__: this.sdkVersion }), diff --git a/build/lib/packager.js b/build/lib/packager.js index f81613a95fe..4f945144925 100644 --- a/build/lib/packager.js +++ b/build/lib/packager.js @@ -32,7 +32,7 @@ const TITANIUM_PREP_LOCATIONS = [ */ async function zip(cwd, filename) { const command = os.platform() === 'win32' ? path.join(ROOT_DIR, 'build/win32/zip') : 'zip'; - await exec(`${command} -9 -q -r "${path.join('..', path.basename(filename))}" *`, { cwd }); + await exec(`${command} -9 -q -r -y "${path.join('..', path.basename(filename))}" *`, { cwd }); const outputFolder = path.resolve(cwd, '..'); const outputFile = path.join(outputFolder, path.basename(filename)); diff --git a/iphone/TitaniumKit/TitaniumKit.xcodeproj/project.pbxproj b/iphone/TitaniumKit/TitaniumKit.xcodeproj/project.pbxproj index 2ce86503091..24cf9984f5b 100644 --- a/iphone/TitaniumKit/TitaniumKit.xcodeproj/project.pbxproj +++ b/iphone/TitaniumKit/TitaniumKit.xcodeproj/project.pbxproj @@ -732,7 +732,6 @@ TargetAttributes = { DB258CCC1F09757E000D0D8D = { CreatedOnToolsVersion = 8.3.3; - ProvisioningStyle = Automatic; }; DB9635BE1F0AB4AC00C41B20 = { CreatedOnToolsVersion = 8.3.3; @@ -988,8 +987,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = NO; - CODE_SIGN_IDENTITY = ""; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -1020,6 +1022,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.appcelerator.TitaniumKit; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; SKIP_INSTALL = YES; VALID_ARCHS = "$(ARCHS_STANDARD)"; }; @@ -1033,8 +1037,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = NO; - CODE_SIGN_IDENTITY = ""; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -1063,6 +1070,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.appcelerator.TitaniumKit; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; SKIP_INSTALL = YES; VALID_ARCHS = "$(ARCHS_STANDARD)"; }; diff --git a/iphone/TitaniumKit/TitaniumKit/Scripts/build-universal-framework.sh b/iphone/TitaniumKit/TitaniumKit/Scripts/build-universal-framework.sh index 3f4ad90f91c..cdfe19054d7 100755 --- a/iphone/TitaniumKit/TitaniumKit/Scripts/build-universal-framework.sh +++ b/iphone/TitaniumKit/TitaniumKit/Scripts/build-universal-framework.sh @@ -1,79 +1,37 @@ # Based on https://medium.com/@syshen/create-an-ios-universal-framework-148eb130a46c, thank you! -###################### -# Options -###################### - -REVEAL_ARCHIVE_IN_FINDER=false - -FRAMEWORK_NAME="${PROJECT_NAME}" - -SIMULATOR_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${FRAMEWORK_NAME}.framework" - -DEVICE_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FRAMEWORK_NAME}.framework" - -UNIVERSAL_LIBRARY_DIR="${BUILD_DIR}/${CONFIGURATION}-iphoneuniversal" - -FRAMEWORK="${UNIVERSAL_LIBRARY_DIR}/${FRAMEWORK_NAME}.framework" - XCODE_VERSION=$(/usr/libexec/PlistBuddy -c "Print :DTXcode" "$(xcode-select -p)/../Info.plist") -###################### -# Build Frameworks -###################### - -# Exclude arm64 architecture from simulator build in XCode 12+- TIMOB-28042 - -if [[ $XCODE_VERSION -ge 1200 ]]; then -xcodebuild -scheme ${PROJECT_NAME} -sdk iphonesimulator EXCLUDED_ARCHS=arm64 -configuration ${CONFIGURATION} clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator 2>&1 -else -xcodebuild -scheme ${PROJECT_NAME} -sdk iphonesimulator -configuration ${CONFIGURATION} clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator 2>&1 -fi - -xcodebuild -scheme ${PROJECT_NAME} -sdk iphoneos -configuration ${CONFIGURATION} clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos 2>&1 - -###################### -# Create directory for universal -###################### - -rm -rf "${UNIVERSAL_LIBRARY_DIR}" - -mkdir "${UNIVERSAL_LIBRARY_DIR}" - -mkdir "${FRAMEWORK}" - - -###################### -# Copy files Framework -###################### - -cp -r "${DEVICE_LIBRARY_PATH}/." "${FRAMEWORK}" - -###################### -# Make an universal binary -###################### - -lipo "${SIMULATOR_LIBRARY_PATH}/${FRAMEWORK_NAME}" "${DEVICE_LIBRARY_PATH}/${FRAMEWORK_NAME}" -create -output "${FRAMEWORK}/${FRAMEWORK_NAME}" | echo - -# For Swift framework, Swiftmodule needs to be copied in the universal framework -if [ -d "${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then -cp -f ${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo -fi - -if [ -d "${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then -cp -f ${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo -fi - -###################### -# On Release, copy the result to release directory -###################### -OUTPUT_DIR="${PROJECT_DIR}/dist/${FRAMEWORK_NAME}-${CONFIGURATION}-iphoneuniversal/" - -rm -rf "$OUTPUT_DIR" -mkdir -p "$OUTPUT_DIR" - -cp -r "${FRAMEWORK}" "$OUTPUT_DIR" - -if [ ${REVEAL_ARCHIVE_IN_FINDER} = true ]; then -open "${OUTPUT_DIR}/" -fi +FRAMEWORK_NAME="${PROJECT_NAME}" \ +SCHEME="${PROJECT_NAME}" \ +UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR} + +#----- Make macCatalyst archive +xcodebuild archive \ +-scheme $SCHEME \ +-archivePath $UNIVERSAL_OUTPUTFOLDER/macCatalyst.xcarchive \ +-sdk macosx \ +SKIP_INSTALL=NO \ +BUILD_LIBRARIES_FOR_DISTRIBUTION=YES \ +SUPPORTS_MACCATALYST=YES \ + +#----- Make iOS Simulator archive +xcodebuild archive \ +-scheme $SCHEME \ +-archivePath $UNIVERSAL_OUTPUTFOLDER/simulator.xcarchive \ +-sdk iphonesimulator \ +SKIP_INSTALL=NO BUILD_LIBRARIES_FOR_DISTRIBUTION=YES + +#----- Make iOS device archive +xcodebuild archive \ +-scheme $SCHEME \ +-archivePath $UNIVERSAL_OUTPUTFOLDER/iosdevice.xcarchive \ +-sdk iphoneos \ +SKIP_INSTALL=NO BUILD_LIBRARIES_FOR_DISTRIBUTION=YES + +#----- Make XCFramework +xcodebuild -create-xcframework \ +-framework $UNIVERSAL_OUTPUTFOLDER/simulator.xcarchive/Products/Library/Frameworks/$SCHEME.framework \ +-framework $UNIVERSAL_OUTPUTFOLDER/iosdevice.xcarchive/Products/Library/Frameworks/$SCHEME.framework \ +-framework $UNIVERSAL_OUTPUTFOLDER/macCatalyst.xcarchive/Products/Library/Frameworks/$SCHEME.framework \ +-output ${PROJECT_DIR}/dist/$SCHEME.xcframework diff --git a/iphone/cli/commands/_build.js b/iphone/cli/commands/_build.js index 47015b9ee3a..481e4758360 100644 --- a/iphone/cli/commands/_build.js +++ b/iphone/cli/commands/_build.js @@ -2188,6 +2188,12 @@ iOSBuilder.prototype.validate = function validate(logger, config, cli) { } else { module.native = true; const frameworkName = this.scrubbedModuleId(module.id) + '.framework'; + const xcFrameworkOfLib = module.id + '.xcframework'; + const xcFrameworkOfFramework = this.scrubbedModuleId(module.id) + '.xcframework'; + + module.isFramework = false; + module.isXCFrameworkOfLib = false; + module.isXCFrameworkOfFramework = false; // Try to load native module as static library (Obj-C) if (fs.existsSync(path.join(module.modulePath, 'lib' + module.id.toLowerCase() + '.a'))) { @@ -2202,10 +2208,35 @@ iOSBuilder.prototype.validate = function validate(logger, config, cli) { module.libName = frameworkName; module.libFile = path.join(module.modulePath, module.libName); module.isFramework = true; + // For Swift frameworks, use the binary inside the .framework for hashing nativeHashes.push(module.hash = this.hash(fs.readFileSync(path.join(module.libFile, this.scrubbedModuleId(module.id))))); + } else if (fs.existsSync(path.join(module.modulePath, xcFrameworkOfLib))) { + module.libName = xcFrameworkOfLib; + module.libFile = path.join(module.modulePath, module.libName); + module.isXCFrameworkOfLib = true; - // Else - fail + // TODO: read Info.plist to get the full scope of targets/arches supported! + let archDir = 'ios-arm64_i386_x86_64-simulator'; + if (!fs.existsSync(path.join(module.libFile, archDir))) { + // Try XCode 11 dir w/o arm64 support + archDir = 'ios-i386_x86_64-simulator'; + } + // TODO: Change hash calculation + nativeHashes.push(module.hash = this.hash(fs.readFileSync(path.join(module.libFile, archDir, 'lib' + module.id.toLowerCase() + '.a')))); + } else if (fs.existsSync(path.join(module.modulePath, xcFrameworkOfFramework))) { + module.libName = xcFrameworkOfFramework; + module.libFile = path.join(module.modulePath, module.libName); + module.isXCFrameworkOfFramework = true; + + // TODO: read Info.plist to get the full scope of targets/arches supported! + let archDir = 'ios-arm64_i386_x86_64-simulator'; + if (!fs.existsSync(path.join(module.libFile, archDir))) { + // Try XCode 11 dir w/o arm64 support + archDir = 'ios-i386_x86_64-simulator'; + } + // TODO: Change hash calculation + nativeHashes.push(module.hash = this.hash(fs.readFileSync(path.join(module.libFile, archDir, this.scrubbedModuleId(module.id) + '.framework', this.scrubbedModuleId(module.id))))); } else { this.logger.error(__('Module %s (%s) is missing library or framework file.', module.id.cyan, (module.manifest.version || 'latest').cyan) + '\n'); this.logger.error(__('Please validate that your module has been packaged correctly and try it again.')); @@ -2285,7 +2316,6 @@ iOSBuilder.prototype.run = function (logger, config, cli, finished) { 'writeInfoPlist', 'writeMain', 'writeXcodeConfigFiles', - 'copyTitaniumLibraries', 'copyTitaniumiOSFiles', 'copyExtensionFiles', 'cleanXcodeDerivedData', @@ -3238,45 +3268,100 @@ iOSBuilder.prototype.createXcodeProject = function createXcodeProject(next) { // Framworks are handled by our framework manager! if (isFramework) { return; - } + } else if (lib.isXCFrameworkOfFramework || lib.isXCFrameworkOfLib) { + const frameworkFileRefUuid = this.generateXcodeUuid(xcodeProject); + const frameworkBuildFileUuid = this.generateXcodeUuid(xcodeProject); + + xobjs.PBXFileReference[frameworkFileRefUuid] = { + isa: 'PBXFileReference', + lastKnownFileType: 'wrapper.xcframework', + name: lib.libName, + path: '"' + lib.libFile + '"', + sourceTree: '""' + }; + xobjs.PBXFileReference[frameworkFileRefUuid + '_comment'] = lib.libName; - // add the file reference - xobjs.PBXFileReference[fileRefUuid] = { - isa: 'PBXFileReference', - lastKnownFileType: 'archive.ar', - name: lib.libName, - path: '"' + lib.libFile + '"', - sourceTree: '""' - }; - xobjs.PBXFileReference[fileRefUuid + '_comment'] = lib.libName; + xobjs.PBXBuildFile[frameworkBuildFileUuid] = { + isa: 'PBXBuildFile', + fileRef: frameworkFileRefUuid, + fileRef_comment: lib.libName + }; + xobjs.PBXBuildFile[frameworkBuildFileUuid + '_comment'] = lib.libName + ' in Frameworks'; - // add the library to the Frameworks group - frameworksGroup.children.push({ - value: fileRefUuid, - comment: lib.libName - }); + frameworksBuildPhase.files.push({ + value: frameworkBuildFileUuid, + comment: xobjs.PBXBuildFile[frameworkBuildFileUuid + '_comment'] + }); - // add the build file - xobjs.PBXBuildFile[buildFileUuid] = { - isa: 'PBXBuildFile', - fileRef: fileRefUuid, - fileRef_comment: lib.libName - }; - xobjs.PBXBuildFile[buildFileUuid + '_comment'] = lib.libName + ' in Frameworks'; + if (lib.isXCFrameworkOfFramework) { + const embedFrameworkBuildFileUuid = this.generateXcodeUuid(xcodeProject); + // add the build file + xobjs.PBXBuildFile[buildFileUuid] = { + isa: 'PBXBuildFile', + fileRef: fileRefUuid, + fileRef_comment: lib.libName, + platformFilter: 'ios' + }; + xobjs.PBXBuildFile[buildFileUuid + '_comment'] = lib.libName + ' in Frameworks'; - // add the library to the frameworks build phase - frameworksBuildPhase.files.push({ - value: buildFileUuid, - comment: lib.libName + ' in Frameworks' - }); + xobjs.PBXBuildFile[embedFrameworkBuildFileUuid] = { + isa: 'PBXBuildFile', + fileRef: frameworkFileRefUuid, + fileRef_comment: lib.libName, + settings: { ATTRIBUTES: [ 'CodeSignOnCopy', 'RemoveHeadersOnCopy' ] } + }; + xobjs.PBXBuildFile[embedFrameworkBuildFileUuid + '_comment'] = lib.libName + ' in Embed Frameworks'; + + copyFilesBuildPhase.files.push({ + value: embedFrameworkBuildFileUuid, + comment: xobjs.PBXBuildFile[embedFrameworkBuildFileUuid + '_comment'] + }); + } - // add the library / framework to the dedicated search paths - xobjs.XCConfigurationList[xobjs.PBXNativeTarget[mainTargetUuid].buildConfigurationList].buildConfigurations.forEach(function (buildConf) { - var buildSettings = xobjs.XCBuildConfiguration[buildConf.value].buildSettings; + frameworksGroup.children.push({ + value: frameworkFileRefUuid, + comment: lib.libName + }); + } else { + // add the file reference + xobjs.PBXFileReference[fileRefUuid] = { + isa: 'PBXFileReference', + lastKnownFileType: 'archive.ar', + name: lib.libName, + path: '"' + lib.libFile + '"', + sourceTree: '""' + }; + xobjs.PBXFileReference[fileRefUuid + '_comment'] = lib.libName; - buildSettings.LIBRARY_SEARCH_PATHS || (buildSettings.LIBRARY_SEARCH_PATHS = []); - buildSettings.LIBRARY_SEARCH_PATHS.push('"\\"' + path.dirname(lib.libFile) + '\\""'); - }); + // add the library to the Frameworks group + frameworksGroup.children.push({ + value: fileRefUuid, + comment: lib.libName + }); + + // add the build file + xobjs.PBXBuildFile[buildFileUuid] = { + isa: 'PBXBuildFile', + fileRef: fileRefUuid, + fileRef_comment: lib.libName, + platformFilter: 'ios' + }; + xobjs.PBXBuildFile[buildFileUuid + '_comment'] = lib.libName + ' in Frameworks'; + + // add the library to the frameworks build phase + frameworksBuildPhase.files.push({ + value: buildFileUuid, + comment: lib.libName + ' in Frameworks' + }); + + // add the library / framework to the dedicated search paths + xobjs.XCConfigurationList[xobjs.PBXNativeTarget[mainTargetUuid].buildConfigurationList].buildConfigurations.forEach(function (buildConf) { + var buildSettings = xobjs.XCBuildConfiguration[buildConf.value].buildSettings; + + buildSettings.LIBRARY_SEARCH_PATHS || (buildSettings.LIBRARY_SEARCH_PATHS = []); + buildSettings.LIBRARY_SEARCH_PATHS.push('"\\"' + path.dirname(lib.libFile) + '\\""'); + }); + } }, this); } else { this.logger.trace(__('No native module libraries to add')); @@ -3768,19 +3853,19 @@ iOSBuilder.prototype.createXcodeProject = function createXcodeProject(next) { xobjs.PBXFileReference[frameworkFileRefUuid] = { isa: 'PBXFileReference', - lastKnownFileType: 'wrapper.framework', - name: '"TitaniumKit.framework"', - path: '"Frameworks/TitaniumKit.framework"', + lastKnownFileType: 'wrapper.xcframework', + name: '"TitaniumKit.xcframework"', + path: '"Frameworks/TitaniumKit.xcframework"', sourceTree: '""' }; - xobjs.PBXFileReference[frameworkFileRefUuid + '_comment'] = 'TitaniumKit.framework'; + xobjs.PBXFileReference[frameworkFileRefUuid + '_comment'] = 'TitaniumKit.xcframework'; xobjs.PBXBuildFile[frameworkBuildFileUuid] = { isa: 'PBXBuildFile', fileRef: frameworkFileRefUuid, - fileRef_comment: 'TitaniumKit.framework' + fileRef_comment: 'TitaniumKit.xcframework' }; - xobjs.PBXBuildFile[frameworkBuildFileUuid + '_comment'] = 'TitaniumKit.framework in Frameworks'; + xobjs.PBXBuildFile[frameworkBuildFileUuid + '_comment'] = 'TitaniumKit.xcframework in Frameworks'; frameworksBuildPhase.files.push({ value: frameworkBuildFileUuid, @@ -3790,10 +3875,10 @@ iOSBuilder.prototype.createXcodeProject = function createXcodeProject(next) { xobjs.PBXBuildFile[embedFrameworkBuildFileUuid] = { isa: 'PBXBuildFile', fileRef: frameworkFileRefUuid, - fileRef_comment: 'TitaniumKit.framework', + fileRef_comment: 'TitaniumKit.xcframework', settings: { ATTRIBUTES: [ 'CodeSignOnCopy', 'RemoveHeadersOnCopy' ] } }; - xobjs.PBXBuildFile[embedFrameworkBuildFileUuid + '_comment'] = 'TitaniumKit.framework in Embed Frameworks'; + xobjs.PBXBuildFile[embedFrameworkBuildFileUuid + '_comment'] = 'TitaniumKit.xcframework in Embed Frameworks'; copyFilesBuildPhase.files.push({ value: embedFrameworkBuildFileUuid, @@ -3802,7 +3887,39 @@ iOSBuilder.prototype.createXcodeProject = function createXcodeProject(next) { frameworksGroup.children.push({ value: frameworkFileRefUuid, - comment: 'TitaniumKit.framework' + comment: 'TitaniumKit.xcframework' + }); + + // add tiverify.framework + xcodeProject.removeFramework('tiverify.xcframework', { customFramework: true, embed: true }); + + const tiverifyFrameworkFileRefUuid = this.generateXcodeUuid(xcodeProject); + const tiverifyFrameworkBuildFileUuid = this.generateXcodeUuid(xcodeProject); + + xobjs.PBXFileReference[tiverifyFrameworkFileRefUuid] = { + isa: 'PBXFileReference', + lastKnownFileType: 'wrapper.xcframework', + name: '"tiverify.xcframework"', + path: '"Frameworks/tiverify.xcframework"', + sourceTree: '""' + }; + xobjs.PBXFileReference[tiverifyFrameworkFileRefUuid + '_comment'] = 'tiverify.xcframework'; + + xobjs.PBXBuildFile[tiverifyFrameworkBuildFileUuid] = { + isa: 'PBXBuildFile', + fileRef: tiverifyFrameworkFileRefUuid, + fileRef_comment: 'tiverify.xcframework' + }; + xobjs.PBXBuildFile[tiverifyFrameworkBuildFileUuid + '_comment'] = 'tiverify.xcframework in Frameworks'; + + frameworksBuildPhase.files.push({ + value: tiverifyFrameworkBuildFileUuid, + comment: xobjs.PBXBuildFile[tiverifyFrameworkBuildFileUuid + '_comment'] + }); + + frameworksGroup.children.push({ + value: tiverifyFrameworkFileRefUuid, + comment: 'tiverify.xcframework' }); // run the xcode project hook @@ -4404,37 +4521,6 @@ iOSBuilder.prototype.writeXcodeConfigFiles = function writeXcodeConfigFiles() { this.unmarkBuildDirFile(dest); }; -iOSBuilder.prototype.copyTitaniumLibraries = function copyTitaniumLibraries() { - this.logger.info(__('Copying Titanium libraries')); - - const libDir = path.join(this.buildDir, 'lib'); - fs.ensureDirSync(libDir); - - [ 'libtiverify.a' ].forEach(function (filename) { - const src = path.join(this.platformPath, filename), - srcStat = fs.statSync(src), - srcMtime = JSON.parse(JSON.stringify(srcStat.mtime)), - dest = path.join(libDir, filename), - destExists = fs.existsSync(dest), - rel = src.replace(path.dirname(this.titaniumSdkPath) + '/', ''), - prev = this.previousBuildManifest.files && this.previousBuildManifest.files[rel], - fileChanged = !destExists || !prev || prev.size !== srcStat.size || prev.mtime !== srcMtime; - - // note: we're skipping the hash check so that we don't have to read in 36MB of data - // this isn't going to be bulletproof, but hopefully the size and mtime will be enough to catch any changes - if (!fileChanged || !this.copyFileSync(src, dest, { forceSymlink: this.symlinkLibrariesOnCopy, forceCopy: false })) { - this.logger.trace(__('No change, skipping %s', dest.cyan)); - } - this.currentBuildManifest.files[rel] = { - hash: null, - mtime: srcMtime, - size: srcStat.size - }; - - this.unmarkBuildDirFile(dest); - }, this); -}; - iOSBuilder.prototype._scrubiOSSourceFile = function _scrubiOSSourceFile(contents) { const name = this.tiapp.name.replace(/[-\W]/g, '_'), namespace = /^[0-9]/.test(name) ? 'k' + name : name, @@ -4466,6 +4552,7 @@ iOSBuilder.prototype.copyTitaniumiOSFiles = function copyTitaniumiOSFiles() { // files to watch for while copying appFiles = {}; + let copyFrameworks = true; appFiles['ApplicationDefaults.m'] = { props: this.tiapp.properties || {}, @@ -4522,7 +4609,7 @@ iOSBuilder.prototype.copyTitaniumiOSFiles = function copyTitaniumiOSFiles() { if (extRegExp.test(srcFile)) { // look up the file to see if the original source changed const prev = this.previousBuildManifest.files && this.previousBuildManifest.files[rel]; - if (destExists && !nameChanged && prev && prev.size === srcStat.size && prev.mtime === srcMtime && prev.hash === srcHash) { + if (destExists && !nameChanged && prev && prev.size === srcStat.size && prev.mtime === srcMtime && prev.hash === srcHash && !(dir === 'Frameworks' && !copyFrameworks)) { // the original hasn't changed, so let's assume that there's nothing to do return null; } @@ -4541,6 +4628,16 @@ iOSBuilder.prototype.copyTitaniumiOSFiles = function copyTitaniumiOSFiles() { this.logger.info(__('Forcing rebuild: %s has changed since last build', rel)); this.forceRebuild = true; } + + if (dir === 'Frameworks' && copyFrameworks) { + // The content of Frameworks directory only change if we change SDK version. So it is safe to copy whole directory. + // Copy whole 'Frameworks' directory from SDK to build directory, to preserve symlink available in Titaniumkit.xcframework. + // TODO: Is there any better way to do this? + + fs.copySync(path.join(this.platformPath, dir), path.join(this.buildDir, dir)); + copyFrameworks = false; + } + this.logger.debug(__('Writing %s', destFile.cyan)); fs.writeFileSync(destFile, contents); @@ -4553,6 +4650,10 @@ iOSBuilder.prototype.copyTitaniumiOSFiles = function copyTitaniumiOSFiles() { } }.bind(this) }); + + if (dir === 'Frameworks') { + this.unmarkBuildDirFiles(path.join(this.buildDir, dir)); + } }, this); function copyAndReplaceFile(src, dest, processContent) { @@ -6532,11 +6633,12 @@ iOSBuilder.prototype.removeFiles = function removeFiles(next) { } }, this); - // remove invalid architectures from TitaniumKit.framework for App Store distributions + // TODO: This should not be required as xcframework builds for specified target + // remove invalid architectures from TitaniumKit.xcframework for App Store distributions if (this.target === 'dist-appstore' || this.target === 'dist-adhoc') { - this.logger.info(__('Removing invalid architectures from TitaniumKit.framework')); + this.logger.info(__('Removing invalid architectures from TitaniumKit.xcframework')); - const titaniumKitPath = path.join(this.buildDir, 'Frameworks', 'TitaniumKit.framework', 'TitaniumKit'); + const titaniumKitPath = path.join(this.buildDir, 'Frameworks', 'TitaniumKit.xcframework', 'TitaniumKit'); async.eachSeries([ 'x86_64', 'i386' ], function (architecture, next) { const args = [ '-remove', architecture, titaniumKitPath, '-o', titaniumKitPath ]; this.logger.debug(__('Running: %s', (this.xcodeEnv.executables.lipo + ' ' + args.join(' ')).cyan)); diff --git a/iphone/cli/hooks/frameworks.js b/iphone/cli/hooks/frameworks.js index bb91a3bbd6e..01d1be34bc0 100644 --- a/iphone/cli/hooks/frameworks.js +++ b/iphone/cli/hooks/frameworks.js @@ -557,7 +557,8 @@ class FrameworkIntegrator { this._xobjs.PBXBuildFile[buildFileUuid] = { isa: 'PBXBuildFile', fileRef: fileRefUuid, - fileRef_comment: frameworkPackageName + fileRef_comment: frameworkPackageName, + platformFilter: 'ios' }; this._xobjs.PBXBuildFile[buildFileUuid + '_comment'] = frameworkPackageName + ' in Frameworks'; this._frameworksBuildPhase.files.push({ @@ -580,7 +581,8 @@ class FrameworkIntegrator { isa: 'PBXBuildFile', fileRef: fileRefUuid, fileRef_comment: frameworkPackageName, - settings: { ATTRIBUTES: [ 'CodeSignOnCopy', 'RemoveHeadersOnCopy' ] } + settings: { ATTRIBUTES: [ 'CodeSignOnCopy', 'RemoveHeadersOnCopy' ] }, + platformFilter: 'ios' }; this._xobjs.PBXBuildFile[embeddedBuildFileUuid + '_comment'] = frameworkPackageName + ' in Embed Frameworks'; @@ -645,14 +647,13 @@ class FrameworkIntegrator { let buildConfigurations = this._xobjs.XCConfigurationList[this._mainTarget.buildConfigurationList].buildConfigurations; for (let buildConf of buildConfigurations) { let buildSettings = this._xobjs.XCBuildConfiguration[buildConf.value].buildSettings; - let searchPaths = (buildSettings.LD_RUNPATH_SEARCH_PATHS || '').replace(/^"/, '').replace(/"$/, ''); + let searchPaths = buildSettings.LD_RUNPATH_SEARCH_PATHS; if (searchPaths.indexOf('$(inherited)') === -1) { searchPaths += ' $(inherited)'; } if (searchPaths.indexOf(dynamicFrameworksSearchPath) === -1) { searchPaths += ` ${dynamicFrameworksSearchPath}`; } - buildSettings.LD_RUNPATH_SEARCH_PATHS = '"' + searchPaths.trim() + '"'; } } diff --git a/iphone/iphone/Titanium.xcodeproj/project.pbxproj b/iphone/iphone/Titanium.xcodeproj/project.pbxproj index bc6a062bbca..16750f0edc2 100644 --- a/iphone/iphone/Titanium.xcodeproj/project.pbxproj +++ b/iphone/iphone/Titanium.xcodeproj/project.pbxproj @@ -2381,8 +2381,10 @@ CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = NO; CODE_SIGN_ENTITLEMENTS = Titanium.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES; DEVELOPMENT_TEAM = ""; @@ -2421,6 +2423,8 @@ SWIFT_OBJC_BRIDGING_HEADER = "Titanium-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; SUPPORTS_MACCATALYST = YES; TARGETED_DEVICE_FAMILY = "1,2"; WARNING_CFLAGS = "-Wno-arc-performSelector-leaks"; @@ -2438,8 +2442,10 @@ CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = NO; CODE_SIGN_ENTITLEMENTS = Titanium.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = YES; DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES; DEVELOPMENT_TEAM = ""; @@ -2475,6 +2481,8 @@ SUPPORTS_MACCATALYST = YES; SWIFT_OBJC_BRIDGING_HEADER = "Titanium-Bridging-Header.h"; SWIFT_VERSION = 5.0; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; SUPPORTS_MACCATALYST = YES; TARGETED_DEVICE_FAMILY = "1,2"; WARNING_CFLAGS = "-Wno-arc-performSelector-leaks"; diff --git a/support/iphone/build_titaniumkit.sh b/support/iphone/build_titaniumkit.sh index 8774a3107bd..ae224b50ad2 100755 --- a/support/iphone/build_titaniumkit.sh +++ b/support/iphone/build_titaniumkit.sh @@ -48,69 +48,110 @@ XCODE_VERSION=$(/usr/libexec/PlistBuddy -c "Print :DTXcode" "$(xcode-select -p)/ FRAMEWORK_NAME="TitaniumKit" -SIMULATOR_LIBRARY_PATH="$(pwd)/build/Release-iphonesimulator/${FRAMEWORK_NAME}.framework" +#SIMULATOR_LIBRARY_PATH="$(pwd)/build/Release-iphonesimulator/${FRAMEWORK_NAME}.framework" -DEVICE_LIBRARY_PATH="$(pwd)/build/Release-iphoneos/${FRAMEWORK_NAME}.framework" +#DEVICE_LIBRARY_PATH="$(pwd)/build/Release-iphoneos/${FRAMEWORK_NAME}.framework" -UNIVERSAL_LIBRARY_DIR="$(pwd)/build/Release-iphoneuniversal" +#UNIVERSAL_LIBRARY_DIR="$(pwd)/build/Release-iphoneuniversal" -FRAMEWORK="${UNIVERSAL_LIBRARY_DIR}/${FRAMEWORK_NAME}.framework" +#FRAMEWORK="${UNIVERSAL_LIBRARY_DIR}/${FRAMEWORK_NAME}.framework" ###################### # Build Frameworks ###################### -XCPRETTY="xcpretty" -which xcpretty || XCPRETTY="cat" +#XCPRETTY="xcpretty" +#which xcpretty || XCPRETTY="cat" -# Exclude arm64 architecture from simulator build in XCode 12+ - TIMOB-28042 +#xcodebuild -scheme TitaniumKit -sdk iphonesimulator -configuration Release clean build CONFIGURATION_BUILD_DIR=build/Release-iphonesimulator | eval $XCPRETTY +#[[ PIPESTATUS[0] -ne 0 ]] && exit 1 -if [[ $XCODE_VERSION -ge 1200 ]]; then -xcodebuild -scheme TitaniumKit -sdk iphonesimulator EXCLUDED_ARCHS=arm64 -configuration Release clean build CONFIGURATION_BUILD_DIR=build/Release-iphonesimulator | eval $XCPRETTY -[[ PIPESTATUS[0] -ne 0 ]] && exit 1 - else -xcodebuild -scheme TitaniumKit -sdk iphonesimulator -configuration Release clean build CONFIGURATION_BUILD_DIR=build/Release-iphonesimulator | eval $XCPRETTY -[[ PIPESTATUS[0] -ne 0 ]] && exit 1 -fi - -xcodebuild -scheme TitaniumKit -sdk iphoneos -configuration Release clean build CONFIGURATION_BUILD_DIR=build/Release-iphoneos | eval $XCPRETTY -[[ PIPESTATUS[0] -ne 0 ]] && exit 1 +#xcodebuild -scheme TitaniumKit -sdk iphoneos -configuration Release clean build CONFIGURATION_BUILD_DIR=build/Release-iphoneos | eval $XCPRETTY +#[[ PIPESTATUS[0] -ne 0 ]] && exit 1 # restore TopTiModule.m -rm TitaniumKit/Sources/API/TopTiModule.m -mv TitaniumKit/Sources/API/TopTiModule.bak TitaniumKit/Sources/API/TopTiModule.m +#rm TitaniumKit/Sources/API/TopTiModule.m +#mv TitaniumKit/Sources/API/TopTiModule.bak TitaniumKit/Sources/API/TopTiModule.m ###################### # Create directory for universal ###################### -rm -rf "${UNIVERSAL_LIBRARY_DIR}" +#rm -rf "${UNIVERSAL_LIBRARY_DIR}" -mkdir "${UNIVERSAL_LIBRARY_DIR}" +#mkdir "${UNIVERSAL_LIBRARY_DIR}" -mkdir "${FRAMEWORK}" +#mkdir "${FRAMEWORK}" ###################### # Copy files Framework ###################### -cp -r "${DEVICE_LIBRARY_PATH}/." "${FRAMEWORK}" +#cp -r "${DEVICE_LIBRARY_PATH}/." "${FRAMEWORK}" ###################### # Make an universal binary ###################### -lipo "${SIMULATOR_LIBRARY_PATH}/${FRAMEWORK_NAME}" "${DEVICE_LIBRARY_PATH}/${FRAMEWORK_NAME}" -create -output "${FRAMEWORK}/${FRAMEWORK_NAME}" | echo +#lipo "${SIMULATOR_LIBRARY_PATH}/${FRAMEWORK_NAME}" "${DEVICE_LIBRARY_PATH}/${FRAMEWORK_NAME}" -create -output "${FRAMEWORK}/${FRAMEWORK_NAME}" | echo # For Swift framework, Swiftmodule needs to be copied in the universal framework -if [ -d "${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then -cp -f ${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo -fi +#if [ -d "${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then +#cp -f ${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo +#fi -if [ -d "${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then -cp -f ${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo -fi +#if [ -d "${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then +#cp -f ${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo +#fi + +#exit 0 + +MAC_ARCHIVE_PATH="$(pwd)/build/macCatalyst.xcarchive" + +DEVICE_ARCHIVE_PATH="$(pwd)/build/iosdevice.xcarchive" + +SIMULATOR_ARCHIVE_PATH="$(pwd)/build/simulator.xcarchive" + +UNIVERSAL_LIBRARY_DIR="$(pwd)/build" + +FRAMEWORK="${UNIVERSAL_LIBRARY_DIR}/${FRAMEWORK_NAME}.xcframework" + +mkdir "${FRAMEWORK}" + +#----- Make macCatalyst archive +xcodebuild archive \ +-scheme $FRAMEWORK_NAME \ +-archivePath $MAC_ARCHIVE_PATH \ +-sdk macosx \ +SKIP_INSTALL=NO \ +BUILD_LIBRARIES_FOR_DISTRIBUTION=YES \ +SUPPORTS_MACCATALYST=YES \ + +#----- Make iOS Simulator archive +xcodebuild archive \ +-scheme $FRAMEWORK_NAME \ +-archivePath $SIMULATOR_ARCHIVE_PATH \ +-sdk iphonesimulator \ +SKIP_INSTALL=NO BUILD_LIBRARIES_FOR_DISTRIBUTION=YES + +#----- Make iOS device archive +xcodebuild archive \ +-scheme $FRAMEWORK_NAME \ +-archivePath $DEVICE_ARCHIVE_PATH \ +-sdk iphoneos \ +SKIP_INSTALL=NO BUILD_LIBRARIES_FOR_DISTRIBUTION=YES + +# restore TopTiModule.m +rm TitaniumKit/Sources/API/TopTiModule.m +mv TitaniumKit/Sources/API/TopTiModule.bak TitaniumKit/Sources/API/TopTiModule.m + +#----- Make XCFramework +xcodebuild -create-xcframework \ +-framework $SIMULATOR_ARCHIVE_PATH/Products/Library/Frameworks/$FRAMEWORK_NAME.framework \ +-framework $DEVICE_ARCHIVE_PATH/Products/Library/Frameworks/$FRAMEWORK_NAME.framework \ +-framework $MAC_ARCHIVE_PATH/Products/Library/Frameworks/$FRAMEWORK_NAME.framework \ +-output $FRAMEWORK exit 0