Skip to content

Commit 79f9533

Browse files
committed
Merge branch 'main' into feature/distributed-erlang
2 parents d799418 + c7d4499 commit 79f9533

21 files changed

+740
-174
lines changed

.github/workflows/build-and-test.yaml

+38-23
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ concurrency:
3434

3535
jobs:
3636
build-and-test:
37-
runs-on: ${{ matrix.os }}
37+
runs-on: ${{ matrix.os || 'ubuntu-24.04' }}
38+
container: ${{ matrix.container }}
3839
strategy:
3940

4041
fail-fast: false
@@ -57,21 +58,21 @@ jobs:
5758
- cc: "gcc-7"
5859
cxx: "g++-7"
5960
compiler_pkgs: "gcc-7 g++-7"
60-
os: "ubuntu-20.04"
61+
container: "ubuntu:20.04"
6162
otp: "27"
6263
elixir_version: "1.17"
6364
rebar3_version: "3.24.0"
6465
- cc: "gcc-8"
6566
cxx: "g++-8"
6667
compiler_pkgs: "gcc-8 g++-8"
67-
os: "ubuntu-20.04"
68+
container: "ubuntu:20.04"
6869
otp: "27"
6970
elixir_version: "1.17"
7071
rebar3_version: "3.24.0"
7172
- cc: "gcc-9"
7273
cxx: "g++-9"
7374
compiler_pkgs: "gcc-9 g++-9"
74-
os: "ubuntu-20.04"
75+
container: "ubuntu:20.04"
7576
# otp: all
7677
- cc: "gcc-10"
7778
cxx: "g++-10"
@@ -119,13 +120,13 @@ jobs:
119120
cxx: "clang++-10"
120121
compiler_pkgs: "clang-10"
121122
cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON"
122-
os: "ubuntu-20.04"
123+
container: "ubuntu:20.04"
123124
# otp: all
124125
- cc: "clang-11"
125126
cxx: "clang++-11"
126127
compiler_pkgs: "clang-11"
127128
cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON"
128-
os: "ubuntu-20.04"
129+
container: "ubuntu:20.04"
129130
otp: "27"
130131
elixir_version: "1.17"
131132
rebar3_version: "3.24.0"
@@ -195,37 +196,41 @@ jobs:
195196
rebar3_version: "3.24.0"
196197

197198
# Old versions of OTP/Elixir
198-
- os: "ubuntu-20.04"
199+
- container: "ubuntu:20.04"
199200
cc: "cc"
200201
cxx: "c++"
201202
cflags: ""
202203
otp: "21"
203204
elixir_version: "1.7"
204205
rebar3_version: "3.15.2"
206+
compiler_pkgs: "g++"
205207

206-
- os: "ubuntu-20.04"
208+
- container: "ubuntu:20.04"
207209
cc: "cc"
208210
cxx: "c++"
209211
cflags: ""
210212
otp: "22"
211213
elixir_version: "1.8"
212214
rebar3_version: "3.18.0"
215+
compiler_pkgs: "g++"
213216

214-
- os: "ubuntu-20.04"
217+
- container: "ubuntu:20.04"
215218
cc: "cc"
216219
cxx: "c++"
217220
cflags: ""
218221
otp: "23"
219222
elixir_version: "1.11"
220223
rebar3_version: "3.20.0"
224+
compiler_pkgs: "g++"
221225

222-
- os: "ubuntu-22.04"
226+
- container: "ubuntu:20.04"
223227
cc: "cc"
224228
cxx: "c++"
225229
cflags: ""
226230
otp: "24"
227231
elixir_version: "1.14"
228232
rebar3_version: "3.23.0"
233+
compiler_pkgs: "g++"
229234

230235
- os: "ubuntu-24.04"
231236
cc: "cc"
@@ -235,13 +240,14 @@ jobs:
235240
rebar3_version: "3.24.0"
236241

237242
# Additional default compiler builds
238-
- os: "ubuntu-20.04"
243+
- container: "ubuntu:20.04"
239244
cc: "cc"
240245
cxx: "c++"
241246
cflags: ""
242247
otp: "27"
243248
elixir_version: "1.17"
244249
rebar3_version: "3.24.0"
250+
compiler_pkgs: "g++"
245251

246252
- os: "ubuntu-22.04"
247253
cc: "cc"
@@ -271,7 +277,7 @@ jobs:
271277
compiler_pkgs: "clang-18"
272278

273279
# Additional 32 bits build
274-
- os: "ubuntu-20.04"
280+
- container: "ubuntu:20.04"
275281
cc: "gcc-10"
276282
cxx: "g++-10"
277283
cflags: "-m32 -O3"
@@ -285,13 +291,30 @@ jobs:
285291
libc6-dbg:i386 zlib1g-dev:i386 libmbedtls-dev:i386"
286292

287293
env:
294+
ImageOS: ${{ matrix.container == 'ubuntu:20.04' && 'ubuntu20' || matrix.os == 'ubuntu-20.04' && 'ubuntu20' || matrix.os == 'ubuntu-22.04' && 'ubuntu22' || matrix.os == 'ubuntu-24.04' && 'ubuntu24' || 'ubuntu24' }}
288295
CC: ${{ matrix.cc }}
289296
CXX: ${{ matrix.cxx }}
290297
CFLAGS: ${{ matrix.cflags }}
291298
CXXFLAGS: ${{ matrix.cflags }}
299+
DEBIAN_FRONTEND: noninteractive
300+
TZ: "Etc/UTC"
292301

293302
steps:
294303
# Setup
304+
- name: "Install deps for containers"
305+
if: matrix.container != ''
306+
run: apt-get update && apt-get install -y --no-install-recommends sudo unzip git tzdata
307+
308+
- name: "Add i386 architecture"
309+
if: matrix.arch == 'i386'
310+
run: sudo dpkg --add-architecture i386
311+
312+
- name: "APT update"
313+
run: sudo apt update -y
314+
315+
- name: "Install deps"
316+
run: sudo apt install -y ${{ matrix.compiler_pkgs}} cmake gperf zlib1g-dev doxygen valgrind libmbedtls-dev
317+
295318
- name: "Checkout repo"
296319
uses: actions/checkout@v4
297320
with:
@@ -308,16 +331,6 @@ jobs:
308331
https://repo.hex.pm
309332
https://cdn.jsdelivr.net/hex
310333
311-
- name: "Add i386 architecture"
312-
if: matrix.arch == 'i386'
313-
run: sudo dpkg --add-architecture i386
314-
315-
- name: "APT update"
316-
run: sudo apt update -y
317-
318-
- name: "Install deps"
319-
run: sudo apt install -y ${{ matrix.compiler_pkgs}} cmake gperf zlib1g-dev doxygen valgrind libmbedtls-dev
320-
321334
# Builder info
322335
- name: "System info"
323336
run: |
@@ -436,10 +449,12 @@ jobs:
436449
working-directory: build
437450
run: |
438451
ulimit -c unlimited
439-
if command -v elixirc &> /dev/null
452+
if command -v elixirc >/dev/null 2>&1 && command -v elixir >/dev/null 2>&1
440453
then
441454
valgrind --error-exitcode=1 ./src/AtomVM ./tests/libs/exavmlib/Tests.avm
442455
./src/AtomVM ./tests/libs/exavmlib/Tests.avm
456+
else
457+
echo "Elixir not installed, skipping Elixir tests"
443458
fi
444459
445460
- name: "Install and smoke test"

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3939
- Added `erlang:get/0` and `erlang:erase/0`.
4040
- Added `erlang:unique_integer/0` and `erlang:unique_integer/1`
4141
- Added support for 'ets:delete/1'.
42+
- Added `lists:flatmap/2`
43+
- Added `io:fwrite/1,2,3` and `io:format/3` as well as few io functions required by remote shell
44+
- Added `code:is_loaded/1` and `code:which/1`
45+
- Added several `io_lib` functions including `io_lib:fwrite/2` and `io_lib:write_atom/1`
46+
- Added `init:get_argument/1`, `init:get_plain_arguments/0` and `init:notify_when_started/1`
4247
- Added `application:get_env/2`
4348

4449
### Changed
@@ -113,6 +118,7 @@ memory error
113118
- Fix `is_function/2` guard
114119
- Fixed segfault when calling `lists:reverse/1` (#1600)
115120
- Fixed nif_atomvm_posix_read GC bug
121+
- Fixed `erlang:is_number/1` function, now returns true also for floats
116122

117123
### Changed
118124

libs/estdlib/src/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ set(ERLANG_MODULES
4848
net_kernel
4949
net_kernel_sup
5050
inet
51+
init
5152
io_lib
5253
io
5354
lists

libs/estdlib/src/code.erl

+36-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
all_loaded/0,
3030
load_abs/1,
3131
load_binary/3,
32-
ensure_loaded/1
32+
ensure_loaded/1,
33+
which/1,
34+
is_loaded/1
3335
]).
3436

3537
%%-----------------------------------------------------------------------------
@@ -58,7 +60,7 @@ all_loaded() ->
5860
erlang:nif_error(undefined).
5961

6062
%%-----------------------------------------------------------------------------
61-
%% @param Filename path to the beam to open, without .beams suffix
63+
%% @param Filename path to the beam to open, without .beam suffix
6264
%% @returns A tuple with the name of the module
6365
%% @doc Load a module from a path.
6466
%% Error return result type is different from Erlang/OTP.
@@ -98,3 +100,35 @@ load_binary(_Module, _Filename, _Binary) ->
98100
Module :: atom().
99101
ensure_loaded(_Module) ->
100102
erlang:nif_error(undefined).
103+
104+
%%-----------------------------------------------------------------------------
105+
%% @param Module module to test
106+
%% @returns Tuple `{file, preloaded}' if module is loaded or `false'
107+
%% @doc Determine if a module is loaded. AtomVM works in
108+
%% an embedded-like mode where modules are loaded at start-up but modules
109+
%% can be loaded explicitely as well (especially from a binary with `load_binary/3').
110+
%% @end
111+
%%-----------------------------------------------------------------------------
112+
is_loaded(Module) ->
113+
case ?MODULE:ensure_loaded(Module) of
114+
{module, _Module} ->
115+
{file, preloaded};
116+
{error, _} ->
117+
false
118+
end.
119+
120+
%%-----------------------------------------------------------------------------
121+
%% @param Module module to test
122+
%% @returns `preloaded' if module is loaded or `false'
123+
%% @doc Determine if a module is loaded. There currently is no way to
124+
%% distinguish a module that was loaded with `load_binary/3' or that was
125+
%% preloaded at startup.
126+
%% @end
127+
%%-----------------------------------------------------------------------------
128+
which(Module) ->
129+
case ?MODULE:ensure_loaded(Module) of
130+
{module, _Module} ->
131+
preloaded;
132+
{error, _} ->
133+
non_existing
134+
end.

libs/estdlib/src/erlang.erl

+13-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
list_to_integer/1,
5858
list_to_integer/2,
5959
list_to_tuple/1,
60+
iolist_size/1,
6061
iolist_to_binary/1,
6162
binary_to_atom/1,
6263
binary_to_atom/2,
@@ -682,13 +683,24 @@ list_to_integer(_String, _Base) ->
682683
list_to_tuple(_List) ->
683684
erlang:nif_error(undefined).
684685

686+
%%-----------------------------------------------------------------------------
687+
%% @equiv byte_size(iolist_to_binary(IOList))
688+
%% @param IOList IO list to compute the binary size of
689+
%% @returns the number of bytes of IOList if it was convered to `binary()'
690+
%% @doc Compute the length in bytes of the IO list or `binary()'
691+
%% @end
692+
%%-----------------------------------------------------------------------------
693+
-spec iolist_size(IOList :: iodata()) -> non_neg_integer().
694+
iolist_size(_IOList) ->
695+
erlang:nif_error(undefined).
696+
685697
%%-----------------------------------------------------------------------------
686698
%% @param IOList IO list to convert to binary
687699
%% @returns a binary with the bytes of the IO list
688700
%% @doc Convert an IO list to binary.
689701
%% @end
690702
%%-----------------------------------------------------------------------------
691-
-spec iolist_to_binary(IOList :: iolist()) -> binary().
703+
-spec iolist_to_binary(IOList :: iodata()) -> binary().
692704
iolist_to_binary(_IOList) ->
693705
erlang:nif_error(undefined).
694706

libs/estdlib/src/init.erl

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
%
2+
% This file is part of AtomVM.
3+
%
4+
% Copyright 2025 Paul Guyot <[email protected]>
5+
%
6+
% Licensed under the Apache License, Version 2.0 (the "License");
7+
% you may not use this file except in compliance with the License.
8+
% You may obtain a copy of the License at
9+
%
10+
% http://www.apache.org/licenses/LICENSE-2.0
11+
%
12+
% Unless required by applicable law or agreed to in writing, software
13+
% distributed under the License is distributed on an "AS IS" BASIS,
14+
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
% See the License for the specific language governing permissions and
16+
% limitations under the License.
17+
%
18+
% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
19+
%
20+
21+
%%-----------------------------------------------------------------------------
22+
%% @doc An implementation of the Erlang/OTP init interface.
23+
%%
24+
%% This module implements a strict subset of the Erlang/OTP init
25+
%% interface.
26+
%% @end
27+
%%-----------------------------------------------------------------------------
28+
-module(init).
29+
30+
-export([
31+
get_argument/1,
32+
get_plain_arguments/0,
33+
notify_when_started/1
34+
]).
35+
36+
%%-----------------------------------------------------------------------------
37+
%% @param Flag flag to get values for
38+
%% @return `error' if no value is associated with provided flag or values in
39+
%% order of the command line
40+
%% @doc Returns values associated with a given command-line user flag.
41+
%% Currently always returns `error' on AtomVM.
42+
%% @end
43+
%%-----------------------------------------------------------------------------
44+
-spec get_argument(Flag :: atom()) -> {ok, [string()]} | error.
45+
get_argument(_Flag) ->
46+
error.
47+
48+
%%-----------------------------------------------------------------------------
49+
%% @return plain command-line arguments as a list of strings.
50+
%% @doc Gets plain command-line arguments.
51+
%% Currently always returns `[]' on AtomVM.
52+
%% @end
53+
%%-----------------------------------------------------------------------------
54+
-spec get_plain_arguments() -> [string()].
55+
get_plain_arguments() ->
56+
[].
57+
58+
%% @private
59+
-spec notify_when_started(Pid :: pid()) -> ok | started.
60+
notify_when_started(_Pid) ->
61+
started.

0 commit comments

Comments
 (0)