Using CMake with the GCC RX/LLVM RL78/GCC RL78 toolchains

From GNU Tools - Wiki
Jump to: navigation, search

1. Introduction

CMake is a cross-platform, free and open-source tool for build automation, testing, packaging and installation of software.

By using platform and compiler independent configuration files, it allows developers to support the compilation process of their tools on multiple platforms.

This guide aims to provide a short overview on how to use CMake together with the GCC RX/LLVM RL78/GCC RL78 toolchains.


2. Overview

Since our target is the RL78/RX microcontroller and we are building on Windows, the following steps are necessary for this cross-compilation scenario:

• creation of a toolchain file (.cmake), since CMake cannot guess the assembler, compiler, linker and their respective option settings
• creation of a CMake configuration file (CMakeLists.txt), which describes the project structure and how the final executable should be produced
• execution of CMake with the previously created configuration files, to generate the Makefile
• execution of make, to build the project

3. Prerequisites

• Renesas compilers for LLVM RL78/GCC RX/GCC RL78: https://llvm-gcc-renesas.com/
• CMake latest release: https://cmake.org/download/
• GNU Make for windows e.g GnuWin32: http://gnuwin32.sourceforge.net/packages/make.htm

Note: Please make sure that the environment variables are correctly set for the installed tools.

4. Project structure and configuration files

Create a project with the following structure:

• project/
  ○ include/
     ∎ foo.h
     ∎ MyClass.h
  ○ src/
     ∎ bar.c
     ∎ Main.cpp
     ∎ MyClass.cpp
  ○ CMakeLists.txt
  ○ cross.cmake

include/foo.h

 #ifdef __cplusplus
 extern "C" {
 #endif
 int bar();
 #ifdef __cplusplus
 }
 #endif

include/MyClass.h

class MyClass {
     public:
        MyClass(int num) : myNum(num) {}
        int process();
     private:
        int myNum;
};

src/bar.c

 #include "foo.h"
 int a = 13;
 int bar() { return a; }

src/Main.cpp

#include "MyClass.h"
#include "foo.h"
     int main() {
        MyClass b(3);
        if (b.process() + bar() != 22)
        return 1;
        return 0;
}

src/MyClass.cpp

#include "MyClass.h"
      int MyClass::process() {
      return this->myNum * 3;
}

4.1 Toolchain file

Example toolchain file for GCC RX:

 set(CMAKE_SYSTEM_NAME Generic)
 set(CMAKE_SYSTEM_PROCESSOR GCCRX)
 set(CMAKE_FIND_ROOT_PATH "{Replace with toolchain install location}/rx-elf/rx-elf/bin")
 set(CMAKE_C_COMPILER ${CMAKE_FIND_ROOT_PATH}/rx-elf-gcc.exe)
 set(CMAKE_CXX_COMPILER ${CMAKE_FIND_ROOT_PATH}/rx-elf-gcc.exe)
 set(CMAKE_SYSROOT ${sysroot_target})
 set(CMAKE_C_OBJCOPY ${CMAKE_FIND_ROOT_PATH}/rx-elf-objcopy.exe)
 set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
 set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
 set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
 set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

Example toolchain file for LLVM RL78:

 set(CMAKE_SYSTEM_NAME Generic)
 set(CMAKE_SYSTEM_PROCESSOR LLVMRL78)
 set(CMAKE_FIND_ROOT_PATH "{Replace with toolchain install location}/bin")
 set(CMAKE_C_COMPILER ${CMAKE_FIND_ROOT_PATH}/clang.exe)
 set(CMAKE_CXX_COMPILER ${CMAKE_FIND_ROOT_PATH}/clang++.exe)
 set(CMAKE_SYSROOT ${sysroot_target})
 set(CMAKE_C_OBJCOPY ${CMAKE_FIND_ROOT_PATH}/llvm-objcopy.exe)
 set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
 set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
 set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
 set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

Example toolchain file for GCC RL78:

 set(CMAKE_SYSTEM_NAME Generic)
 set(CMAKE_SYSTEM_PROCESSOR GCCRL78)
 set(CMAKE_FIND_ROOT_PATH "{Replace with toolchain install location}/bin")
 set(CMAKE_C_COMPILER ${CMAKE_FIND_ROOT_PATH}/rl78-elf-gcc.exe)
 set(CMAKE_CXX_COMPILER ${CMAKE_FIND_ROOT_PATH}/rl78-elf-gcc.exe)
 set(CMAKE_SYSROOT ${sysroot_target})
 set(CMAKE_C_OBJCOPY ${CMAKE_FIND_ROOT_PATH}/rl78-elf-objcopy.exe)
 set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
 set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
 set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
 set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

4.2 Configuration file

Project configuration example for GCC RX:

 cmake_minimum_required(VERSION 3.16.4)
 project(Project VERSION 1.0.0)
 enable_language(C ASM)
 file(GLOB_RECURSE Source_Files "${CMAKE_CURRENT_SOURCE_DIR}/src/*.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
 include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
 SET(CMAKE_ASM_FLAGS "-g2 -mcpu=rx100 -misa=v1 -mlittle-endian-data")
 SET(CMAKE_C_FLAGS "${CMAKE_ASM_FLAGS} -ffunction-sections -fdata-sections -fdiagnostics-parseable-fixits -Wstack-usage=100")
 SET(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS})
 SET(CMAKE_EXE_LINKER_FLAGS "-msim -Wl,-Map=${PROJECT_NAME}.map")
 add_executable(${PROJECT_NAME}.elf ${Source_Files})
 add_custom_target(${PROJECT_NAME}.bin ALL DEPENDS ${PROJECT_NAME}.elf)
 add_custom_command(TARGET ${PROJECT_NAME}.bin
 COMMAND ${CMAKE_C_OBJCOPY} ARGS -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin)

Project configuration example for LLVM RL78 or GCC RL78:

 cmake_minimum_required(VERSION 3.16.4) 
 project(Project VERSION 1.0.0)
 enable_language(C ASM)
 file(GLOB_RECURSE Source_Files "${CMAKE_CURRENT_SOURCE_DIR}/src/*.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp" )
 include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
 SET(CMAKE_ASM_FLAGS "-g -mcpu=s3")
 SET(CMAKE_C_FLAGS "${CMAKE_ASM_FLAGS} -ffunction-sections -fdata-sections")
 SET(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS})
 SET(CMAKE_EXE_LINKER_FLAGS "-fsim -Wl,-Map=${PROJECT_NAME}.map")
 add_executable(${PROJECT_NAME}.elf ${Source_Files})
 add_custom_target(${PROJECT_NAME}.bin ALL DEPENDS ${PROJECT_NAME}.elf)
 add_custom_command(TARGET ${PROJECT_NAME}.bin
 COMMAND ${CMAKE_C_OBJCOPY} ARGS -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin)

5. Project build

5.1 Build file generation

We have to tell CMake which target generator we want to use (via -G option) and that we are cross-compiling (by specifying the toolchain file via option -DCMAKE_TOOLCHAIN_FILE).

 >cd project
 >cmake -H. -Bbuild -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=cross.cmake

Executing this command results in the creation of the project/build folder, which contains the build system specific configuration files.

5.2 Build execution

After CMake successfully generates the native build files, GNU Make needs to be executed to build the project:

 >cd build
 >make all

If the build was successful, the linked executable can be found in the project/build folder.