PHP GD on AWS Lambda (using Bref)

Warning: This is still a work in progress — i’ve tried to get as far as I could to but ran out of time.

The current error is the following, which I think is due to the GD extension using config from a later version of PHP, rather than the version Bref uses;

PHP Warning: PHP Startup: Unable to load dynamic library 'gd' (tried: /opt/bref/lib/php/extensions/no-debug-zts-20180731/gd (/opt/bref/lib/php/extensions/no-debug-zts-20180731/gd: cannot open shared object file: No such file or directory), /opt/bref/lib/php/extensions/no-debug-zts-20180731/gd.so (/opt/bref/lib/php/extensions/no-debug-zts-20180731/gd.so: undefined symbol: executor_globals)) in Unknown on line 0

Basically the following needs to be done to get GD added as a layer (and thus, extension) available to PHP, within AWS Lambda (using PHP Bref).

  1. Compile GD as a ‘bundle’ (including all required libraries as part of it).
  2. Zip up the gd.so bundle file, along with any other libraries it requires
    This is unzipped in the /opt dir in lambda, so the directory structure in the Zip file should be setup in whatever way makes it all work
  3. Publish the zip file as a layer, which is then included after the bref layer in lambda

Compile GD

I followed this guide for the commands;

Download and compile the following required libraries;

  • libwebp (GD compiles, but then complains the library isn’t there when you try to use the GD PHP extension if you don’t include this library)
    libxpm (GD doesn’t seem to compile without it, and it’s not included using the AWS AMI by default)

Follow the instructions on each of their respective websites to build, and run the ‘./configure’ command with ‘–with-prefix=/opt/…’ (replacing ‘…’ with the name of the library)

Download PHP from the php.net site, (get the same version of PHP as Bref uses).

Unzip, and go into the /modules/gd dir (in your unzipped PHP dir)

Run the following to generate a ./configure command and make files

sudo phpize

The following configures and compiles the GD extension, followed by ‘make test’ to check the extension is working.

It references the ‘libwebp’ and ‘libxpm’ directories which are already compiled and output in the /opt/… dir (using ./configure –with-prefix=/opt/.. command)

sudo ./configure --with-php-config=/usr/bin/php-config --with-gd --with-freetype-dir=/usr --with-jpeg-dir=/usr --with-xpm-dir=/opt/libxpm/ --with-png-dir=/usr --with-webp-dir=/opt/libwebp/
sudo make
make test

Zip up the gd bundle

For me, I include the following in the zip file;

  • libwebp (GD compiles, but then complains the library isn’t there when you try to use the GD PHP extension if you don’t include this library)
  • libxpm (GD doesn’t seem to compile without it, and it’s not included using the AWS AMI by default)
  • bref/lib/php/extensions/no-debug-zts-20180731/gd.so
    This is my compiled GD extension, in this directory (to coincide with the extensions dir bref uses — found using phpinfo(); )

The following command creates a ‘gd.zip’ file with the above libraries & files;

zip -r gd.zip lib* bref

Publish the zip file as an AWS lambda layer

This part’s the easy one;

aws lambda publish-layer-version --layer-name php-7-3-gd --description "gd php extension" --zip-file fileb://gd.zip

The lambda layer name can be whatever you like, along with the description. The file part (.zip) refers to the zip file you’ve created, stored on your local machine

AWS will spit out some JSON, with the ‘LayerVersionArn’ as well — this is what you need to include in your list of Lambda layers for your function, eg;

     ....
     "LayerVersionArn": "arn:aws:lambda:ap-southeast-2:1234567:layer:php-7-3-gd:16", 
     "Version": 16, 
     "Description": "gd php extension",
     ....
}