aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authorShankho Boron Ghosh <shankhoghosh123@gmail.com>2020-11-25 22:33:01 +0530
committerJan-Simon Moeller <jsmoeller@linuxfoundation.org>2020-12-02 13:23:40 +0000
commit73d87cf88c657b4f7411d79b3ec9acc742f1ebef (patch)
treee462fc82d9fc0d457ffdbc324621e1ab49622429 /docs
parentfcbc9285aa3061dff9cb4cae5c69e59f274ef74f (diff)
Added SDK & Service guides
Revised Developer Guides with tutorials on installing the SDK and creating a new service from scratch. v2 : Removed trailing whitespaces. v3 : Removed duplicated output. Bug-AGL: [SPEC-3633] Signed-off-by: Shankho Boron Ghosh <shankhoghosh123@gmail.com> Change-Id: I5a1854f54f476ac69498956e4dd22fa4b6e85eee Reviewed-on: https://gerrit.automotivelinux.org/gerrit/c/AGL/documentation/+/25642 Reviewed-by: Jan-Simon Moeller <jsmoeller@linuxfoundation.org> Tested-by: Jan-Simon Moeller <jsmoeller@linuxfoundation.org>
Diffstat (limited to 'docs')
-rw-r--r--docs/3_Developer_Guides/1_Setting_Up_AGL_SDK.md52
-rw-r--r--docs/3_Developer_Guides/2_Creating_a_New_Service.md471
2 files changed, 523 insertions, 0 deletions
diff --git a/docs/3_Developer_Guides/1_Setting_Up_AGL_SDK.md b/docs/3_Developer_Guides/1_Setting_Up_AGL_SDK.md
new file mode 100644
index 0000000..c4ea431
--- /dev/null
+++ b/docs/3_Developer_Guides/1_Setting_Up_AGL_SDK.md
@@ -0,0 +1,52 @@
+---
+title: Setting Up AGL SDK
+---
+
+AGL provides a pre-built ready-made Software Development Kit (SDK) to help
+quickstart the service and application development process.
+
+1. Download the prebuilt SDK :
+
+ - **x86** : [qemux86-64](https://download.automotivelinux.org/AGL/snapshots/master/latest/qemux86-64/deploy/sdk/poky-agl-glibc-x86_64-agl-demo-platform-crosssdk-corei7-64-qemux86-64-toolchain-10.90.0+snapshot.sh)
+
+ - **ARM 32 bit** : [qemuarm](https://download.automotivelinux.org/AGL/snapshots/master/latest/qemuarm/deploy/sdk/poky-agl-glibc-x86_64-agl-demo-platform-crosssdk-armv7vet2hf-neon-vfpv4-qemuarm-toolchain-10.90.0+snapshot.sh)
+
+ - **AARCH64 - ARM 64bit** : [qemuarm64](https://download.automotivelinux.org/AGL/snapshots/master/latest/qemuarm64/deploy/sdk/poky-agl-glibc-x86_64-agl-demo-platform-crosssdk-aarch64-qemuarm64-toolchain-10.90.0+snapshot.sh)
+
+ *Henceforth,* **qemux86-64** *is used in these guides, unless specified
+ otherwise.*
+
+2. Create application developmment directory and copy SDK into them :
+
+ ```sh
+ $ mkdir ~/agl-app
+ $ cp ~/Downloads/poky-agl-glibc-x86_64-agl-demo-platform-crosssdk-corei7-64-qemux86-64-toolchain-10.90.0+snapshot.sh ~/agl-app/
+ $ cd ~/agl-app
+ ```
+
+3. Install the downloaded SDK :
+
+ ```sh
+ $ chmod 777 poky-agl-glibc-x86_64-agl-demo-platform-crosssdk-corei7-64-qemux86-64-toolchain-10.90.0+snapshot.sh
+ $ mkdir agl-sdk/
+ $ ./poky-agl-glibc-x86_64-agl-demo-platform-crosssdk-corei7-64-qemux86-64-toolchain-10.90.0+snapshot.sh
+ ```
+ Select target directory for SDK : `~/agl-app/agl-sdk`
+
+ ```sh
+ Automotive Grade Linux SDK installer version 10.90.0+snapshot
+ =============================================================
+ Enter target directory for SDK (default: /opt/agl-sdk/10.90.0+snapshot-corei7-64): ~/agl-app/agl-sdk
+ You are about to install the SDK to "/home/boron/agl-app/agl-sdk". Proceed [Y/n]? Y
+ Extracting SDK..........................................................................................................................................done
+ Setting it up...done
+ SDK has been successfully set up and is ready to be used.
+ Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g.
+ $ . /home/boron/agl-app/agl-sdk/environment-setup-corei7-64-agl-linux
+ ```
+
+4. Source the SDK environment setup, each time you wish to use the SDK in a new shell session :
+
+ ```sh
+ $ source ~/agl-app/agl-sdk/environment-setup-corei7-64-agl-linux
+ ``` \ No newline at end of file
diff --git a/docs/3_Developer_Guides/2_Creating_a_New_Service.md b/docs/3_Developer_Guides/2_Creating_a_New_Service.md
new file mode 100644
index 0000000..bbaa609
--- /dev/null
+++ b/docs/3_Developer_Guides/2_Creating_a_New_Service.md
@@ -0,0 +1,471 @@
+---
+title: Creating a New Service
+---
+
+This tutorial provides instructions on **Creating a New Service** from scratch.
+
+### 1. Create new project development directory
+
+ ```sh
+ $ cd ~/agl-app
+ $ mkdir newservice/
+ $ cd newservice/
+ ```
+
+### 2. Source the SDK environment setup
+
+ ```sh
+ $ source ~/agl-app/agl-sdk/environment-setup-corei7-64-agl-linux
+ ```
+
+### 3. Copy initial CMAKE configuration templates
+
+ ```sh
+ $ mkdir -p conf.d/cmake
+ $ cp ${OECORE_NATIVE_SYSROOT}/usr/share/doc/CMakeAfbTemplates/samples.d/config.cmake.sample conf.d/cmake/config.cmake
+ $ cp ${OECORE_NATIVE_SYSROOT}/usr/share/doc/CMakeAfbTemplates/samples.d/CMakeLists.txt.sample CMakeLists.txt
+ ```
+
+### 4. Edit CMAKE configuration template
+
+ ```sh
+ $ vim ~/agl-app/newservice/conf.d/cmake/config.cmake
+
+ ###########################################################################
+ # Copyright 2020 # INSERT YEAR
+ #
+ # author: John Doe <john.doe@example.com> # INSERT AUTHOR DETAILS
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+ ###########################################################################
+
+ # Project Info
+ # ------------------
+ set(PROJECT_NAME hellocount) # INSERT NEW PROJECT NAME
+ set(API_NAME hellocount) #INSERT NEW API NAME
+ set(PROJECT_PRETTY_NAME "Example")
+ set(PROJECT_DESCRIPTION "AGL hellocount application example") # INSERT CONCISE PROJECT DESCRIPTION
+ set(PROJECT_URL "https://gerrit.automotivelinux.org/gerrit/apps/cmake-apps-module")
+ set(PROJECT_ICON "icon.png")
+ set(PROJECT_AUTHOR "John Doe") # INSERT AUTHOR NAME
+ set(PROJECT_AUTHOR_MAIL "john.doe@example.com") # INSERT AUTHOR EMAIL
+ set(PROJECT_LICENSE "APL2.0")
+ set(PROJECT_LANGUAGES "C")
+ set(PROJECT_VERSION "1.0.0") # INSERT PROJECT VERSION
+
+ # Which directories inspect to find CMakeLists.txt target files
+ # set(PROJECT_SRC_DIR_PATTERN "*")
+
+ # Where are stored the project configuration files
+ # relative to the root project directory
+ set(PROJECT_CMAKE_CONF_DIR "conf.d")
+
+ # Compilation Mode (DEBUG, RELEASE, COVERAGE or PROFILING)
+ # ----------------------------------
+ set(BUILD_TYPE "RELEASE") # SELECT BUILD TYPE
+ #set(USE_EFENCE 1)
+
+ # Kernel selection if needed. You can choose between a
+ # mandatory version to impose a minimal version.
+ # Or check Kernel minimal version and just print a Warning
+ # about missing features and define a preprocessor variable
+ # to be used as preprocessor condition in code to disable
+ # incompatibles features. Preprocessor define is named
+ # KERNEL_MINIMAL_VERSION_OK.
+ #
+ # NOTE*** FOR NOW IT CHECKS KERNEL Yocto environment and
+ # Yocto SDK Kernel version.
+ # -----------------------------------------------
+ #set (kernel_mandatory_version 4.8)
+ #set (kernel_minimal_version 4.8)
+
+ # Compiler selection if needed. Impose a minimal version.
+ # -----------------------------------------------
+ set (gcc_minimal_version 4.9)
+
+ # PKG_CONFIG required packages
+ # -----------------------------
+ set (PKG_REQUIRED_LIST
+ json-c
+ afb-daemon
+ )
+
+ # You can also consider to include libsystemd
+ # -----------------------------------
+ #list (APPEND PKG_REQUIRED_LIST libsystemd>=222)
+
+ # Prefix path where will be installed the files
+ # Default: /usr/local (need root permission to write in)
+ # ------------------------------------------------------
+ #set(INSTALL_PREFIX /opt/AGL CACHE PATH "INSTALL PREFIX PATH")
+
+ # Customize link option
+ # -----------------------------
+ #list(APPEND link_libraries -an-option)
+
+ # Compilation options definition
+ # Use CMake generator expressions to specify only for a specific language
+ # Values are prefilled with default options that is currently used.
+ # Either separate options with ";", or each options must be quoted separately
+ # DO NOT PUT ALL OPTION QUOTED AT ONCE , COMPILATION COULD FAILED !
+ # ----------------------------------------------------------------------------
+ #set(COMPILE_OPTIONS
+ # -Wall
+ # -Wextra
+ # -Wconversion
+ # -Wno-unused-parameter
+ # -Wno-sign-compare
+ # -Wno-sign-conversion
+ # -Werror=maybe-uninitialized
+ # -Werror=implicit-function-declaration
+ # -ffunction-sections
+ # -fdata-sections
+ # -fPIC
+ # CACHE STRING "Compilation flags")
+ #set(C_COMPILE_OPTIONS "" CACHE STRING "Compilation flags for C language.")
+ #set(CXX_COMPILE_OPTIONS "" CACHE STRING "Compilation flags for C++ language.")
+ #set(PROFILING_COMPILE_OPTIONS
+ # -g
+ # -O0
+ # -pg
+ # -Wp,-U_FORTIFY_SOURCE
+ # CACHE STRING "Compilation flags for PROFILING build type.")
+ #set(DEBUG_COMPILE_OPTIONS
+ # -g
+ # -ggdb
+ # CACHE STRING "Compilation flags for DEBUG build type.")
+ #set(COVERAGE_COMPILE_OPTIONS
+ # -g
+ # -O0
+ # --coverage
+ # CACHE STRING "Compilation flags for COVERAGE build type.")
+ #set(RELEASE_COMPILE_OPTIONS
+ # -O2
+ # -pipe
+ # -D_FORTIFY_SOURCE=2
+ # -fstack-protector-strong
+ # -Wformat -Wformat-security
+ # -Werror=format-security
+ # -feliminate-unused-debug-types
+ # -Wl,-O1
+ # -Wl,--hash-style=gnu
+ # -Wl,--as-needed
+ # -fstack-protector-strong
+ # -Wl,-z,relro,-z,now
+ # CACHE STRING "Compilation flags for RELEASE build type.")
+
+ # Location for config.xml.in template file.
+ #
+ # If you keep them commented then it will build with a default minimal widget
+ # template which is very simple and it is highly probable that it will not suit
+ # to your app.
+ # -----------------------------------------
+ #set(WIDGET_ICON "conf.d/wgt/${PROJECT_ICON}" CACHE PATH "Path to the widget icon")
+ set(WIDGET_CONFIG_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/conf.d/wgt/config.xml.in" CACHE PATH "Path to widget config file template (config.xml.in)") # UNCOMMENT WIDGET_CONFIG_TEMPLATE
+ #set(TEST_WIDGET_CONFIG_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/conf.d/wgt/test-config.xml.in" CACHE PATH "Path to the test widget config file template (test-config.xml.in)")
+
+ # Mandatory widget Mimetype specification of the main unit
+ # --------------------------------------------------------------------------
+ # Choose between :
+ #- text/html : HTML application,
+ # content.src designates the home page of the application
+ #
+ #- application/vnd.agl.native : AGL compatible native,
+ # content.src designates the relative path of the binary.
+ #
+ # - application/vnd.agl.service: AGL service, content.src is not used.
+ #
+ #- ***application/x-executable***: Native application,
+ # content.src designates the relative path of the binary.
+ # For such application, only security setup is made.
+ #
+ set(WIDGET_TYPE application/vnd.agl.service) # UNCOMMENT WIDGET_TYPE
+
+ # Mandatory Widget entry point file of the main unit
+ # --------------------------------------------------------------
+ # This is the file that will be executed, loaded,
+ # at launch time by the application framework.
+ #
+ set(WIDGET_ENTRY_POINT lib/libhellocount.so) # UNCOMMENT WIDGET_ENTRY_POINT
+
+ # Optional dependencies order
+ # ---------------------------
+ #set(EXTRA_DEPENDENCIES_ORDER)
+
+ # Optional Extra global include path
+ # -----------------------------------
+ #set(EXTRA_INCLUDE_DIRS)
+
+ # Optional extra libraries
+ # -------------------------
+ #set(EXTRA_LINK_LIBRARIES)
+
+ # Optional force binding Linking flag
+ # ------------------------------------
+ # set(BINDINGS_LINK_FLAG LinkOptions )
+
+ # Optional force package prefix generation, like widget
+ # -----------------------------------------------------
+ # set(PKG_PREFIX DestinationPath)
+
+ # Optional Application Framework security token
+ # and port use for remote debugging.
+ #------------------------------------------------------------
+ #set(AFB_TOKEN "" CACHE PATH "Default binder security token") # COMMENT AFB_TOKEN
+ #set(AFB_REMPORT "1234" CACHE PATH "Default binder listening port") # COMMENT AFB_REMPORT
+
+ # Print a helper message when every thing is finished
+ # ----------------------------------------------------
+ set(CLOSING_MESSAGE "Typical binding launch: cd ${CMAKE_BINARY_DIR}/package \\&\\& afb-daemon --port=${AFB_REMPORT} --workdir=. --ldpaths=lib --roothttp=htdocs --token=\"${AFB_TOKEN}\" --tracereq=common --verbose")
+ set(PACKAGE_MESSAGE "Install widget file using in the target : afm-util install ${PROJECT_NAME}.wgt")
+
+ # Optional schema validator about now only XML, LUA and JSON
+ # are supported
+ #------------------------------------------------------------
+ #set(LUA_CHECKER "luac" "-p" CACHE STRING "LUA compiler")
+ #set(XML_CHECKER "xmllint" CACHE STRING "XML linter")
+ #set(JSON_CHECKER "json_verify" CACHE STRING "JSON linter")
+
+ include(CMakeAfbTemplates)
+ ```
+
+### 5. Copy WGT configuration template
+
+ ```sh
+ $ mkdir -p conf.d/wgt
+ $ cp ${OECORE_NATIVE_SYSROOT}/usr/share/doc/CMakeAfbTemplates/samples.d/config.xml.in.sample conf.d/wgt/config.xml.in
+ ```
+
+### 6. Run CMAKE and Generate autobuild
+
+ ```sh
+ $ mkdir build/
+ $ cd build/
+ $ cmake ..
+ $ make autobuild
+ ```
+
+### 7. Create service directory
+
+ ```sh
+ $ cd ..
+ $ mkdir service/
+ $ cd service/
+ ```
+ This `service` directory holds the C code & CMakeLists.txt ;
+
+ - Add `hellocount-service.c` file which contains the functional C code :
+
+ ```sh
+ $ vim hellocount-service.c
+
+ /*
+ * Copyright 2020 The Linux Foundation # INSERT YEAR & ORG
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ #define _GNU_SOURCE
+ #include <stdio.h>
+ #include <string.h>
+ #include <json-c/json.h>
+
+ #define AFB_BINDING_VERSION 3
+ #include <afb/afb-binding.h>
+
+ static void pingSample(afb_req_t request)
+ {
+ static int pingcount = 0;
+
+ afb_req_success_f(request, json_object_new_int(pingcount), "Ping count = %d", pingcount);
+
+ AFB_API_NOTICE(afbBindingV3root, "Verbosity macro at level notice invoked at ping invocation count = %d", pingcount);
+
+ pingcount++;
+ }
+
+ static void count(afb_req_t request)
+ {
+ static int counter = 0;
+
+ afb_req_success_f(request, json_object_new_int(counter), "Counter = %d", counter);
+
+ AFB_API_NOTICE(afbBindingV3root, "Verbosity macro at level notice invoked at count invocation count = %d", counter);
+
+ counter++;
+ }
+
+
+
+ static const afb_verb_t verbs[] =
+ {
+ /*Without security*/
+ {.verb = "ping", .session = AFB_SESSION_NONE, .callback = pingSample, .auth = NULL},
+ {.verb = "count", .session = AFB_SESSION_NONE, .callback = count, .auth = NULL},
+ {NULL}
+ };
+
+ const afb_binding_t afbBindingExport =
+ {
+ .api = "count",
+ .specification = "HelloCount API",
+ .verbs = verbs,
+ .preinit = NULL,
+ .init = NULL,
+ .onevent = NULL,
+ .userdata = NULL,
+ .provide_class = NULL,
+ .require_class = NULL,
+ .require_api = NULL,
+ .noconcurrency = 0
+ };
+ ```
+
+- Add `CMakeLists.txt` file :
+
+ ```sh
+ $ vim CMakeLists.txt
+
+ ###########################################################################
+ # Copyright 2020 The Linux Foundation # INSERT YEAR & ORG
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+ ###########################################################################
+
+ # Add target to project dependency list
+ PROJECT_TARGET_ADD(hellocount)
+ # Define project Targets
+ ADD_LIBRARY(${TARGET_NAME} MODULE hellocount-service.c)
+
+ # Binder exposes a unique public entry point
+ SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
+ PREFIX "afb-"
+ LABELS "BINDING"
+ OUTPUT_NAME ${TARGET_NAME}
+ )
+ ```
+
+### 8. Build and Package `wgt` using autobuild
+
+ ```sh
+ $ cd ..
+
+ $ ./autobuild/agl/autobuild build
+
+ make[1]: Entering directory '/home/boron/agl-app/newservice/build'
+ make[2]: Entering directory '/home/boron/agl-app/newservice/build'
+ make[3]: Entering directory '/home/boron/agl-app/newservice/build'
+ make[3]: Leaving directory '/home/boron/agl-app/newservice/build'
+ [100%] Built target autobuild
+ make[2]: Leaving directory '/home/boron/agl-app/newservice/build'
+ make[1]: Leaving directory '/home/boron/agl-app/newservice/build'
+
+ $ ./autobuild/agl/autobuild package
+
+ make[1]: Entering directory '/home/boron/agl-app/newservice/build'
+ make[2]: Entering directory '/home/boron/agl-app/newservice/build'
+ make[3]: Entering directory '/home/boron/agl-app/newservice/build'
+ make[3]: Leaving directory '/home/boron/agl-app/newservice/build'
+ [100%] Built target autobuild
+ make[2]: Leaving directory '/home/boron/agl-app/newservice/build'
+ make[1]: Leaving directory '/home/boron/agl-app/newservice/build'
+ make[1]: Entering directory '/home/boron/agl-app/newservice/build'
+ make[2]: Entering directory '/home/boron/agl-app/newservice/build'
+ make[3]: Entering directory '/home/boron/agl-app/newservice/build'
+ make[4]: Entering directory '/home/boron/agl-app/newservice/build'
+ Scanning dependencies of target prepare_package
+ make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
+ make[4]: Entering directory '/home/boron/agl-app/newservice/build'
+ [ 6%] Generating package
+ [ 12%] Generating package/bin
+ [ 18%] Generating package/etc
+ [ 25%] Generating package/lib
+ [ 31%] Generating package/htdocs
+ [ 37%] Generating package/var
+ make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
+ [ 37%] Built target prepare_package
+ make[4]: Entering directory '/home/boron/agl-app/newservice/build'
+ Scanning dependencies of target prepare_package_test
+ make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
+ make[4]: Entering directory '/home/boron/agl-app/newservice/build'
+ [ 43%] Generating package-test
+ [ 50%] Generating package-test/bin
+ [ 56%] Generating package-test/etc
+ [ 62%] Generating package-test/lib
+ [ 68%] Generating package-test/htdocs
+ [ 75%] Generating package-test/var
+ make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
+ [ 75%] Built target prepare_package_test
+ make[4]: Entering directory '/home/boron/agl-app/newservice/build'
+ Scanning dependencies of target populate
+ make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
+ [ 75%] Built target populate
+ make[4]: Entering directory '/home/boron/agl-app/newservice/build'
+ Scanning dependencies of target widget_files
+ make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
+ make[4]: Entering directory '/home/boron/agl-app/newservice/build'
+ [ 81%] Generating package/icon.png
+ [ 87%] Generating package/config.xml
+ make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
+ [ 93%] Built target widget_files
+ make[4]: Entering directory '/home/boron/agl-app/newservice/build'
+ Scanning dependencies of target widget
+ make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
+ make[4]: Entering directory '/home/boron/agl-app/newservice/build'
+ [100%] Generating hellocount.wgt
+ NOTICE: -- PACKING widget hellocount.wgt from directory /home/boron/agl-app/newservice/build/package
+ ++ Install widget file using in the target : afm-util install hellocount.wgt
+ make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
+ [100%] Built target widget
+ make[3]: Leaving directory '/home/boron/agl-app/newservice/build'
+ make[2]: Leaving directory '/home/boron/agl-app/newservice/build'
+ make[1]: Leaving directory '/home/boron/agl-app/newservice/build'
+ ```
+
+ - The `hellocount.wgt` file is packaged and available at `~/agl-app/newservice/build`.
+
+### 9. Install the service
+
+ - Local System :
+ ```sh
+ # Copy hellocount.wgt to remote AGL system
+ $ scp ~/agl-app/newservice/build/hellocount.wgt root@<ip-address>:/home/0/
+ ```
+
+ - Remote AGL System :
+ ```sh
+ # Install using the service using afm-util
+ $ afm-util install ./hellocount.wgt
+ # Reboot the system
+ $ reboot -f
+ ``` \ No newline at end of file