ce9a74529f8b340c54d05cfedda31f9530bf575f
[AGL/documentation.git] / docs / 3_Developer_Guides / 2_Creating_a_New_Service.md
1 ---
2 title: Creating a New Service
3 ---
4
5 This tutorial provides instructions on **Creating a New Service** from scratch.
6
7 ### 1. Create new project development directory
8
9    ```sh
10    $ cd ~/agl-app
11    $ mkdir newservice/
12    $ cd newservice/
13    ```
14
15 ### 2. Source the SDK environment setup
16
17   ```sh
18   $ source ~/agl-app/agl-sdk/environment-setup-corei7-64-agl-linux
19   ```
20
21 ### 3. Copy initial CMAKE configuration templates
22
23   ```sh
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
27   ```
28
29 ### 4. Edit CMAKE configuration template
30
31   ```sh
32   $ vim ~/agl-app/newservice/conf.d/cmake/config.cmake
33
34     ###########################################################################
35     # Copyright 2020 # INSERT YEAR
36     #
37     # author: John Doe <john.doe@example.com> # INSERT AUTHOR DETAILS
38     #
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
42     #
43     #     http://www.apache.org/licenses/LICENSE-2.0
44     #
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     ###########################################################################
51
52     # Project Info
53     # ------------------
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
65
66     # Which directories inspect to find CMakeLists.txt target files
67     # set(PROJECT_SRC_DIR_PATTERN "*")
68
69     # Where are stored the project configuration files
70     # relative to the root project directory
71     set(PROJECT_CMAKE_CONF_DIR "conf.d/cmake")
72
73     # Compilation Mode (DEBUG, RELEASE, COVERAGE or PROFILING)
74     # ----------------------------------
75     set(BUILD_TYPE "RELEASE") # SELECT BUILD TYPE
76     #set(USE_EFENCE 1)
77
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.
85     #
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)
91
92     # Compiler selection if needed. Impose a minimal version.
93     # -----------------------------------------------
94     set (gcc_minimal_version 4.9)
95
96     # PKG_CONFIG required packages
97     # -----------------------------
98     set (PKG_REQUIRED_LIST
99       json-c
100       afb-daemon
101       afb-helpers
102     )
103
104     # You can also consider to include libsystemd
105     # -----------------------------------
106     #list (APPEND PKG_REQUIRED_LIST libsystemd>=222)
107
108     if(IS_DIRECTORY $ENV{HOME}/opt/afb-monitoring)
109     set(MONITORING_ALIAS "--alias=/monitoring:$ENV{HOME}/opt/afb-monitoring")
110     endif()
111
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")
116
117
118
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")
123
124     # Customize link option
125     # -----------------------------
126     #list(APPEND link_libraries -an-option)
127
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     # ----------------------------------------------------------------------------
134     #set(COMPILE_OPTIONS
135     # -Wall
136     # -Wextra
137     # -Wconversion
138     # -Wno-unused-parameter
139     # -Wno-sign-compare
140     # -Wno-sign-conversion
141     # -Werror=maybe-uninitialized
142     # -Werror=implicit-function-declaration
143     # -ffunction-sections
144     # -fdata-sections
145     # -fPIC
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
150     # -g
151     # -O0
152     # -pg
153     # -Wp,-U_FORTIFY_SOURCE
154     # CACHE STRING "Compilation flags for PROFILING build type.")
155     #set(DEBUG_COMPILE_OPTIONS
156     # -g
157     # -ggdb
158     # CACHE STRING "Compilation flags for DEBUG build type.")
159     #set(COVERAGE_COMPILE_OPTIONS
160     # -g
161     # -O0
162     # --coverage
163     # CACHE STRING "Compilation flags for COVERAGE build type.")
164     #set(RELEASE_COMPILE_OPTIONS
165     # -O2
166     # -pipe
167     # -D_FORTIFY_SOURCE=2
168     # -fstack-protector-strong
169     # -Wformat -Wformat-security
170     # -Werror=format-security
171     # -feliminate-unused-debug-types
172     # -Wl,-O1
173     # -Wl,--hash-style=gnu
174     # -Wl,--as-needed
175     # -fstack-protector-strong
176     # -Wl,-z,relro,-z,now
177     # CACHE STRING "Compilation flags for RELEASE build type.")
178
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)
184
185     # Location for config.xml.in template file.
186     #
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
189     # to your app.
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)")
195
196     # Mandatory widget Mimetype specification of the main unit
197     # --------------------------------------------------------------------------
198     # Choose between :
199     #- text/html : HTML application,
200     #   content.src designates the home page of the application
201     #
202     #- application/vnd.agl.native : AGL compatible native,
203     #   content.src designates the relative path of the binary.
204     #
205     # - application/vnd.agl.service: AGL service, content.src is not used.
206     #
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.
210     #
211     set(WIDGET_TYPE application/vnd.agl.service)    # UNCOMMENT WIDGET_TYPE
212
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.
217     #
218     set(WIDGET_ENTRY_POINT config.xml)    # UNCOMMENT WIDGET_ENTRY_POINT
219
220     # Optional dependencies order
221     # ---------------------------
222     #set(EXTRA_DEPENDENCIES_ORDER)
223
224     # Optional Extra global include path
225     # -----------------------------------
226     #set(EXTRA_INCLUDE_DIRS)
227
228     # Optional extra libraries
229     # -------------------------
230     #set(EXTRA_LINK_LIBRARIES)
231
232     # Optional force binding Linking flag
233     # ------------------------------------
234     # set(BINDINGS_LINK_FLAG LinkOptions )
235
236     # Optional force package prefix generation, like widget
237     # -----------------------------------------------------
238     # set(PKG_PREFIX DestinationPath)
239
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
245
246     # Optional schema validator about now only XML, LUA and JSON
247     # are supported
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")
252
253     include(CMakeAfbTemplates)
254   ```
255
256 ### 5. Copy WGT configuration template
257
258   ```sh
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
261   ```
262   - Edit `config.xml` file
263     ```sh
264     $ vim conf.d/wgt/config.xml.in
265
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@ &lt;@PROJECT_AUTHOR_MAIL@&gt;</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" />
276         </feature>
277         <feature name="urn:AGL:widget:provided-api">
278            <param name="hellocount" value="ws" />
279         </feature>
280         <feature name="urn:AGL:widget:required-binding">
281            <param name="lib/afb-hellocount.so" value="local" />
282         </feature>
283       </widget>
284
285     ```
286
287
288 ### 6. Run CMAKE and Generate autobuild
289
290   ```sh
291   $ mkdir build/
292   $ cd build/
293   $ cmake ..
294   $ make autobuild
295   ```
296
297 ### 7. Create service directory
298
299   ```sh
300   $ cd ..
301   $ mkdir service/
302   $ cd service/
303   ```
304   This `service` directory holds the C code & CMakeLists.txt ;
305
306   - Add `hellocount-service.c` file which contains the functional C code :
307
308     ```sh
309     $ vim hellocount-service.c
310
311       /*
312        * Copyright 2020 The Linux Foundation # INSERT YEAR & ORG
313        *
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
317        *
318        *   http://www.apache.org/licenses/LICENSE-2.0
319        *
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.
325        */
326
327       #define _GNU_SOURCE
328       #include <stdio.h>
329       #include <string.h>
330       #include <json-c/json.h>
331
332       #define AFB_BINDING_VERSION 3
333       #include <afb/afb-binding.h>
334
335       static void pingSample(afb_req_t request)
336       {
337         static int pingcount = 0;
338
339         afb_req_success_f(request, json_object_new_int(pingcount), "Ping count = %d", pingcount);
340
341         AFB_API_NOTICE(afbBindingV3root, "Verbosity macro at level notice invoked at ping invocation count = %d", pingcount);
342
343         pingcount++;
344       }
345
346       static void count(afb_req_t request)
347       {
348         static int counter = 0;
349
350         afb_req_success_f(request, json_object_new_int(counter), "Counter = %d", counter);
351
352         AFB_API_NOTICE(afbBindingV3root, "Verbosity macro at level notice invoked at count invocation count = %d", counter);
353
354         counter++;
355       }
356
357
358
359       static const afb_verb_t verbs[] =
360       {
361         /*Without security*/
362         {.verb = "ping", .session = AFB_SESSION_NONE, .callback = pingSample, .auth = NULL},
363         {.verb = "count", .session = AFB_SESSION_NONE, .callback = count, .auth = NULL},
364         {NULL}
365       };
366
367       const afb_binding_t afbBindingExport =
368       {
369         .api = "hellocount",
370         .specification = "HelloCount API",
371         .verbs = verbs,
372         .preinit = NULL,
373         .init = NULL,
374         .onevent = NULL,
375         .userdata = NULL,
376         .provide_class = NULL,
377         .require_class = NULL,
378         .require_api = NULL,
379         .noconcurrency = 0
380       };
381     ```
382
383 - Add `CMakeLists.txt` file :
384
385     ```sh
386     $ vim CMakeLists.txt
387
388       ###########################################################################
389       # Copyright 2020 The Linux Foundation # INSERT YEAR & ORG
390       #
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
394       #
395       #     http://www.apache.org/licenses/LICENSE-2.0
396       #
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       ###########################################################################
403
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)
408
409           # Binder exposes a unique public entry point
410           SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
411           PREFIX "afb-"
412           LABELS "BINDING"
413           OUTPUT_NAME ${TARGET_NAME}
414           )
415     ```
416
417 ### 8. Build and Package `wgt` using autobuild
418
419   ```sh
420   $ cd ..
421
422   $ ./autobuild/agl/autobuild build
423
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'
431
432   $ ./autobuild/agl/autobuild package
433
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'
492   ```
493
494   - The `hellocount.wgt` file is packaged and available at `~/agl-app/newservice/build`.
495
496 ### 9. Install the service
497
498   - Local System :
499     ```sh
500     # Copy hellocount.wgt to remote AGL system
501     $ scp ~/agl-app/newservice/build/hellocount.wgt root@<ip-address>:/home/0/
502     ```
503
504   - Remote AGL System :
505     ```sh
506     # Install using the service using afm-util
507     $ afm-util install ./hellocount.wgt
508     # Reboot the system
509     $ reboot -f
510     ```