├── .gitignore ├── LICENSE.txt ├── Makefile ├── Makefile_Rsvg ├── README-SAR.md ├── README.md ├── example ├── .gitignore ├── Makefile ├── src │ ├── child-process-promise.js │ ├── index.js │ └── s3-util.js └── template.yaml └── template.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | result 2 | build 3 | *.pdf 4 | *.png 5 | *.svg 6 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | LibRSVG license, see https://gitlab.gnome.org/GNOME/librsvg/blob/master/COPYING 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) 2 | 3 | DOCKER_IMAGE ?= lambci/lambda-base-2:build 4 | TARGET ?=/opt/ 5 | 6 | MOUNTS = -v $(PROJECT_ROOT):/var/task \ 7 | -v $(PROJECT_ROOT)result:$(TARGET) 8 | 9 | DOCKER = docker run -it --rm -w=/var/task/build 10 | build result: 11 | mkdir $@ 12 | 13 | clean: 14 | rm -rf build result 15 | 16 | bash: 17 | $(DOCKER) $(MOUNTS) --entrypoint /bin/bash -t $(DOCKER_IMAGE) 18 | 19 | all libs: 20 | $(DOCKER) $(MOUNTS) --entrypoint /usr/bin/make -t $(DOCKER_IMAGE) TARGET_DIR=$(TARGET) -f ../Makefile_Rsvg init $@ 21 | 22 | 23 | STACK_NAME ?= rsvg-layer 24 | 25 | result/bin/rsvg: all 26 | 27 | build/output.yaml: template.yaml 28 | aws cloudformation package --template $< --s3-bucket $(DEPLOYMENT_BUCKET) --output-template-file $@ 29 | 30 | deploy: build/output.yaml 31 | aws cloudformation deploy --template $< --stack-name $(STACK_NAME) 32 | aws cloudformation describe-stacks --stack-name $(STACK_NAME) --query Stacks[].Outputs --output table 33 | 34 | deploy-example: 35 | cd example && \ 36 | make deploy DEPLOYMENT_BUCKET=$(DEPLOYMENT_BUCKET) RSVG_STACK_NAME=$(STACK_NAME) 37 | -------------------------------------------------------------------------------- /Makefile_Rsvg: -------------------------------------------------------------------------------- 1 | LIBPNG_VERSION ?= 1.6.37 2 | UTIL_LINUX_VERSION ?= 2.33 3 | LIBJPEG_VERSION ?= 9c 4 | OPENJP2_VERSION ?= 2.3.1 5 | LIBTIFF_VERSION ?= 4.0.9 6 | LIBXML2_VERSION ?= 2.9.9 7 | GLIB_VERSION ?= 2.58.3 8 | CAIRO_VERSION ?= 1.14.8 9 | LIBCROCO_VERSION ?= 0.6.8 10 | PANGO_VERSION ?= 1.28.4 11 | GDK_PIXBUF_VERSION ?= 2.28.2 12 | LIBFFI_VERSION ?= 3.2.1 13 | LIBRSVG_VERSION ?= 2.26.3 14 | PIXMAN_VERSION ?= 0.38.4 15 | FONTCONFIG_VERSION ?= 2.13.0 16 | FREETYPE_VERSION ?= 2.10.0 17 | BZIP2_VERSION ?= 1.0.6 18 | HARFBUZZ_VERSION ?= 2.4.0 19 | 20 | #fontconfig-2.10.95-11.amzn2.0.2.x86_64.rpm 21 | #harfbuzz-1.3.2-1.amzn2.0.2.x86_64.rpm 22 | #freetype-2.4.11-15.amzn2.0.2.x86_64.rpm 23 | 24 | 25 | # what to tell RSVG where it will expect to run from 26 | 27 | TARGET_DIR ?= /opt/ 28 | 29 | PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) 30 | 31 | ## this is a temporary area for libraries; we don't use the main destination 32 | ## because a bunch of these libraries install additional tools and things 33 | ## that the final package does not need. in order to minimise the final 34 | ## Lambda layer size, this build script first makes/installs static 35 | ## dependencies with their docs and command line tools to the cache area, 36 | ## and then just finally installs rsvg into the actual target 37 | 38 | CACHE_DIR=$(PROJECT_ROOT)build/cache 39 | 40 | 41 | 42 | .ONESHELL: 43 | 44 | CMAKE=cmake3 45 | PKG_CONFIG=PKG_CONFIG_PATH=$(CACHE_DIR)/lib/pkgconfig 46 | CONFIGURE = ./configure \ 47 | CPPFLAGS=-I$(CACHE_DIR)/include \ 48 | LDFLAGS="-L$(CACHE_DIR)/lib -L$(CACHE_DIR)/lib64" \ 49 | $(PKG_CONFIG) \ 50 | --disable-dependency-tracking \ 51 | --disable-shared \ 52 | --enable-static \ 53 | --disable-rpath \ 54 | --prefix=$(CACHE_DIR) 55 | 56 | ## dev tool istallation 57 | 58 | init: 59 | yum install -y gcc gcc-c++ cmake3 intltool flex bison shared-mime-info gperf 60 | 61 | ## util-linux has libmount and libuuid etc 62 | 63 | LIBUUID=$(CACHE_DIR)/lib/libuuid.a 64 | 65 | UTIL_LINUX_SOURCE=util-linux-$(UTIL_LINUX_VERSION).tar.xz 66 | $(UTIL_LINUX_SOURCE): 67 | curl -LO https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v$(UTIL_LINUX_VERSION)/$(UTIL_LINUX_SOURCE) 68 | 69 | $(LIBUUID): $(UTIL_LINUX_SOURCE) 70 | tar xf $< 71 | cd util-linux* 72 | $(CONFIGURE) \ 73 | --disable-all-programs \ 74 | --enable-libuuid 75 | make 76 | make install 77 | 78 | ## libffi 79 | 80 | LIBFFI_SOURCE=libffi-$(LIBFFI_VERSION).tar.gz 81 | LIBFFI=$(CACHE_DIR)/lib64/libffi.a 82 | 83 | $(LIBFFI_SOURCE): 84 | curl -LO ftp://sourceware.org/pub/libffi/$(LIBFFI_SOURCE) 85 | 86 | $(LIBFFI): $(LIBFFI_SOURCE) 87 | tar xf $< 88 | cd libffi* 89 | $(CONFIGURE) 90 | make 91 | make install 92 | 93 | ## GLIB, 94 | # see https://developer.gnome.org/glib/stable/glib-building.html 95 | # 96 | GLIB_SOURCE=glib-$(GLIB_VERSION).tar.xz 97 | GLIB_MINOR_VERSION=$(basename $(GLIB_VERSION)) 98 | GLIB_MAJOR_VERSION=$(basename $(GLIB_MINOR_VERSION)) 99 | GLIB=$(CACHE_DIR)/lib/libglib-$(GLIB_MAJOR_VERSION).0.a 100 | 101 | $(GLIB_SOURCE): 102 | curl -LO http://ftp.gnome.org/pub/gnome/sources/glib/$(GLIB_MINOR_VERSION)/$(GLIB_SOURCE) 103 | 104 | $(GLIB): $(GLIB_SOURCE) $(LIBFFI) 105 | tar xf $< 106 | cd glib* 107 | $(PKG_CONFIG) ./autogen.sh 108 | $(CONFIGURE) \ 109 | --disable-gtk-doc \ 110 | --disable-man \ 111 | --disable-libmount \ 112 | --disable-fam \ 113 | --disable-libelf \ 114 | --disable-xattr \ 115 | --disable-installed-tests \ 116 | --with-pcre=internal 117 | make 118 | make install 119 | 120 | ## libxml2 121 | 122 | LIBXML2_SOURCE=libxml2-$(LIBXML2_VERSION).tar.gz 123 | LIBXML2=$(CACHE_DIR)/lib/libxml2.a 124 | $(LIBXML2_SOURCE): 125 | curl -LO ftp://xmlsoft.org/libxml2/$(LIBXML2_SOURCE) 126 | 127 | $(LIBXML2): $(LIBXML2_SOURCE) 128 | tar xf $< 129 | cd libxml2* 130 | $(CONFIGURE) \ 131 | --without-history \ 132 | --without-python 133 | make 134 | make install 135 | 136 | ## licroco 137 | 138 | LIBCROCO_SOURCE=libcroco-$(LIBCROCO_VERSION).tar.xz 139 | LIBCROCO_MINOR_VERSION=$(basename $(LIBCROCO_VERSION)) 140 | LIBCROCO=$(CACHE_DIR)/lib/libcroco-$(LIBCROCO_MINOR_VERSION).a 141 | 142 | $(LIBCROCO_SOURCE): 143 | curl -OL http://ftp.gnome.org/pub/GNOME/sources/libcroco/$(LIBCROCO_MINOR_VERSION)/$(LIBCROCO_SOURCE) 144 | 145 | $(LIBCROCO): $(LIBCROCO_SOURCE) $(LIBXML2) $(GLIB) 146 | tar xf $< 147 | cd libcroco* 148 | $(CONFIGURE) \ 149 | --disable-gtk-doc \ 150 | --disable-gtk-doc-html 151 | make 152 | make install 153 | 154 | ## libjpg 155 | 156 | LIBJPEG_SOURCE=jpegsrc.v$(LIBJPEG_VERSION).tar.gz 157 | 158 | LIBJPEG=$(CACHE_DIR)/lib/libjpeg.a 159 | 160 | $(LIBJPEG_SOURCE): 161 | curl -LO http://ijg.org/files/$(LIBJPEG_SOURCE) 162 | 163 | $(LIBJPEG): $(LIBJPEG_SOURCE) 164 | tar xf $< 165 | cd jpeg* 166 | $(CONFIGURE) 167 | make 168 | make install 169 | 170 | ## libpng 171 | 172 | LIBPNG_SOURCE=libpng-$(LIBPNG_VERSION).tar.xz 173 | LIBPNG=$(CACHE_DIR)/lib/libpng.a 174 | 175 | $(LIBPNG_SOURCE): 176 | curl -LO http://prdownloads.sourceforge.net/libpng/$(LIBPNG_SOURCE) 177 | 178 | $(LIBPNG): $(LIBPNG_SOURCE) 179 | tar xf $< 180 | cd libpng* 181 | $(CONFIGURE) 182 | make 183 | make install 184 | 185 | # libbz2 186 | 187 | BZIP2_SOURCE=bzip2-$(BZIP2_VERSION).tar.gz 188 | LIBBZ2=$(CACHE_DIR)/lib/libbz2.a 189 | 190 | $(BZIP2_SOURCE): 191 | curl -LO http://prdownloads.sourceforge.net/bzip2/bzip2-$(BZIP2_VERSION).tar.gz 192 | 193 | $(LIBBZ2): $(BZIP2_SOURCE) 194 | tar xf $< 195 | cd bzip2-* 196 | make libbz2.a 197 | make install PREFIX=$(CACHE_DIR) 198 | 199 | # libtiff 200 | 201 | LIBTIFF_SOURCE=tiff-$(LIBTIFF_VERSION).tar.gz 202 | LIBTIFF=$(CACHE_DIR)/lib/libtiff.a 203 | 204 | $(LIBTIFF_SOURCE): 205 | curl -LO http://download.osgeo.org/libtiff/$(LIBTIFF_SOURCE) 206 | 207 | $(LIBTIFF): $(LIBTIFF_SOURCE) 208 | tar xf $< 209 | cd tiff-* 210 | $(CONFIGURE) \ 211 | --disable-jpeg \ 212 | --disable-old-jpeg \ 213 | --disable-lzma \ 214 | --disable-jpeg12 \ 215 | --without-x 216 | make 217 | make install 218 | 219 | ## libopenjp2 220 | 221 | OPENJP2_SOURCE=openjp2-$(OPENJP2_VERSION).tar.gz 222 | 223 | $(OPENJP2_SOURCE): 224 | curl -L https://github.com/uclouvain/openjpeg/archive/v$(OPENJP2_VERSION).tar.gz -o $(OPENJP2_SOURCE) 225 | 226 | LIBOPENJP2=$(CACHE_DIR)/lib/libopenjp2.a 227 | 228 | $(LIBOPENJP2): $(OPENJP2_SOURCE) $(LIBPNG) $(LIBTIFF) 229 | tar xf $< 230 | cd openjpeg-* 231 | mkdir -p build 232 | cd build 233 | $(PKG_CONFIG) $(CMAKE) .. \ 234 | -DCMAKE_BUILD_TYPE=Release \ 235 | -DCMAKE_INSTALL_PREFIX=$(CACHE_DIR) \ 236 | -DBUILD_SHARED_LIBS:bool=off \ 237 | -DBUILD_CODEC:bool=off 238 | make 239 | make install 240 | 241 | ## pixman 242 | 243 | PIXMAN_SOURCE=pixman-$(PIXMAN_VERSION).tar.gz 244 | LIBPIXMAN=$(CACHE_DIR)/lib/libpixman-1.a 245 | 246 | $(PIXMAN_SOURCE): 247 | curl -LO https://www.cairographics.org/releases/$(PIXMAN_SOURCE) 248 | 249 | $(LIBPIXMAN): $(PIXMAN_SOURCE) $(LIBPNG) 250 | tar xf $< 251 | cd pixman* 252 | $(CONFIGURE) \ 253 | --disable-gtk 254 | make 255 | make install 256 | 257 | ## freetype and harfbuzz co-depend on each other, so freetype needs to be 258 | ## built without harfbuzz first, then harfbuzz with freetype, then freetype again 259 | ## see http://www.linuxfromscratch.org/blfs/view/svn/general/harfbuzz.html 260 | 261 | FREETYPE_SOURCE=freetype-$(FREETYPE_VERSION).tar.gz 262 | LIBFREETYPE=$(CACHE_DIR)/lib/libfreetype.a 263 | HARFBUZZ_SOURCE=harfbuzz-$(HARFBUZZ_VERSION).tar.bz2 264 | LIBHARFBUZZ=$(CACHE_DIR)/lib/libharfbuzz.a 265 | 266 | $(FREETYPE_SOURCE): 267 | curl -LO https://download.savannah.gnu.org/releases/freetype/$(FREETYPE_SOURCE) 268 | 269 | $(HARFBUZZ_SOURCE): 270 | curl -LO https://www.freedesktop.org/software/harfbuzz/release/$(HARFBUZZ_SOURCE) 271 | 272 | FT_WITHOUT_HB_DIR=$(PROJECT_ROOT)build/freetype-$(FREETYPE_VERSION)-without-harfbuzz 273 | FT_WITHOUT_HB=$(FT_WITHOUT_HB_DIR)/objs/.libs/libfreetype.a 274 | 275 | $(FT_WITHOUT_HB): $(FREETYPE_SOURCE) 276 | tar xf $< -C /tmp 277 | rm -rf $(FT_WITHOUT_HB_DIR) 278 | mv /tmp/freetype-$(FREETYPE_VERSION) $(FT_WITHOUT_HB_DIR) 279 | cd $(FT_WITHOUT_HB_DIR) 280 | $(CONFIGURE) --without-harfbuzz 281 | make 282 | make install 283 | 284 | $(LIBHARFBUZZ): $(HARFBUZZ_SOURCE) $(FT_WITHOUT_HB) 285 | tar xf $< 286 | cd harfbuzz-$(HARFBUZZ_VERSION) 287 | $(CONFIGURE) \ 288 | --with-freetype 289 | make 290 | make install 291 | 292 | $(LIBFREETYPE): $(FREETYPE_SOURCE) $(GLIB) $(LIBPNG) $(LIBBZ2) $(LIBHARFBUZZ) 293 | tar xf $< 294 | cd freetype-$(FREETYPE_VERSION) 295 | $(CONFIGURE) \ 296 | --with-harfbuzz \ 297 | --with-png \ 298 | --with-bzip2 299 | make distclean clean 300 | make 301 | make install 302 | 303 | ## fontconfig 304 | 305 | FONTCONFIG_SOURCE=fontconfig-$(FONTCONFIG_VERSION).tar.bz2 306 | LIBFONTCONFIG=$(CACHE_DIR)/lib/libfontconfig.a 307 | 308 | $(FONTCONFIG_SOURCE): 309 | curl -LO https://www.freedesktop.org/software/fontconfig/release/$(FONTCONFIG_SOURCE) 310 | 311 | fontconfig $(LIBFONTCONFIG): $(FONTCONFIG_SOURCE) $(LIBXML2) $(LIBFREETYPE) $(LIBUUID) 312 | tar xf $< 313 | cd fontconfig-$(FONTCONFIG_VERSION) 314 | $(CONFIGURE) --enable-libxml2 315 | make 316 | make install 317 | 318 | ## cairo 319 | 320 | CAIRO_SOURCE=cairo-$(CAIRO_VERSION).tar.xz 321 | 322 | LIBCAIRO:=$(CACHE_DIR)/lib/libcairo.a 323 | 324 | $(CAIRO_SOURCE): 325 | curl -OL https://www.cairographics.org/releases/$(CAIRO_SOURCE) 326 | 327 | cairo $(LIBCAIRO): $(CAIRO_SOURCE) $(LIBPNG) $(LIBXML2) $(LIBFONTCONFIG) $(LIBPIXMAN) 328 | tar xf $< 329 | cd cairo* 330 | $(CONFIGURE) \ 331 | --disable-gtk-doc \ 332 | --disable-gtk-doc-html \ 333 | --disable-valgrind \ 334 | --disable-xlib \ 335 | --disable-xlib-xrender \ 336 | --disable-xcb \ 337 | --disable-xlib-xcb \ 338 | --disable-xcb-shm \ 339 | --disable-qt \ 340 | --disable-quartz \ 341 | --disable-quartz-font \ 342 | --disable-quartz-image \ 343 | --enable-png \ 344 | --enable-pdf \ 345 | --enable-svg \ 346 | --disable-test-surfaces \ 347 | --disable-gobject \ 348 | --without-x \ 349 | --disable-interpreter \ 350 | --disable-full-testing \ 351 | --disable-gl \ 352 | --disable-glx \ 353 | --disable-egl \ 354 | --disable-wgl \ 355 | --disable-test-suite \ 356 | --enable-xml \ 357 | --disable-trace 358 | make 359 | make install 360 | 361 | ## pango 362 | 363 | PANGO_SOURCE=pango-$(PANGO_VERSION).tar.bz2 364 | PANGO_MINOR_VERSION=$(basename $(PANGO_VERSION)) 365 | PANGO_MAJOR_VERSION=$(basename $(PANGO_MINOR_VERSION)) 366 | LIBPANGO:=$(CACHE_DIR)/lib/libpango-$(PANGO_MAJOR_VERSION).0.a 367 | 368 | $(PANGO_SOURCE): 369 | curl -OL http://ftp.gnome.org/pub/GNOME/sources/pango/$(PANGO_MINOR_VERSION)/$(PANGO_SOURCE) 370 | 371 | $(LIBPANGO): $(PANGO_SOURCE) $(LIBCROCO) $(LIBCAIRO) 372 | tar xf $< 373 | cd pango* 374 | $(CONFIGURE) \ 375 | --with-included-modules \ 376 | --disable-introspection \ 377 | --disable-gtk-doc \ 378 | --disable-gtk-doc-html \ 379 | --disable-doc-cross-references \ 380 | --without-x 381 | make 382 | make install 383 | 384 | 385 | ### GDK_PIXBUF 386 | 387 | GDK_PIXBUF_SOURCE=gdk-pixbuf-$(GDK_PIXBUF_VERSION).tar.xz 388 | GDK_PIXBUF_MINOR_VERSION=$(basename $(GDK_PIXBUF_VERSION)) 389 | GDK_PIXBUF_MAJOR_VERSION=$(basename $(GDK_PIXBUF_MINOR_VERSION)) 390 | 391 | LIBGDK_PIXBUF=$(CACHE_DIR)/lib/libgdk_pixbuf-$(GDK_PIXBUF_MAJOR_VERSION).0.a 392 | 393 | $(GDK_PIXBUF_SOURCE): 394 | curl -OL http://ftp.gnome.org/pub/GNOME/sources/gdk-pixbuf/$(GDK_PIXBUF_MINOR_VERSION)/$(GDK_PIXBUF_SOURCE) 395 | 396 | 397 | $(LIBGDK_PIXBUF): $(GDK_PIXBUF_SOURCE) $(LIBPNG) $(LIBOPENJP2) $(LIBJPEG) $(LIBTIFF) $(GLIB) 398 | tar xf $< 399 | cd gdk-pixbuf* 400 | $(CONFIGURE) \ 401 | --without-gdiplus \ 402 | --disable-modules \ 403 | --disable-glibtest \ 404 | --disable-introspection \ 405 | --disable-gtk-doc-html \ 406 | --with-included-loaders=yes \ 407 | --disable-gio-sniffing \ 408 | --disable-rpath \ 409 | --disable-gtk-doc \ 410 | --without-x11 411 | make 412 | make install 413 | 414 | 415 | ## RSVG 416 | 417 | LIBS:=$(LIBCROCO) $(LIBPANGO) $(LIBCAIRO) $(LIBGDK_PIXBUF) 418 | 419 | LIBRSVG_SOURCE=librsvg-$(LIBRSVG_VERSION).tar.gz 420 | LIBRSVG_MINOR_VERSION=$(basename $(LIBRSVG_VERSION)) 421 | LIBRSVG_MAJOR_VERSION=$(basename $(LIBRSVG_MINOR_VERSION)) 422 | 423 | $(LIBRSVG_SOURCE): 424 | curl -OL http://ftp.gnome.org/pub/GNOME/sources/librsvg/$(LIBRSVG_MINOR_VERSION)/$(LIBRSVG_SOURCE) 425 | 426 | $(CACHE_DIR)/bin/rsvg-convert: $(LIBRSVG_SOURCE) $(LIBS) 427 | tar xf $< 428 | cd librsvg-* 429 | make clean distclean 430 | $(CONFIGURE) \ 431 | --disable-pixbuf-loader \ 432 | --disable-gtk-theme \ 433 | --without-x \ 434 | --disable-gtk-doc 435 | make all 436 | make install 437 | 438 | $(TARGET_DIR)bin/rsvg-convert: $(CACHE_DIR)/bin/rsvg-convert 439 | mkdir -p $(TARGET_DIR)bin 440 | cp $< $@ 441 | strip -s $@ 442 | 443 | libs: $(LIBS) 444 | 445 | all: $(TARGET_DIR)bin/rsvg-convert 446 | -------------------------------------------------------------------------------- /README-SAR.md: -------------------------------------------------------------------------------- 1 | # RSVG-Convert Lambda Layer for Amazon Linux 2 AMIs 2 | 3 | Static build of rsvg-convert (LibRSVG) for Amazon Linux 2, packaged as a Lambda layer. 4 | Bundles librsvg 2.26.3. 5 | 6 | This application provides a single output, `LayerVersion`, which points to a 7 | Lambda Layer ARN you can use with Lambda runtimes based on Amazon Linux 2 (such 8 | as the `nodejs10.x` runtime). 9 | 10 | The layer contains the system utility `/opt/bin/rsvg-convert`, which you can invoke directly 11 | as a subprocess or from a shell. 12 | 13 | For an example of how to use the layer, check out 14 | . 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RSVG-Convert (LibRSVG) for AWS Lambda 2 | 3 | Scripts to compile LibRSVG for AWS Lambda instances powered by Amazon Linux 2.x, such as the `nodejs10.x` runtime, and the updated 2018.03 Amazon Linux 1 runtimes. 4 | 5 | ## Usage 6 | 7 | Absolutely the easiest way of using this is to pull it directly from the AWS Serverless Application repository into a CloudFormation/SAM application, or deploy directly from the Serverless Application Repository into your account, and then link as a layer. 8 | 9 | The `rsvg` binary will be in `/opt/bin/rsvg-convert` after linking the layer to a Lambda function. 10 | 11 | For more information, check out the [rsvg-convert-lambda-layer](https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:145266761615:applications~rsvg-convert-lambda-layer) application in the Serverless App Repository. 12 | 13 | For manual deployments and custom builds, read below... 14 | 15 | ## Prerequisites 16 | 17 | * Docker desktop 18 | * Unix Make environment 19 | * AWS command line utilities (just for deployment) 20 | 21 | ## Compiling the code 22 | 23 | * start Docker services 24 | * `make all` 25 | 26 | There are two `make` scripts in this project. 27 | 28 | * [`Makefile`](Makefile) is intended to run on the build system, and just starts a Docker container matching the AWS Linux 2 environment for Lambda runtimes to compile Rsvg using the second script. 29 | * [`Makefile_Rsvg`](Makefile_Rsvg) is the script that will run inside the container, and actually compile binaries. 30 | 31 | The output will be in the `result` dir. 32 | 33 | ### Configuring the build 34 | 35 | By default, this compiles a version expecting to run as a Lambda layer from `/opt`. You can change the expected location by providing a `TARGET` variable when invoking `make`. 36 | 37 | The default Docker image used is `lambci/lambda-base-2:build`. To use a different base, provide a `DOCKER_IMAGE` variable when invoking `make`. 38 | 39 | Modify the versions of libraries or librsvg directly in [`Makefile_Rsvg`](Makefile_Rsvg). 40 | 41 | ### Experimenting 42 | 43 | * `make bash` to open an interactive shell with all the build directories mounted 44 | 45 | ### Compiled info 46 | 47 | ``` 48 | rsvg-convert version 2.26.3 49 | ``` 50 | 51 | ## Deploying to AWS as a layer 52 | 53 | Run the following command to deploy the compiled result as a layer in your AWS account. 54 | 55 | ``` 56 | make deploy DEPLOYMENT_BUCKET= 57 | ``` 58 | 59 | ### configuring the deployment 60 | 61 | By default, this uses `rsvg-layer` as the stack name. Provide a `STACK_NAME` variable when 62 | calling `make deploy` to use an alternative name. 63 | 64 | ### example usage 65 | 66 | An example project is in the [example](example) directory. It sets up two buckets, and listens to file uploads on the first bucket to convert and generate PDF files from SVG images. You can deploy it from the root Makefile using: 67 | 68 | ``` 69 | make deploy-example DEPLOYMENT_BUCKET= 70 | ``` 71 | 72 | For more information, check out: 73 | 74 | * https://github.com/GNOME/librsvg 75 | 76 | ## Author 77 | 78 | Gojko Adzic 79 | 80 | ## License 81 | 82 | * These scripts: [MIT](https://opensource.org/licenses/MIT) 83 | * Rsvg: 84 | * Contained libraries all have separate licenses, check the respective web sites for more information 85 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | output.yaml 2 | -------------------------------------------------------------------------------- /example/Makefile: -------------------------------------------------------------------------------- 1 | STACK_NAME ?= rsvg-layer-example 2 | RSVG_STACK_NAME ?= rsvg-layer 3 | 4 | RSVG_LAYER ?=$(shell aws cloudformation describe-stacks --stack-name $(RSVG_STACK_NAME) --query Stacks[].Outputs[].OutputValue --output text) 5 | SOURCES=$(shell find src/) 6 | 7 | clean: 8 | rm -rf build 9 | 10 | output.yaml: template.yaml $(SOURCES) 11 | mkdir -p build 12 | aws cloudformation package --template-file $< --output-template-file $@ --s3-bucket $(DEPLOYMENT_BUCKET) 13 | 14 | deploy: output.yaml 15 | aws cloudformation deploy --template-file $< --stack-name $(STACK_NAME) --capabilities CAPABILITY_IAM --parameter-overrides RsvgLayer=$(RSVG_LAYER) 16 | aws cloudformation describe-stacks --stack-name $(STACK_NAME) --query Stacks[].Outputs --output table 17 | 18 | -------------------------------------------------------------------------------- /example/src/child-process-promise.js: -------------------------------------------------------------------------------- 1 | /*global module, require, console, Promise */ 2 | 'use strict'; 3 | const childProcess = require('child_process'), 4 | spawnPromise = function (command, argsarray, envOptions) { 5 | return new Promise((resolve, reject) => { 6 | console.log('executing', command, argsarray.join(' ')); 7 | const childProc = childProcess.spawn(command, argsarray, envOptions || {env: process.env, cwd: process.cwd()}), 8 | resultBuffers = []; 9 | childProc.stdout.on('data', buffer => { 10 | console.log(buffer.toString()); 11 | resultBuffers.push(buffer); 12 | }); 13 | childProc.stderr.on('data', buffer => console.error(buffer.toString())); 14 | childProc.on('exit', (code, signal) => { 15 | console.log(`${command} completed with ${code}:${signal}`); 16 | if (code || signal) { 17 | reject(`${command} failed with ${code || signal}`); 18 | } else { 19 | resolve(Buffer.concat(resultBuffers).toString().trim()); 20 | } 21 | }); 22 | }); 23 | }; 24 | module.exports = { 25 | spawn: spawnPromise 26 | }; 27 | -------------------------------------------------------------------------------- /example/src/index.js: -------------------------------------------------------------------------------- 1 | 2 | const s3Util = require('./s3-util'), 3 | childProcessPromise = require('./child-process-promise'), 4 | path = require('path'), 5 | os = require('os'), 6 | FILE_TYPE = process.env.FILE_TYPE, 7 | OUTPUT_BUCKET = process.env.OUTPUT_BUCKET, 8 | MIME_TYPE = process.env.MIME_TYPE; 9 | 10 | exports.handler = function (eventObject, context) { 11 | const eventRecord = eventObject.Records && eventObject.Records[0], 12 | inputBucket = eventRecord.s3.bucket.name, 13 | key = eventRecord.s3.object.key, 14 | id = context.awsRequestId, 15 | extension = `.${FILE_TYPE}`, 16 | resultKey = key.replace(/\.[^.]+$/, extension), 17 | workdir = os.tmpdir(), 18 | inputFile = path.join(workdir, id + path.extname(key)), 19 | outputFile = path.join(workdir, 'converted-' + id + extension); 20 | 21 | 22 | console.log('converting', inputBucket, key, 'using', inputFile); 23 | return s3Util.downloadFileFromS3(inputBucket, key, inputFile) 24 | .then(() => childProcessPromise.spawn( 25 | '/opt/bin/rsvg-convert', 26 | [inputFile, '-f', FILE_TYPE, '-o', outputFile], 27 | {env: process.env, cwd: workdir} 28 | )) 29 | .then(() => s3Util.uploadFileToS3(OUTPUT_BUCKET, resultKey, outputFile, MIME_TYPE)); 30 | }; 31 | -------------------------------------------------------------------------------- /example/src/s3-util.js: -------------------------------------------------------------------------------- 1 | /*global module, require, Promise, console */ 2 | 3 | const aws = require('aws-sdk'), 4 | fs = require('fs'), 5 | s3 = new aws.S3(), 6 | downloadFileFromS3 = function (bucket, fileKey, filePath) { 7 | 'use strict'; 8 | console.log('downloading', bucket, fileKey, filePath); 9 | return new Promise(function (resolve, reject) { 10 | const file = fs.createWriteStream(filePath), 11 | stream = s3.getObject({ 12 | Bucket: bucket, 13 | Key: fileKey 14 | }).createReadStream(); 15 | stream.on('error', reject); 16 | file.on('error', reject); 17 | file.on('finish', function () { 18 | console.log('downloaded', bucket, fileKey); 19 | resolve(filePath); 20 | }); 21 | stream.pipe(file); 22 | }); 23 | }, uploadFileToS3 = function (bucket, fileKey, filePath, contentType) { 24 | 'use strict'; 25 | console.log('uploading', bucket, fileKey, filePath); 26 | return s3.upload({ 27 | Bucket: bucket, 28 | Key: fileKey, 29 | Body: fs.createReadStream(filePath), 30 | ACL: 'private', 31 | ContentType: contentType 32 | }).promise(); 33 | }; 34 | 35 | module.exports = { 36 | downloadFileFromS3: downloadFileFromS3, 37 | uploadFileToS3: uploadFileToS3 38 | }; -------------------------------------------------------------------------------- /example/template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: > 4 | Example project demonstrating the usage of the RsvgConvert Layer for AWS Linux 2 runtimes. 5 | 6 | Parameters: 7 | RsvgLayer: 8 | Type: String 9 | ConversionFileType: 10 | Type: String 11 | Default: pdf 12 | ConversionMimeType: 13 | Type: String 14 | Default: application/pdf 15 | Resources: 16 | UploadBucket: 17 | Type: AWS::S3::Bucket 18 | 19 | ResultsBucket: 20 | Type: AWS::S3::Bucket 21 | 22 | ConvertFileFunction: 23 | Type: AWS::Serverless::Function 24 | Properties: 25 | Handler: index.handler 26 | Timeout: 180 27 | MemorySize: 1024 28 | Runtime: nodejs10.x 29 | CodeUri: src 30 | Layers: 31 | - !Ref RsvgLayer 32 | Policies: 33 | - S3CrudPolicy: 34 | BucketName: !Sub "${AWS::StackName}-*" 35 | Environment: 36 | Variables: 37 | OUTPUT_BUCKET: !Ref ResultsBucket 38 | FILE_TYPE: !Ref ConversionFileType 39 | MIME_TYPE: !Ref ConversionMimeType 40 | Events: 41 | FileUpload: 42 | Type: S3 43 | Properties: 44 | Bucket: !Ref UploadBucket 45 | Events: s3:ObjectCreated:* 46 | 47 | Outputs: 48 | UploadBucket: 49 | Description: "Upload S3 bucket" 50 | Value: !Ref UploadBucket 51 | ResultsBucket: 52 | Description: "Results S3 bucket" 53 | Value: !Ref ResultsBucket 54 | 55 | -------------------------------------------------------------------------------- /template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: > 4 | Static build of rsvg-convert (librsvg) for Amazon Linux 2 5 | 6 | Check out https://github.com/serverlesspub/rsvg-convert-aws-lambda-binary 7 | for more information. 8 | Resources: 9 | RsvgConvertLayer: 10 | Type: AWS::Serverless::LayerVersion 11 | Properties: 12 | LayerName: rsvg-convert 13 | Description: Static build of rsvg-convert (librsvg) for Amazon Linux 2 14 | ContentUri: result/ 15 | CompatibleRuntimes: 16 | - nodejs10.x 17 | LicenseInfo: https://gitlab.gnome.org/GNOME/librsvg/blob/master/COPYING 18 | RetentionPolicy: Retain 19 | 20 | Outputs: 21 | LayerVersion: 22 | Description: Layer ARN Reference 23 | Value: !Ref RsvgConvertLayer 24 | 25 | Metadata: 26 | AWS::ServerlessRepo::Application: 27 | Name: rsvg-convert-lambda-layer 28 | Description: > 29 | Static build of RsvgConvert for Amazon Linux 2, 30 | packaged as a Lambda layer. Bundles RsvgConvert 2.26.3. 31 | Author: Gojko Adzic 32 | SpdxLicenseId: GPL-2.0 33 | LicenseUrl: LICENSE.txt 34 | ReadmeUrl: README-SAR.md 35 | Labels: ['layer', 'svg', 'pdf', 'png', 'lambda', 'librsvg', 'rsvg-convert'] 36 | HomePageUrl: https://github.com/serverlesspub/rsvg-convert-aws-lambda-binary 37 | SemanticVersion: 1.0.0 38 | SourceCodeUrl: https://github.com/serverlesspub/rsvg-convert-aws-lambda-binary 39 | --------------------------------------------------------------------------------