rake-arduino 0.0.1.alpha

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ build/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rake-arduino.gemspec
4
+ gemspec
@@ -0,0 +1,78 @@
1
+ rake-arduino
2
+ ============
3
+ _A Flexible build tool for Arduino development_
4
+
5
+ ## Usage
6
+ _`rake-arduino` is very pre-alpha at the moment. Be prepared to find and fix a
7
+ lot of bugs while using it._
8
+
9
+ After installing the gem (see below), simply add a Rakefile that looks like
10
+ this to the root of your project:
11
+
12
+ require 'rubygems'
13
+ require 'rake/arduino'
14
+
15
+ Rake::Arduino::Sketch.new do |s|
16
+ s.sources << "MySketch.cpp"
17
+ s.libraries << "Servo"
18
+
19
+ s.board = Rake::Arduino::Board["Arduino Uno"]
20
+ end
21
+
22
+ See the `examples` directory for more advanced usage.
23
+
24
+ Then, to build your project run:
25
+
26
+ rake
27
+
28
+ To upload it to your arduino:
29
+
30
+ rake upload
31
+
32
+ If your arduino installation is somewhere non-standard, you'll need to
33
+ configure that at the top of your Rakefile:
34
+
35
+ Rake::Arduino.configure do |c|
36
+ c.home = "/home/me/apps/arduino-0022"
37
+ end
38
+
39
+ ## Installation
40
+ You'll need ruby and rubygems installed (use your system's package manager, or
41
+ RVM).
42
+
43
+ As a gem:
44
+
45
+ gem install rake-arduino
46
+
47
+ From source:
48
+
49
+ gem install bundler rake
50
+
51
+ git clone https://github.com/wjbuys/rake-arduino
52
+ cd rake-arduino
53
+ rake install
54
+
55
+ ## Background
56
+ Arduino is great. The arduino IDE: not so great. Once your project moves beyond
57
+ a nontrivial size, it's a massive pain to use. Sorry Arduino team, but it's
58
+ just painful and ugly (and stupid, if you're used to Vim/Emacs).
59
+
60
+ At this point all the gurus say: "Just use a `Makefile`!". Unfortunately, this
61
+ becomes a very roll-your-own mission (there's no centrally maintained version).
62
+
63
+ Also, the `Makefile` syntax makes my eyes bleed. Inevitably multiple copies of
64
+ the same `Makefile` with minor tweaks will end up around all my projects, because
65
+ I'm lazy.
66
+
67
+ *Luckily, there's a solution: _Rake_.* Rake is Ruby, so
68
+
69
+ 1. the syntax is gorgeous,
70
+ 1. you get a real programming language to do additional pre-processing,
71
+ 1. and you can wrap common logic up neatly into a central library.
72
+
73
+ ## TODO
74
+
75
+ 1. Support `.pde` sketch pre-processing
76
+ 1. Add some specs (I just ripped this out of a project I was working on, so no
77
+ tests :( )
78
+ 1. Support config from ~/.rake-arduino
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,14 @@
1
+ #include <WProgram.h>
2
+
3
+ int led = 11;
4
+
5
+ void setup() {
6
+ pinMode(led, OUTPUT);
7
+ };
8
+
9
+ void loop() {
10
+ digitalWrite(led, HIGH);
11
+ delay(1000);
12
+ digitalWrite(led, LOW);
13
+ delay(1000);
14
+ };
@@ -0,0 +1,25 @@
1
+ $:.unshift "../../lib"
2
+ require 'rake/arduino'
3
+
4
+ # The basic configuration of a project is done via the
5
+ # Rake::Arduino::Sketch task:
6
+
7
+ Rake::Arduino::Sketch.new do |s|
8
+ # Add your main source files to the s.sources array:
9
+ s.sources << "Blink.cpp"
10
+
11
+ # If you need any Arduino libraries, add them to s.libraries:
12
+ s.libraries << "Servo"
13
+
14
+ # Specify the board you'd like to use. Boards are defined
15
+ # in lib/rake/arduino/boards.rb, and referenced by name:
16
+ s.board = Rake::Arduino.board("Arduino Uno") do |b|
17
+
18
+ # In the board block, you can customize board parameters
19
+ # for your specific needs.
20
+ b.cpu_speed = 8000000
21
+
22
+ # See the Board class docs for a full list of settings that
23
+ # can be configured.
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ #include <WProgram.h>
2
+
3
+ int led = 11;
4
+
5
+ void setup() {
6
+ pinMode(led, OUTPUT);
7
+ };
8
+
9
+ void loop() {
10
+ digitalWrite(led, HIGH);
11
+ delay(1000);
12
+ digitalWrite(led, LOW);
13
+ delay(1000);
14
+ };
@@ -0,0 +1,33 @@
1
+ $:.unshift "../../lib"
2
+ require 'rake/arduino'
3
+
4
+ # rake-arduino supports defining multiple targets in a single rakefile.
5
+ # This allows you to build variations on the same project quite easily.
6
+ # Say, for example, you'd like to compile hex files for both the classic
7
+ # arduino, and for the Teensy:
8
+
9
+ Rake::Arduino::Sketch.new :arduino do |s|
10
+ s.sources << "Blink.cpp"
11
+ s.board = Rake::Arduino.board("Arduino Uno")
12
+ end
13
+
14
+ Rake::Arduino::Sketch.new :teensy do |s|
15
+ s.sources << "Blink.cpp"
16
+ s.board = Rake::Arduino.board("Teensy 2.0")
17
+ end
18
+
19
+ # Now you can build each target with `rake <target>`
20
+ # If you want to build them all at once, add a default task that references
21
+ # both targets:
22
+
23
+ task :default => [:arduino, :teensy]
24
+
25
+ # You can even have both platforms built in parallel:
26
+
27
+ multitask :all => [:arduino, :teensy]
28
+
29
+ # Now `rake` will build .hex files for both platforms in one go.
30
+ #
31
+ # Note: Your targets don't have to relate to each other at all. If you'd
32
+ # like to build completely separate projects from the same Rakefile, you
33
+ # can do that too.
@@ -0,0 +1,10 @@
1
+ module Rake
2
+ module Arduino
3
+ require "rake/arduino/version"
4
+ require "rake/arduino/config"
5
+ require "rake/arduino/toolchain"
6
+ require "rake/arduino/board"
7
+ require "rake/arduino/boards"
8
+ require "rake/arduino/sketch"
9
+ end
10
+ end
@@ -0,0 +1,37 @@
1
+ module Rake
2
+ module Arduino
3
+ class Board
4
+ attr_accessor :name
5
+ attr_accessor :cores, :defines
6
+ attr_accessor :mcu, :cpu_speed
7
+ attr_accessor :max_size
8
+
9
+ @boards = {}
10
+ def self.[](name)
11
+ @boards[name]
12
+ end
13
+
14
+ def self.register(board)
15
+ @boards[board.name] = board
16
+ end
17
+
18
+ def register
19
+ self.class.register(self)
20
+ end
21
+
22
+ def initialize(name)
23
+ self.name = name
24
+ self.defines = []
25
+ self.cores = []
26
+
27
+ yield self if block_given?
28
+ end
29
+ end
30
+
31
+ def self.board(name)
32
+ board = Board[name]
33
+ yield board if block_given?
34
+ board
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,16 @@
1
+ module Rake::Arduino
2
+ Board.new("Arduino Uno") do |b|
3
+ b.cores = ["arduino"]
4
+ b.cpu_speed = 16000000
5
+ b.mcu = "atmega328p"
6
+ b.max_size = 30720
7
+ end.register
8
+
9
+ Board.new("Teensy 2.0") do |b|
10
+ b.cores = ["teensy", "usb_serial"]
11
+ b.defines = ["USB_SERIAL"]
12
+ b.cpu_speed = 16000000
13
+ b.mcu = "atmega32u4"
14
+ b.max_size = 32256
15
+ end.register
16
+ end
@@ -0,0 +1,34 @@
1
+ module Rake
2
+ module Arduino
3
+ class Config
4
+ attr_accessor :home, :hardware_path, :library_path
5
+ attr_accessor :cores
6
+
7
+ def initialize
8
+ yield self if block_given?
9
+
10
+ self.home ||= ENV["HOME"] + "/apps/arduino"
11
+
12
+ self.hardware_path ||= home + "/hardware"
13
+ self.library_path ||= home + "/libraries"
14
+
15
+ self.cores ||= Dir.glob(hardware_path + "/**/cores/*")
16
+ end
17
+
18
+ def self.read_defaults
19
+ load ENV["HOME"] + "/.rake-arduino"
20
+ rescue LoadError
21
+ end
22
+ end
23
+
24
+ class << self
25
+ def config
26
+ @config ||= Config.new
27
+ end
28
+
29
+ def configure(&block)
30
+ @config = Config.new(&block)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ require 'pathname'
2
+
3
+ class Array
4
+ def to_paths
5
+ self.map do |path|
6
+ Pathname(path) unless path.is_a? Pathname
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ require 'pathname'
2
+
3
+ class Pathname
4
+ def to_str; to_s; end
5
+ end
@@ -0,0 +1,156 @@
1
+ require 'rake/arduino/core_ext/pathname'
2
+ require 'rake/arduino/core_ext/array'
3
+
4
+ module Rake
5
+ module Arduino
6
+ class Sketch
7
+ include Rake::DSL
8
+
9
+ attr_accessor :sources
10
+ attr_accessor :name
11
+ attr_accessor :target
12
+ attr_accessor :board
13
+ attr_accessor :libraries
14
+ attr_accessor :hex, :elf
15
+ attr_accessor :programmer, :upload_rate
16
+ attr_accessor :usb_type
17
+ attr_accessor :build_root, :root
18
+ attr_accessor :toolchain
19
+
20
+ def initialize(target = :default)
21
+ Config.read_defaults
22
+
23
+ self.target = target.to_sym
24
+ self.build_root = "build/#{target}"
25
+
26
+ self.root = Pathname.pwd
27
+
28
+ self.sources = []
29
+ self.libraries = []
30
+
31
+ yield self
32
+
33
+ raise "You have to specify a board for the sketch" unless board
34
+
35
+ self.sources = sources.to_paths
36
+ self.build_root = Pathname(build_root)
37
+
38
+ self.name ||= root.basename.to_s
39
+
40
+ self.elf ||= build("#{name}.elf")
41
+ self.hex ||= build("#{name}.hex")
42
+
43
+ self.programmer ||= "avr109"
44
+ self.upload_rate ||= 19200
45
+
46
+ self.toolchain = Toolchain.new(self)
47
+
48
+ create_tasks
49
+ end
50
+
51
+
52
+ def config
53
+ Rake::Arduino.config
54
+ end
55
+
56
+ def core_paths
57
+ @core_paths ||= config.cores.to_paths.select do |core|
58
+ board.cores.include? core.basename.to_s
59
+ end
60
+ end
61
+
62
+ def library_paths
63
+ libraries.map do |lib|
64
+ Pathname(config.library_path) + lib
65
+ end
66
+ end
67
+
68
+ def build(path)
69
+ path = Pathname(path)
70
+ path = path.relative_path_from(root) if path.absolute?
71
+
72
+ # Use fully-qualified paths for source outside the project root
73
+ path = path.expand_path.sub(/^\//, "") if path.to_s.start_with? ".."
74
+
75
+ build_path = Pathname(build_root) + path
76
+ end
77
+
78
+ def compile(*source_files)
79
+ source_files = [source_files].flatten
80
+ object_files = source_files.map do |source|
81
+ build(source.sub_ext(".o"))
82
+ end
83
+
84
+ object_files.zip(source_files).each do |object_file, source_file|
85
+ file object_file => source_file do
86
+ object_file.parent.mkpath
87
+ toolchain.compile source_file, :into => object_file
88
+ end
89
+ end
90
+
91
+ object_files
92
+ end
93
+
94
+ def create_tasks
95
+ compiled_libraries = [
96
+ *board.cores,
97
+ *libraries
98
+ ].map{|l| build("#{l}.a")}
99
+
100
+ task target => [*compiled_libraries, hex]
101
+
102
+ main_objects = compile sources
103
+
104
+ (core_paths + library_paths).each do |path|
105
+ library_out = build(path.basename.sub_ext(".a"))
106
+
107
+ object_files = compile Pathname.glob(path +"**/*.{c,cpp}")
108
+
109
+ file library_out => object_files do
110
+ object_files.each do |object_file|
111
+ library_out.parent.mkpath
112
+ toolchain.archive object_file, :into => library_out
113
+ end
114
+ end
115
+ end
116
+
117
+ file elf => main_objects + compiled_libraries do
118
+ toolchain.link main_objects, :with => compiled_libraries, :into => elf
119
+ end
120
+
121
+ file hex => elf do
122
+ size = toolchain.convert_binary(elf, :hex => hex)
123
+
124
+ if size > board.max_size
125
+ puts "The sketch size (#{size} bytes) has overriden the maximum size (#{board.max_size} bytes)."
126
+ rm hex
127
+ exit -1
128
+ else
129
+ puts "Sketch size: #{size} bytes (of a #{board.max_size} bytes maximum)."
130
+ end
131
+ end
132
+
133
+ task :upload => [:all, :upload_pre] do
134
+ sh "#{avrdude} -V -F -p #{board.mcu} -c #{programmer} -P #{port} -b #{upload_rate} -D -Uflash:w:#{hex}:i"
135
+ end
136
+
137
+ task :clean do
138
+ rm_rf Dir["build"]
139
+ rm_f Dir["**/*.{o,a,hex,elf}"]
140
+ end
141
+ end
142
+
143
+ def includes
144
+ ["/usr/lib/avr/include/avr", *core_paths, *library_paths]
145
+ end
146
+
147
+ def defines
148
+ ["F_CPU=#{board.cpu_speed}L", "ARDUINO=18", *board.defines]
149
+ end
150
+
151
+ def avrdude
152
+ "avrdude"
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,65 @@
1
+ module Rake
2
+ module Arduino
3
+ class Toolchain
4
+ include FileUtils
5
+
6
+ attr_accessor :sketch
7
+
8
+ def initialize(sketch)
9
+ self.sketch = sketch
10
+ end
11
+
12
+ def mcu
13
+ sketch.board.mcu
14
+ end
15
+
16
+ def cpp_flags
17
+ [
18
+ "-Wall",
19
+ "-std=gnu++0x",
20
+ "-g",
21
+ "-Os",
22
+ "-w",
23
+ "-fno-exceptions",
24
+ "-ffunction-sections",
25
+ "-fdata-sections",
26
+ "-mmcu=#{mcu}",
27
+ *sketch.defines.map{|d| "-D#{d}"},
28
+ *sketch.includes.map{|i| "-I'#{i}'"}
29
+ ]
30
+ end
31
+
32
+ def ld_flags
33
+ ["-Os", "-Wl,--gc-sections", "-mmcu=#{mcu}"]
34
+ end
35
+
36
+ def ar_flags
37
+ ['rcs']
38
+ end
39
+
40
+ def compile(source_file, options = {})
41
+ object_file = options[:into]
42
+ sh "avr-gcc #{cpp_flags.join(" ")} -c #{source_file} -o #{object_file}"
43
+ end
44
+
45
+ def link(main_objects, options)
46
+ compiled_libraries = options[:with]
47
+ binary = options[:into]
48
+ sh "avr-gcc #{ld_flags.join(" ")} #{main_objects.join(" ")} #{compiled_libraries.join(" ")} -lm -o #{binary}"
49
+ end
50
+
51
+ def archive(object_file, options = {})
52
+ archive = options[:into]
53
+ sh "avr-ar #{ar_flags.join(" ")} #{archive} #{object_file}"
54
+ end
55
+
56
+ def convert_binary(binary, options)
57
+ hex = options[:hex]
58
+ sh "avr-objcopy -O ihex -R .eeprom #{binary} #{hex}"
59
+
60
+ `avr-size -A --mcu=#{mcu} #{hex}` =~ /Total(\s*)(\d*)/
61
+ $2.to_i
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,5 @@
1
+ module Rake
2
+ module Arduino
3
+ VERSION = "0.0.1.alpha"
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/rake/arduino/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Jacob Buys"]
6
+ gem.email = ["wjbuys@gmail.com"]
7
+ gem.summary = %q{Flexible build system for Arduino projects.}
8
+ gem.description = %q{rake-arduino allows you to easily build Arduino sketches using Rake.}
9
+ gem.homepage = "https://github.com/wjbuys/rake-arduino"
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.name = "rake-arduino"
14
+ gem.require_paths = ["lib"]
15
+ gem.version = Rake::Arduino::VERSION
16
+
17
+ gem.add_dependency "rake"
18
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rake-arduino
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.alpha
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - Jacob Buys
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-09 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &12055520 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *12055520
25
+ description: rake-arduino allows you to easily build Arduino sketches using Rake.
26
+ email:
27
+ - wjbuys@gmail.com
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - .gitignore
33
+ - Gemfile
34
+ - README.md
35
+ - Rakefile
36
+ - examples/basic/Blink.cpp
37
+ - examples/basic/Rakefile
38
+ - examples/multi_target/Blink.cpp
39
+ - examples/multi_target/Rakefile
40
+ - lib/rake/arduino.rb
41
+ - lib/rake/arduino/board.rb
42
+ - lib/rake/arduino/boards.rb
43
+ - lib/rake/arduino/config.rb
44
+ - lib/rake/arduino/core_ext/array.rb
45
+ - lib/rake/arduino/core_ext/pathname.rb
46
+ - lib/rake/arduino/sketch.rb
47
+ - lib/rake/arduino/toolchain.rb
48
+ - lib/rake/arduino/version.rb
49
+ - rake-arduino.gemspec
50
+ homepage: https://github.com/wjbuys/rake-arduino
51
+ licenses: []
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ segments:
63
+ - 0
64
+ hash: -1016166330329218044
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>'
69
+ - !ruby/object:Gem::Version
70
+ version: 1.3.1
71
+ requirements: []
72
+ rubyforge_project:
73
+ rubygems_version: 1.8.6
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: Flexible build system for Arduino projects.
77
+ test_files: []