rakeoe 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +674 -0
- data/README.md +234 -0
- data/Rakefile +1 -0
- data/lib/rakeoe/app.rb +158 -0
- data/lib/rakeoe/binary_base.rb +492 -0
- data/lib/rakeoe/config.rb +93 -0
- data/lib/rakeoe/defaults.rb +45 -0
- data/lib/rakeoe/key_value_reader.rb +165 -0
- data/lib/rakeoe/lib.rb +100 -0
- data/lib/rakeoe/prj_file_cache.rb +119 -0
- data/lib/rakeoe/qt_settings.rb +88 -0
- data/lib/rakeoe/test_framework.rb +40 -0
- data/lib/rakeoe/toolchain/environment-arm-none-eabi +47 -0
- data/lib/rakeoe/toolchain/environment-arm-none-eabi.Linux +46 -0
- data/lib/rakeoe/toolchain/environment-arm-none-eabi.osx +46 -0
- data/lib/rakeoe/toolchain/environment-arm-stm32f072-eabi.Linux +46 -0
- data/lib/rakeoe/toolchain/environment-arm-stm32f072-eabi.osx +46 -0
- data/lib/rakeoe/toolchain.rb +457 -0
- data/lib/rakeoe/version.rb +3 -0
- data/lib/rakeoe.rb +94 -0
- data/rakeoe.gemspec +30 -0
- metadata +129 -0
data/README.md
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
# RakeOE : Rake Optimized for Embedded
|
2
|
+
|
3
|
+
**A build system for test driven Embedded C/C++ Development based on Ruby rake**
|
4
|
+
|
5
|
+
RakeOE is a build system for application development. It can parse OpenEmbedded / Yocto environment files.<br/>
|
6
|
+
In this way it knows how to cross compile in whatever target platform the cross compiler builds.<br/>
|
7
|
+
It uses automatically the appropriate include paths and libraries of the given platform.<br/>
|
8
|
+
If not otherwise specified, it uses the native toolchain of the host platform.<br/>
|
9
|
+
|
10
|
+
RakeOE uses a *convention over configuration* paradigm to enable a fast jump start for developers.<br/>
|
11
|
+
E.g. it assumes that the project follows a certain directory hierarchy or how sub projects are organized.<br/>
|
12
|
+
It is possible to override default settings, though one can get a long way without doing so.<br/>
|
13
|
+
|
14
|
+
## Prerequisites
|
15
|
+
### OS
|
16
|
+
Rake OE has been tested on Linux, Windows and Mac OSX. It should work on whatever platform Ruby/Rake runs on.<br/>
|
17
|
+
|
18
|
+
### GCC or GCC-compatible compiler
|
19
|
+
For the time beeing, **gcc** or a gcc-compatible compiler like **clang** or **icc** is required.<br/>
|
20
|
+
Besides compilation, gcc is used e.g. for header file dependency generation or platform information.
|
21
|
+
|
22
|
+
### Ruby
|
23
|
+
RakeOE is based on Rake. Rake comes bundled with Ruby. Therefore you should have installed a recent [Ruby version](http://www.ruby-lang.org/en/ "[Latest Ruby") on your development machine.<br/>
|
24
|
+
Recommended is **Ruby >= 2.0.0**.
|
25
|
+
|
26
|
+
### OpenEmbedded / Yocto
|
27
|
+
If you want to use RakeOE for cross development, you should also have some flavour of OpenEmbedded installed on your host platform.<br/> When cross compilating for target platforms via Yocto/OpenEmbedded, a Linux host machine is a must.<br/>
|
28
|
+
RakeOE has been tested with [ELDK-5.3/Yocto Danny](http://www.denx.de/wiki/ELDK-5/ "[ELDK-5.3/Yocto Danny") but other OpenEmbedded based toolchains should work similarly well.<br/>
|
29
|
+
|
30
|
+
## Features
|
31
|
+
### Subproject autodiscovery
|
32
|
+
Any subdirectory inside the configured source directories will be scanned for a **prj.rake** file. This file contains standardized settings<br/>
|
33
|
+
for building libraries or applications and defining dependencies. Any subproject that has such a prj.rake file will be automatically<br/>
|
34
|
+
picked up for building.
|
35
|
+
|
36
|
+
### Qt
|
37
|
+
RakeOE has built-in support for Qt. It will automatically parse header files in Qt enabled sub projects and run the moc compiler <br/>
|
38
|
+
on them if a **Q_OBJECT** declaration is encountered.
|
39
|
+
|
40
|
+
### Subproject specific settings
|
41
|
+
Here is an overview of the settings that can be specified in the subprojects **prj.rake** file.<br/>
|
42
|
+
See the documentation of each setting for explanations.
|
43
|
+
|
44
|
+
# Project type, possible values are APP for applications, LIB for static libraries,
|
45
|
+
# SOLIB for shared objects and DISABLED if this project should be excluded from building.
|
46
|
+
PRJ_TYPE = 'DISABLED'
|
47
|
+
|
48
|
+
# Additional white space separated list of sub directories this project uses for finding source files.
|
49
|
+
# By default only sources in the projects top directory will be used for compilation.
|
50
|
+
ADD_SOURCE_DIRS = ''
|
51
|
+
|
52
|
+
# White space separated list of ignored source files. These will be excluded from compilation.
|
53
|
+
IGNORED_SOURCES = ''
|
54
|
+
|
55
|
+
# Additional white space separated list of sub directories this project uses for finding includes.
|
56
|
+
# By default the subdirectory 'include/' is always supposed.
|
57
|
+
ADD_INC_DIRS = ''
|
58
|
+
|
59
|
+
# White space separated list of test source directories.
|
60
|
+
TEST_SOURCE_DIRS = ''
|
61
|
+
|
62
|
+
# Additional white space separated list of CFLAGS. Used for all platforms.
|
63
|
+
# E.g. '-O3 -Wextra'
|
64
|
+
ADD_CFLAGS = ''
|
65
|
+
|
66
|
+
# Additional white space separated list of CXXFLAGS. Used for all platforms.
|
67
|
+
# E.g. '-O3 -Wextra'
|
68
|
+
ADD_CXXFLAGS = ''
|
69
|
+
|
70
|
+
# Additional white space separated list of libraries this project depends on. These can be either libraries provided
|
71
|
+
# from other subprojects or external libraries. In case of the former the include/ directory of that library
|
72
|
+
# is used for compilation as well. Used for all platforms.
|
73
|
+
# e.g. 'pthread rt m'
|
74
|
+
ADD_LIBS = ''
|
75
|
+
|
76
|
+
# Additional white space separated list of linker flags. Used for all platforms.
|
77
|
+
ADD_LDFLAGS = ''
|
78
|
+
|
79
|
+
# Set to 1 if you need Qt support. If enabled, all header files will be parsed for the
|
80
|
+
# declaration of the keyword Q_OBJECT and if found used as input for the moc compiler.
|
81
|
+
# By default QtCore and QtNetwork libs are enabled. If you need more Qt libraries,
|
82
|
+
# place them in ADD_LIBS variable.
|
83
|
+
USE_QT = 0
|
84
|
+
|
85
|
+
# White space separated list of ignored platforms, i.e. platforms this project will _not_ be compiled for.
|
86
|
+
# Possible values depend on your toolchain.
|
87
|
+
# E.g. 'arm-linux-gnueabi i686-linux-gnu'
|
88
|
+
IGNORED_PLATFORMS = ''
|
89
|
+
|
90
|
+
|
91
|
+
### Pass Version String
|
92
|
+
You can pass a version string to all compiled files via environment variable SW_VERSION_ENV. The content of this environment
|
93
|
+
variable is passed to the build in CFLAGS/CXXFLAGS as -DPROGRAM_VERSION.
|
94
|
+
The default value in case no such environment variable is present is "unversioned".
|
95
|
+
|
96
|
+
|
97
|
+
## Usage:
|
98
|
+
rake <target> <TOOLCHAIN_ENV=filename> <RELEASE=1>
|
99
|
+
|
100
|
+
|
101
|
+
Use **` rake all`**<br/>
|
102
|
+
to compile all applications and libraries
|
103
|
+
|
104
|
+
Use **` rake app:all`**<br/>
|
105
|
+
to compile only applications
|
106
|
+
|
107
|
+
Use **` rake lib:all`**<br/>
|
108
|
+
to compile only libraries
|
109
|
+
|
110
|
+
Use **` rake test`**<br/>
|
111
|
+
to execute all unit tests for applications/libraries
|
112
|
+
|
113
|
+
Use **` rake -T `**<br/>
|
114
|
+
for a list of important targets with explanation.
|
115
|
+
|
116
|
+
Use **` rake -T -A `**<br/>
|
117
|
+
for a list of all possible targets.
|
118
|
+
|
119
|
+
|
120
|
+
If no parameter given, **`rake all`** is assumed and the native compiler of the host system is used.<br/>
|
121
|
+
Furthermore without any parameters, no compiler optimization settings are enabled.
|
122
|
+
|
123
|
+
If **`RELEASE`** is set to any value, compilation is executed with optimizations **and** debugging set to on.
|
124
|
+
|
125
|
+
By setting the variable **`TOOLCHAIN_ENV`**, the native toolchain settings can be overwritten with the environment file.<br/>
|
126
|
+
from OpenEmbedded. This file is parsed by RakeOE and configures the specific toolchain settings.
|
127
|
+
|
128
|
+
## Examples:
|
129
|
+
|
130
|
+
1. **`rake`**
|
131
|
+
Uses the native host toolchain as defined in rake/toolchain/environment-setup-native-linux-gnu
|
132
|
+
|
133
|
+
1. **`rake all RELEASE=1`**
|
134
|
+
Same as above but a release build will be triggered
|
135
|
+
|
136
|
+
1. **`rake all TOOLCHAIN_ENV=/data/eldk-5.3/nitrogen/environment-setup-armv7a-vfp-neon-linux-gnueabi`**
|
137
|
+
Cross compiles in debug mode with the cross compiler definitions found in provided ELDK-5.3 environment
|
138
|
+
file.<br/>In this particular case it would cross compile with the armv7a-vfp-neon gcc of a 5.3 ELDK
|
139
|
+
|
140
|
+
|
141
|
+
|
142
|
+
## Shell autocompletion for rake:
|
143
|
+
|
144
|
+
If you'd like to save on key presses when trying to find out which rake task to run, add bash autocompletion for rake tasks like this:
|
145
|
+
|
146
|
+
1. download https://github.com/mernen/completion-ruby/blob/master/completion-rake
|
147
|
+
1. copy downloaded file to /etc/bash_completion.d/rake
|
148
|
+
|
149
|
+
|
150
|
+
* * *
|
151
|
+
|
152
|
+
## Defaults:
|
153
|
+
|
154
|
+
### Directory layout
|
155
|
+
The build systems assumes a directory layout similar to this:
|
156
|
+
|
157
|
+
project-root
|
158
|
+
├── build
|
159
|
+
│ └── <platform>
|
160
|
+
│ ├── dbg
|
161
|
+
│ │ ├── apps
|
162
|
+
│ │ └── libs
|
163
|
+
│ └── release
|
164
|
+
│ ├── apps
|
165
|
+
│ └── libs
|
166
|
+
├── rake
|
167
|
+
├── Rakefile
|
168
|
+
└── src
|
169
|
+
├── 3rdparty
|
170
|
+
│ └── CppUTest
|
171
|
+
│ └── prj.rake
|
172
|
+
├── app
|
173
|
+
│ └── appA
|
174
|
+
│ └── prj.rake
|
175
|
+
└── lib
|
176
|
+
└── libB
|
177
|
+
└── prj.rake
|
178
|
+
|
179
|
+
####build/
|
180
|
+
The build sub directory contains all build artefacts. `<platform>` is the platform specific build directory. For each unique platform a new build<br/>
|
181
|
+
directory is created. Inside those directories the directories `dbg` and `release` are created, depending on if you<br/>
|
182
|
+
started a debug or a release build.<br/>
|
183
|
+
Directly therunder the directories `apps/` and `libs/` can be found in which either application or library binaries are built.<br/>
|
184
|
+
|
185
|
+
Whenever you start a build with a different build configuration of either platform or debug mode, instead of overwriting<br/>
|
186
|
+
binaries from the previous build configuration a separate new directory is used.<br/>
|
187
|
+
|
188
|
+
The build directory setting can be changed via Rakefile.<br/>
|
189
|
+
|
190
|
+
####rake/
|
191
|
+
In this directory most build system relevant files and classes can be found. Most are internal and typically will not<br/>
|
192
|
+
be changed by the user.
|
193
|
+
|
194
|
+
####Rakefile
|
195
|
+
This file is the main Rakefile and will be automatically parsed by Rake. You can do configuration changes here like setting<br/>
|
196
|
+
paths of source/build directories, file suffix assignments, etc.
|
197
|
+
|
198
|
+
####src/
|
199
|
+
The RakeOE build system knows the build primitives *library* and *application*. It expects libraries and<br/>
|
200
|
+
applications to be in separate source directories.<br/>
|
201
|
+
|
202
|
+
By default these are in `src/lib` and `src/app`. The directory `src/3rdparty/` is treated by RakeOE as a normal library<br/>
|
203
|
+
directory and is meant as structural separation between 3rd party components that are not part of the platform SDK and<br/>
|
204
|
+
project specific libraries in `src/lib`.<br/>
|
205
|
+
The directory `src/app/appA` contains some user application project and `src/lib/libB` some user library project.<br/>
|
206
|
+
As mentioned above all those projects beneath `src/` have to contain a `prj.rake` file.
|
207
|
+
|
208
|
+
The source directory setting can be changed via Rakefile.<br/>
|
209
|
+
|
210
|
+
## Installation
|
211
|
+
|
212
|
+
Add this line to your application's Gemfile:
|
213
|
+
|
214
|
+
gem 'rakeoe'
|
215
|
+
|
216
|
+
And then execute:
|
217
|
+
|
218
|
+
$ bundle
|
219
|
+
|
220
|
+
Or install it yourself as:
|
221
|
+
|
222
|
+
$ gem install rakeoe
|
223
|
+
|
224
|
+
## Usage
|
225
|
+
|
226
|
+
TODO: Write usage instructions here
|
227
|
+
|
228
|
+
## Contributing
|
229
|
+
|
230
|
+
1. Fork it
|
231
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
232
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
233
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
234
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/rakeoe/app.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
require 'rakeoe/binary_base'
|
5
|
+
|
6
|
+
module RakeOE
|
7
|
+
|
8
|
+
# Finds all source codes in specified directory
|
9
|
+
# and encapsulates App projects
|
10
|
+
class App < RakeOE::BinaryBase
|
11
|
+
attr_reader :binary
|
12
|
+
|
13
|
+
#
|
14
|
+
# The following parameters are expected in given hash params:
|
15
|
+
#
|
16
|
+
# @param [String] name Name of the application
|
17
|
+
# @param [String] settings Settings for application
|
18
|
+
# @param [String] tool Toolchain builder to use
|
19
|
+
#
|
20
|
+
def initialize(name, settings, tool)
|
21
|
+
super(:name => name,
|
22
|
+
:settings => settings,
|
23
|
+
:bin_dir => tool.settings['APP_OUT'],
|
24
|
+
:toolchain => tool)
|
25
|
+
|
26
|
+
# We need to divide our app into an app lib and the app main object file
|
27
|
+
# for testing.
|
28
|
+
#
|
29
|
+
# This is the convention: 'name.o' is supposed to contain the main() function.
|
30
|
+
# All other object files are linked into a static library 'libname-app.a'.
|
31
|
+
# Finally both are linked together with all dependent external libraries
|
32
|
+
# to the application binary.
|
33
|
+
#
|
34
|
+
# In case of tests, the test objects are linked against 'libname-app.a'
|
35
|
+
# and all dependent external libraries.
|
36
|
+
#
|
37
|
+
@app_main_obj = objs.select{|obj| File.basename(obj) == "#{name}.o"}
|
38
|
+
@app_main_dep = @app_main_obj.map {|obj| obj.ext('.d')}
|
39
|
+
@app_lib_objs = objs - @app_main_obj
|
40
|
+
@app_lib_deps = @app_lib_objs.map {|obj| obj.ext('.d')}
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# create all rules, tasks and dependencies
|
45
|
+
# for the app
|
46
|
+
def create
|
47
|
+
unless project_can_build?
|
48
|
+
disable_build
|
49
|
+
return
|
50
|
+
end
|
51
|
+
|
52
|
+
# create build directory
|
53
|
+
directory build_dir
|
54
|
+
|
55
|
+
binary_targets = paths_of_local_libs() + @app_main_dep + @app_main_obj + [@settings['PRJ_FILE']]
|
56
|
+
|
57
|
+
# This is only necessary if we have more than a single app main file
|
58
|
+
if @app_lib_objs.any?
|
59
|
+
create_app_lib_rules(binary_targets)
|
60
|
+
end
|
61
|
+
|
62
|
+
prj_libs = search_libs(settings)
|
63
|
+
linked_libs = prj_libs[:all]
|
64
|
+
|
65
|
+
file binary => binary_targets do
|
66
|
+
tc.app(:libs => linked_libs,
|
67
|
+
:app => binary,
|
68
|
+
:objects => @app_main_obj,
|
69
|
+
:settings => @settings,
|
70
|
+
:includes => src_dirs)
|
71
|
+
end
|
72
|
+
|
73
|
+
if test_objs.any?
|
74
|
+
create_test_rules(binary_targets, linked_libs)
|
75
|
+
end
|
76
|
+
|
77
|
+
# link dependent library to lib target (e.g. libXXX.a => lib:XXX)
|
78
|
+
# this makes a connection from the dependency in variable libs above to the appropriate rule as defined
|
79
|
+
# inside the lib class. If one would know the absolute path to the library, one could alternatively draw
|
80
|
+
# a dependency to the lib binary instead of the name, then these two rules wouldn't be necessary
|
81
|
+
rule '.a' => [ proc {|tn| 'lib:' + File.basename(tn.name).gsub('lib', '').gsub('.a','') } ]
|
82
|
+
rule '.so' => [ proc {|tn| 'lib:' + File.basename(tn.name).gsub('lib', '').gsub('.so','') } ]
|
83
|
+
|
84
|
+
# create standard rules
|
85
|
+
create_build_rules
|
86
|
+
|
87
|
+
desc "Create #{name}"
|
88
|
+
task name => binary_targets + [binary]
|
89
|
+
|
90
|
+
#desc "Clean #{name}"
|
91
|
+
task name+'_clean' do
|
92
|
+
tc.rm (objs + deps + [binary]).join(' ')
|
93
|
+
end
|
94
|
+
|
95
|
+
# add this application as dependency for the app:all task
|
96
|
+
task :all => name
|
97
|
+
|
98
|
+
# create runner
|
99
|
+
task "#{name}_run" => name do
|
100
|
+
tc.run binary
|
101
|
+
end
|
102
|
+
|
103
|
+
# add files for the clean rule
|
104
|
+
CLEAN.include('*.o', build_dir)
|
105
|
+
CLEAN.include(@app_lib, build_dir)
|
106
|
+
CLEAN.include(binary, build_dir)
|
107
|
+
CLOBBER.include('*.d', build_dir)
|
108
|
+
end
|
109
|
+
|
110
|
+
def create_app_lib_rules(binary_targets)
|
111
|
+
app_lib_targets = @app_lib_deps + @app_lib_objs + [@settings['PRJ_FILE']]
|
112
|
+
file @app_lib => app_lib_targets do
|
113
|
+
tc.lib(:objects => @app_lib_objs,
|
114
|
+
:lib => @app_lib,
|
115
|
+
:settings => @settings)
|
116
|
+
end
|
117
|
+
|
118
|
+
# add this to the dependent targets of app binary
|
119
|
+
binary_targets << @app_lib
|
120
|
+
|
121
|
+
# we treat the app lib as an object file. This makes linking easier.
|
122
|
+
@app_main_obj << @app_lib
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
def create_test_rules(binary_targets, linked_libs)
|
127
|
+
namespace 'test' do
|
128
|
+
desc "Test #{name}"
|
129
|
+
task "#{name}" => test_binary do
|
130
|
+
tc.run(test_binary)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Build the library and execute tests
|
134
|
+
task "#{name}_junit" => test_binary do
|
135
|
+
tc.run_junit_test(test_binary)
|
136
|
+
end
|
137
|
+
|
138
|
+
# 'hidden' task just for building the test
|
139
|
+
task "#{name}_build" => test_binary
|
140
|
+
|
141
|
+
file test_binary => [@test_fw.binary_path] + binary_targets + test_deps + test_objs do
|
142
|
+
tc.test(:objects => test_objs + [@app_lib],
|
143
|
+
:test => test_binary,
|
144
|
+
:libs => linked_libs,
|
145
|
+
:framework => @test_fw.name,
|
146
|
+
:settings => @settings,
|
147
|
+
:includes => test_dirs)
|
148
|
+
end
|
149
|
+
CLEAN.include(test_binary, build_dir)
|
150
|
+
task :all => "#{name}"
|
151
|
+
task :junit => "#{name}_junit"
|
152
|
+
task :build => "#{name}_build"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|