Skip to content

Commit

Permalink
[TIMOB-25927] Add Swift support for native modules, move SDK-core int…
Browse files Browse the repository at this point in the history
…o "TitaniumKit.framework" (#10218)

* Move core to TitaniumKit, link core-framework to the SDK

* Updates to tooling and native module templates

* Remove unused libraries, update package.json

* Lint new iOS source

* Lint TitaniumKit

* Fix Swift module template with characters that are disallowed in frameworks (new) but not libraries (old)

* Use relative imports for backwards compatibility with old modules

* Hack together backwards compatibility for old modules

* Fix ESLint errors

* Do not replace TitaniumKit imports with the project name

* Move ApplicationMods and ApplicationDefaults back to main target

* Add TiSharedConfig to main.m template

* Fix up generated main.m, add ApplicationMods / ApplicationDefaults to pbxproj

* Inject constants properly

* Refactor log-server, link C-libraries properly

* More cleanup to the main.m and related constants

* Link TitaniumKit as an embedded framework, finally a stable build!

* Proof of concept of extending TitaniumKit via the core to retain preprocessor flags concept

* Solve all USE_TI_* preprocessor macros, always compile in Hyperloop-related code since it's guarded

* Add instructions for using Carthage to build a universal framework

* Allow native apps to pass -TI_USE_NATIVE=1 to use Titanium

* Linting

* Resolve more merge conflicts

* Integrating more merge conflicts

* Fine-tune config to handle all fields

* Fix duplicate declarations

* Attempt to use Jazzy for generating docs

* Migrate Ti.Blob changes manually

* Fix up module build, get a proper library for both Obj-C and Swift again

* Update app build for new framework handling

* Fix damn typos

* Fix suffix in templates

* Working module inclusion!

* Precompile TitaniumKit.framework, copy it to dist

* Re-link the framework into the iOS build directory

* Start documenting more core-API's

* Add build-settings hook to Swift-based modules

* Fix typos

* Ignore TiCore for now, making switches between branches during dev easier

* Fix format, fix launch-screen state

* Fix possible Ti.Buffer / Ti.Blob leaks for edge-cases, wrap iOS 12 proxy-API's (not required but looks more clean)

* chore: change comments header, put some macros back in

* chore: use iOS 8 in TitaniumKit for now again

* retain storyboard-view properly

* fix: resolve remaining merge conflicts

* fix: restore auto-release-pool

* Fix bad merge on Ti.Ui.Window.safeArea code to remove ifdef no longer used
  • Loading branch information
hansemannn authored and sgtcoolguy committed Oct 1, 2018
1 parent 7860b46 commit fbae1cf
Show file tree
Hide file tree
Showing 668 changed files with 13,242 additions and 2,361 deletions.
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,13 @@
*.BASE.*
*.LOCAL.*
*.REMOTE.*
anvil/driver/config.js
._*
npm-debug.log

node_modules/

retirejs.output.json

anvil/driver/titanium_mobile
anvil/hub/config.js
support/ti_mocha_script/testApp

/titanium-mobile-mocha-suite
Expand All @@ -38,3 +35,7 @@ android/.idea/modules.xml
android/.idea/scopes/scope_settings.xml
android/.idea/vcs.xml
*.iml
/iphone/TitaniumKit/Carthage
/iphone/TitaniumKit/docs
/iphone/TitaniumKit/build
/iphone/lib/libTiCore.a
30 changes: 30 additions & 0 deletions TitaniumKit.podspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Use the --use-libraries switch when pushing or linting this podspec

Pod::Spec.new do |s|

s.name = "TitaniumKit"
s.version = "1.0.0"
s.summary = "Axway Titanium iOS Core framework"

s.description = <<-DESC
The Axway Titanium iOS Core framework.
DESC

s.homepage = "https://github.com/appcelerator/titanium_mobile"
s.license = { :type => "Apache 2", :file => "LICENSE" }
s.author = 'Axway Appcelerator'

s.platform = :ios
s.ios.deployment_target = '8.0'

s.source = { :git => "https://github.com/appcelerator/titanium_mobile.git" }

s.vendored_libraries = 'iphone/TitaniumKit/TitaniumKit/Libraries/**/*.{a}'
s.preserve_paths = 'iphone/TitaniumKit/TitaniumKit/Libraries/**/*.{a}'

s.ios.weak_frameworks = 'UIKit', 'Foundation'
s.requires_arc = false

s.public_header_files = 'iphone/TitaniumKit/TitaniumKit/**/**/*.h'
s.source_files = 'iphone/TitaniumKit/TitaniumKit/Sources/**/**/*.{h,m}', 'iphone/TitaniumKit/TitaniumKit/Libraries/**/*.h', 'iphone/TitaniumKit/TitaniumKit/TitaniumKit.h'
end
76 changes: 61 additions & 15 deletions build/ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ const path = require('path'),
async = require('async'),
fs = require('fs-extra'),
utils = require('./utils'),
{ spawn } = require('child_process'), // eslint-disable-line security/detect-child-process
copyFiles = utils.copyFiles,
copyAndModifyFile = utils.copyAndModifyFile,
copyAndModifyFiles = utils.copyAndModifyFiles,
globCopy = utils.globCopy,
globCopyFlat = utils.globCopyFlat,
ROOT_DIR = path.join(__dirname, '..'),
IOS_ROOT = path.join(ROOT_DIR, 'iphone'),
IOS_LIB = path.join(IOS_ROOT, 'lib');
Expand All @@ -30,8 +31,27 @@ IOS.prototype.clean = function (next) {
};

IOS.prototype.build = function (next) {
// no-op (used to fetch TiCore in the past)
next();
console.log('Building TitaniumKit ...');

const child = spawn(path.join(ROOT_DIR, 'support', 'iphone', 'build_titaniumkit.sh'));

child.stdout.on('data', (data) => {
console.log(`\n${data}`);
});

child.stderr.on('data', (data) => {
console.log(`\n${data}`);
});

child.on('exit', function (code, signal) {
if (code) {
console.log(`An error occurred: ${signal}`);
return next(signal);
}

console.log('TitaniumKit built successfully!');
return next();
});
};

IOS.prototype.package = function (packager, next) {
Expand All @@ -42,30 +62,56 @@ IOS.prototype.package = function (packager, next) {
async.parallel([
function (callback) {
async.series([
function (cb) {
globCopy('**/*.h', path.join(IOS_ROOT, 'Classes'), path.join(DEST_IOS, 'include'), cb);
// Copy legacy copies of TiBase.h, TiApp.h etc into 'include/' to retain backwards compatibility in SDK 8.0.0
// TODO: Inject a deprecation warning if used and remove in SDK 9.0.0
function copyLegacyCoreHeaders (cb) {
globCopyFlat('**/*.h', path.join(IOS_ROOT, 'TitaniumKit', 'TitaniumKit', 'Sources'), path.join(DEST_IOS, 'include'), cb);
},
function (cb) {
// Copy legacy copies of APSAnalytics.h and APSHTTPClient.h into 'include/' to retain backwards compatibility in SDK 8.0.0
// TODO: Inject a deprecation warning if used and remove in SDK 9.0.0
function copyLegacyLibraryHeaders (cb) {
globCopy('**/*.h', path.join(IOS_ROOT, 'TitaniumKit', 'TitaniumKit', 'Libraries'), path.join(DEST_IOS, 'include'), cb);
},
// Copy meta files and directories
function copyMetaFiles (cb) {
copyFiles(IOS_ROOT, DEST_IOS, [ 'AppledocSettings.plist', 'Classes', 'cli', 'iphone', 'templates' ], cb);
},
// Copy TitaniumKit
function copyTitaniumKit (cb) {
copyFiles(path.join(IOS_ROOT, 'TitaniumKit', 'build', 'Release-iphoneuniversal'), path.join(DEST_IOS, 'Frameworks'), [ 'TitaniumKit.framework' ], cb);
},
// Copy module templates (Swift & Obj-C)
function copyModuleTemplates (cb) {
copyFiles(IOS_ROOT, DEST_IOS, [ 'AppledocSettings.plist', 'Classes', 'cli', 'iphone', 'templates' ], cb);
},
// Copy and inject values for special source files
function (cb) {
function injectSDKConstants (cb) {
const subs = {
__VERSION__: this.sdkVersion,
__TIMESTAMP__: this.timestamp,
__GITHASH__: this.gitHash
__SDK_VERSION__: this.sdkVersion,
__BUILD_DATE__: this.timestamp,
__BUILD_HASH__: this.gitHash
};
copyAndModifyFiles(path.join(IOS_ROOT, 'Classes'), path.join(DEST_IOS, 'Classes'), [ 'TopTiModule.m', 'TiApp.m' ], subs, cb);
// TODO: DO we need this? The above constants are not even used so far.
const dest = path.join(DEST_IOS, 'main.m');
const contents = fs.readFileSync(path.join(ROOT_DIR, 'support', 'iphone', 'main.m')).toString().replace(/(__.+?__)/g, function (match, key) {
const s = subs.hasOwnProperty(key) ? subs[key] : key;
return typeof s === 'string' ? s.replace(/"/g, '\\"').replace(/\n/g, '\\n') : s;
});
fs.writeFileSync(dest, contents);
cb();
}.bind(this),
function (cb) {

// Copy Ti.Verify
function copyTiVerify (cb) {
copyFiles(IOS_LIB, DEST_IOS, [ 'libtiverify.a' ], cb);
},
// copy iphone/package.json, but replace __VERSION__ with our version!
function (cb) {
// Copy iphone/package.json, but replace __VERSION__ with our version!
function copyPackageJSON (cb) {
copyAndModifyFile(IOS_ROOT, DEST_IOS, 'package.json', { __VERSION__: this.sdkVersion }, cb);
}.bind(this),
// Copy iphone/Resources/modules/<name>/* to this.zipSDKDir/iphone/modules/<name>/images
function (cb) {
// TODO: Pretty sure these can be removed nowadays
function copyModuleAssets (cb) {
fs.copy(path.join(IOS_ROOT, 'Resources', 'modules'), path.join(DEST_IOS, 'modules'), cb);
}
], callback);
Expand Down
11 changes: 5 additions & 6 deletions build/packager.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,11 @@ Packager.prototype.generateManifestJSON = function (next) {
*/
Packager.prototype.zipIOS = function (next) {
const IOS = require('./ios');
// FIXME Pass along the version/gitHash/options!
new IOS({ sdkVersion: this.version, gitHash: this.gitHash, timestamp: this.timestamp }).package(this, next);
};

Packager.prototype.zipWindows = function (next) {
const Windows = require('./windows');
// FIXME Pass along the version/gitHash/options!
new Windows({ sdkVersion: this.version, gitHash: this.gitHash, timestamp: this.timestamp }).package(this, next);
};

Expand All @@ -149,7 +147,6 @@ Packager.prototype.zipWindows = function (next) {
*/
Packager.prototype.zipAndroid = function (next) {
const Android = require('./android');
// FIXME Pass along the ndk/sdk/version/apiLevel/options!
new Android({ sdkVersion: this.version, gitHash: this.gitHash, timestamp: this.timestamp }).package(this, next);
};

Expand All @@ -158,7 +155,7 @@ Packager.prototype.zipAndroid = function (next) {
* @param {Function} next callback function
*/
Packager.prototype.cleanZipDir = function (next) {
console.log('Cleaning previous zipfile and tmp dir...');
console.log('Cleaning previous zipfile and tmp dir');
// IF zipDir exists, wipe it
if (fs.existsSync(this.zipDir)) {
fs.removeSync(this.zipDir);
Expand All @@ -175,7 +172,7 @@ Packager.prototype.cleanZipDir = function (next) {
* @param {Function} next callback function
*/
Packager.prototype.includePackagedModules = function (next) {
console.log('Zipping packaged modules...');
console.log('Zipping packaged modules');
// Unzip all the zipfiles in support/module/packaged
let supportedPlatforms = this.platforms.concat([ 'commonjs' ]);
// Include aliases for ios/iphone/ipad
Expand Down Expand Up @@ -261,14 +258,16 @@ Packager.prototype.zip = function (next) {
* @param {Function} next callback function
*/
Packager.prototype.package = function (next) {
console.log('Zipping Mobile SDK...');
console.log('Zipping Mobile SDK');
async.series([
this.cleanZipDir.bind(this),
this.generateManifestJSON.bind(this),
function (cb) {
console.log('Writing JSCA');
fs.copy(path.join(this.outputDir, 'api.jsca'), path.join(this.zipSDKDir, 'api.jsca'), cb);
}.bind(this),
function (cb) {
console.log('Copying SDK files');
// Copy some root files, cli/, common/, templates/, node_modules minus .bin sub-dir
this.copy([ 'CREDITS', 'README.md', 'package.json', 'cli', 'common', 'node_modules', 'templates' ], cb);
}.bind(this),
Expand Down
14 changes: 14 additions & 0 deletions build/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ Utils.globCopy = function (pattern, srcFolder, destFolder, next) {
});
};

Utils.globCopyFlat = function (pattern, srcFolder, destFolder, next) {
glob(pattern, { cwd: srcFolder }, function (err, files) {
if (err) {
console.error(err);
return next(err);
}

async.each(files, function (filename, cb) {
const filenameWithoutDirectory = filename.split('/')[1]; // TODO: Refactor to simply copy without it's source directory
fs.copy(path.join(srcFolder, filename), path.join(destFolder, filenameWithoutDirectory), cb);
}, next);
});
};

Utils.copyAndModifyFile = function (srcFolder, destFolder, filename, substitutions, next) {
// FIXME If this is a directory, we need to recurse into directory!

Expand Down
48 changes: 43 additions & 5 deletions cli/lib/creator.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* access build properties.
*
* @copyright
* Copyright (c) 2014-2017 by Appcelerator, Inc. All Rights Reserved.
* Copyright (c) 2014-2018 by Appcelerator, Inc. All Rights Reserved.
*
* @license
* Licensed under the terms of the Apache Public License
Expand Down Expand Up @@ -244,6 +244,44 @@ Creator.prototype.configOptionId = function configOptionId(order) {
};
};

/**
* Defines the -c option to selec the code base (Swift or Obj-C).
*
* @param {Integer} order - The order to apply to this option.
*
* @returns {Object}
*/
Creator.prototype.configOptionCodeBase = function configCodeBase(order) {
const cli = this.cli;
const validTypes = [ 'swift', 'objc' ];
const logger = this.logger;

function validate(value, callback) {
if (!value || !validTypes.includes(value)) {
logger.error(__('Please specify a valid code base') + '\n');
return callback(true);
}
callback(null, value);
}

return {
abbr: 'c',
desc: __('the code base of the project'),
order: order,
default: !cli.argv.prompt ? 'objc' : undefined, // if we're prompting, then force the platforms to be prompted for, otherwise force 'all'
prompt: function (callback) {
callback(fields.text({
promptLabel: __('Code base (' + validTypes.join('|') + ')'),
default: 'objc',
validate: validate
}));
},
required: true,
validate: validate,
values: validTypes
};
};

/**
* Defines the --name option.
*
Expand Down Expand Up @@ -505,10 +543,10 @@ Creator.prototype.configOptionWorkspaceDir = function configOptionWorkspaceDir(o
*/
Creator.prototype.processTemplate = function processTemplate(next) {
// try to resolve the template dir
const template = this.cli.argv.template = this.cli.argv.template || 'default',
builtinTemplateDir = appc.fs.resolvePath(this.sdk.path, 'templates', this.cli.argv.type, template),
searchPaths = [],
additionalPaths = this.config.get('paths.templates');
const template = this.cli.argv.template = this.cli.argv.template || 'default';
const additionalPaths = this.config.get('paths.templates');
const builtinTemplateDir = appc.fs.resolvePath(this.sdk.path, 'templates', this.cli.argv.type, template);
const searchPaths = [];

// first check if the specified template is a built-in template name
if (fs.existsSync(builtinTemplateDir)) {
Expand Down
13 changes: 7 additions & 6 deletions cli/lib/creators/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,12 @@ util.inherits(ModuleCreator, Creator);
ModuleCreator.prototype.init = function init() {
return {
options: {
id: this.configOptionId(150),
name: this.configOptionName(140),
platforms: this.configOptionPlatforms(120),
template: this.configOptionTemplate(110),
'workspace-dir': this.configOptionWorkspaceDir(170)
id: this.configOptionId(150),
name: this.configOptionName(140),
platforms: this.configOptionPlatforms(120),
template: this.configOptionTemplate(110),
'workspace-dir': this.configOptionWorkspaceDir(170),
'code-base': this.configOptionCodeBase(150)
}
};
};
Expand Down Expand Up @@ -152,7 +153,7 @@ ModuleCreator.prototype.run = function run(callback) {
platforms.scrubbed.forEach(function (platform) {
// if we're using the built-in template, load the platform specific template hooks
const usingBuiltinTemplate = templateDir.indexOf(this.sdk.path) === 0,
platformTemplateDir = path.join(this.sdk.path, platform, 'templates', this.projectType, this.cli.argv.template);
platformTemplateDir = path.join(this.sdk.path, platform, 'templates', this.projectType, this.cli.argv['code-base'] || this.cli.argv.template);

if (usingBuiltinTemplate) {
this.cli.scanHooks(path.join(platformTemplateDir, 'hooks'));
Expand Down
2 changes: 1 addition & 1 deletion iphone/Classes/AccelerometerModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
#import "TiModule.h"
#import <TitaniumKit/TiModule.h>

#ifdef USE_TI_ACCELEROMETER
#import <CoreMotion/CoreMotion.h>
Expand Down
2 changes: 1 addition & 1 deletion iphone/Classes/AnalyticsModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Please see the LICENSE included with this distribution for details.
*/

#import "TiModule.h"
#import <TitaniumKit/TiModule.h>

@interface AnalyticsModule : TiModule

Expand Down
2 changes: 1 addition & 1 deletion iphone/Classes/AnalyticsModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

#import "AnalyticsModule.h"
#import "APSAnalytics/APSAnalytics.h"
#import <TitaniumKit/APSAnalytics.h>

extern BOOL const TI_APPLICATION_ANALYTICS;
static NSMutableArray *_filteredEvents;
Expand Down
2 changes: 1 addition & 1 deletion iphone/Classes/AppModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
#import "TiModule.h"
#import <TitaniumKit/TiModule.h>

#ifdef USE_TI_APP

Expand Down
8 changes: 4 additions & 4 deletions iphone/Classes/AppModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
#ifdef USE_TI_APP

#import "AppModule.h"
#import "ListenerEntry.h"
#import "TiApp.h"
#import "TiHost.h"
#import <TitaniumKit/ListenerEntry.h>
#import <TitaniumKit/TiApp.h>
#import <TitaniumKit/TiHost.h>
#if defined(USE_TI_APPIOS)
#import "TiAppiOSProxy.h"
#endif

#import "TiLayoutQueue.h"
#import <TitaniumKit/TiLayoutQueue.h>
#import <UIKit/UILocalNotification.h>
#import <unistd.h>

Expand Down

0 comments on commit fbae1cf

Please sign in to comment.