2 title: Creating a New Service
5 This tutorial provides instructions on **Creating a New Service** from scratch.
7 ### 1. Create new project development directory
15 ### 2. Source the SDK environment setup
18 $ source ~/agl-app/agl-sdk/environment-setup-corei7-64-agl-linux
21 ### 3. Copy initial CMAKE configuration templates
24 $ mkdir -p conf.d/cmake
25 $ cp ${OECORE_NATIVE_SYSROOT}/usr/share/doc/CMakeAfbTemplates/samples.d/config.cmake.sample conf.d/cmake/config.cmake
26 $ cp ${OECORE_NATIVE_SYSROOT}/usr/share/doc/CMakeAfbTemplates/samples.d/CMakeLists.txt.sample CMakeLists.txt
29 ### 4. Edit CMAKE configuration template
32 $ vim ~/agl-app/newservice/conf.d/cmake/config.cmake
34 ###########################################################################
35 # Copyright 2020 # INSERT YEAR
37 # author: John Doe <john.doe@example.com> # INSERT AUTHOR DETAILS
39 # Licensed under the Apache License, Version 2.0 (the "License");
40 # you may not use this file except in compliance with the License.
41 # You may obtain a copy of the License at
43 # http://www.apache.org/licenses/LICENSE-2.0
45 # Unless required by applicable law or agreed to in writing, software
46 # distributed under the License is distributed on an "AS IS" BASIS,
47 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
48 # See the License for the specific language governing permissions and
49 # limitations under the License.
50 ###########################################################################
54 set(PROJECT_NAME hellocount) # INSERT NEW PROJECT NAME
55 set(API_NAME "hellocount") #INSERT NEW API NAME
56 set(PROJECT_PRETTY_NAME "Example")
57 set(PROJECT_DESCRIPTION "AGL hellocount application example") # INSERT CONCISE PROJECT DESCRIPTION
58 set(PROJECT_URL "https://gerrit.automotivelinux.org/gerrit/apps/cmake-apps-module")
59 set(PROJECT_ICON "icon.png")
60 set(PROJECT_AUTHOR "John Doe") # INSERT AUTHOR NAME
61 set(PROJECT_AUTHOR_MAIL "john.doe@example.com") # INSERT AUTHOR EMAIL
62 set(PROJECT_LICENSE "APL2.0")
63 set(PROJECT_LANGUAGES "C")
64 set(PROJECT_VERSION "1.0.0") # INSERT PROJECT VERSION
66 # Which directories inspect to find CMakeLists.txt target files
67 # set(PROJECT_SRC_DIR_PATTERN "*")
69 # Where are stored the project configuration files
70 # relative to the root project directory
71 set(PROJECT_CMAKE_CONF_DIR "conf.d/cmake")
73 # Compilation Mode (DEBUG, RELEASE, COVERAGE or PROFILING)
74 # ----------------------------------
75 set(BUILD_TYPE "RELEASE") # SELECT BUILD TYPE
78 # Kernel selection if needed. You can choose between a
79 # mandatory version to impose a minimal version.
80 # Or check Kernel minimal version and just print a Warning
81 # about missing features and define a preprocessor variable
82 # to be used as preprocessor condition in code to disable
83 # incompatibles features. Preprocessor define is named
84 # KERNEL_MINIMAL_VERSION_OK.
86 # NOTE*** FOR NOW IT CHECKS KERNEL Yocto environment and
87 # Yocto SDK Kernel version.
88 # -----------------------------------------------
89 #set (kernel_mandatory_version 4.8)
90 #set (kernel_minimal_version 4.8)
92 # Compiler selection if needed. Impose a minimal version.
93 # -----------------------------------------------
94 set (gcc_minimal_version 4.9)
96 # PKG_CONFIG required packages
97 # -----------------------------
98 set (PKG_REQUIRED_LIST
104 # You can also consider to include libsystemd
105 # -----------------------------------
106 #list (APPEND PKG_REQUIRED_LIST libsystemd>=222)
108 if(IS_DIRECTORY $ENV{HOME}/opt/afb-monitoring)
109 set(MONITORING_ALIAS "--alias=/monitoring:$ENV{HOME}/opt/afb-monitoring")
112 # Print a helper message when every thing is finished
113 # ----------------------------------------------------
114 set(CLOSING_MESSAGE "Debug from afb-daemon --port=1234 ${MONITORING_ALIAS} --ldpaths=package --workdir=. --roothttp=../htdocs --token= --verbose ")
115 set(PACKAGE_MESSAGE "Install widget file using in the target : afm-util install ${PROJECT_NAME}.wgt")
119 # Prefix path where will be installed the files
120 # Default: /usr/local (need root permission to write in)
121 # ------------------------------------------------------
122 #set(INSTALL_PREFIX /opt/AGL CACHE PATH "INSTALL PREFIX PATH")
124 # Customize link option
125 # -----------------------------
126 #list(APPEND link_libraries -an-option)
128 # Compilation options definition
129 # Use CMake generator expressions to specify only for a specific language
130 # Values are prefilled with default options that is currently used.
131 # Either separate options with ";", or each options must be quoted separately
132 # DO NOT PUT ALL OPTION QUOTED AT ONCE , COMPILATION COULD FAILED !
133 # ----------------------------------------------------------------------------
138 # -Wno-unused-parameter
140 # -Wno-sign-conversion
141 # -Werror=maybe-uninitialized
142 # -Werror=implicit-function-declaration
143 # -ffunction-sections
146 # CACHE STRING "Compilation flags")
147 #set(C_COMPILE_OPTIONS "" CACHE STRING "Compilation flags for C language.")
148 #set(CXX_COMPILE_OPTIONS "" CACHE STRING "Compilation flags for C++ language.")
149 #set(PROFILING_COMPILE_OPTIONS
153 # -Wp,-U_FORTIFY_SOURCE
154 # CACHE STRING "Compilation flags for PROFILING build type.")
155 #set(DEBUG_COMPILE_OPTIONS
158 # CACHE STRING "Compilation flags for DEBUG build type.")
159 #set(COVERAGE_COMPILE_OPTIONS
163 # CACHE STRING "Compilation flags for COVERAGE build type.")
164 #set(RELEASE_COMPILE_OPTIONS
167 # -D_FORTIFY_SOURCE=2
168 # -fstack-protector-strong
169 # -Wformat -Wformat-security
170 # -Werror=format-security
171 # -feliminate-unused-debug-types
173 # -Wl,--hash-style=gnu
175 # -fstack-protector-strong
176 # -Wl,-z,relro,-z,now
177 # CACHE STRING "Compilation flags for RELEASE build type.")
179 # (BUG!!!) as PKG_CONFIG_PATH does not work [should be an env variable]
180 # ---------------------------------------------------------------------
181 set(INSTALL_PREFIX $ENV{HOME}/opt)
182 set(CMAKE_PREFIX_PATH ${CMAKE_INSTALL_PREFIX}/lib64/pkgconfig ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig)
183 set(LD_LIBRARY_PATH ${CMAKE_INSTALL_PREFIX}/lib64 ${CMAKE_INSTALL_PREFIX}/lib)
185 # Location for config.xml.in template file.
187 # If you keep them commented then it will build with a default minimal widget
188 # template which is very simple and it is highly probable that it will not suit
190 # -----------------------------------------
191 #set(WIDGET_ICON "conf.d/wgt/${PROJECT_ICON}" CACHE PATH "Path to the widget icon")
192 set(WIDGET_ICON ${PROJECT_APP_TEMPLATES_DIR}/wgt/${PROJECT_ICON})
193 set(WIDGET_CONFIG_TEMPLATE ${CMAKE_SOURCE_DIR}/conf.d/wgt/config.xml.in CACHE PATH "Path to widget config file template (config.xml.in)") # UNCOMMENT WIDGET_CONFIG_TEMPLATE
194 #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)")
196 # Mandatory widget Mimetype specification of the main unit
197 # --------------------------------------------------------------------------
199 #- text/html : HTML application,
200 # content.src designates the home page of the application
202 #- application/vnd.agl.native : AGL compatible native,
203 # content.src designates the relative path of the binary.
205 # - application/vnd.agl.service: AGL service, content.src is not used.
207 #- ***application/x-executable***: Native application,
208 # content.src designates the relative path of the binary.
209 # For such application, only security setup is made.
211 set(WIDGET_TYPE application/vnd.agl.service) # UNCOMMENT WIDGET_TYPE
213 # Mandatory Widget entry point file of the main unit
214 # --------------------------------------------------------------
215 # This is the file that will be executed, loaded,
216 # at launch time by the application framework.
218 set(WIDGET_ENTRY_POINT config.xml) # UNCOMMENT WIDGET_ENTRY_POINT
220 # Optional dependencies order
221 # ---------------------------
222 #set(EXTRA_DEPENDENCIES_ORDER)
224 # Optional Extra global include path
225 # -----------------------------------
226 #set(EXTRA_INCLUDE_DIRS)
228 # Optional extra libraries
229 # -------------------------
230 #set(EXTRA_LINK_LIBRARIES)
232 # Optional force binding Linking flag
233 # ------------------------------------
234 # set(BINDINGS_LINK_FLAG LinkOptions )
236 # Optional force package prefix generation, like widget
237 # -----------------------------------------------------
238 # set(PKG_PREFIX DestinationPath)
240 # Optional Application Framework security token
241 # and port use for remote debugging.
242 #------------------------------------------------------------
243 #set(AFB_TOKEN "" CACHE PATH "Default binder security token") # COMMENT AFB_TOKEN
244 #set(AFB_REMPORT "1234" CACHE PATH "Default binder listening port") # COMMENT AFB_REMPORT
246 # Optional schema validator about now only XML, LUA and JSON
248 #------------------------------------------------------------
249 #set(LUA_CHECKER "luac" "-p" CACHE STRING "LUA compiler")
250 #set(XML_CHECKER "xmllint" CACHE STRING "XML linter")
251 #set(JSON_CHECKER "json_verify" CACHE STRING "JSON linter")
253 include(CMakeAfbTemplates)
256 ### 5. Copy WGT configuration template
259 $ mkdir -p conf.d/wgt
260 $ cp ${OECORE_NATIVE_SYSROOT}/usr/share/doc/CMakeAfbTemplates/samples.d/config.xml.in.sample conf.d/wgt/config.xml.in
262 - Edit `config.xml` file
264 $ vim conf.d/wgt/config.xml.in
266 <?xml version="1.0" encoding="UTF-8"?>
267 <widget xmlns="http://www.w3.org/ns/widgets" id="@PROJECT_NAME@" version="@PROJECT_VERSION@">
268 <name>@PROJECT_NAME@</name>
269 <icon src="@PROJECT_ICON@"/>
270 <content src="@WIDGET_ENTRY_POINT@" type="@WIDGET_TYPE@"/>
271 <description>@PROJECT_DESCRIPTION@</description>
272 <author>@PROJECT_AUTHOR@ <@PROJECT_AUTHOR_MAIL@></author>
273 <license>@PROJECT_LICENSE@</license>
274 <feature name="urn:AGL:widget:required-permission">
275 <param name="urn:AGL:permission::partner:scope-platform" value="required" />
277 <feature name="urn:AGL:widget:provided-api">
278 <param name="hellocount" value="ws" />
280 <feature name="urn:AGL:widget:required-binding">
281 <param name="lib/afb-hellocount.so" value="local" />
288 ### 6. Run CMAKE and Generate autobuild
297 ### 7. Create service directory
304 This `service` directory holds the C code & CMakeLists.txt ;
306 - Add `hellocount-service.c` file which contains the functional C code :
309 $ vim hellocount-service.c
312 * Copyright 2020 The Linux Foundation # INSERT YEAR & ORG
314 * Licensed under the Apache License, Version 2.0 (the "License");
315 * you may not use this file except in compliance with the License.
316 * You may obtain a copy of the License at
318 * http://www.apache.org/licenses/LICENSE-2.0
320 * Unless required by applicable law or agreed to in writing, software
321 * distributed under the License is distributed on an "AS IS" BASIS,
322 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
323 * See the License for the specific language governing permissions and
324 * limitations under the License.
330 #include <json-c/json.h>
332 #define AFB_BINDING_VERSION 3
333 #include <afb/afb-binding.h>
335 static void pingSample(afb_req_t request)
337 static int pingcount = 0;
339 afb_req_success_f(request, json_object_new_int(pingcount), "Ping count = %d", pingcount);
341 AFB_API_NOTICE(afbBindingV3root, "Verbosity macro at level notice invoked at ping invocation count = %d", pingcount);
346 static void count(afb_req_t request)
348 static int counter = 0;
350 afb_req_success_f(request, json_object_new_int(counter), "Counter = %d", counter);
352 AFB_API_NOTICE(afbBindingV3root, "Verbosity macro at level notice invoked at count invocation count = %d", counter);
359 static const afb_verb_t verbs[] =
362 {.verb = "ping", .session = AFB_SESSION_NONE, .callback = pingSample, .auth = NULL},
363 {.verb = "count", .session = AFB_SESSION_NONE, .callback = count, .auth = NULL},
367 const afb_binding_t afbBindingExport =
370 .specification = "HelloCount API",
376 .provide_class = NULL,
377 .require_class = NULL,
383 - Add `CMakeLists.txt` file :
388 ###########################################################################
389 # Copyright 2020 The Linux Foundation # INSERT YEAR & ORG
391 # Licensed under the Apache License, Version 2.0 (the "License");
392 # you may not use this file except in compliance with the License.
393 # You may obtain a copy of the License at
395 # http://www.apache.org/licenses/LICENSE-2.0
397 # Unless required by applicable law or agreed to in writing, software
398 # distributed under the License is distributed on an "AS IS" BASIS,
399 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
400 # See the License for the specific language governing permissions and
401 # limitations under the License.
402 ###########################################################################
404 # Add target to project dependency list
405 PROJECT_TARGET_ADD(hellocount)
406 # Define project Targets
407 ADD_LIBRARY(${TARGET_NAME} MODULE hellocount-service.c)
409 # Binder exposes a unique public entry point
410 SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
413 OUTPUT_NAME ${TARGET_NAME}
417 ### 8. Build and Package `wgt` using autobuild
422 $ ./autobuild/agl/autobuild build
424 make[1]: Entering directory '/home/boron/agl-app/newservice/build'
425 make[2]: Entering directory '/home/boron/agl-app/newservice/build'
426 make[3]: Entering directory '/home/boron/agl-app/newservice/build'
427 make[3]: Leaving directory '/home/boron/agl-app/newservice/build'
428 [100%] Built target autobuild
429 make[2]: Leaving directory '/home/boron/agl-app/newservice/build'
430 make[1]: Leaving directory '/home/boron/agl-app/newservice/build'
432 $ ./autobuild/agl/autobuild package
434 make[1]: Entering directory '/home/boron/agl-app/newservice/build'
435 make[2]: Entering directory '/home/boron/agl-app/newservice/build'
436 make[3]: Entering directory '/home/boron/agl-app/newservice/build'
437 make[3]: Leaving directory '/home/boron/agl-app/newservice/build'
438 [100%] Built target autobuild
439 make[2]: Leaving directory '/home/boron/agl-app/newservice/build'
440 make[1]: Leaving directory '/home/boron/agl-app/newservice/build'
441 make[1]: Entering directory '/home/boron/agl-app/newservice/build'
442 make[2]: Entering directory '/home/boron/agl-app/newservice/build'
443 make[3]: Entering directory '/home/boron/agl-app/newservice/build'
444 make[4]: Entering directory '/home/boron/agl-app/newservice/build'
445 Scanning dependencies of target prepare_package
446 make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
447 make[4]: Entering directory '/home/boron/agl-app/newservice/build'
448 [ 6%] Generating package
449 [ 12%] Generating package/bin
450 [ 18%] Generating package/etc
451 [ 25%] Generating package/lib
452 [ 31%] Generating package/htdocs
453 [ 37%] Generating package/var
454 make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
455 [ 37%] Built target prepare_package
456 make[4]: Entering directory '/home/boron/agl-app/newservice/build'
457 Scanning dependencies of target prepare_package_test
458 make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
459 make[4]: Entering directory '/home/boron/agl-app/newservice/build'
460 [ 43%] Generating package-test
461 [ 50%] Generating package-test/bin
462 [ 56%] Generating package-test/etc
463 [ 62%] Generating package-test/lib
464 [ 68%] Generating package-test/htdocs
465 [ 75%] Generating package-test/var
466 make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
467 [ 75%] Built target prepare_package_test
468 make[4]: Entering directory '/home/boron/agl-app/newservice/build'
469 Scanning dependencies of target populate
470 make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
471 [ 75%] Built target populate
472 make[4]: Entering directory '/home/boron/agl-app/newservice/build'
473 Scanning dependencies of target widget_files
474 make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
475 make[4]: Entering directory '/home/boron/agl-app/newservice/build'
476 [ 81%] Generating package/icon.png
477 [ 87%] Generating package/config.xml
478 make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
479 [ 93%] Built target widget_files
480 make[4]: Entering directory '/home/boron/agl-app/newservice/build'
481 Scanning dependencies of target widget
482 make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
483 make[4]: Entering directory '/home/boron/agl-app/newservice/build'
484 [100%] Generating hellocount.wgt
485 NOTICE: -- PACKING widget hellocount.wgt from directory /home/boron/agl-app/newservice/build/package
486 ++ Install widget file using in the target : afm-util install hellocount.wgt
487 make[4]: Leaving directory '/home/boron/agl-app/newservice/build'
488 [100%] Built target widget
489 make[3]: Leaving directory '/home/boron/agl-app/newservice/build'
490 make[2]: Leaving directory '/home/boron/agl-app/newservice/build'
491 make[1]: Leaving directory '/home/boron/agl-app/newservice/build'
494 - The `hellocount.wgt` file is packaged and available at `~/agl-app/newservice/build`.
496 ### 9. Install the service
500 # Copy hellocount.wgt to remote AGL system
501 $ scp ~/agl-app/newservice/build/hellocount.wgt root@<ip-address>:/home/0/
504 - Remote AGL System :
506 # Install using the service using afm-util
507 $ afm-util install ./hellocount.wgt