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 interested 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:

  • Linux (tested on CI).
  • BSDs (FreeBSD, NetBSD, OpenBSD tested on CI).
  • MacOS (tested on CI).
  • Windows 7+ (Windows 10+ tested on CI).
  • Other operating systems may or may not work (nothing else tested on CI).

CPU architectures supported:

  • X86 - Both 32-bit and 64-bit targets are supported
  • ARM - Reference pipelines only (reference pipelines currently don't provide ASIMD/NEON acceleration)
  • Other - Not accelerated, using reference pipelines written in C++

C++ compilers recommended:

  • Clang 8+ with C++11 support enabled (Clang 10+ tested on CI)
  • GCC 5.0+ with C++11 support enabled (GCC 7.0+ tested on CI)
  • MSVC 2019+ (VS-2019 and VS-2022 tested on CI)

Important

It's strongly advised to use latest compilers to compile Blend2D on all platforms to achieve maximum performance. Many floating point computations that are implemented in C++ can be auto-vectorized, so a capable compiler can make a significant difference.

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 CMake 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 auto-detect 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 (ASAN), memory (MSAN), thread (TSAN), undefined (UBSAN):
  • This option is only useful for Blend2D developers and individuals that want to run instrumented Blend2D or their own code that uses Blend2D
  • All sanitizers are already used by CI in addition to valgrind
  • Sanitizer-enabled builds are slower, but can discover issues that would not be discovered by regular debug or release builds
  • memory sanitizer (MSAN) must be used with BLEND2D_NO_JIT option enabled, because the JIT code is not instrumented. If MSAN is used with JIT enabled it would report a lot of issues such as reading an uninitialized value, however, such uninitialized values were most likely written by JIT pipelines. We recommend using valgrind instead, which works with JIT compilers very well
BLEND2D_SANITIZE_OPTS (unset) Additional sanitizer options to pass to the C++ compiler
BLEND2D_NO_FUTEX false Disables using futexes (this is only useful for testing or as a workaround to disable Futexes in case that there is a bug in Blend2D)
BLEND2D_NO_INTRINSICS false Disables the use of non-SIMD intrinsics in Blend2D (there is no reason to explicitly turn on this option, it's only useful for testing)
BLEND2D_NO_INSTALL false If true Blend2D won't install blend2d library and public header files. Useful in cases in which Blend2D is compiled statically as a part of another project, which has install targets, but installing Blend2D is unwanted
BLEND2D_NO_JIT false (auto-detected) Disables JIT compiler and AsmJit dependency (experimental, not recommended for production as portable pipelines are slower than JIT pipelines)
BLEND2D_NO_JIT_LOGGING false Disables JIT compiler logging feature. This option can be used to make Blend2D a little bit smaller as it would compile AsmJit without logging feature and Blend2D would have this feature disabled as well. We do not recommend using this option as it doesn't save that much space and sometimes JIT logging can be beneficial when solving problems. Note that JIT logging must be explicitly turned on by the application that uses Blend2D, it's never enabled by default
BLEND2D_NO_NATVIS false Disables embedding blend2d.natvis file in Blend2D binary
BLEND2D_NO_STDCXX (auto-detected) Disables linking to a C++ standard library. This option is auto-detected - dynamically linked Blend2D library would not link to a standard C++ library by default
BLEND2D_NO_TLS false Disables the use of thread-local storage (there is no reason to explicitly turn on this option unless you are having issues with TLS or your target is operating system that has a very limited size of TLS)

Building From Source

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

# Get Blend2D and optional dependencies.
$ git clone https://github.com/blend2d/blend2d
$ git clone https://github.com/asmjit/asmjit blend2d/3rdparty/asmjit

# 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 Blend2D and optional dependencies.
$ git clone https://github.com/blend2d/blend2d
$ git clone https://github.com/asmjit/asmjit blend2d/3rdparty/asmjit

# Get Blend2D interactive demos and a benchmarking tool.
$ git clone https://github.com/blend2d/blend2d-apps

# Build blend2d-apps - will try to auto-detect Cairo and Qt.
$ mkdir blend2d-apps/build
$ cd blend2d-apps/build
$ cmake .. -DCMAKE_BUILD_TYPE=Release
$ cmake --build .
$ cd ..

# 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 to build.

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:

Compile-Time Definition Description
NDEBUGShould be always defined for release builds (standard C/C++ macro)
BL_BUILD_DEBUGForces debug build, overrides auto-detection based on NDEBUG (optional)
BL_BUILD_RELEASEForce release build, overrides auto-detection based on NDEBUG (optional)

Define the following compile-time definitions to enable architecture-specific optimizations:

Compile-Time Definition Description
BL_BUILD_OPT_SSE2Enables SSE2 optimizations (always enabled on X86 targets)
BL_BUILD_OPT_SSE3Enables SSE3 optimizations
BL_BUILD_OPT_SSSE3Enables SSSE3 optimizations
BL_BUILD_OPT_SSE4_1Enables SSE4.1 optimizations
BL_BUILD_OPT_SSE4_2Enables SSE4.2 optimizations
BL_BUILD_OPT_AVXEnables AVX optimizations
BL_BUILD_OPT_AVX2Enables AVX2 optimizations
BL_BUILD_OPT_AVX512Enables AVX512_[F|BW|DQ|CD] optimizations

Please note that BL_BUILD_OPT_XXX compile-time definitions just tell Blend2D to build support for the optimizations, but to not rely on the presence of the extensions. Blend2D would use these optimizations if the CPU extension(s) required to use them were detected at run-time.

Compiler Specific Setup - GCC & Clang

Use the following [optional] compiler flags to make the resulting binaries better:

Compiler flag Description
-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 option 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 Blend2D may benefit from auto-vectorization, if not done automatically by the C++ compiler. Recent GCC and Clang enable it automatically at -O2 level
-O2 or -O3 It should be enough to use -O2 as -O3 often only increases code-size without increasing its performance

Additionally, each file with a certain suffix requires to be compiled with extra flags that enable architecture specific optimizations:

Compile Flag(s) File Suffix Description
-msse2 *_sse2.cpp Must be used if BL_BUILD_OPT_SSE2 was enabled
-msse3 *_sse3.cpp Must be used if BL_BUILD_OPT_SSE3 was enabled
-mssse3 *_ssse3.cpp Must be used if BL_BUILD_OPT_SSSE3 was enabled
-msse4.1 *_sse4_1.cpp Must be used if BL_BUILD_OPT_SSE4_1 was enabled
-msse4.2 *_sse4_2.cpp Must be used if BL_BUILD_OPT_SSE4_2 was enabled
-mavx *_avx.cpp Must be used if BL_BUILD_OPT_AVX was enabled
-mavx2 *_avx2.cpp Must be used if BL_BUILD_OPT_AVX2 was enabled
-mavx512f -mavx512bw -mavx512dq -mavx512cd -mavx512vl *_avx512.cpp Must be used if BL_BUILD_OPT_AVX512 was enabled

Compiler Specific Setup - MSVC

Use the following [optional] compiler flags to make the resulting binaries better:

Compile Flag(s) Description
-O2 Favor performance over size

Each file with a certain suffix requires to be compiled with extra flags that enable architecture specific optimizations:

Compile Flag(s) File Suffix Description
-arch:SSE2 -D__SSE2__ *_sse2.cpp Must be used if BL_BUILD_OPT_SSE2 was enabled
-arch:SSE2 -D__SSE3__ *_sse3.cpp Must be used if BL_BUILD_OPT_SSE3 was enabled
-arch:SSE2 -D__SSSE3__ *_ssse3.cpp Must be used if BL_BUILD_OPT_SSSE3 was enabled
-arch:SSE2 -D__SSE4_1__ *_sse4_1.cpp Must be used if BL_BUILD_OPT_SSE4_1 was enabled
-arch:SSE2 -D__SSE4_2__ *_sse4_2.cpp Must be used if BL_BUILD_OPT_SSE4_2 was enabled
-arch:AVX *_avx.cpp Must be used if BL_BUILD_OPT_AVX was enabled
-arch:AVX2 *_avx2.cpp Must be used if BL_BUILD_OPT_AVX2 was enabled
-arch:AVX512 *_avx512.cpp Must be used if BL_BUILD_OPT_AVX512 was enabled

If you use LLVM toolchain, which meas that a clang-cl compiler is used instead of the 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 100% compatible with MS stock compiler in this area:

Compile Flag(s) File Suffix Description
-arch:SSE2 *_sse2.cpp Must be used if BL_BUILD_OPT_SSE2 was enabled
-arch:SSE2 -msse3 *_sse3.cpp Must be used if BL_BUILD_OPT_SSE3 was enabled
-arch:SSE2 -mssse3 *_ssse3.cpp Must be used if BL_BUILD_OPT_SSSE3 was enabled
-arch:SSE2 -msse4.1 *_sse4_1.cpp Must be used if BL_BUILD_OPT_SSE4_1 was enabled
-arch:SSE2 -msse4.2 *_sse4_2.cpp Must be used 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 (if not part of standard C library)
  • librt (Required on Linux by clock_gettime() function)