comet-build 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +59 -0
- data/.rspec +1 -0
- data/.rubocop.yml +14 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +58 -0
- data/LICENSE +9 -0
- data/README.md +311 -0
- data/Rakefile +1 -0
- data/bin/comet +30 -0
- data/comet-build.gemspec +26 -0
- data/lib/comet/dsl/bin_output.rb +19 -0
- data/lib/comet/dsl/c/source.rb +57 -0
- data/lib/comet/dsl/cpp/source.rb +57 -0
- data/lib/comet/dsl/elf_output.rb +19 -0
- data/lib/comet/dsl/firmware.rb +65 -0
- data/lib/comet/dsl/hardware.rb +56 -0
- data/lib/comet/dsl/helpers.rb +9 -0
- data/lib/comet/dsl/hex_output.rb +19 -0
- data/lib/comet/dsl/include_walker.rb +42 -0
- data/lib/comet/dsl/library.rb +21 -0
- data/lib/comet/dsl/linker.rb +45 -0
- data/lib/comet/dsl/map_output.rb +19 -0
- data/lib/comet/dsl/native/source.rb +44 -0
- data/lib/comet/dsl/options.rb +44 -0
- data/lib/comet/dsl/software.rb +42 -0
- data/lib/comet/dsl/source.rb +24 -0
- data/lib/comet/dsl/target.rb +64 -0
- data/lib/comet/makefile.rb +129 -0
- data/lib/comet/parser.rb +114 -0
- data/lib/comet/rules/alias.rb +29 -0
- data/lib/comet/rules/build.rb +118 -0
- data/lib/comet/rules/clean.rb +29 -0
- data/lib/comet/rules/codegen.rb +51 -0
- data/lib/comet/rules/compile.rb +72 -0
- data/lib/comet/rules/error.rb +33 -0
- data/lib/comet/rules/link.rb +74 -0
- data/lib/comet/rules/merge.rb +37 -0
- data/lib/comet/rules/objcopy.rb +41 -0
- data/lib/comet/rules/tmpdir.rb +39 -0
- data/lib/comet/version.rb +3 -0
- data/lib/comet.rb +76 -0
- data/spec/comet/complex_c_program/Makefile +57 -0
- data/spec/comet/complex_c_program/comet.rb +43 -0
- data/spec/comet/complex_c_program/include/public_api.h +2 -0
- data/spec/comet/complex_c_program/src/common.h +3 -0
- data/spec/comet/complex_c_program/src/library.h +2 -0
- data/spec/comet/complex_c_program/src/main.c +6 -0
- data/spec/comet/complex_c_program/src/module_a/impl.c +1 -0
- data/spec/comet/complex_c_program/src/module_a/impl.h +1 -0
- data/spec/comet/complex_c_program/src/module_b/impl.c +1 -0
- data/spec/comet/complex_c_program/src/module_b/impl.h +1 -0
- data/spec/comet/empty_build_file/Makefile +10 -0
- data/spec/comet/empty_build_file/comet.rb +0 -0
- data/spec/comet/empty_build_file/folder/.keep +0 -0
- data/spec/comet/generator_spec.rb +67 -0
- data/spec/comet/nested_circular_reference/Makefile +5 -0
- data/spec/comet/nested_circular_reference/comet.rb +8 -0
- data/spec/comet/no_build_file/Makefile +5 -0
- data/spec/comet/self_referential/Makefile +5 -0
- data/spec/comet/self_referential/comet.rb +5 -0
- data/spec/comet/simple_c_program/Makefile +30 -0
- data/spec/comet/simple_c_program/comet.rb +15 -0
- data/spec/comet/simple_c_program/main.c +5 -0
- data/spec/comet/simple_c_program/stuff.h +0 -0
- metadata +215 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 670917577b152678f86951ca8a0e93a869913be0
|
4
|
+
data.tar.gz: c748f50c7ae73456251b01826c8ddb8d4f257b3d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a6d1fcb5c2fe0ea3d5d3cbfa1a13c85b63cae9ae8e45405f61a705d5f899f9812a32b0bc7691eec9cbc22ae3a945550467d1c5c8bdea87b3654512ac3ee24cc5
|
7
|
+
data.tar.gz: 4cab4c5ecec92d24f0ecc1fd83a9ef6a7412d8b7ec90c5241f3cbd697673c847b54f443875227131dd56e66aea158f64a14f2997e44f0f918a2eed9cc425ae8f
|
data/.gitignore
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
## Specific to RubyMotion:
|
17
|
+
.dat*
|
18
|
+
.repl_history
|
19
|
+
build/
|
20
|
+
*.bridgesupport
|
21
|
+
build-iPhoneOS/
|
22
|
+
build-iPhoneSimulator/
|
23
|
+
|
24
|
+
## Specific to RubyMotion (use of CocoaPods):
|
25
|
+
#
|
26
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
27
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
28
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
29
|
+
#
|
30
|
+
# vendor/Pods/
|
31
|
+
|
32
|
+
## Documentation cache and generated files:
|
33
|
+
/.yardoc/
|
34
|
+
/_yardoc/
|
35
|
+
/doc/
|
36
|
+
/rdoc/
|
37
|
+
|
38
|
+
## Environment normalization:
|
39
|
+
/.bundle/
|
40
|
+
/vendor/bundle
|
41
|
+
/lib/bundler/man/
|
42
|
+
|
43
|
+
# for a library or gem, you might want to ignore these files since the code is
|
44
|
+
# intended to run in multiple environments; otherwise, check them in:
|
45
|
+
# Gemfile.lock
|
46
|
+
# .ruby-version
|
47
|
+
# .ruby-gemset
|
48
|
+
|
49
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
50
|
+
.rvmrc
|
51
|
+
|
52
|
+
# avoid checking in temporary build folders
|
53
|
+
.comet
|
54
|
+
|
55
|
+
# various backup files from editors
|
56
|
+
*~
|
57
|
+
~*
|
58
|
+
.swp*
|
59
|
+
.swo*
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-c -f documentation --order random
|
data/.rubocop.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
comet (0.1.0)
|
5
|
+
require_all
|
6
|
+
slop
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
ast (2.3.0)
|
12
|
+
diff-lcs (1.3)
|
13
|
+
parallel (1.12.0)
|
14
|
+
parser (2.4.0.0)
|
15
|
+
ast (~> 2.2)
|
16
|
+
powerpack (0.1.1)
|
17
|
+
rainbow (2.2.2)
|
18
|
+
rake
|
19
|
+
rake (12.0.0)
|
20
|
+
require_all (1.4.0)
|
21
|
+
rspec (3.6.0)
|
22
|
+
rspec-core (~> 3.6.0)
|
23
|
+
rspec-expectations (~> 3.6.0)
|
24
|
+
rspec-mocks (~> 3.6.0)
|
25
|
+
rspec-core (3.6.0)
|
26
|
+
rspec-support (~> 3.6.0)
|
27
|
+
rspec-expectations (3.6.0)
|
28
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
29
|
+
rspec-support (~> 3.6.0)
|
30
|
+
rspec-mocks (3.6.0)
|
31
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
32
|
+
rspec-support (~> 3.6.0)
|
33
|
+
rspec-support (3.6.0)
|
34
|
+
rubocop (0.49.1)
|
35
|
+
parallel (~> 1.10)
|
36
|
+
parser (>= 2.3.3.1, < 3.0)
|
37
|
+
powerpack (~> 0.1)
|
38
|
+
rainbow (>= 1.99.1, < 3.0)
|
39
|
+
ruby-progressbar (~> 1.7)
|
40
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
41
|
+
rubocop-rspec (1.15.1)
|
42
|
+
rubocop (>= 0.42.0)
|
43
|
+
ruby-progressbar (1.8.1)
|
44
|
+
slop (4.5.0)
|
45
|
+
unicode-display_width (1.3.0)
|
46
|
+
|
47
|
+
PLATFORMS
|
48
|
+
ruby
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
bundler (~> 1.7)
|
52
|
+
comet!
|
53
|
+
rake (~> 12.0)
|
54
|
+
rspec
|
55
|
+
rubocop-rspec
|
56
|
+
|
57
|
+
BUNDLED WITH
|
58
|
+
1.15.3
|
data/LICENSE
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Thomas Bénéteau
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
6
|
+
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,311 @@
|
|
1
|
+
Comet
|
2
|
+
=====
|
3
|
+
|
4
|
+
Comet is a no-nonsense build tool primarily oriented towards embedded or cross-compiled applications written in languages that can compile to LLVM bitcode, such as C, C++, D, etc. It adheres to four core principles:
|
5
|
+
|
6
|
+
* **Simplicity**: Your build tool should be your friend, not your enemy. Comet does not force you to learn crazy languages and use strange idiosyncracies to build your program, instead exposing a simple and pleasant DSL to describe how you want your program built.
|
7
|
+
|
8
|
+
* **Predictability**: Good software should be predictable, so Comet requires you to specify every aspect of your build configuration, leaving no opportunity for hazardous defaults to sneak in. Comet also steers you away from bad practices by enforcing sane conventions.
|
9
|
+
|
10
|
+
* **Focus**: Comet does not try to deal with the rest of your release process, such as generating documentation, preparing artifacts, running tests, and so on. Comet is concerned solely with the process of building your source files into executables, and is easily integrated into other scripts.
|
11
|
+
|
12
|
+
* **Performance**: Due to Comet's design and LLVM integration, you get many features for free such as whole-program optimization, cross-compilation and multi-language support. Comet itself is also efficient and does not slow down your builds.
|
13
|
+
|
14
|
+
Functionally, Comet is a Makefile generator which accepts a domain-specific language from a build file, produces a Makefile, and executes it, placing all intermediate files inside a hidden `.comet` temporary directory. The only thing you need to do as a developer is write your `comet.rb` build file and add `.comet` to your gitignore file.
|
15
|
+
|
16
|
+
**WARNING**: this software is still in the testing phase, use in production at your own risk. Improvement suggestions and pull requests are welcome and appreciated. Currently only the C language is supported (C++ will be added shortly) and the tool probably only works on Linux as of now, but just a couple parts of the code are OS-dependent.
|
17
|
+
|
18
|
+
Installation
|
19
|
+
------------
|
20
|
+
|
21
|
+
gem install comet-build
|
22
|
+
|
23
|
+
Comet wraps Make, consuming only two command line arguments and forwarding the rest.
|
24
|
+
|
25
|
+
- `-f PATH`: search for the build file at the specified path instead of `comet.rb`
|
26
|
+
- `-s`: don't execute the generated Makefile, print it to standard output instead
|
27
|
+
|
28
|
+
Comet generates the following convenience Make targets:
|
29
|
+
|
30
|
+
- `all`: build absolutely everything (this is also the default target)
|
31
|
+
- `clean`: delete the `.comet` folder (there is no invididual clean)
|
32
|
+
|
33
|
+
It doesn't matter where in your source tree you invoke Comet, as it will walk its way back up the filesystem looking for your build file until it hits a filesystem boundary, similar to Git. Furthermore, the `.comet` folder is always next to the build file Comet is operating on.
|
34
|
+
|
35
|
+
No external (non-Ruby) dependencies are required for *generating* the Makefile. However, the Makefile itself expects the Clang and LLVM tools to be installed in the user's path. If cross-compiling, it also requires the appropriate binutils toolchains to be installed, e.g. `arm-none-eabi` for embedded ARM software. When executing the Makefile, Comet will call out to the system's Make implementation, which can be overridden with the `MAKE` environment variable.
|
36
|
+
|
37
|
+
Supported Languages
|
38
|
+
-------------------
|
39
|
+
|
40
|
+
Language support for compiling source files is shown below. Adding support for a language consists of supplying a suitable DSL object for it, and implementing a Make rule to compile source files of this language into a single LLVM bitcode file. This Make rule will need to call out to language-specific compilers and other tools, which should be documented in the table below.
|
41
|
+
|
42
|
+
| Language | DSL keyword | Required compilers |
|
43
|
+
| -------- | ----------- | ------------------ |
|
44
|
+
| *Native* | `:native` | None (link-only) |
|
45
|
+
| C | `:c` | Clang |
|
46
|
+
|
47
|
+
Native languages are those for which the source code is either already LLVM bitcode, or is already in a lower representation than LLVM IR, such as assembly. These will be passed directly to the linker after compiled LLVM bitcode, therefore:
|
48
|
+
|
49
|
+
* they cannot reference symbols from non-native source files
|
50
|
+
* they must be given in the usual "reverse dependency" order
|
51
|
+
* they must actually be accepted by the linker as input files
|
52
|
+
|
53
|
+
Planned features
|
54
|
+
----------------
|
55
|
+
|
56
|
+
- C++ language support
|
57
|
+
- Windows support
|
58
|
+
- Clarification of linker parameters (triple, isa, cpu)
|
59
|
+
- Ability to import other build files recursively
|
60
|
+
- Integration with other build systems when linking vendored libraries
|
61
|
+
|
62
|
+
Build File Syntax
|
63
|
+
-----------------
|
64
|
+
|
65
|
+
The Ruby DSL used for describing your program is very straightforward. You begin by defining three high-level structures:
|
66
|
+
|
67
|
+
- `software`, describing hardware-agnostic source code
|
68
|
+
- `hardware`, describing source code tied to a specific device
|
69
|
+
- `firmware`, describing software/hardware combinations of interest
|
70
|
+
|
71
|
+
All paths in the build file are relative to the build file's location. Spaces in filenames are **not** supported. The ordering of distinct directives is unimportant, i.e. you do not have to specify them in this order. The relative ordering of some directives, however, is meaningful, such as library imports which are passed to the linker in order of appearance.
|
72
|
+
|
73
|
+
Note that Ruby allows you to write blocks with either `do` and `end` or curly braces. Curly brace blocks are not always usable syntactically in some cases, but the DSL does not hit any of them, so just use whichever style you prefer - `do` and `end` will be used throughout this section.
|
74
|
+
|
75
|
+
### Software Directive
|
76
|
+
|
77
|
+
A `software` directive must be uniquely named, and may include any number of `source` directives (but at least one) describing the source code contained under it. It may also include any number of dependencies, which can be either software or hardware directives, referenced by name. Software directives cannot include *native* source directives.
|
78
|
+
|
79
|
+
#### Grammar
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
software 'name', depends: ['dep1', 'dep2', ...] do
|
83
|
+
# source directives
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
#### Examples
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
software 'i2c', depends: ['i2c-hal'] do
|
91
|
+
source language: :c, headers: 'include' do
|
92
|
+
import 'src/drivers/i2c.c'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
### Hardware Directive
|
98
|
+
|
99
|
+
A `hardware` directive need not be uniquely named (it is namespaced by the device it targets) and may include any number of `source` directives, including none at all. It must specify a single `targets:` parameter, indicating which device is being targeted; the device name itself is arbitrary and is referenced in subsequent `firmware` directives. If native source directives are included, they must be compatible with the targeted device.
|
100
|
+
|
101
|
+
#### Grammar
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
hardware 'name', targets: :device do
|
105
|
+
# source directives
|
106
|
+
# import directives
|
107
|
+
# linker directive
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
#### Examples
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
hardware 'startup', targets: :lpc1114 do
|
115
|
+
linker 'arm-none-eabi', isa: 'armv6', cpu: 'cortex-m0' do
|
116
|
+
script 'src/LPC1114.ld'
|
117
|
+
option :nostdlib
|
118
|
+
end
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
122
|
+
### Firmware Directive
|
123
|
+
|
124
|
+
A `firmware` directive must be uniquely named, and takes an `imports` parameter referencing `software` directives by name. It may include any number of `target` directives, enumerating which devices to build the imported software for. A firmware directive becomes a Make target of the same name, which will build the firmware against *all* the specified devices. Additional Make targets of the form `firmware/device` will build it for individual devices.
|
125
|
+
|
126
|
+
#### Grammar
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
firmware 'name', imports: ['software1', 'software2', ...] do
|
130
|
+
# target directives
|
131
|
+
end
|
132
|
+
```
|
133
|
+
|
134
|
+
#### Examples
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
firmare 'hello_world', imports: ['hello_world_main'] do
|
138
|
+
target :linux_x64 do
|
139
|
+
elf 'bin/hello_world'
|
140
|
+
end
|
141
|
+
end
|
142
|
+
```
|
143
|
+
|
144
|
+
### Linker Directive
|
145
|
+
|
146
|
+
Exactly one hardware directive per firmware per device must have a linker directive, which describes how the source code is to be linked together into an executable. The optimization parameter is used for whole-program link time optimization, and can be either a symbol or an integer passed to the linker via `-O`, e.g. `2` for `-O2` or `:fast` for `-Ofast`. Options are passed as-is to the linker, and a linker script can be provided.
|
147
|
+
|
148
|
+
#### Grammar
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
linker 'triple', isa: 'isa', cpu: 'cpu', opt: :opt do
|
152
|
+
# option directives
|
153
|
+
# script directive
|
154
|
+
end
|
155
|
+
```
|
156
|
+
|
157
|
+
#### Example
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
linker 'arm-none-eabi', isa: 'armv6-m', cpu: 'cortex-m0', opt: :fast do
|
161
|
+
script 'src/cortex-m0.ld'
|
162
|
+
option :nostdlib
|
163
|
+
end
|
164
|
+
```
|
165
|
+
|
166
|
+
### Target Directive
|
167
|
+
|
168
|
+
A `target` directive takes a single device name as a parameter, and includes any number of output directives such as `elf` or `bin`. These directives control whether to generate a given build artifact, and where to place it.
|
169
|
+
|
170
|
+
The following output directives are available:
|
171
|
+
|
172
|
+
- `elf`: links the software for the device into an ELF file
|
173
|
+
- `bin`: runs the ELF file through `objcopy -O binary`
|
174
|
+
- `hex`: runs the ELF file through `objcopy -O ihex`
|
175
|
+
- `map`: generates a map file while linking
|
176
|
+
|
177
|
+
#### Grammar
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
target :device do
|
181
|
+
# elf directive
|
182
|
+
# bin directive
|
183
|
+
# hex directive
|
184
|
+
# map directive
|
185
|
+
end
|
186
|
+
```
|
187
|
+
|
188
|
+
#### Examples
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
target :cortex_m4 do
|
192
|
+
elf 'bin/program.elf'
|
193
|
+
map 'bin/program_layout.map'
|
194
|
+
end
|
195
|
+
```
|
196
|
+
|
197
|
+
### Source Directive
|
198
|
+
|
199
|
+
A source directive represents a collection of source files of the same language and configuration. All parameters and nested directives depend on the language selected, which the exception of `language:` which specifies said language.
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
source language: :language, ... do
|
203
|
+
# language-specific directives
|
204
|
+
end
|
205
|
+
```
|
206
|
+
|
207
|
+
### Native Source Directive
|
208
|
+
|
209
|
+
Native source directives have no options besides importing files. The source files provided will be passed directly to the linker, in the order given, with no processing performed on them. They can be whatever format the linker understands, such as assembly files or object files for the correct architecture.
|
210
|
+
|
211
|
+
#### Grammar
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
source language: :native do
|
215
|
+
# import directives
|
216
|
+
end
|
217
|
+
```
|
218
|
+
|
219
|
+
#### Examples
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
source language: :native do
|
223
|
+
import 'src/main.S'
|
224
|
+
import 'lib/startup-armv6.o'
|
225
|
+
end
|
226
|
+
```
|
227
|
+
|
228
|
+
### C Source Directive
|
229
|
+
|
230
|
+
C source directives take an array of header include paths as a parameter, and accept source file import directives, option directives (to pass in compiler flags) and define directives (to pass in preprocessor macros).
|
231
|
+
|
232
|
+
#### Grammar
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
source language: :c, headers: ['dir1', 'dir2', ...] do
|
236
|
+
# import directives
|
237
|
+
# option directives
|
238
|
+
# define directives
|
239
|
+
end
|
240
|
+
```
|
241
|
+
|
242
|
+
#### Examples
|
243
|
+
|
244
|
+
```ruby
|
245
|
+
source language: :c do
|
246
|
+
import 'src/main.c'
|
247
|
+
option :ffreestanding
|
248
|
+
define :NDEBUG
|
249
|
+
define :_POSIX_C_SOURCE => '200809L'
|
250
|
+
end
|
251
|
+
```
|
252
|
+
|
253
|
+
Advanced Usage
|
254
|
+
--------------
|
255
|
+
|
256
|
+
### Mixins and Ruby Procs
|
257
|
+
|
258
|
+
You can use Ruby procs together with the `inject` shorthand, which will effectively run your proc in the context of a directive, like so:
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
cflags = proc do
|
262
|
+
option :myflag => 'myvalue'
|
263
|
+
end
|
264
|
+
|
265
|
+
# later...
|
266
|
+
|
267
|
+
source language: :c do
|
268
|
+
inject &cflags
|
269
|
+
end
|
270
|
+
```
|
271
|
+
|
272
|
+
### Using Ruby in the build file
|
273
|
+
|
274
|
+
The build file is otherwise ordinary Ruby code extended with a custom DSL, therefore you can write any Ruby code inside it, although it is encouraged to keep the build file free of undocumented dependencies such as gems or external commands. For instance, you can do this:
|
275
|
+
|
276
|
+
```ruby
|
277
|
+
source language: :c, headers: 'include' do
|
278
|
+
define :VERSION => quote(`git rev-parse HEAD`)
|
279
|
+
end
|
280
|
+
```
|
281
|
+
|
282
|
+
### Hardware Abstraction Layers
|
283
|
+
|
284
|
+
Because hardware directive names are namespaced by the device they target, HALs are supported by default, as shown below. When built for a given device, this `hal` software directive will resolve to the appropriate hardware directive for that device, assuming one is present:
|
285
|
+
|
286
|
+
```ruby
|
287
|
+
software 'module', depends: ['hal'] do
|
288
|
+
# ...
|
289
|
+
end
|
290
|
+
|
291
|
+
hardware 'hal', targets: :device1 do
|
292
|
+
# ...
|
293
|
+
end
|
294
|
+
|
295
|
+
hardware 'hal', targets: :device2 do
|
296
|
+
# ...
|
297
|
+
end
|
298
|
+
```
|
299
|
+
|
300
|
+
### Some helper Ruby methods
|
301
|
+
|
302
|
+
In the spirit of its DSL, Comet defines some convenience methods to make your build file more expressive.
|
303
|
+
|
304
|
+
#### quote
|
305
|
+
|
306
|
+
The **quote** method will take a string, strip any surrounding whitespace, and surround the result in double quotes. This is useful for passing strings to the C preprocessor through macros. For instance, `define :FOO => quote('bar')` translates to `-DFOO=\"bar\"` which is equivalent to `#define FOO "bar"`.
|
307
|
+
|
308
|
+
License
|
309
|
+
-------
|
310
|
+
|
311
|
+
This software is released under the MIT license. See the LICENSE file for details.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/bin/comet
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'comet'
|
4
|
+
require 'slop'
|
5
|
+
|
6
|
+
# HACK: until https://github.com/leejarvis/slop/pull/214 is fixed
|
7
|
+
ARGV.unshift '-f', 'comet.rb' if !ARGV.empty? && ARGV[0] == '--'
|
8
|
+
|
9
|
+
options = Slop.parse suppress_errors: true do |opts|
|
10
|
+
opts.banner = 'Usage: comet [-f PATH] [-s] [make arguments...]'
|
11
|
+
opts.string '-f', 'filename of build file', default: 'comet.rb'
|
12
|
+
opts.bool '-V', 'show all makefile output', default: false
|
13
|
+
opts.bool '-s', 'show produced makefile', default: false
|
14
|
+
opts.on '--version', 'print the tool version' do
|
15
|
+
puts "comet v#{Comet::VERSION}"
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
opts.on '-h', '--help', 'show this help message' do
|
19
|
+
puts opts
|
20
|
+
exit
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
generator = Comet::Generator.new(options[:f])
|
25
|
+
|
26
|
+
if options[:s]
|
27
|
+
puts generator.makefile.contents
|
28
|
+
else
|
29
|
+
generator.makefile.execute options.arguments, verbose: options[:V]
|
30
|
+
end
|
data/comet-build.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
lib = File.expand_path '../lib', __FILE__
|
2
|
+
$LOAD_PATH.unshift lib unless $LOAD_PATH.include? lib
|
3
|
+
require 'comet/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.authors = ['Thomas Beneteau']
|
7
|
+
gem.email = ['thomas@bitwise.me']
|
8
|
+
gem.description = 'The no-nonsense build tool for embedded software'
|
9
|
+
gem.summary = 'Comet is a fast and simple LLVM-oriented build tool'
|
10
|
+
gem.homepage = 'https://github.com/TomCrypto/Comet'
|
11
|
+
|
12
|
+
gem.files = `git ls-files`.split($\)
|
13
|
+
gem.executables = ['comet']
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.name = 'comet-build'
|
16
|
+
gem.require_paths = ['lib']
|
17
|
+
gem.version = Comet::VERSION
|
18
|
+
|
19
|
+
gem.add_development_dependency 'bundler', '~> 1.7'
|
20
|
+
gem.add_development_dependency 'rake', '~> 12.0'
|
21
|
+
gem.add_development_dependency 'rspec'
|
22
|
+
gem.add_development_dependency 'rubocop-rspec'
|
23
|
+
|
24
|
+
gem.add_runtime_dependency 'require_all'
|
25
|
+
gem.add_runtime_dependency 'slop'
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Comet
|
2
|
+
module DSL
|
3
|
+
class BinOutput
|
4
|
+
def initialize(path)
|
5
|
+
@path = path
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
'bin output'
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :path
|
13
|
+
|
14
|
+
def validate!
|
15
|
+
raise "#{self} path is invalid" if @path.strip.empty?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Comet
|
2
|
+
module DSL
|
3
|
+
module C
|
4
|
+
class Source
|
5
|
+
include Comet::DSL::Helpers
|
6
|
+
alias inject instance_exec
|
7
|
+
|
8
|
+
def import(pattern)
|
9
|
+
@imports.push pattern
|
10
|
+
end
|
11
|
+
|
12
|
+
def option(*args, **kwargs)
|
13
|
+
@options.add('', *args, **kwargs)
|
14
|
+
end
|
15
|
+
|
16
|
+
def define(*args, **kwargs)
|
17
|
+
@options.add('D', *args, **kwargs)
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(headers:, &block)
|
21
|
+
@headers = headers
|
22
|
+
@imports = []
|
23
|
+
@options = Comet::DSL::Options.new
|
24
|
+
|
25
|
+
instance_exec(&block) if block_given?
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
'C source'
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :headers
|
33
|
+
attr_reader :imports
|
34
|
+
attr_reader :options
|
35
|
+
|
36
|
+
def language
|
37
|
+
:c
|
38
|
+
end
|
39
|
+
|
40
|
+
def native?
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
def files
|
45
|
+
@imports.flat_map do |pattern|
|
46
|
+
Dir.glob pattern
|
47
|
+
end.uniq
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate!
|
51
|
+
raise "#{self} references no source files" if @imports.empty?
|
52
|
+
@options.validate!
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Comet
|
2
|
+
module DSL
|
3
|
+
module CPP
|
4
|
+
class Source
|
5
|
+
include Comet::DSL::Helpers
|
6
|
+
alias inject instance_exec
|
7
|
+
|
8
|
+
def import(pattern)
|
9
|
+
@imports.push pattern
|
10
|
+
end
|
11
|
+
|
12
|
+
def option(*args, **kwargs)
|
13
|
+
@options.add('', *args, **kwargs)
|
14
|
+
end
|
15
|
+
|
16
|
+
def define(*args, **kwargs)
|
17
|
+
@options.add('D', *args, **kwargs)
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(headers:, &block)
|
21
|
+
@headers = headers
|
22
|
+
@imports = []
|
23
|
+
@options = Comet::DSL::Options.new
|
24
|
+
|
25
|
+
instance_exec(&block) if block_given?
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
'C++ source'
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :headers
|
33
|
+
attr_reader :imports
|
34
|
+
attr_reader :options
|
35
|
+
|
36
|
+
def language
|
37
|
+
:cpp
|
38
|
+
end
|
39
|
+
|
40
|
+
def native?
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
def files
|
45
|
+
@imports.flat_map do |pattern|
|
46
|
+
Dir.glob pattern
|
47
|
+
end.uniq
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate!
|
51
|
+
raise "#{self} references no source files" if @imports.empty?
|
52
|
+
@options.validate!
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Comet
|
2
|
+
module DSL
|
3
|
+
class ElfOutput
|
4
|
+
def initialize(path)
|
5
|
+
@path = path
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
'elf output'
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :path
|
13
|
+
|
14
|
+
def validate!
|
15
|
+
raise "#{self} path is invalid" if @path.strip.empty?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|