trueinteractions / tint2

Native Javascript Applications
1.59k stars 41 forks source link

Add compiler and app packaging tools #29

Closed trevorlinton closed 9 years ago

voronianski commented 10 years ago

@trevorlinton as I understand there's no way to package app as dmg for example?

voronianski commented 10 years ago

@trevorlinton I'm in doubt 'cause I would like to use tint for the OS X app development and not sure whether this could be a solid choice.

For example:

If one of application's dependencies is libspotify - I will need to build framework somehow not inside ~/Library/Frameworks as Homebrew does but inside the folder of my app, in order to tint be able to package all related app files as dmg, am I right?

trevorlinton commented 10 years ago

@voronianski We have some test packaging tools available but at the moment they're for our paying customers and will be released in October. These allow you to build full applications using Tint.

Building a full application requires:

  1. A Info.plist file that has all of the settings and description of the application (its just an XML file). As well as describes what command line it should execute to start the app.
  2. The tint runtime placed in the "MacOS" directory
  3. Any resources you need (icons, images, html files, javascript files) in the "Resources" directory
  4. Any additional frameworks or libraries you want to include in your application (such as libspotify) in the "Frameworks" directory.

The layout of an application is:

./MyAppName.app/Contents/
./MyAppName.app/Contents/MacOS/  (must include the tint executable, the exec name and args are specified in the Info.plist)
./MyAppName.app/Contents/Frameworks/ (should include any frameworks/libraries needed. You can import the frameworks with Tint's language runtime)
./MyAppName.app/Contents/Info.plist (specifies the executable to run, the arguments, icons, file types it handles, and a whole lot of other information)
./MyAppName.app/Contents/Resources (all of your images, icons, html, js files needed.)

One of the unit tests (notifications.js) actually creates a full OS X application for testing.

You can find the commands to build a minimal application here: https://github.com/trueinteractions/tint2/blob/master/test/tools/utilities.js (~ line 320)

In addition a template application is provided here: https://github.com/trueinteractions/tint2/tree/master/test/tools/Shell.app/Contents

As well as a test Info.plist file here: https://github.com/trueinteractions/tint2/blob/master/test/tools/Shell.app/Contents/Info.plist

Hope this helps.

voronianski commented 10 years ago

@trevorlinton Thanks!

test packaging tools available but at the moment they're for our paying customers and will be released in October

Will they be released as open-source?

trevorlinton commented 10 years ago

In addition you can find information on what all the keys/values mean in the Info.plist file here:

https://developer.apple.com/library/ios/documentation/general/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html

You can also find out a wealth of information on how OS X application bundles work here:

https://developer.apple.com/library/mac/documentation/corefoundation/conceptual/cfbundles/BundleTypes/BundleTypes.html

Note, there's a whole other part of this (signing your application) which requires setting up entitlements and using the codesign tool to distribute it to computers that have "default" OS X security settings.

Also note, none of this is proprietary to Tint, this is how all applications work (everything is actually just a command line!) Although tools like Xcode and other IDE's handle all of this packaging for you.

trevorlinton commented 10 years ago

@voronianski

Yes, the CLI packaging tools will be released open source.

Our commercial offering integrates into Xcode/Visual Studio/Sublime/WebStorm by adding compile tools and also contains a GUI based compiler tool that allows you to package and sign apps easily. Those will not be open source (but anyone could create one).

voronianski commented 10 years ago

@trevorlinton yeah, XCode simplifies life a lot.. but possibility to build a native app with javascript is soo seductive :)

trevorlinton commented 10 years ago

@voronianski The CLI packaging tools we have just read all of the necessary values (App name, version, icon location, JS startup file) from package.json then build up a full application for you. It's (in my opinion) more straight forward than Xcode ;).

voronianski commented 10 years ago

@trevorlinton yeah, but if I want to distribute this app just as .dmg (without App Store) probably I'll need a certificates, signing and other stuff from Apple anyway?

Though I didn't have experience with OS X apps I published several iOS applications and for managing this stuff XCode helps a lot.

trevorlinton commented 10 years ago

@voronianski You can create a DMG several ways, using a HDIUTIL command line, or there are (dozens and dozens) of open source tools to create DMG's from applications:

https://github.com/andreyvit/yoursway-create-dmg

There's also Xcode that can package up existing applications into DMG's. Or, you can use OSXes built in package builder tools:

https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man1/pkgbuild.1.html https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/productbuild.1.html https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/pkgutil.1.html

Those CLI tools provided by Apple are the most common way, they create installers with the standard licensing text.

You can use any of these methods.

trevorlinton commented 10 years ago

@voronianski You'll need to sign the app prior to making a DMG/installer, any OS X install without GateKeeper turned off won't run any application that isn't signed.

There's a CLI command line tool for it though: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/codesign.1.html

voronianski commented 10 years ago

@trevorlinton thanks a lot for your answers! They are very helpful.

I also would like to ask one more because of your experience, if you don't mind of course :)

I'm a bit confused in such things without XCode.. In order to use cocoa lib inside tint I need to build it, but how? clang?

trevorlinton commented 10 years ago

@voronianski

It depends on how you want to use the Framework/Library.

Objective-C supports reflection so if you have a binary (and its an objective-c library), you're fine, just use process.bridge.import('Path/To/Library.dylib').

If it's a normal-run-of-the-mill C library (or POSIX library) you can use use node-ffi which is built in to the process.bridge as well (inspect the process.bridge object, there's tons of methods to import, load and execute C functions).

Finally you also can use node bindings and import the library with a require() (see node-gyp, it has plenty of information on how to compile/include native binaries with node - which tint supports).

So you have a plethora of options on how you can pull in the native library. In addition I suppose you can get the sources, add the sources of the library you want and build it in with Tint, that's possible but i'm unsure what it really gives you in the end.

trevorlinton commented 10 years ago

@voronianski

I went and downloaded CocoaLibSpotify, it's somewhat weird they don't provide a binary download. However I built it and did a quick test and everything seems to work fine.

https://www.trueinteractions.com/libspotifyontint.zip

You'll find a libspotifytest.js file in there.

trevorlinton commented 10 years ago

There's also a node libspotify wrapper if you want to try your luck with that, might be easier if you're unfamiliar with Objective-C (especially using the JS syntax):

https://github.com/Floby/node-libspotify

voronianski commented 10 years ago

@trevorlinton

I went and downloaded CocoaLibSpotify, it's somewhat weird they don't provide a binary download. However I built it and did a quick test and everything seems to work fine.

Could you please share how you built it? :collision:

Your example looks exactly what I wanted to achieve. Thanks!

https://github.com/Floby/node-libspotify

I've checked it already, the project looks dead and not fully implements the API (as well as https://github.com/FrontierPsychiatrist/node-spotify). I'm fine with Objective-C though I used it for developing few iOS apps and not an expert yet.

voronianski commented 10 years ago

@trevorlinton also is there a simple way to read .c file and make consts inside available as js variables?

#include <stdint.h>
#include <stdlib.h>
const uint8_t g_key[] = {
   0x01, 0x21, 0x26, 0x7E, 0xA6, 0x5C, 0x8D, 0xA1, 0xFB, 0xF2, 0x06, 0xE4, 0xFD, 0x78, 0xEA, 0xB9
};
const size_t g_key_size = sizeof(g_key);
trevorlinton commented 10 years ago

@voronianski

My apologies, i must have missed this. You can create structs using process.bridge.struct, first create a definition with: var structType = process.bridge.struct({name:type, name2:type}); The various types allowed are either existing structs you've defined or those on process.bridge.types (general C types). You can then instantiate a new struct with var mystruct = new structType; The fields can then be set directly using mystruct.name = someval;. For constants you can simply pass those directly into the functions and the FFI bridge will figure out the appropriate conversion from JS -> C.

So for above just do:

var g_key = [0x01, 0x21, 0x26, 0x7E, 0xA6, 0x5C, 0x8D, 0xA1, 0xFB, 0xF2, 0x06, 0xE4, 0xFD, 0x78, 0xEA, 0xB9];

If you need to create a pointer of g_key you can sue process.bridge.ref to copy g_key to a memory block and use .ref() to create a pointer (or a pointer of a pointer).

See modules/Bridge/win32.js, it has examples of how to use C libraries. If you're using an objective-C library most of the functions and structs are already defined for you. (such as NSRectMake, etc). the DotNet bridge is similar, all of the structs already exist in their appropriate namespace. You can create new ones simply by doing a new process.bridge.dotnet.NameSpace.StructureName (or objc for objective-c).

voronianski commented 10 years ago

@trevorlinton

just curious about :)

test packaging tools available but at the moment they're for our paying customers and will be released in October

trevorlinton commented 10 years ago

@voronianski We're both a commercial and open source company, we have packaging tool plugins that integrate with sublime, web storm, and a stand alone GUI packager for our customers. We haven't yet separated out the code to be an independent CLI tool. Once we do this we'll add the cli packaging tool to this repo (the remaining packaging plugins are held for those who've purchased commercial support).