-
Notifications
You must be signed in to change notification settings - Fork 222
Cross compilation
Users always encounter some problems when using source code compilation. This article aims to introduce the cross-compilation process and some parameter descriptions.
Basic configuration and parameter configuration
# set the minimum version required by cmake. If the version of cmake used is lower than this version, an error will be reported
cmake_minimum_required(VERSION 3.12)
# declare the project name
project(neuron)
# open the test function of the current and subordinate directories
enable_testing()
# enable c language support
enable_language(C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# build type, available values Debug, Release, etc.
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
endif()
# CMake identifier for the target platform to build
if(NOT CMAKE_SYSTEM_NAME)
set(CMAKE_SYSTEM_NAME "Linux")
endif()
# disable alarms: =ON means disabled, =OFF means abled
if(NOT DISABLE_WERROR)
set(CMAKE_C_FLAGS "$ENV{CFLAGS} -Werror")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -g")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O1")
# disable asan: =ON means disabled, =OFF means abled
if(NOT DISABLE_ASAN)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -fsanitize=address")
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -fsanitize=address")
endif()
DISABLE_UT parameter, disables unit testing, =ON means disabled, =OFF means abled.
In addition to the configuration variables in the cmake.lists.txt document, .cmake files are also used to configure cmake. The CMAKE_TOOLCHAIN_FILE parameter is used to specify the path to the .cmake file.
# target system name
set(CMAKE_SYSTEM_NAME Linux)
# target platform architecture
set(COMPILER_PREFIX arm-linux-gnueabihf)
set(CMAKE_SYSTEM_PROCESSOR armv7l)
# library directory
set(LIBRARY_DIR /opt/externs/libs)
# language compiler
set(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++)
# The name of the archive tool for the static library
set(CMAKE_AR ${COMPILER_PREFIX}-ar)
set(CMAKE_LINKER ${COMPILER_PREFIX}-ld)
set(CMAKE_NM ${COMPILER_PREFIX}-nm)
set(CMAKE_OBJDUMP ${COMPILER_PREFIX}-objdump)
# static library randomization tool name
set(CMAKE_RANLIB ${COMPILER_PREFIX}-ranlib)
# The CMAKE_STAGING_PREFIX variable is used to specify the path to install to the host
set(CMAKE_STAGING_PREFIX ${LIBRARY_DIR}/${COMPILER_PREFIX})
# The CMAKE_PREFIX_PATH variable is used to specify the installation location where the files to be compiled are located
set(CMAKE_PREFIX_PATH ${CMAKE_STAGING_PREFIX})
include_directories(SYSTEM ${CMAKE_STAGING_PREFIX}/include)
include_directories(SYSTEM ${CMAKE_STAGING_PREFIX}/openssl/include)
# Specify the cross-compilation environment
set(CMAKE_FIND_ROOT_PATH ${CMAKE_STAGING_PREFIX})
# Never look for utility programs in the specified directory
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# Only look for library files in the specified directory
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
# Only look for header files in the specified directory
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
link_directories(${CMAKE_STAGING_PREFIX})
# The location of the dependency library file search is selected by the CMAKE_STAGING_PREFIX parameter
if (CMAKE_STAGING_PREFIX)
# When cross-compiling, specify the search path for header files
include_directories(${CMAKE_STAGING_PREFIX}/include)
# Add the library file directory that needs to be linked
link_directories(${CMAKE_STAGING_PREFIX}/lib)
else()
# When not cross-compiling, specify the search path for header files
include_directories(/usr/local/include)
link_directories(/usr/local/lib)
endif()
The CMAKE_STAGING_PREFIX parameter is configured in the .cmake file. The .cmake file is used to configure the variables and properties of cmake, for example arm-linux-gnueabihf.cmake is used to set the compiler for ARM platform.
Cross-compilation can be understood that under the current compilation platform, the compiled program can run on another target platform with a different architecture, but the compilation platform itself cannot run the program.
The cross-compilation chain is a complete set of tools formed by multiple sub-tools for compiling the program code of the cross-platform architecture. When the source file (.c) is specified, it will automatically call the unused subtools according to the compilation process, and automatically generate the executable file. The key point of the cross-compilation chain is the cross-compiler. Compilers of different platforms are used to generate executable programs that can run on the platform. The process example is as follows.
set(PERSIST_SOURCES
src/persist/persist.c
src/persist/json/persist_json_plugin.c)
set(NEURON_SOURCES
src/main.c
src/argparse.c
src/daemon.c
src/core/manager_internal.c
src/core/manager.c
src/core/subscribe.c
src/core/sub_msg.c
src/core/plugin_manager.c
src/core/node_manager.c
src/core/storage.c
src/adapter/storage.c
src/adapter/adapter.c
src/adapter/driver/cache.c
src/adapter/driver/driver.c
plugins/restful/handle.c
plugins/restful/license.c
plugins/restful/license_handle.c
plugins/restful/log_handle.c
plugins/restful/normal_handle.c
plugins/restful/rw_handle.c
plugins/restful/adapter_handle.c
plugins/restful/datatag_handle.c
plugins/restful/group_config_handle.c
plugins/restful/plugin_handle.c
plugins/restful/version_handle.c
plugins/restful/rest.c
plugins/restful/http.c
plugins/restful/proxy.c
plugins/restful/websocket.c
${PERSIST_SOURCES})
# Set the build path variable to the current path
set(CMAKE_BUILD_RPATH ./)
# Define the name of the executable file as neuron, compile the executable program
add_executable(neuron)
# Specify the source file, used with add_executable, to generate the dynamic link file from the source file NEURON_SOURCES into neuron.
target_sources(neuron PRIVATE ${NEURON_SOURCES})
# Add the header library path to neuron
target_include_directories(neuron PRIVATE include/neuron src plugins)
# Link the object file neuron with the library file
target_link_libraries(neuron dl neuron-base sqlite3 -lm)
Execute the following command to install the compiler for armv4 architecture.
$ sudo apt-get update
$ sudo apt-get install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf pkg-config libtool alien unzip
Before cross-compiling the source code, the user needs to cross-compile the dependent library used in the cross-compilation, so that the dependent library is consistent with the platform for cross-compilation. Create a new directory file to store installation files, such as install.
With the continuous updating of the code, the cross-compilation dependency library will also change. Please refer to install dependencies for details.
cmake general parameter description.
-
-D configures the parameters of cmake, the function is similar to set.
-
CMAKE_C_COMPILER , cross-compile macro variables, specify the compilation tool of c.
-
CMAKE_CXX_COMPILER , cross-compile macro variable, specify the compilation tool of c++.
-
CMAKE_STAGING_PREFIX , cross-compilation variable, specifies the path installed on the host.
-
CMAKE_PREFIX_PATH, a cross-compilation variable, specifies the installation location where the files to be compiled are located.
In the install directory, execute the following command to install the openssl dependency library.
$ echo "Installing openssl (1.1.1)"
$ git clone -b OpenSSL_1_1_1 https://github.com/openssl/openssl.git
$ cd openssl
$ sudo mkdir -p /opt/externs/libs/arm-linux-gnueabihf/openssl/ssl
$ ./Configure linux-armv4 no-asm shared --prefix=/opt/externs/libs/arm-linux-gnueabihf --openssldir=/opt/externs/libs/arm-linux-gnueabihf/openssl/ssl --cross-compile-prefix=arm-linux-gnueabihf-
$ make clean
$ make
$ sudo make install_sw
$ make clean
In the install directory, execute the following command to install the zlog dependent library.
$ git clone -b 1.2.15 https://github.com/HardySimpson/zlog.git
$ cd zlog
$ make CC=arm-linux-gnueabihf-gcc
$ sudo make PREFIX=/opt/externs/libs/arm-linux-gnueabihf install
In the install directory, execute the following command to install the jansson dependency library.
$ git clone https://github.com/neugates/jansson.git
$ cd jansson
$ mkdir build && cd build
$ cmake .. -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ -DCMAKE_STAGING_PREFIX=/opt/externs/libs/arm-linux-gnueabihf -DCMAKE_PREFIX_PATH=/opt/externs/libs/arm-linux-gnueabihf -DJANSSON_BUILD_DOCS=OFF -DJANSSON_EXAMPLES=OFF
$ make
$ sudo make install
In the install directory, execute the following command to install the nng dependency library.
$ git clone -b neuron https://github.com/neugates/NanoSDK.git
$ cd NanoSDK && mkdir build && cd build
$ cmake .. -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ -DCMAKE_STAGING_PREFIX=/opt/externs/libs/arm-linux-gnueabihf -DCMAKE_PREFIX_PATH=/opt/externs/libs/arm-linux-gnueabihf -DBUILD_SHARED_LIBS=OFF -DNNG_TESTS=OFF -DNNG_ENABLE_SQLITE=ON -DNNG_ENABLE_TLS=ON
$ make
$ sudo make install
In the install directory, execute the following command to install the jwt dependency library.
$ git clone -b v1.13.1 https://github.com/benmcollins/libjwt.git
$ cd libjwt
$ mkdir build && cd build
$ cmake .. -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ -DCMAKE_STAGING_PREFIX=/opt/externs/libs/arm-linux-gnueabihf -DCMAKE_PREFIX_PATH=/opt/externs/libs/arm-linux-gnueabihf -DENABLE_PIC=ON -DBUILD_SHARED_LIBS=OFF
$ make
$ sudo make install
In the install directory, execute the following command to install the mbedtls dependency library.
$ git clone -b v2.16.12 https://github.com/Mbed-TLS/mbedtls.git
$ cd mbedtls && mkdir build && cd build
$ cmake .. -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ -DCMAKE_STAGING_PREFIX=/opt/externs/libs/arm-linux-gnueabihf -DCMAKE_PREFIX_PATH=/opt/externs/libs/arm-linux-gnueabihf -DBUILD_SHARED_LIBS=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=OFF -DENABLE_TESTING=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON
$ make
$ sudo make install
In the install directory, execute the following command to install the googletest dependency library.
$ git clone -b release-1.11.0 https://github.com/google/googletest.git
$ cd googletest && mkdir build && cd build
$ cmake .. -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ -DCMAKE_STAGING_PREFIX=/opt/externs/libs/arm-linux-gnueabihf -DCMAKE_PREFIX_PATH=/opt/externs/libs/arm-linux-gnueabihf -DBUILD_SHARED_LIBS=OFF
$ make
$ sudo make install
In the install directory, execute the following command to install the sqlite3 dependency library.
$ curl https://www.sqlite.org/2022/sqlite-autoconf-3390000.tar.gz --output sqlite3.tar.gz
$ mkdir -p sqlite3
$ tar xzf sqlite3.tar.gz --strip-components=1 -C sqlite3
$ cd sqlite3
$ ./configure --prefix=/opt/externs/libs/arm-linux-gnueabihf --disable-shared --disable-readline --host armv4 CC=arm-linux-gnueabihf-gcc
$ make
$ sudo make install
For cross-compilation of dependent libraries, please refer to https://github.com/emqx/neuron/blob/main/install.sh.
Execute the following command to download the source code and cross-compile.
$ git clone https://github.com/emqx/neuron
$ cd neuron
$ git submodule update --init
$ mkdir build && cd build
$ cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/arm-linux-gnueabihf.cmake -DCMAKE_BUILD_TYPE=Release -DDISABLE_UT=ON
$ make