757c1517fd8c657e659cc9361ff1b30a80fafdd8
[AGL/documentation.git] / docs / 3_Developer_Guides / 3_Creating_a_New_Application.md
1 ---
2 title: Creating a New Application
3 ---
4
5 This tutorial provides instructions on **Creating a New Application** from scratch.
6
7 ### 1. Create new project development directory
8
9    ```sh
10    $ cd ~/agl-app
11    $ mkdir newapp/
12    $ cd newapp/
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/newapp/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 helloworld count app") #INSERT PRETTY NAME
57     set(PROJECT_DESCRIPTION "AGL hellocount application example")   # INSERT CONCISE PROJECT DESCRIPTION
58     set(PROJECT_URL "https://git.somewhere.org/foo")
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")
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     )
102
103     # You can also consider to include libsystemd
104     # -----------------------------------
105     #list (APPEND PKG_REQUIRED_LIST libsystemd>=222)
106
107     # Prefix path where will be installed the files
108     # Default: /usr/local (need root permission to write in)
109     # ------------------------------------------------------
110     #set(INSTALL_PREFIX /opt/AGL CACHE PATH "INSTALL PREFIX PATH")
111
112     # Customize link option
113     # -----------------------------
114     #list(APPEND link_libraries -an-option)
115
116     # Compilation options definition
117     # Use CMake generator expressions to specify only for a specific language
118     # Values are prefilled with default options that is currently used.
119     # Either separate options with ";", or each options must be quoted separately
120     # DO NOT PUT ALL OPTION QUOTED AT ONCE , COMPILATION COULD FAILED !
121     # ----------------------------------------------------------------------------
122     #set(COMPILE_OPTIONS
123     # -Wall
124     # -Wextra
125     # -Wconversion
126     # -Wno-unused-parameter
127     # -Wno-sign-compare
128     # -Wno-sign-conversion
129     # -Werror=maybe-uninitialized
130     # -Werror=implicit-function-declaration
131     # -ffunction-sections
132     # -fdata-sections
133     # -fPIC
134     # CACHE STRING "Compilation flags")
135     #set(C_COMPILE_OPTIONS "" CACHE STRING "Compilation flags for C language.")
136     #set(CXX_COMPILE_OPTIONS "" CACHE STRING "Compilation flags for C++ language.")
137     #set(PROFILING_COMPILE_OPTIONS
138     # -g
139     # -O0
140     # -pg
141     # -Wp,-U_FORTIFY_SOURCE
142     # CACHE STRING "Compilation flags for PROFILING build type.")
143     #set(DEBUG_COMPILE_OPTIONS
144     # -g
145     # -ggdb
146     # CACHE STRING "Compilation flags for DEBUG build type.")
147     #set(COVERAGE_COMPILE_OPTIONS
148     # -g
149     # -O0
150     # --coverage
151     # CACHE STRING "Compilation flags for COVERAGE build type.")
152     #set(RELEASE_COMPILE_OPTIONS
153     # -O2
154     # -pipe
155     # -D_FORTIFY_SOURCE=2
156     # -fstack-protector-strong
157     # -Wformat -Wformat-security
158     # -Werror=format-security
159     # -feliminate-unused-debug-types
160     # -Wl,-O1
161     # -Wl,--hash-style=gnu
162     # -Wl,--as-needed
163     # -fstack-protector-strong
164     # -Wl,-z,relro,-z,now
165     # CACHE STRING "Compilation flags for RELEASE build type.")
166
167     # Location for config.xml.in template file.
168     #
169     # If you keep them commented then it will build with a default minimal widget
170     # template which is very simple and it is highly probable that it will not suit
171     # to your app.
172     # -----------------------------------------
173     #set(WIDGET_ICON "conf.d/wgt/${PROJECT_ICON}" CACHE PATH "Path to the widget icon")
174     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
175     #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)")
176
177     # Mandatory widget Mimetype specification of the main unit
178     # --------------------------------------------------------------------------
179     # Choose between :
180     #- text/html : HTML application,
181     #   content.src designates the home page of the application
182     #
183     #- application/vnd.agl.native : AGL compatible native,
184     #   content.src designates the relative path of the binary.
185     #
186     # - application/vnd.agl.service: AGL service, content.src is not used.
187     #
188     #- ***application/x-executable***: Native application,
189     #   content.src designates the relative path of the binary.
190     #   For such application, only security setup is made.
191     #
192     set(WIDGET_TYPE application/vnd.agl.service)    # UNCOMMENT WIDGET_TYPE
193
194     # Mandatory Widget entry point file of the main unit
195     # --------------------------------------------------------------
196     # This is the file that will be executed, loaded,
197     # at launch time by the application framework.
198     #
199     set(WIDGET_ENTRY_POINT hellocount)    # UNCOMMENT WIDGET_ENTRY_POINT
200
201     # Optional dependencies order
202     # ---------------------------
203     #set(EXTRA_DEPENDENCIES_ORDER)
204
205     # Optional Extra global include path
206     # -----------------------------------
207     #set(EXTRA_INCLUDE_DIRS)
208
209     # Optional extra libraries
210     # -------------------------
211     #set(EXTRA_LINK_LIBRARIES)
212
213     # Optional force binding Linking flag
214     # ------------------------------------
215     # set(BINDINGS_LINK_FLAG LinkOptions )
216
217     # Optional force package prefix generation, like widget
218     # -----------------------------------------------------
219     # set(PKG_PREFIX DestinationPath)
220
221     # Optional Application Framework security token
222     # and port use for remote debugging.
223     #------------------------------------------------------------
224     #set(AFB_TOKEN   ""     CACHE PATH "Default binder security token")   # COMMENT AFB_TOKEN
225     #set(AFB_REMPORT "1234" CACHE PATH "Default binder listening port")   # COMMENT AFB_REMPORT
226
227     # Print a helper message when every thing is finished
228     # ----------------------------------------------------
229     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")
230     set(PACKAGE_MESSAGE "Install widget file using in the target : afm-util install ${PROJECT_NAME}.wgt")
231
232     # Optional schema validator about now only XML, LUA and JSON
233     # are supported
234     #------------------------------------------------------------
235     #set(LUA_CHECKER "luac" "-p" CACHE STRING "LUA compiler")
236     #set(XML_CHECKER "xmllint" CACHE STRING "XML linter")
237     #set(JSON_CHECKER "json_verify" CACHE STRING "JSON linter")
238
239     include(CMakeAfbTemplates)
240   ```
241
242 ### 5. Copy WGT configuration template
243
244   ```sh
245   $ mkdir -p conf.d/wgt
246   $ cp ${OECORE_NATIVE_SYSROOT}/usr/share/doc/CMakeAfbTemplates/samples.d/config.xml.in.sample conf.d/wgt/config.xml.in
247   ```
248
249 ### 6. Run CMAKE and Generate autobuild
250
251   ```sh
252   $ mkdir build/
253   $ cd build/
254   $ cmake ..
255   $ make autobuild
256   ```
257
258 ### 7. Create app directory
259
260   ```sh
261   $ cd ..
262   $ mkdir app/
263   $ cd app/
264   ```
265   This `app` directory holds the C++, qrc, qml code & CMakeLists.txt ;
266
267   - Add `main.cpp` file which contains the functional C code :
268
269     ```sh
270     $ vim main.cpp
271
272      /*
273       * Copyright (C) 2016 The Qt Company Ltd. # INSERT YEAR & ORG
274       *               2020 The Linux Foundation
275       *
276       * Licensed under the Apache License, Version 2.0 (the "License");
277       * you may not use this file except in compliance with the License.
278       * You may obtain a copy of the License at
279       *
280       *      http://www.apache.org/licenses/LICENSE-2.0
281       *
282       * Unless required by applicable law or agreed to in writing, software
283       * distributed under the License is distributed on an "AS IS" BASIS,
284       * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
285       * See the License for the specific language governing permissions and
286       * limitations under the License.
287       */
288
289       #include <QGuiApplication>
290       #include <QtCore/QCommandLineParser>
291       #include <QtCore/QUrlQuery>
292       #include <QtGui/QGuiApplication>
293       #include <QtQml/QQmlContext>
294       #include <QtQml/QQmlApplicationEngine>
295       #include <QtQml/qqml.h>
296       #include <QDebug>
297
298       int main(int argc, char *argv[])
299       {
300               QGuiApplication app(argc, argv);
301               app.setDesktopFileName("Hellocount");
302
303           QQmlApplicationEngine engine;
304           QQmlContext *context = engine.rootContext();
305
306           QCommandLineParser parser;
307           parser.addPositionalArgument("port", app.translate("main", "port for binding"));
308           parser.addPositionalArgument("secret", app.translate("main", "secret for binding"));
309           parser.addHelpOption();
310           parser.addVersionOption();
311           parser.process(app);
312           QStringList positionalArguments = parser.positionalArguments();
313
314           if (positionalArguments.length() == 2) {
315         int port = positionalArguments.takeFirst().toInt();
316         QString secret = positionalArguments.takeFirst();
317
318         QUrl bindingAddress;
319         QUrlQuery query;
320
321         bindingAddress.setScheme(QStringLiteral("ws"));
322         bindingAddress.setHost(QStringLiteral("localhost"));
323         bindingAddress.setPort(port);
324         bindingAddress.setPath(QStringLiteral("/api"));
325
326
327         query.addQueryItem(QStringLiteral("token"), secret);
328         bindingAddress.setQuery(query);
329         context->setContextProperty(QStringLiteral("bindingAddress"), bindingAddress);
330           }
331
332           engine.load(QUrl(QStringLiteral("qrc:/Hellocount.qml")));
333               return app.exec();
334
335       }
336     ```
337
338   - Add `Hellocount.qml` file which contains the functional qml code :
339
340     ```sh
341     $ vim Hellocount.qml
342
343       /*
344       * Copyright 2020 The Linux Foundation # INSERT YEAR & ORG
345       *
346       * Licensed under the Apache License, Version 2.0 (the "License");
347       * you may not use this file except in compliance with the License.
348       * You may obtain a copy of the License at
349       *
350       *      http://www.apache.org/licenses/LICENSE-2.0
351       *
352       * Unless required by applicable law or agreed to in writing, software
353       * distributed under the License is distributed on an "AS IS" BASIS,
354       * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
355       * See the License for the specific language governing permissions and
356       * limitations under the License.
357       */
358
359       import QtQuick 2.6
360       import QtQuick.Layouts 1.1
361       import QtQuick.Controls 2.0
362       import AGL.Demo.Controls 1.0
363
364       import QtQuick.Window 2.13
365
366       ApplicationWindow {
367
368           // ----- Setup
369           id: root
370           width: Window.width * roles.scale
371           height: Window.height * roles.scale
372
373           // ----- Childs
374           Label {
375         id: title
376         font.pixelSize: 48
377         text: "Hello World Counter"
378         anchors.horizontalCenter: parent.horizontalCenter
379           }
380
381       }
382     ```
383
384 - Add `Hellocount.qrc` file :
385
386     ```sh
387     $ vim Hellocount.qrc
388
389       <RCC>
390           <qresource prefix="/">
391               <file>Hellocount.qml</file>
392           </qresource>
393       </RCC>
394     ```
395
396 - Add `CMakeLists.txt` file :
397
398     ```sh
399     $ vim CMakeLists.txt
400
401       ###########################################################################
402       # Copyright 2020 The Linux Foundation # INSERT YEAR & ORG
403       #
404       # Licensed under the Apache License, Version 2.0 (the "License");
405       # you may not use this file except in compliance with the License.
406       # You may obtain a copy of the License at
407       #
408       #     http://www.apache.org/licenses/LICENSE-2.0
409       #
410       # Unless required by applicable law or agreed to in writing, software
411       # distributed under the License is distributed on an "AS IS" BASIS,
412       # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
413       # See the License for the specific language governing permissions and
414       # limitations under the License.
415       ###########################################################################
416
417       set(CMAKE_INCLUDE_CURRENT_DIR ON)
418       set(CMAKE_AUTOMOC ON)
419       set(CMAKE_AUTORCC ON)
420       set(CMAKE_CXX_STANDARD 14)
421       set(CMAKE_CXX_STANDARD_REQUIRED ON)
422       set(OE_QMAKE_PATH_EXTERNAL_HOST_BINS $ENV{OE_QMAKE_PATH_HOST_BINS})
423
424       find_package(Qt5 COMPONENTS Core Gui QuickControls2 QuickWidgets WebSockets REQUIRED)
425
426       PROJECT_TARGET_ADD(hellocount)
427
428       add_executable(hellocount
429           "main.cpp"
430           "Hellocount.qrc"
431       )
432
433       set_target_properties(hellocount PROPERTIES
434           LABELS "EXECUTABLE"
435           PREFIX ""
436           COMPILE_FLAGS " -DFOR_AFB_BINDING"
437           LINK_FLAGS "${BINDINGS_LINK_FLAG}"
438           OUTPUT_NAME "${TARGET_NAME}"
439       )
440
441       target_link_libraries(hellocount
442           Qt5::WebSockets
443           Qt5::QuickWidgets
444           Qt5::QuickControls2
445           json-c
446           libafb-helpers-qt.a
447       )
448     ```
449
450 ### 8. Build and Package `wgt` using autobuild
451
452   ```sh
453   $ cd ..
454
455   $ ./autobuild/agl/autobuild build
456
457     make[1]: Entering directory '/home/boron/agl-app/newapp/build'
458     make[2]: Entering directory '/home/boron/agl-app/newapp/build'
459     make[3]: Entering directory '/home/boron/agl-app/newapp/build'
460     make[3]: Leaving directory '/home/boron/agl-app/newapp/build'
461     [100%] Built target autobuild
462     make[2]: Leaving directory '/home/boron/agl-app/newapp/build'
463     make[1]: Leaving directory '/home/boron/agl-app/newapp/build'
464
465
466   $ ./autobuild/agl/autobuild package
467
468     make[1]: Entering directory '/home/boron/agl-app/newapp/build'
469     make[2]: Entering directory '/home/boron/agl-app/newapp/build'
470     make[3]: Entering directory '/home/boron/agl-app/newapp/build'
471     make[3]: Leaving directory '/home/boron/agl-app/newapp/build'
472     [100%] Built target autobuild
473     make[2]: Leaving directory '/home/boron/agl-app/newapp/build'
474     make[1]: Leaving directory '/home/boron/agl-app/newapp/build'
475     make[1]: Entering directory '/home/boron/agl-app/newapp/build'
476     make[2]: Entering directory '/home/boron/agl-app/newapp/build'
477     make[3]: Entering directory '/home/boron/agl-app/newapp/build'
478     make[4]: Entering directory '/home/boron/agl-app/newapp/build'
479     Scanning dependencies of target prepare_package
480     make[4]: Leaving directory '/home/boron/agl-app/newapp/build'
481     make[4]: Entering directory '/home/boron/agl-app/newapp/build'
482     [  6%] Generating package
483     [ 12%] Generating package/bin
484     [ 18%] Generating package/etc
485     [ 25%] Generating package/lib
486     [ 31%] Generating package/htdocs
487     [ 37%] Generating package/var
488     make[4]: Leaving directory '/home/boron/agl-app/newapp/build'
489     [ 37%] Built target prepare_package
490     make[4]: Entering directory '/home/boron/agl-app/newapp/build'
491     Scanning dependencies of target prepare_package_test
492     make[4]: Leaving directory '/home/boron/agl-app/newapp/build'
493     make[4]: Entering directory '/home/boron/agl-app/newapp/build'
494     [ 43%] Generating package-test
495     [ 50%] Generating package-test/bin
496     [ 56%] Generating package-test/etc
497     [ 62%] Generating package-test/lib
498     [ 68%] Generating package-test/htdocs
499     [ 75%] Generating package-test/var
500     make[4]: Leaving directory '/home/boron/agl-app/newapp/build'
501     [ 75%] Built target prepare_package_test
502     make[4]: Entering directory '/home/boron/agl-app/newapp/build'
503     Scanning dependencies of target populate
504     make[4]: Leaving directory '/home/boron/agl-app/newapp/build'
505     [ 75%] Built target populate
506     make[4]: Entering directory '/home/boron/agl-app/newapp/build'
507     Scanning dependencies of target widget_files
508     make[4]: Leaving directory '/home/boron/agl-app/newapp/build'
509     make[4]: Entering directory '/home/boron/agl-app/newapp/build'
510     [ 81%] Generating package/icon.png
511     [ 87%] Generating package/config.xml
512     make[4]: Leaving directory '/home/boron/agl-app/newapp/build'
513     [ 93%] Built target widget_files
514     make[4]: Entering directory '/home/boron/agl-app/newapp/build'
515     Scanning dependencies of target widget
516     make[4]: Leaving directory '/home/boron/agl-app/newapp/build'
517     make[4]: Entering directory '/home/boron/agl-app/newapp/build'
518     [100%] Generating hellocount.wgt
519     NOTICE: -- PACKING widget hellocount.wgt from directory /home/boron/agl-app/newapp/build/package
520     ++ Install widget file using in the target : afm-util install hellocount.wgt
521     make[4]: Leaving directory '/home/boron/agl-app/newapp/build'
522     [100%] Built target widget
523     make[3]: Leaving directory '/home/boron/agl-app/newapp/build'
524     make[2]: Leaving directory '/home/boron/agl-app/newapp/build'
525     make[1]: Leaving directory '/home/boron/agl-app/newapp/build'
526   ```
527
528   - The `hellocount.wgt` file is packaged and available at `~/agl-app/newapp/build`.
529
530 ### 9. Install the service
531
532   - Local System :
533     ```sh
534     # Copy hellocount.wgt to remote AGL system
535     $ scp ~/agl-app/newapp/build/hellocount.wgt root@<ip-address>:/home/0/
536     ```
537
538   - Remote AGL System :
539     ```sh
540     # Install using the service using afm-util
541     $ afm-util install ./hellocount.wgt
542     # Reboot the system
543     $ reboot -f
544     ```