Skip to content

Commit cfffe7c

Browse files
committed
Igniter installer
(install igniter: mix archive.install hex igniter_new) you can try mix igniter.new my_project --install exatomvm@github:petermm/exatomvm && cd my_project adds dependency and atomvm project config and the start function. early days in igniter world, but should be good to go. Signed-off-by: Peter M <[email protected]>
1 parent 434f730 commit cfffe7c

File tree

2 files changed

+209
-1
lines changed

2 files changed

+209
-1
lines changed

lib/mix/tasks/ExAtomVM.install.ex

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
defmodule Mix.Tasks.Exatomvm.Install do
2+
use Igniter.Mix.Task
3+
4+
@example "mix igniter.new my_project --install exatomvm@github:atomvm/exatomvm && cd my_project"
5+
6+
@shortdoc "Add and config AtomVM"
7+
@moduledoc """
8+
#{@shortdoc}
9+
10+
## Example
11+
12+
```bash
13+
#{@example}
14+
```
15+
16+
"""
17+
18+
@impl Igniter.Mix.Task
19+
def info(_argv, _composing_task) do
20+
%Igniter.Mix.Task.Info{
21+
# Groups allow for overlapping arguments for tasks by the same author
22+
# See the generators guide for more.
23+
group: :exatomvm,
24+
# dependencies to add
25+
adds_deps: [],
26+
# dependencies to add and call their associated installers, if they exist
27+
installs: [],
28+
# An example invocation
29+
example: @example,
30+
# A list of environments that this should be installed in.
31+
only: nil,
32+
# a list of positional arguments, i.e `[:file]`
33+
positional: [],
34+
# Other tasks your task composes using `Igniter.compose_task`, passing in the CLI argv
35+
# This ensures your option schema includes options from nested tasks
36+
composes: [],
37+
# `OptionParser` schema
38+
schema: [],
39+
# Default values for the options in the `schema`
40+
defaults: [],
41+
# CLI aliases
42+
aliases: [],
43+
# A list of options in the schema that are required
44+
required: []
45+
}
46+
end
47+
48+
@impl Igniter.Mix.Task
49+
def igniter(igniter) do
50+
selected_instructions =
51+
Igniter.Util.IO.select(
52+
"What device do you want to show instructions for?\n(Project is configured for all devices - this is just for further flashing instructions):",
53+
["ESP32", "Pico", "STM32", "All"]
54+
)
55+
56+
IO.inspect(selected_instructions)
57+
58+
selected_port_auto_mode =
59+
Igniter.Util.IO.yes?(
60+
"Do you want to have the ESP32 port configured in \"auto\" mode?\n(where the esptool flash tool uses first ESP32 found connected)\n"
61+
)
62+
63+
options = [
64+
start: Igniter.Project.Module.module_name_prefix(igniter),
65+
esp32_flash_offset: Sourceror.parse_string!("0x250000"),
66+
stm32_flash_offset: Sourceror.parse_string!("0x8080000"),
67+
chip: "auto"
68+
]
69+
70+
options =
71+
if selected_port_auto_mode == true,
72+
do: options ++ [port: "auto"],
73+
else: options ++ [port: "/dev/ttyUSB0"]
74+
75+
Igniter.update_elixir_file(igniter, "mix.exs", fn zipper ->
76+
with {:ok, zipper} <- Igniter.Code.Function.move_to_def(zipper, :project, 0),
77+
{:ok, zipper} <-
78+
Igniter.Code.Keyword.put_in_keyword(
79+
zipper,
80+
[:atomvm],
81+
options
82+
) do
83+
{:ok, zipper}
84+
end
85+
end)
86+
|> Igniter.mkdir("avm_deps")
87+
|> Igniter.Project.Module.find_and_update_module!(
88+
Igniter.Project.Module.module_name_prefix(igniter),
89+
fn zipper ->
90+
case Igniter.Code.Function.move_to_def(zipper, :start, 0) do
91+
:error ->
92+
# start function not available, so let's create one
93+
zipper =
94+
Igniter.Code.Common.add_code(
95+
zipper,
96+
"""
97+
def start do
98+
IO.inspect("Hello AtomVM!")
99+
:ok
100+
end
101+
""",
102+
placement: :before
103+
)
104+
105+
{:ok, zipper}
106+
107+
_ ->
108+
{:ok, zipper}
109+
end
110+
end
111+
)
112+
|> output_instructions(selected_instructions, selected_port_auto_mode)
113+
end
114+
115+
defp common_intro do
116+
"""
117+
Your AtomVM project is now ready.
118+
Make sure you have installed AtomVM itself on the device:
119+
(make sure to choose the Elixir enabled build)
120+
"""
121+
end
122+
123+
defp output_instructions(igniter, selected_instructions, selected_port_auto_mode)
124+
when selected_instructions == "ESP32" do
125+
igniter
126+
|> Igniter.add_notice(selected_instructions)
127+
|> Igniter.add_notice("""
128+
#{common_intro()}
129+
https://www.atomvm.net/doc/main/getting-started-guide.html#flashing-a-binary-image-to-esp32 (binary available)
130+
131+
you can also use the web flasher (using Chrome):
132+
https://petermm.github.io/atomvm-web-tools/
133+
""")
134+
|> Igniter.add_notice("""
135+
You need to have esptool.py installed for flashing:
136+
https://docs.espressif.com/projects/esptool/en/latest/esp32/installation.html#{if is_mac?(), do: "\n(or 'brew install esptool' if using homebrew)"}
137+
138+
You are then ready to flash your project to your device using:
139+
140+
#{if selected_port_auto_mode == true,
141+
do: """
142+
Connect your ESP32 device and flash the "hello world!" using:
143+
(port is in "auto" mode and will find first connected ESP32)
144+
mix atomvm.esp32.flash [https://github.com/atomvm/exatomvm?tab=readme-ov-file#the-atomvmesp32flash-task]
145+
146+
""",
147+
else: """
148+
Connect your ESP32 device and flash the "hello world!" using:
149+
(configure port in mix.exs, or override when using mix task - NB change to correct port)
150+
mix atomvm.esp32.flash --port /dev/ttyUSB0 [https://github.com/atomvm/exatomvm?tab=readme-ov-file#the-atomvmesp32flash-task]
151+
152+
"""}
153+
""")
154+
end
155+
156+
defp output_instructions(igniter, selected_instructions, _selected_port_auto_mode)
157+
when selected_instructions == "Pico" do
158+
igniter
159+
|> Igniter.add_notice(selected_instructions)
160+
|> Igniter.add_notice("""
161+
#{common_intro()}
162+
https://www.atomvm.net/doc/main/getting-started-guide.html#flashing-a-binary-image-to-pico (binary available)
163+
164+
""")
165+
|> Igniter.add_notice("""
166+
167+
You are then ready to flash your project to your device using:
168+
169+
mix atomvm.pico.flash [https://github.com/atomvm/exatomvm?tab=readme-ov-file#the-atomvmpicoflash-task]
170+
""")
171+
end
172+
173+
defp output_instructions(igniter, selected_instructions, _selected_port_auto_mode)
174+
when selected_instructions == "STM32" do
175+
igniter
176+
|> Igniter.add_notice(selected_instructions)
177+
|> Igniter.add_notice("""
178+
#{common_intro()}
179+
You need to build AtomVM for your board:
180+
https://www.atomvm.net/doc/main/build-instructions.html#building-for-stm32
181+
182+
And have st-link installed to flash:
183+
https://github.com/stlink-org/stlink?tab=readme-ov-file#installation
184+
https://www.atomvm.net/doc/main/getting-started-guide.html#flashing-a-binary-image-to-stm32
185+
""")
186+
|> Igniter.add_notice("""
187+
You are then ready to flash your project to your device using:
188+
189+
mix atomvm.stm32.flash [https://github.com/atomvm/exatomvm?tab=readme-ov-file#the-atomvmstm32flash-task]
190+
""")
191+
end
192+
193+
defp output_instructions(igniter, selected_instructions, selected_port_auto_mode)
194+
when selected_instructions == "All" do
195+
igniter
196+
|> output_instructions("ESP32", selected_port_auto_mode)
197+
|> output_instructions("Pico", selected_port_auto_mode)
198+
|> output_instructions("STM32", selected_port_auto_mode)
199+
end
200+
201+
defp is_mac? do
202+
case :os.type() do
203+
{:unix, :darwin} -> true
204+
_ -> false
205+
end
206+
end
207+
end

mix.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ defmodule ExAtomVM.MixProject do
2121
# Run "mix help deps" to learn about dependencies.
2222
defp deps do
2323
[
24-
{:uf2tool, "1.1.0"}
24+
{:uf2tool, "1.1.0"},
25+
{:igniter, "~> 0.5", runtime: false, optional: true}
2526
# {:dep_from_hexpm, "~> 0.3.0"},
2627
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
2728
]

0 commit comments

Comments
 (0)