Skip to content

Cross Compiling for Synology NAS with CMake

Background

Synology DS218j

Synology DS218j 1

Few years ago, I purchased a Synology DS218j as a file server in my local area network. As I'm adding more and more IoT devices to build smart home, I need to have a server that runs 24/7 to cooridinate all the IoT devices and my Synology NAS becomes one of the good choices. However, given it's an entry level model, the Synology DS218j lacks the support to run Docker on its DSM operating system. On the other hand, the DSM operating system at least provides some support for Node.js, Python, Perl and PHP.

As a developer who wants to interact with the kernel and fully exploit the performance provided by its Marvell Armada 385 88F6820 CPU and DDR3 512MB RAM, it would be nice to build native programs for it to run with C / C++. To achquire the toolchain needed for cross compiling, we can go the Synology website below and use their provided toolchain. The toolchain are grouped based on target platform and DSM version.

Synology Toolchain Download Page Synology Toolchain Download Page

Synology Toolchain Download Page

Integration with CMake

Consider the following project structure:

wtz@7600x:/data/synology$ tree -L 2
.
├── CMakeLists.txt
├── src
│   └── hello.cpp
└── toolchain
    └── synology.cmake
src/hello.cpp
#include <iostream>

int main() {
    std::cout << "hello" << std::endl;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)

project(synology CXX)
set(CMAKE_CXX_STANDARD 17)

add_executable(hello "src/hello.cpp")

To cross-compile this program, we first need to download the toolchain and set up the toolchain file for CMake.

cd toolchain/
wget "https://global.synologydownload.com/download/ToolChain/toolchain/7.2-72746/Marvell%20Armada%2038x%20Linux%203.10.108/armada38x-gcc1220_glibc236_hard-GPL.txz"
tar -xf armada38x-gcc1220_glibc236_hard-GPL.txz
cd -
toolchain/synology.cmake
cmake_minimum_required(VERSION 3.10)

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR armv7)

set(TOOLCHAIN_ROOT "${CMAKE_SOURCE_DIR}/toolchain/arm-unknown-linux-gnueabi")
set(TOOLCHAIN_PREFIX "bin/arm-unknown-linux-gnueabi-")

set(CMAKE_C_COMPILER   "${TOOLCHAIN_ROOT}/${TOOLCHAIN_PREFIX}gcc")
set(CMAKE_CXX_COMPILER "${TOOLCHAIN_ROOT}/${TOOLCHAIN_PREFIX}g++")

set(CMAKE_FIND_ROOT_PATH "${TOOLCHAIN_ROOT}/arm-unknown-linux-gnueabi/sysroot")

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

After setting up all these files, we can then start the cross compile process.

mkdir build
cd build/
cmake .. -DCMAKE_TOOLCHAIN_FILE=../toolchain/synology.cmake
make

If we check the output executable, we can see it has been compiled as an ARM executable.

wtz@7600x:/data/synology/build$ file hello 
hello: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, with debug_info, not stripped

This is very basic example on how to cross-compile for Synology NAS. Given that a project may contain many dependencies, and all these dependencies also need to be cross-compiled, it may become a better choice to use a software repository for embedded devices like Entware and add your own project as a package there in order to reuse some of the depencencies that already have been cross-compiled to the target platform.