Build Instructions

Blend2D uses CMake to create native platform (or IDE) projects and to build them. Consult cmake-generators page to see which generators are supported on your target platform. You don't have to use CMake if you prefer other tools, but then you would have to set some compile flags and definitions manually, which is covered by Building Without CMake section. At the moment Blend2D only depends on AsmJit library, which is part of Blend2D source releases, but it's not part of Blend2D git repository. Git users have to clone AsmJit library separately.

Note

This page documents the process of building Blend2D. If you are more intersted in using Blend2D within your own project the Getting Started page is much easier and provides all the information to use Blend2D in a CMake project.

Build Requirements

Operating systems supported:

  • POSIX compatible operating systems including Linux, BSDs, and OSX.
  • Windows 7+ (Windows XP or less is not supported).
  • Other operating systems may require some minor support (Haiku reported to work).

CPU architectures supported:

  • X86 - Both 32-bit and 64-bit targets are supported
  • ARM - Reference pipeline only (reference pipeline is currently limited to solid fills only and doesn't provide NEON acceleration)
  • Other architectures will be supported through reference pipeline that is written in C++

C++ compilers supported:

  • Clang (with C++11 support)
  • GCC 4.8+
  • MSVC 2017+
  • Intel compiler should work, but it's not tested by our continuous integration

Important

It's strongly advised to use latest GCC or Clang to compile Blend2D on all platforms to achieve maximum performance. Both compilers can optimize Blend2D C++ code very well and can vectorize many floating point computations that are used during geometry processing. A C++ Compilers page provides a summary of compiler optimizations that Blend2D benefits from and will be extended in the future to cover more constructs relevant to Blend2D.

Unsafe Optimizations

Never use unsafe math optimizations like -ffast-math, -ffinite-math-only, or /fp:fast as Blend2D relies on existence of NaN and Infinity. Additionally, C++ compiler should never reorder any floating point expressions as some expressions are very sensitive to such reordering. The only optimization that is allowed is using fused-multiply-add (FMA) instructions if they are available.

Build Configuration

By default only dynamically linked blend2d library is built. The following build options are available:

Option Default Description
CMAKE_BUILD_TYPE (unset) Highly depends on CMake generator used:
  • If you use IDE that supports multiple configurations like Visual Studio or Xcode then leave it empty and use your IDE to select the build type you want
  • If you use a makefile based generator or ninja then you should set it to Release as Debug builds are order of magnitude slower than release builds
ASMJIT_DIR (unset) Where to find AsmJit library for static inclusion. Should be unset to let Blend2D autodetect the location:
  • <blend2d>/3rdparty/asmjit - Third party directory used by source releases
  • <blend2d>/../asmjit - Git users usually clone AsmJit at the same directory level as Blend2D
BLEND2D_TEST false Whether to build tests.
BLEND2D_EMBED false Whether to embed Blend2D library, which enables:
  • Building Blend2D as part of your project without creating any intermediate targets like static or dynamic libraries
  • Building Blend2D statically - BL_STATIC is implied by BL_EMBED so the build won't export any symbols
BLEND2D_STATIC false Whether to build Blend2D statically:
  • This would create a static library blend2d and provide Blend2D::Blend2D target that you can link to
  • When enabled BL_STATIC is defined during the build and must be defined as well by any code that includes Blend2D. If you use Blend2D::Blend2D target then you don't have to worry about anything as all the necessary stuff would be deduced from using the target
BLEND2D_SANITIZE (unset) Sanitizers to use to build Blend2D, possible options are address, undefined, thread, etc...
  • This option is only useful for Blend2D developers or for people that are facing runtime problems
  • Sanitizer-enabled builds are slower, but can discover issues that would not be discovered by normal debug builds
  • memory sanitizer is not reliable as Blend2D uses JIT compile that doesn't instrument the code, using it would lead to false positives
BLEND2D_NO_INSTALL false If true Blend2D won't install blend2d library and public header files. Useful in cases in which Blend2D is compiles statically as a part of another project, which has install targets, but installing Blend2D is unwanted.

Building From Source

The following steps can be used to clone and build Blend2D directly from git:

# Get both Blend2D and AsmJit.
$ git clone https://github.com/asmjit/asmjit
$ git clone https://github.com/blend2d/blend2d

# Create build directory.
$ mkdir blend2d/build
$ cd blend2d/build

# Configure the project. This would create either makefiles or
# IDE specific project files that are required to compile the
# project. Use BLEND2D_TEST to build tests.
#
# NOTE: Leave build type empty if you use Visual Studio or Xcode
$ cmake .. -DCMAKE_BUILD_TYPE=Release -DBLEND2D_TEST=TRUE

# Build the project. The build command depends on cmake-generator
# used to configure the project. If you use makefiles then `make`
# would be the command, otherwise it could be `ninja` or other IDE
# specific command.
$ cmake --build .

# Alternatively, if you use IDE such as Visual Studio or Xcode you
# may need to select the build type, which would default to Debug
# by default.
$ cmake -- build . --config Release

# DONE: You should have either blend2d.dll or libblend2d.so library.

The following steps can be used to build Blend2D source release:

# Get source release directly from blend2d.com.
$ wget https://blend2d.com/download/blend2d-VERSION.zip
$ unzip blend2d-VERSION.zip

# Create build directory.
$ mkdir blend2d/build
$ cd blend2d/build

# Configure and build (see the previous section for more details).
$ cmake .. -DCMAKE_BUILD_TYPE=Release -DBLEND2D_TEST=TRUE
$ cmake --build .

# DONE: You should have either blend2d.dll or libblend2d.so library.

Building Sample Applications

The same approach can be used to build sample applications. The following example shows how to clone everything from Blend2D git repositories, but it would work with source as well:

# Get both Blend2D and AsmJit.
$ git clone https://github.com/asmjit/asmjit
$ git clone https://github.com/blend2d/blend2d

# Get Blend2D samples and benchmarking tool.
$ git clone https://github.com/blend2d/blend2d-bench
$ git clone https://github.com/blend2d/blend2d-samples

# Build blend2d-bench, will try to autodetect Cairo and Qt.
$ mkdir blend2d-bench/build
$ cd blend2d-bench/build
$ cmake .. -DCMAKE_BUILD_TYPE=Release
$ cmake --build .
$ cd ..

# Build blend2d-samples (use a category you are interested in).
$ cd blend2d-samples/<category>
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Release
$ cmake --build .

# DONE: Your samples are compiled...

Building Without CMake

This page documents the process of building Blend2D without any help of CMake build scripts. It can be used as a reference of what CMake scripts are doing and as a recommendation of building Blend2D with other build tools or no build tools at all. Blend2D exports C API, but it's still a library written in C++ and requires at least C++11 capable compiler.

Compiler Independent Setup

  • Add the following source files to your target:
    • All source files in Blend2D src directory
    • All source files in AsmJit src directory. If you downloaded a source release of Blend2D then AsmJit will be at 3rdparty/asmjit directory within Blend2D project
  • Setup the C++ compiler in the following way:
    • Enable at least C++11 through -std=c++11 or /std:c++latest. C++17 is preferred though
    • Add ${ASMJIT_DIR}/src to your include path through -I... option
    • Define ASMJIT_STATIC to tell asmjit that it will be built statically
  • Define the following compile-time definitions to select a build type:
    • NDEBUG - should be always defined for release builds (standard C way)
    • BL_BUILD_DEBUG - force debug build, overrides autodetection based on NDEBUG (optional).
    • BL_BUILD_RELEASE - force release build, overrides autodetection based on NDEBUG (optional)
  • Define the following compile-time definitions to enable architecture-specific optimizations:
    • BL_BUILD_OPT_SSE2 - enables SSE2 optimizations (should be always enabled)
    • BL_BUILD_OPT_SSE3 - enables SSE3 optimizations
    • BL_BUILD_OPT_SSSE3 - enables SSSE3 optimizations
    • BL_BUILD_OPT_SSE4_1 - enables SSE4.1 optimizations
    • BL_BUILD_OPT_SSE4_2 - enables SSE4.2 optimizations
    • BL_BUILD_OPT_AVX - enables AVX optimizations
    • BL_BUILD_OPT_AVX2 - enables AVX2 optimizations

Compiler Specific Setup [GCC & Clang]

  • Use the following [optional] compiler flags to make the resulting binaries better:
    • -fvisibility=hidden - Blend2D API uses explicit public visibility so everything else should be hidden by default. Alternatively -fvisibility-inlines-hidden can be specified
    • -fno-exceptions - Blend2D doesn't use exceptions so you can turn them off
    • -fno-rtti - Blend2D doesn't use runtime type information or dynamic casts so you can turn this feature off
    • -fno-math-errno - Blend2D doesn't check errno after calling math functions, this option may help the C++ compiler to inline some intrinsic functions like sqrt
    • -fno-semantic-interposition - Better code generated as the compiler doesn't have to assume semantic interposition, GCC documentation , Clang uses this flag by default
    • -fno-threadsafe-statics - Blend2D has its own initialization step, which initializes everything required to make the library functional, thus thread-safe statics are not needed to guard initialization of static variables
    • -fmerge-all-constants - Blend2D doesn't compare pointers of constants so it's perfectly fine to merge constants having the same values
    • -ftree-vectorize - some compilers need this option to vectorize some constructs that Blend2D uses, however, this option would be probably set automatically at certain optimization levels by the compiler
    • -O2 or -O3 - it should be enough to use -O2 as -O3 often only increases code-size without increasing its performance
  • Each file with a certain suffix requires to be compiled with extra flags that enable architecture specific optimizations:
    • -msse2 must be used to compile *_sse2.cpp files if BL_BUILD_OPT_SSE2 was enabled
    • -msse3 must be used to compile *_sse3.cpp files if BL_BUILD_OPT_SSE3 was enabled
    • -mssse3 must be used to compile *_ssse3.cpp files if BL_BUILD_OPT_SSSE3 was enabled
    • -msse4.1 must be used to compile *_sse4_1.cpp files if BL_BUILD_OPT_SSE4_1 was enabled
    • -msse4.2 must be used to compile *_sse4_2.cpp files if BL_BUILD_OPT_SSE4_2 was enabled
    • -mavx must be used to compile *_avx.cpp files if BL_BUILD_OPT_AVX was enabled
    • -mavx2 must be used to compile *_avx2.cpp files if BL_BUILD_OPT_AVX2 was enabled

Compiler Specific Setup [MSVC]

  • Use the following [optional] compiler flags to make the resulting binaries better:
    • -O2 - favor performance over size
  • Each file with a certain suffix requires to be compiled with extra flags that enable architecture specific optimizations:
    • -arch:SSE2 and -D__SSE2__ must be used to compile *_sse2.cpp files if BL_BUILD_OPT_SSE2 was enabled
    • -arch:SSE2 and -D__SSE3__ must be used to compile *_sse3.cpp files if BL_BUILD_OPT_SSE3 was enabled
    • -arch:SSE2 and -D__SSSE3__ must be used to compile *_ssse3.cpp files if BL_BUILD_OPT_SSSE3 was enabled
    • -arch:SSE2 and -D__SSE4_1__ must be used to compile *_sse4_1.cpp files if BL_BUILD_OPT_SSE4_1 was enabled
    • -arch:SSE2 and -D__SSE4_2__ must be used to compile *_sse4_2.cpp files if BL_BUILD_OPT_SSE4_2 was enabled
    • -arch:AVX must be used to compile *_avx.cpp files if BL_BUILD_OPT_AVX was enabled
    • -arch:AVX2 must be used to compile *_avx2.cpp files if BL_BUILD_OPT_AVX2 was enabled
  • If you use LLVM toolchain, which meas that a clang-cl compiler is used instead of stock cl it's important to explicitly enable SSE3, SSSE3, SSE4.1, and SSE4.2 optimizations together with -arch:SSE2, otherwise the compilation would fail as Clang is not fully compatible with MS stock compiler:
    • -arch:SSE2 and -msse3 must be used to compile *_sse3.cpp files if BL_BUILD_OPT_SSE3 was enabled
    • -arch:SSE2 and -mssse3 must be used to compile *_ssse3.cpp files if BL_BUILD_OPT_SSSE3 was enabled
    • -arch:SSE2 and -msse4.1 must be used to compile *_sse4_1.cpp files if BL_BUILD_OPT_SSE4_1 was enabled
    • -arch:SSE2 and -msse4.2 must be used to compile *_sse4_2.cpp files if BL_BUILD_OPT_SSE4_2 was enabled

Linker Options

  • The following libraries are required on Windows:
    • (to be documented)
  • The following libraries are required on Linux, BSDs, and others:
    • libc (standard C library)
    • libm (if not part of standard C library)
    • libpthread (required to support multithreading)
    • librt (Required on Linux by clock_gettime() function)