heroku installation woes #114

jgreene opened this Issue Aug 26, 2011 · 10 comments

7 participants


I've been attempting to install node-canvas on heroku the last couple of days and have hit a brick wall. The problem boils down to it's dependence upon the cairo library and the "node-waf configure build" wscript that checks for it's existence. Since we can't install libraries directly on heroku I attempted placing the precompiled libraries in the /app/bin folder (which is in heroku's $PATH), then I set the PKG_CONFIG_PATH to /app/bin/pkgconfig so that "pkg-config --libs cairo" could find the library (which is basically what the wscript calls to see if it exists), finally I ensured that the .pc files in the /app/bin/pkgconfig directory were modified to properly point to the libraries/header files in /app/bin.

All of this works fine on my local machine, so I'm not really sure this should be considered an issue for the node-canvas project, but I've been unable to get around this limitation in heroku and was hoping someone with more knowledge could help me get it running, or suggest some changes to the node-canvas package that could help with the cairo dependency issues.


I placed this line into the canvas build script (wscript):
os.system('pkg-config --libs cairo')
This checks for the existence of the cairo package on the system, and produces the following output:

Package cairo was not found in the pkg-config search path.
Perhaps you should add the directory containing `cairo.pc'
to the PKG_CONFIG_PATH environment variable

I have already set the PKG_CONFIG_PATH using:
heroku config:add PKG_CONFIG_PATH=/app/bin/pkgconfig

When I run:
heroku run bash
and in the bash prompt use the same command from above:
pkg-config --libs cairo

I get the result:
-L/app/bin -lcairo

which is correct.

This tells me that there is something strange/wrong with the heroku build system and it's pkg-config implementation since it does not seem to be honoring the PKG_CONFIG_PATH environment variable that I have set.


It looks like this comes down to a permissions issue. Heroku's build process doesn't have permission to access the /app folder, so you can't store dependencies there. I suppose the only way to get around this limitation would be to create a node-canvas branch that builds cairo automatically, anyone have any ideas on how to go about this?


I ended up figuring out how to do this, I'll put the steps below.

1) Check out the canvas package from github.
2) Compile the cairo package on 64bit ubuntu.
3) Create a subdirectory named cairo inside the canvas package, place the compiled cairo module library, and header files inside this directory.

4) Modify your wscript to this:

import glob
import Options
import os
import Utils
from TaskGen import feature, after, before

srcdir = '.'
blddir = 'build'
VERSION = '0.0.1'

def set_options(opt):
opt.add_option('--profile', action='store_true', help='Enable profiling', dest='profile', default=False)

def configure(conf):
o = Options.options
conf.env['USE_PROFILING'] = o.profile
conf.env.append_value('CPPFLAGS', '-DNDEBUG')

if conf.check(lib='gif', libpath=['/lib', '/usr/lib', '/usr/local/lib'], uselib_store='GIF', mandatory=False):
conf.env.append_value('CPPFLAGS', '-DHAVE_GIF=1')

if conf.check(lib='jpeg', libpath=['/lib', '/usr/lib', '/usr/local/lib'], uselib_store='JPEG', mandatory=False):
conf.env.append_value('CPPFLAGS', '-DHAVE_JPEG=1')

if conf.env['USE_PROFILING'] == True:
conf.env.append_value('CXXFLAGS', ['-pg'])
conf.env.append_value('LINKFLAGS', ['-pg'])

#conf.check_cfg(package='cairo', args='--cflags --libs', mandatory=True)
flags = ['-O3', '-Wall', '-D_FILE_OFFSET_BITS=64', '-D_LARGEFILE_SOURCE', '-fPIC']
conf.env.append_value('CCFLAGS', flags)
conf.env.append_value('CXXFLAGS', flags)

def apply_add_precompiled(tgen):
if hasattr(tgen, 'add_precompiled'):
for i in Utils.to_list(tgen.add_precompiled):
input_node = tgen.bld.srcnode.find_resource(i)

def build(bld):

obj = bld.new_task_gen('cxx', 'shlib', 'node_addon')
obj.target = 'canvas'
obj.source = bld.glob('src/*.cc')
obj.includes = 'cairo'
obj.uselib = ['GIF', 'JPEG']
obj.add_precompiled = ['cairo/libcairo.so']


Wow. This sounds really impressive.

Naive questions:

  1. What is the "compiled cairo module library" ? Is that a .dylib file? a group of files? or which?
  2. Header files refers to the .h files in the /src of cairo ?
  3. I do not understand how to get heroku to execute a node-waf configure build on my wscript file. I've only been able to get heroku to execute stuff from package.json. (running bash on heroku it can't find node-waf). Is there a way for me to refer to a local package in package.json? As in getting package.json to depend on something within my app as opposed to from a remote repository. [EDIT] I was able to refer to a repository by http, so forking this guy worked in my package.json:
, "canvas": "https://github.com/elspoono/node-canvas/tarball/master"

Holy crap.

That actually worked.


I couldn't get jpeg and gif support working ... but all I needed was png anyways. Anyone else feel free to use or look at my node-canvas-heroku fork if interested in performing this same hack. Feel free to contact me too ... I'm interested in improving this, but am not yet learned enough to do more. Appreciate questions and advice.



Just did a test on Nodejitsu. node-canvas appears fully supported.

Was able to successfully deploy live clock example ( https://github.com/LearnBoost/node-canvas/blob/master/examples/live-clock.js ) using just the jitsu deploy command ( no additional configuration was required )



@Marak I'm having an issue with Nodejitsu and node-canvas. Deploy works fine, but it appears that you guys have an old version of jpeglib installed.

Wrong JPEG library version: library is 62, caller expects 80

Judging by this wiki entry node-canvas requires libcairo2-dev & libjpeg8-dev.

EDIT: I ended up just using a simple imagemagick convert png -> jpg to get around the jpeglib issue.


For others wanting to use node-canvas on Heroku I've made a custom buildpack for node.js which also imports Cairo and Pixman so that the official node-canvas package will build when you push. See Heroku's Devcenter for more on custom buildpacks.

Simply do heroku config:add BUILDPACK_URL=git://github.com/bloomtime/heroku-buildpack-nodejs.git#cairo to use the buildpack. You can inspect the differences yourself, or fork the original and make your own fixes.

I haven't tested everything yet, but basic PNG rendering is working at least. Most likely it will need a little bit more work to get JPG rendering working. If I decide to get fancy I may try to use composable buildpacks so I can keep using the official nodejs buildpack and just bring cairo in separately. Ping me if you're interested in trying that!

See http://www.ryandaigle.com/a/using-vulcan-to-build-binary-dependencies-on-heroku and the last few comments on heroku/vulcan#20 if you also want to build your own (or newer) cairo and pixman binaries.


Just wanted to note here that the custom buildback currently only works on the for node-canvas versions 0.12.x. Node-canvas 0.13.x seems to fail to find the cairo libraries when using gyp.


I've brought @RandomEtc's buildpack up-to-date with current pixman (0.28.2), freetype (2.4.11), and cairo (1.12.14) libraries: https://github.com/mojodna/heroku-buildpack-nodejs

To use this buildpack, heroku config:add BUILDPACK_URL=git://github.com/mojodna/heroku-buildpack-nodejs.git#cairo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment