You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

254 lines
11 KiB

11 months ago
  1. ceedling-dependencies
  2. =====================
  3. Plugin for supporting release dependencies. It's rare for an embedded project to
  4. be built completely free of other libraries and modules. Some of these may be
  5. standard internal libraries. Some of these may be 3rd party libraries. In either
  6. case, they become part of the project's ecosystem.
  7. This plugin is intended to make that relationship easier. It allows you to specify
  8. a source for dependencies. If required, it will automatically grab the appropriate
  9. version of that dependency.
  10. Most 3rd party libraries have a method of building already in place. While we'd
  11. love to convert the world to a place where everything downloads with a test suite
  12. in Ceedling, that's not likely to happen anytime soon. Until then, this plugin
  13. will allow the developer to specify what calls Ceedling should make to oversee
  14. the build process of those third party utilities. Are they using Make? CMake? A
  15. custom series of scripts that only a mad scientist could possibly understand? No
  16. matter. Ceedling has you covered. Just specify what should be called, and Ceedling
  17. will make it happen whenever it notices that the output artifacts are missing.
  18. Output artifacts? Sure! Things like static and dynamic libraries, or folders
  19. containing header files that might want to be included by your release project.
  20. So how does all this magic work?
  21. First, you need to add the `:dependencies` plugin to your list. Then, we'll add a new
  22. section called :dependencies. There, you can list as many dependencies as you desire. Each
  23. has a series of fields which help Ceedling to understand your needs. Many of them are
  24. optional. If you don't need that feature, just don't include it! In the end, it'll look
  25. something like this:
  26. ```
  27. :dependencies:
  28. :libraries:
  29. - :name: WolfSSL
  30. :source_path: third_party/wolfssl/source
  31. :build_path: third_party/wolfssl/build
  32. :artifact_path: third_party/wolfssl/install
  33. :fetch:
  34. :method: :zip
  35. :source: \\shared_drive\third_party_libs\wolfssl\wolfssl-4.2.0.zip
  36. :environment:
  37. - CFLAGS+=-DWOLFSSL_DTLS_ALLOW_FUTURE
  38. :build:
  39. - "autoreconf -i"
  40. - "./configure --enable-tls13 --enable-singlethreaded"
  41. - make
  42. - make install
  43. :artifacts:
  44. :static_libraries:
  45. - lib/wolfssl.a
  46. :dynamic_libraries:
  47. - lib/wolfssl.so
  48. :includes:
  49. - include/**
  50. ```
  51. Let's take a deeper look at each of these features.
  52. The Starting Dash & Name
  53. ------------------------
  54. Yes, that opening dash tells the dependencies plugin that the rest of these fields
  55. belong to our first dependency. If we had a second dependency, we'd have another
  56. dash, lined up with the first, and followed by all the fields indented again.
  57. By convention, we use the `:name` field as the first field for each tool. Ceedling
  58. honestly doesn't care which order the fields are given... but as humans, it makes
  59. it easier for us to see the name of each dependency with starting dash.
  60. The name field is only used to print progress while we're running Ceedling. You may
  61. call the name of the field whatever you wish.
  62. Working Folders
  63. ---------------
  64. The `:source_path` field allows us to specify where the source code for each of our
  65. dependencies is stored. If fetching the dependency from elsewhere, it will be fetched
  66. to this location. All commands to build this dependency will be executed from
  67. this location (override this by specifying a `:build_path`). Finally, the output
  68. artifacts will be referenced to this location (override this by specifying a `:artifact_path`)
  69. If unspecified, the `:source_path` will be `dependencies\dep_name` where `dep_name`
  70. is the name specified in `:name` above (with special characters removed). It's best,
  71. though, if you specify exactly where you want your dependencies to live.
  72. If the dependency is directly included in your project (you've specified `:none` as the
  73. `:method` for fetching), then `:source_path` should be where your Ceedling can find the
  74. source for your dependency in you repo.
  75. All artifacts are relative to the `:artifact_path` (which defaults to be the same as
  76. `:source_path`)
  77. Fetching Dependencies
  78. ---------------------
  79. The `:dependencies` plugin supports the ability to automatically fetch your dependencies
  80. for you... using some common methods of fetching source. This section contains only a
  81. couple of fields:
  82. - `:method` -- This is the method that this dependency is fetched.
  83. - `:none` -- This tells Ceedling that the code is already included in the project.
  84. - `:zip` -- This tells Ceedling that we want to unpack a zip file to our source path.
  85. - `:git` -- This tells Ceedling that we want to clone a git repo to our source path.
  86. - `:svn` -- This tells Ceedling that we want to checkout a subversion repo to our source path.
  87. - `:custom` -- This tells Ceedling that we want to use a custom command or commands to fetch the code.
  88. - `:source` -- This is the path or url to fetch code when using the zip or git method.
  89. - `:tag`/`:branch` -- This is the specific tag or branch that you wish to retrieve (git only. optional).
  90. - `:hash` -- This is the specific SHA1 hash you want to fetch (git only. optional, requires a deep clone).
  91. - `:revision` -- This is the specific revision you want to fetch (svn only. optional).
  92. - `:executable` -- This is a list of commands to execute when using the `:custom` method
  93. Environment Variables
  94. ---------------------
  95. Many build systems support customization through environment variables. By specifying
  96. an array of environment variables, Ceedling will customize the shell environment before
  97. calling the build process.
  98. Environment variables may be specified in three ways. Let's look at one of each:
  99. ```
  100. :environment:
  101. - ARCHITECTURE=ARM9
  102. - CFLAGS+=-DADD_AWESOMENESS
  103. - CFLAGS-=-DWASTE
  104. ```
  105. In the first example, you see the most straightforward method. The environment variable
  106. `ARCHITECTURE` is set to the value `ARM9`. That's it. Simple.
  107. The next two options modify an existing symbol. In the first one, we use `+=`, which tells
  108. Ceedling to add the define `ADD_AWESOMENESS` to the environment variable `CFLAGS`. The second
  109. tells Ceedling to remove the define `WASTE` from the same environment variable.
  110. There are a couple of things to note here.
  111. First, when adding to a variable, Ceedling has no way of knowing
  112. what delimiter you are expecting. In this example you can see we manually added some whitespace.
  113. If we had been modifying `PATH` instead, we might have had to use a `:` on a unux or `;` on
  114. Windows.
  115. Second, removing an argument will have no effect on the argument if that argument isn't found
  116. precisely. It's case sensitive and the entire string must match. If symbol doesn't already exist,
  117. it WILL after executing this command... however it will be assigned to nothing.
  118. Building Dependencies
  119. ---------------------
  120. The heart of the `:dependencies` plugin is the ability for you, the developer, to specify the
  121. build process for each of your dependencies. You will need to have any required tools installed
  122. before using this feature.
  123. The steps are specified as an array of strings. Ceedling will execute those steps in the order
  124. specified, moving from step to step unless an error is encountered. By the end of the process,
  125. the artifacts should have been created by your process... otherwise an error will be produced.
  126. Artifacts
  127. ---------
  128. These are the outputs of the build process. There are there types of artifacts. Any dependency
  129. may have none or some of these. Calling out these files tells Ceedling that they are important.
  130. Your dependency's build process may produce many other files... but these are the files that
  131. Ceedling understands it needs to act on.
  132. ### `static_libraries`
  133. Specifying one or more static libraries will tell Ceedling where it should find static libraries
  134. output by your build process. These libraries are automatically added to the list of dependencies
  135. and will be linked with the rest of your code to produce the final release.
  136. If any of these libraries don't exist, Ceedling will trigger your build process in order for it
  137. to produce them.
  138. ### `dynamic_libraries`
  139. Specifying one or more dynamic libraries will tell Ceedling where it should find dynamic libraries
  140. output by your build process. These libraries are automatically copied to the same folder as your
  141. final release binary.
  142. If any of these libraries don't exist, Ceedling will trigger your build process in order for it
  143. to produce them.
  144. ### `includes`
  145. Often when libraries are built, the same process will output a collection of includes so that
  146. your release code knows how to interact with that library. It's the public API for that library.
  147. By specifying the directories that will contain these includes (don't specify the files themselves,
  148. Ceedling only needs the directories), Ceedling is able to automatically add these to its internal
  149. include list. This allows these files to be used while building your release code, as well we making
  150. them mockable during unit testing.
  151. ### `source`
  152. It's possible that your external dependency will just produce additional C files as its output.
  153. In this case, Ceedling is able to automatically add these to its internal source list. This allows
  154. these files to be used while building your release code.
  155. Tasks
  156. -----
  157. Once configured correctly, the `:dependencies` plugin should integrate seamlessly into your
  158. workflow and you shouldn't have to think about it. In the real world, that doesn't always happen.
  159. Here are a number of tasks that are added or modified by this plugin.
  160. ### `ceedling dependencies:clean`
  161. This can be issued in order to completely remove the dependency from its source path. On the
  162. next build, it will be refetched and rebuilt from scratch. This can also apply to a particular
  163. dependency. For example, by specifying `dependencies:clean:DepName`.
  164. ### `ceedling dependencies:fetch`
  165. This can be issued in order to fetch each dependency from its origin. This will have no effect on
  166. dependencies that don't have fetch instructions specified. This can also apply to a particular
  167. dependency. For example, by specifying `dependencies:fetch:DepName`.
  168. ### `ceedling dependencies:make`
  169. This will force the dependencies to all build. This should happen automatically when a release
  170. has been triggered... but if you're just getting your dependency configured at this moment, you
  171. may want to just use this feature instead. A single dependency can also be built by specifying its
  172. name, like `dependencies:make:MyTunaBoat`.
  173. ### `ceedling dependencies:deploy`
  174. This will force any dynamic libraries produced by your dependencies to be copied to your release
  175. build directory... just in case you clobbered them.
  176. ### `paths:include`
  177. Maybe you want to verify that all the include paths are correct. If you query Ceedling with this
  178. request, it will list all the header file paths that it's found, including those produced by
  179. dependencies.
  180. ### `files:include`
  181. Maybe you want to take that query further and actually get a list of ALL the header files
  182. Ceedling has found, including those belonging to your dependencies.
  183. Testing
  184. =======
  185. Hopefully all your dependencies are fully tested... but we can't always depend on that.
  186. In the event that they are tested with Ceedling, you'll probably want to consider using
  187. the `:subprojects` plugin instead of this one. The purpose of this plugin is to pull in
  188. third party code for release... and to provide a mockable interface for Ceedling to use
  189. during its tests of other modules.
  190. If that's what you're after... you've found the right plugin!
  191. Happy Testing!