Ensighten/grunt-spritesmith — pull request #65 by tastycode (2014-01-31 19:07:08+00:00)
Title: Add npm dependencies to engine descriptions

After installing grunt-spritesmith
`npm install grunt-spritesmith --save-dev`

and setting it up to load some icons originally from a rails project

```javascript
//grunt config
sprite:{
all: {
src: ['<%= yeoman.app %>/../../app/assets/images/icons/*.png'],
destImg: '<%= yeoman.app %>/images/icons.png',
destCSS: '<%= yeoman.app %>/styles/icons.scss',
cssFormat: 'scss',
engine: 'phantomjs'
}
},
```

after running `grunt sprite --stack` I get this
```
Running "sprite:all" (sprite) task
Fatal error: spawn ENOENT
Error: spawn ENOENT
at errnoException (child_process.js:980:11)
at Process.ChildProcess._handle.onexit (child_process.js:771:34)
```

I found where we are calling spawn

```
$ cd node_modules/grunt-spritesmith/
$ grep -R spawn .
./node_modules/spritesmith/node_modules/gmsmith/node_modules/gm/lib/command.js:var spawn = require('child_process').spawn;
./node_modules/spritesmith/node_modules/gmsmith/node_modules/gm/lib/command.js: self._spawn(self.args(), true, callback);
./node_modules/spritesmith/node_modules/gmsmith/node_modules/gm/lib/command.js: return self._spawn(self.args(), false, callback);
./node_modules/spritesmith/node_modules/gmsmith/node_modules/gm/lib/command.js: return this._spawn(args, true, callback);
./node_modules/spritesmith/node_modules/gmsmith/node_modules/gm/lib/command.js: proto._spawn = function _spawn (args, bufferOutput, callback) {
./node_modules/spritesmith/node_modules/gmsmith/node_modules/gm/lib/command.js: var proc = spawn(bin, args)
./node_modules/spritesmith/node_modules/pngsmith/node_modules/concat-stream/test.js:var spawn = require('child_process').spawn
./node_modules/spritesmith/node_modules/pngsmith/node_modules/concat-stream/test.js:var cmd = spawn('ls')
```

The spawn is trying to launch "convert" or "identify", but those binaries exist. Assuming there is some irreparable bug, I moved on to a few other less mature sprite frameworks with less success.

I gave grunt-spritesmith another shot, this time searching for the node.js call for spawn, which apparently is compiled. I fired up `dtrace` to see the underlying syscalls. Here is the output when getting the `spawn ENOENT`

```
$ sudo dtruss -n node
//...
58995/0x1da156d: ioctl(0x2, 0x8004667E, 0x7FFF5FBFE95C) = 0 0
58995/0x1da156d: execve("/Users/hulahoop/.rvm/gems/ruby-2.0.0-p353@rally/bin/gm\0", 0x100C00FF0, 0x100C01CD0) = -1 Err#2
58995/0x1da156d: execve("/Users/hulahoop/.rvm/gems/ruby-2.0.0-p353@global/bin/gm\0", 0x100C00FF0, 0x100C01CD0) = -1 Err#2
58995/0x1da156d: execve("/Users/hulahoop/.rvm/rubies/ruby-2.0.0-p353/bin/gm\0", 0x100C00FF0, 0x100C01CD0) = -1 Err#2
58995/0x1da156d: execve("/Users/hulahoop/.rvm/bin/gm\0", 0x100C00FF0, 0x100C01CD0) = -1 Err#2
58995/0x1da156d: execve("/usr/local/sbin/gm\0", 0x100C00FF0, 0x100C01CD0) = -1 Err#2
58995/0x1da156d: execve("/usr/local/bin/gm\0", 0x100C00FF0, 0x100C01CD0) = -1 Err#2
58995/0x1da156d: execve("/usr/bin/gm\0", 0x100C00FF0, 0x100C01CD0) = -1 Err#2
58995/0x1da156d: execve("/bin/gm\0", 0x100C00FF0, 0x100C01CD0) = -1 Err#2
58995/0x1da156d: execve("/usr/sbin/gm\0", 0x100C00FF0, 0x100C01CD0) = -1 Err#2
58995/0x1da156d: execve("/sbin/gm\0", 0x100C00FF0, 0x100C01CD0) = -1 Err#2
58995/0x1da156d: execve("/opt/X11/bin/gm\0", 0x100C00FF0, 0x100C01CD0) = -1 Err#2
58995/0x1da156d: execve("/usr/X11/bin/gm\0", 0x100C00FF0, 0x100C01CD0) = -1 Err#2
58995/0x1da156d: write(0x12, "\002\0", 0x4) = 4 0
```

Apparently there is some bug loading the "gm" spritesmith engine. I don't have graphicsmagic installed on the system anywhere, and couldn't find it with brew.

After reading the spritesmith docs it seemed that phantomjs would be the better choice. The docs say I just need to make sure phantomjs is installed.
```
brew install phantomjs
```

```
grunt sprite --stack
Error loading phantomjs { [Error: Cannot find module 'phantomjssmith'] code: 'MODULE_NOT_FOUND' }
Running "sprite:all" (sprite) task
Warning: Sorry, the spritesmith engine 'phantomjs' could not be loaded. Please be sure you have installed it properly on your machine. Use --force to continue.
```

Digging through the source, I found some troubling code.
```
var canvasEngine,
gmEngine,
phantomjsEngine,
pngEngine;
try {
canvasEngine = require('canvassmith');
} catch (e) {}

try {
gmEngine = require('gmsmith');
} catch (e) {}

try {
phantomjsEngine = require('phantomjssmith');
} catch (e) {}

try {
pngEngine = require('pngsmith');
} catch (e) {}

if (canvasEngine) { addEngine('canvas', canvasEngine); }
if (gmEngine) { addEngine('gm', gmEngine); }
if (phantomjsEngine) { addEngine('phantomjs', phantomjsEngine); }
if (pngEngine) { addEngine('pngsmith', pngEngine); }
```
I did `npm install phantomjssmith --save-dev` then ran `grunt sprite` and everything worked!

It seems that the main README.md does not mention these packages have to be installed to use the engines.

I'm going to err on the side that there is something obvious that I missed so that I had to go down this rabbit hole. In case I didn't miss anything, here is a PR to clear this up a bit.