|
| 1 | +# Modular structure of Embox |
| 2 | + |
| 3 | +Important features of Embox are: **modularity** and **configurability**. |
| 4 | + |
| 5 | +A modularity is splitting project into small logical parts that is modules. |
| 6 | + |
| 7 | +And **configurability** is ability to determinate the characteristics of the end system, |
| 8 | +based on list of modules and their parameters. |
| 9 | + |
| 10 | +For this purpose we use "Mybuild" assembly system with a dictionary specification language, |
| 11 | +which allows to describe the modules and system as a whole. |
| 12 | + |
| 13 | +At the same time, programming logic of modules is located separately from a description |
| 14 | +and it's developed on general-purpose programming language. |
| 15 | + |
| 16 | +## The files of module description |
| 17 | +### The packages of modules |
| 18 | +Modules are organized into hierarhical groups (namespace). |
| 19 | +This structure allows to avoid mess in names of modules and makes them short. |
| 20 | + |
| 21 | +As usual, package name coincides with the path in the file system. |
| 22 | +It relieves search for module files in source code tree. |
| 23 | + |
| 24 | +The example of package naming: |
| 25 | +```java |
| 26 | + package embox.arch |
| 27 | +``` |
| 28 | +### Interfaces and abstract modules |
| 29 | +Interfaces for modules are direct analogues of abstract classes and interfaces in OOP. |
| 30 | + |
| 31 | +Module description language supports **interface** that allows to to introduce the **interface** concept (modules without implementation) |
| 32 | +and **abstract modules** (modules with partial implementation). |
| 33 | + |
| 34 | +This method allows you to choose from the list of modules (that implement the same interface, but have different algorithm) the needed one. |
| 35 | + |
| 36 | +To mark a module as inherited, you need to use `abstract` keyword. |
| 37 | + |
| 38 | +The example of module declaration: |
| 39 | +```java |
| 40 | + package embox.arch |
| 41 | + //... |
| 42 | + abstract module interrupt {} |
| 43 | + //... |
| 44 | +``` |
| 45 | +To point at inheritance, we use `extends` keyword. |
| 46 | + |
| 47 | +The instance of inheritance from the abstract module: |
| 48 | +```java |
| 49 | + module interrupt_stub extends embox.arch.interrupt { |
| 50 | + //... |
| 51 | + } |
| 52 | +``` |
| 53 | +### Attributes of modules |
| 54 | +Description of every module consists of several possible attributes: |
| 55 | + |
| 56 | +* **files of source code** |
| 57 | +* **options** |
| 58 | +* **dependencies** |
| 59 | + |
| 60 | +#### Files of source code |
| 61 | +A module can point at list of file, which you need to compile and to add in a final image. |
| 62 | +Except "ordinary" files in C and assembler, it's possible to include header files and additional linker scripts. |
| 63 | + |
| 64 | +Types of files differ according to file extension: `.c/.S`, `.h`, `.lds.S`. |
| 65 | + |
| 66 | +**.c/.S** is a source code, written in C or assembler. In the assembly process it's compelled and included in final image of system. |
| 67 | +During the compilation it's possible to get values of options of module that connected with files of source code. |
| 68 | + |
| 69 | +**.h** is a header file containing the definitions, needed for implementation of interface. |
| 70 | +During the building of module the special header file is generated. It has all listed .h-files of this module. |
| 71 | + |
| 72 | +It allows you to use different implementations of some interface without changing the source code of the modules that use it. |
| 73 | +Such way of abstraction is necessary, because different implementations can define one or the other structure in different ways |
| 74 | +while this structure can be used by other modules without knowledge about details of implementation. |
| 75 | + |
| 76 | +**.lds.S** are linker scripts that allow you to affect on loading the modules in final image. The typical using is an addition of new sections. |
| 77 | + |
| 78 | +The example of adding the **.h-file** to the module: |
| 79 | +```java |
| 80 | + module interrupt_stub extends embox.arch.interrupt { |
| 81 | + source "interrupt_stub.h" |
| 82 | + } |
| 83 | +``` |
| 84 | +The instance of adding the **.lds.S-file** and **.c-file** to the module: |
| 85 | +```java |
| 86 | + module static_heap extends heap_place { |
| 87 | + //... |
| 88 | + source "heap.lds.S" |
| 89 | + source "static_heap.c" |
| 90 | + //... |
| 91 | + |
| 92 | + } |
| 93 | +``` |
| 94 | + |
| 95 | +#### Options |
| 96 | +**The characteristics of options:** |
| 97 | + |
| 98 | +* allow you to define numerical, boolean and string parameters at the configuration stage |
| 99 | +* their parameters can affect how the module is assembled, initialized and how it works |
| 100 | +* can have default value, if the value doesn't exist -- ad it to your configuration |
| 101 | + |
| 102 | +Options allow you to define **numerical**, **boolean** and **string parameters** at the configuration stage. |
| 103 | +These parameters can affect how the module is assembled, initialized and how it works. |
| 104 | + |
| 105 | +To define a type of some options, it's needed to write it after the `option` keyword. |
| 106 | + |
| 107 | +To get a value of some option during the compilation of source code, it's used the next **special macros**: |
| 108 | + |
| 109 | +* **OPTION_STRING_GET** is for string options |
| 110 | +* **OPTION_NUMBER_GET** is for numerical options |
| 111 | +* **OPTION_BOOLEAN_GET** is for boolean options |
| 112 | +The argument of macro is option name defined in **my-file**. |
| 113 | + |
| 114 | +#### Dependencies |
| 115 | +**Dependencies** are the way to show to the assembly system that the correct module working is impossible without other ones. |
| 116 | + |
| 117 | +The list of dependencies can include some interfaces. It means that only one module implemented required interface can be included in a building. |
| 118 | + |
| 119 | +Use the `depends` attribute to define dependencies between modules. |
| 120 | +You can count modules and interfaces in value of this attribute. |
| 121 | + |
| 122 | +Assembly system guarantees that the dependencies of specific module will be added when this module is included in the system. |
| 123 | +We use of the interface implementations in case when dependencies have interface. |
| 124 | + |
| 125 | +In some cases you just need to add a module what you need without changing the loading order. |
| 126 | +This method is used for such global modules as, for example: **multiprocessing support**, **logging**, **debug statement (assert)**. |
| 127 | + |
| 128 | +Due to the fact that these modules don't have a status in the usual sence (such as "loaded" or "unloaded"), |
| 129 | +it's required to add the *@NoRuntime* annotation to the **depends** attribute. |
| 130 | +In this case, the dependencies will be used during the building , but won't determine module loading order. |
| 131 | + |
| 132 | +### Annotations |
| 133 | +**The characteristics of annotations:** |
| 134 | + |
| 135 | +* are used for changing the semantics of description elements |
| 136 | +* allow to extend description language without changing the grammar |
| 137 | +* make description language more flexible |
| 138 | + |
| 139 | +The instance of implementation the abstract module with help of the annotation: |
| 140 | +```java |
| 141 | + @DefaultImpl(embox.arch.generic.interrupt_stub) |
| 142 | + abstract module interrupt {} |
| 143 | +``` |
| 144 | + |
| 145 | +## Configuration description |
| 146 | +**Module description** is used to create a target image. |
| 147 | +During the configuration the assembly system allows to merge modules of system (e. g. kernel modules, drivers, tests, applications) |
| 148 | +and to install parameters for these, and also to define additional parameters to create an image for different hardware platforms. |
| 149 | + |
| 150 | +### The structure of configuration |
| 151 | +Image configuration is running through file editing in the **conf/** directory. |
| 152 | +It contains the following: |
| 153 | + |
| 154 | +* **lds.conf** -- contains the definition of memory card, which is used by specific hardware platforms |
| 155 | +* **mods.conf** -- contains names and options of modules, which will be included in OS image. |
| 156 | +Also you can set every modules in this file to new values |
| 157 | +* **rootfs** -- contains files, which will be included into the file system |
| 158 | + |
| 159 | +### Configuration process |
| 160 | +To use some module in OS image means to add it into some OS configuration. |
| 161 | + |
| 162 | +#### Basic configuration |
| 163 | +A preparation any configuration to building is a long process. A basic configuration is used to save your time. |
| 164 | + |
| 165 | +OS has several configuration that intended to be used as basic. |
| 166 | +Several configurations with different properties have been prepared for each platform. |
| 167 | + |
| 168 | +For example, to get a basic configuration to support x86 platform, use the next command: |
| 169 | +``` |
| 170 | + make confload-x86/qemu |
| 171 | +``` |
| 172 | +This command loads basic "qemu" configuration for x86 platform in the **conf/** directory. |
| 173 | + |
| 174 | +The list of basic configurations you can see and choose the needed one, type: |
| 175 | +``` |
| 176 | + make confload |
| 177 | +``` |
| 178 | + |
| 179 | +#### Inclusion of module into configurations |
| 180 | +The list of modules (that you can include in your configuration) locates in the "conf/mods.conf". |
| 181 | +This file has the next structure: |
| 182 | +``` |
| 183 | + package genconfig |
| 184 | +
|
| 185 | + configuration conf { |
| 186 | + [module_list] |
| 187 | + } |
| 188 | +``` |
| 189 | +Where **[module_list]** defines the position of set of strings, each of the last ones is responsible for inclusion. |
| 190 | + |
| 191 | +Add a new line to the module list: |
| 192 | +``` |
| 193 | + include pkg.new_package.empty |
| 194 | +``` |
| 195 | +To get the following: |
| 196 | +``` |
| 197 | + package genconfig |
| 198 | +
|
| 199 | + configuration conf { |
| 200 | + [module_list] |
| 201 | + include pkg.new_package.empty |
| 202 | + } |
| 203 | +``` |
| 204 | +Then the "empty" module from "pkg.new_package" will be included in the building. |
| 205 | + |
| 206 | +To check the consistency of received building and to create OS image, type: |
| 207 | +``` |
| 208 | + make |
| 209 | +``` |
| 210 | +If everything was completed successful, you'll see the "Build complete" message on your screen. |
| 211 | + |
| 212 | +To be confident that new module appeared in OS, do the following: |
| 213 | +``` |
| 214 | + lsmod -n empty |
| 215 | +``` |
| 216 | +We typed the "lsmod" command with the "-n" and "empty" parameters in the line above. |
| 217 | +This command displays the list of module list, which have in their names "empty" substring. |
| 218 | + |
| 219 | +The result of "lsmod" is below: |
| 220 | +``` |
| 221 | + * pkg.new_package.empty |
| 222 | +``` |
| 223 | +This output tells us that the "pkg.new_package.empty" is in the system, and the `*` symbol -- that at this moment the module is loaded and it works. |
0 commit comments