🌐 English

    Building#

    Oasis application development and building are primarily conducted on a host PC (such as x86_64 Ubuntu).

    Since Oasis is modularly structured by component, applications are built using only the specific component libraries they require.

    If the processor of the target device where the Oasis application will run differs from the host PC's processor or lacks binary compatibility, cross-compilation is performed.

    This section explains how to build using a Makefile and how to build using CMake.

    It is assumed that the target device processor is aarch64 and the GCC cross-toolchain is installed at /opt/vtcs_toolchain/leipzig on the host PC.

    The Oasis SDK is assumed to be located in the following directories on the host PC:

    • Libraries: /opt/oasis/sdk-4.3.29/lib
    • Header Files: /opt/oasis/sdk-4.3.29/include

    hello.cpp#

    The following code (hello.cpp) is an application code provided to demonstrate the build process.

    Once the build is complete, the Oasis application named hello will be generated.

    #include "OasisAPI.h"
    #include "OasisLog.h"
    #include "OasisUI.h"
    #include "OasisUtil.h"
    #include "OasisDisplay.h"
    
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <dirent.h>
    
    #include <thread>
    #include <mutex>
    #include <memory>
    #include <condition_variable>
    
    
    #undef DLOG_TAG
    #define DLOG_TAG "Hello"
    
    
    using namespace oasis;
    
    bool got_interrupt = false;
    
    #include <signal.h>
    
    // SIGINT handler. Terminates the program.
    void cancel_handler(int sig)
    {
      got_interrupt = true;
    }
    
    // Function called when the "Capture Me!" button is clicked. Captures the screen and saves it to /tmp.
    void captureMeClicked(ui::WidgetRef widget)
    {
      ui::ScreenRef screen = ui::getDefaultScreen();
    
      std::vector<uint8_t> png_data;
      char image_path[PATH_MAX];
      time_t t;
      struct tm tm_t;
      time(&t);
      localtime_r(&t, &tm_t);    
    
      sprintf(image_path, "/tmp/snapshot_%4d-%02d-%02d-%02d-%02d-%02d.png", tm_t.tm_year + 1900, tm_t.tm_mon + 1, tm_t.tm_mday, tm_t.tm_hour, tm_t.tm_min, tm_t.tm_sec);
      if(ui::takeScreenShot(screen, png_data) > 0) {
        printf("saved to %s\n", image_path);
        writeFile(png_data.data(), png_data.size(), image_path);
      }
    }
    
    // Function called when the "Goodbye!" button is clicked. Terminates the program.
    void goodbyeClicked(ui::WidgetRef widget)
    {
      got_interrupt = true;
    }
    
    int main(int argc, char *argv[])
    {
      int32_t err;
    
      signal(SIGINT, cancel_handler);
    
      oasis::key_value_map_t parameters;
    
      // Initializes Oasis. Disables the Oasis file system.
      parameters["offs-disable"] = "1";
      if(oasis::initialize(parameters) < 0) {
        DLOG(DLOG_ERROR, "Oasis init failed\n");
        return -1;
      }
    
    
      // Initializes the display device.
      parameters.clear();
    
      parameters["memory-type"] = "ion"; // cma
      parameters["screen-width"] = "480";
      parameters["screen-height"] = "320";
    
      display::setup(parameters);
    
      // Initializes the GUI.
      parameters.clear();
    
      parameters["system-font-size"] = "11";
      parameters["system-font-path"] = "/mnt/sd/NanumGothicCoding.ttf";
      parameters["display-rotation"] = "0";
      parameters["enable-touch"] = "1";
      parameters["touch-cal-data-path"] = "/mnt/sd/cal.dat";
    
      err = ui::setup(parameters);
      if (err < 0) {
        DLOG(DLOG_ERROR, "Oasis ui::setup failed\n");
        oasis::finalize();
        return -1;
      }
    
      // Obtains the default screen object.
      ui::ScreenRef screen = ui::getDefaultScreen();
    
      // Creates the top-level Window. It is hidden upon creation.
      ui::WindowRef window = ui::createWindow("Hello");
    
      // Creates a vertical Box layout object inside the top-level Window.
      ui::BoxRef vbox = ui::createBox(ui::kOrientationVertical, false, 6);
      // Ensures the Box layout is centered after being added to the Window.
      ui::setVAlign(vbox, ui::kAlignCenter);
    
      // Creates Labels 1, 2, and 3, and adds each to the Box layout.
      ui::LabelRef label = ui::createLabelWithText("Hello, World!");
      ui::setVAlign(label, ui::kAlignCenter);
      ui::setHAlign(label, ui::kAlignCenter);
      ui::setLabelHorzJustification(label, ui::kJustificationCenter);
      ui::setLabelVertJustification(label, ui::kJustificationCenter);
      ui::setLabelFontPointSize(label, 16);
    
      ui::boxPackStart(vbox, label, true, true, 0);
    
      ui::LabelRef label2 = ui::createLabelWithText("μ•ˆλ…•ν•˜μ„Έμš”!");
      ui::setVAlign(label2, ui::kAlignCenter);
      ui::setHAlign(label2, ui::kAlignCenter);
      ui::setLabelHorzJustification(label2, ui::kJustificationCenter);
      ui::setLabelVertJustification(label2, ui::kJustificationCenter);
      ui::setLabelFontPointSize(label2, 13);
    
      ui::boxPackStart(vbox, label2, true, true, 0);
    
      ui::LabelRef label3 = ui::createLabelWithText("こんにけは!");
      ui::setVAlign(label3, ui::kAlignCenter);
      ui::setHAlign(label3, ui::kAlignCenter);
      ui::setLabelHorzJustification(label3, ui::kJustificationCenter);
      ui::setLabelVertJustification(label3, ui::kJustificationCenter);
      ui::setLabelFontPointSize(label3, 13);
    
      ui::boxPackStart(vbox, label3, true, true, 0);
    
      // Creates the "Goodbye!" button and adds it starting from the end of the Box layout.
      ui::ButtonRef close_button = ui::createButtonWithLabel("Goodbye!", true);
      ui::setID(close_button, "close_button");
      ui::setLabelFontPointSize(ui::getButtonLabel(close_button), 13);
      ui::setLabelTextColor(ui::getButtonLabel(close_button), Color(255, COLOR_YELLOW));
      ui::setVAlign(close_button, ui::kAlignCenter);
      ui::setHAlign(close_button, ui::kAlignCenter);
      ui::boxPackEnd(vbox, close_button, false, true, 0);
    
      // Creates the "Capture Me!" button and adds it starting from the end of the Box layout.
      ui::ButtonRef capture_button = ui::createButtonWithLabel("Capture Me!", true);
      ui::setID(capture_button, "capture_me_button");
      ui::setLabelFontPointSize(ui::getButtonLabel(capture_button), 13);
      ui::setLabelTextColor(ui::getButtonLabel(capture_button), Color(255, COLOR_YELLOW));
      ui::setVAlign(capture_button, ui::kAlignCenter);
      ui::setHAlign(capture_button, ui::kAlignCenter);
      ui::boxPackEnd(vbox, capture_button, false, true, 20);
    
      // Connects the callback function for the "Capture Me!" button click event.
      ui::connectSignal(capture_button, "clicked", clicked_slot_t(sig::ptr_fn(&captureMeClicked)), 0);
    
      // Connects the callback function for the "Goodbye!" button click event.
      ui::connectSignal(close_button, "clicked", clicked_slot_t(sig::ptr_fn(&goodbyeClicked)), 0);
    
      // Adds the Box layout to the top-level Window.
      ui::containerAdd(window, vbox);
      // Adds the Window to the screen.
      ui::screenAdd(screen, window);
    
      // Makes the top-level Window visible.
      ui::setVisible(window, true);
    
      // Keeps the main thread waiting until a termination signal is received.
      do {
        usleep(100000);
      } while(got_interrupt == false);
    
      // Releases the GUI.
      err = ui::cleanup();
    
      // Releases Oasis.
      oasis::finalize();
    
      return 0;
    }
    

    Building with a Makefile#

    1. Create a Makefile with the following content in the source directory containing hello.cpp.

      # Set up the cross-toolchain environment.
      CROSS_COMPILER_PREFIX = aarch64-linux-
      EXTERNAL_TOOLCHAIN_ROOT = /opt/vtcs_toolchain/leipzig/usr/
      EXTERNAL_TOOLCHAIN_PATH = $(EXTERNAL_TOOLCHAIN_ROOT)bin/
      SYSROOT = $(EXTERNAL_TOOLCHAIN_ROOT)/aarch64-buildroot-linux-gnu/sysroot
      
      CC = $(EXTERNAL_TOOLCHAIN_PATH)$(CROSS_COMPILER_PREFIX)gcc
      CXX = $(EXTERNAL_TOOLCHAIN_PATH)$(CROSS_COMPILER_PREFIX)g++
      LD = $(EXTERNAL_TOOLCHAIN_PATH)$(CROSS_COMPILER_PREFIX)ld
      AR = $(EXTERNAL_TOOLCHAIN_PATH)$(CROSS_COMPILER_PREFIX)ar
      
      # Set up the Oasis SDK environment.
      OASIS_SDK_ROOT = /opt/oasis/sdk-4.3.29/
      OASIS_INC_PATH = $(OASIS_SDK_ROOT)/include
      OASIS_LIB_PATH = $(OASIS_SDK_ROOT)/lib
      OASIS_LIBS = -loasis_codec -loasis_fs -loasis_pipe -loasis_media -loasis_ui -loasis_util -loasis_certs -loasis_disp -loasis
      OASIS_DEFS = -DOASIS_NO_NVWA
      
      # Configure the target.
      TARGET = hello
      SRCS = hello.cpp
      OBJS = $(SRCS:.cpp=.o)
      
      CXXFLAGS += -I$(OASIS_INC_PATH) --sysroot=$(SYSROOT)
      LDFLAGS += -s -L$(OASIS_LIB_PATH) $(OASIS_LIBS)
      
      CXXFLAGS += -std=c++17 -O2 -g $(OASIS_DEFS)
      
      # Configure other dependent libraries.
      LIBS = -lexif -lpng16 -ljpeg -lfreetype -lz -ljsoncpp -lrt -lpthread -lcva -lvmf_nnm -lvmf -lvdec -lutil -liniparser
      
      .PHONY: all clean
      
      all: $(TARGET)
      
      $(TARGET): $(OBJS)
        $(CXX) $(LDFLAGS) $^ $(LIBS) -o $@
      
      %.o: %.cpp
        $(CXX) $(CXXFLAGS) -c $< -o $@
      
      clean:
        rm -f $(OBJS) $(TARGET)
      
    2. Build the application inside the source directory using the make command.

      $ make
      $ ls -l
      total 1144
      -rwxrwxr-x 1 cobenhan cobenhan  133176  Mar 14 00:59 hello
      -rw-rw-r-- 1 cobenhan cobenhan    5121  Mar 14 00:43 hello.cpp
      -rw-rw-r-- 1 cobenhan cobenhan 1023288  Mar 14 00:59 hello.o
      -rw-rw-r-- 1 cobenhan cobenhan    1446  Mar 14 00:59 Makefile
      

    Building with CMake#

    1. Create a toolchain.cmake file with the following content in the source directory containing hello.cpp.

      # this one is important
      SET(CMAKE_SYSTEM_NAME Linux)
      #this one not so much
      SET(CMAKE_SYSTEM_VERSION 1)
      SET(CMAKE_SYSTEM_PROCESSOR aarch64)
      
      SET(EXTERNAL_TOOLCHAIN_ROOT /opt/vtcs_toolchain/leipzig/usr/)
      SET(EXTERNAL_TOOLCHAIN_PATH ${EXTERNAL_TOOLCHAIN_ROOT}/bin)
      SET(CROSS_COMPILER_PREFIX aarch64-linux-)
      
      # specify the cross compiler
      SET(CMAKE_C_COMPILER   /opt/vtcs_toolchain/leipzig/usr/bin/aarch64-linux-gcc)
      SET(CMAKE_CXX_COMPILER ${EXTERNAL_TOOLCHAIN_PATH}/aarch64-linux-g++)
      SET(CMAKE_AR_COMPILER ${EXTERNAL_TOOLCHAIN_PATH}/aarch64-linux-ar)
      SET(CMAKE_STRIP_COMPILER ${EXTERNAL_TOOLCHAIN_PATH}/aarch64-linux-strip)
      SET(CMAKE_SYSROOT ${EXTERNAL_TOOLCHAIN_ROOT}/aarch64-buildroot-linux-gnu/sysroot)
      
      # where is the target environment 
      SET(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${EXTERNAL_TOOLCHAIN_ROOT})
      SET(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${EXTERNAL_TOOLCHAIN_ROOT}/aarch64-buildroot-linux-gnu)
      SET(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${EXTERNAL_TOOLCHAIN_ROOT}/aarch64-buildroot-linux-gnu/sysroot/lib)
      
      # search for programs in the build host directories
      SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
      # for libraries and headers in the target directories
      SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
      SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
      
      # SET(TOOLSDIR /opt/vtcs_toolchain/leipzig)
      
      SET(CMAKE_ASM_COMPILER   ${EXTERNAL_TOOLCHAIN_PATH}/${CROSS_COMPILER_PREFIX}gcc)
      # Override ar and ranlib tools that CMake should use for linking lib
      SET(CMAKE_AR             ${EXTERNAL_TOOLCHAIN_PATH}/${CROSS_COMPILER_PREFIX}ar      CACHE STRING "")
      SET(CMAKE_RANLIB        ${EXTERNAL_TOOLCHAIN_PATH}/${CROSS_COMPILER_PREFIX}ranlib  CACHE STRING "")
      
    2. Create a CMakeLists.txt file with the following content in the source directory containing hello.cpp.

      cmake_minimum_required (VERSION 3.5.1)
      
      project (Hello)
      
      # Configure the Oasis SDK environment.
      include_directories(SYSTEM "/opt/oasis/sdk-4.3.29/include")
      #-Wl,-rpath,path1:path2:path3...
      link_directories(/opt/oasis/sdk-4.3.29/lib)
      add_definitions(-DOASIS_NO_NVWA -DOFFS_NO_NVWA)
      
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O2 -g")
      # strip
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s")
      
      # Configure the target.
      add_executable(hello hello.cpp)
      
      target_link_libraries(hello oasis_codec oasis_fs oasis_pipe oasis_media oasis_ui oasis_util oasis_certs oasis_disp oasis)
      
      target_link_libraries(hello cva vmf_nnm vmf vdec util iniparser)
      target_link_libraries(hello exif png16 jpeg freetype z jsoncpp)
      target_link_libraries(hello rt pthread)
      
    3. Proceed with the build as follows:

      $ mkdir build
      $ ls -l
      total 20
      drwxrwxr-x 3 cobenhan cobenhan 4096  Mar 14 01:46 build
      -rw-rw-r-- 1 cobenhan cobenhan  751  Mar 14 01:44 CMakeLists.txt
      -rw-rw-r-- 1 cobenhan cobenhan 5121  Mar 14 00:43 hello.cpp
      -rwxrwxr-x 1 cobenhan cobenhan 1679  Dec 11 16:27 toolchain.cmake
      $ cd build
      build$ cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake ..
      build$ make
      build$ ls -l
      total 164
      -rw-rw-r-- 1 cobenhan cobenhan  14549  Mar 14 01:46 CMakeCache.txt
      drwxrwxr-x 6 cobenhan cobenhan   4096  Mar 14 01:46 CMakeFiles
      -rw-rw-r-- 1 cobenhan cobenhan   1716  Mar 14 01:46 cmake_install.cmake
      -rwxrwxr-x 1 cobenhan cobenhan 133176  Mar 14 01:46 hello
      -rw-rw-r-- 1 cobenhan cobenhan   5246  Mar 14 01:46 Makefile
      

    Execution Result#

    Following the build, install the application on the target device by referring to the Installation guide.

    Below is the captured image generated by touching the Capture Me! button after running the application on the target device.

    Hello

    Download Example