Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dialyzer-related fixes and improvements #762

Merged
merged 1 commit into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/build-and-test-macos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ jobs:
export PATH="/usr/local/opt/erlang@${{ matrix.otp }}/bin:$PATH"
ninja

- name: "Build: run dialyzer"
working-directory: build
run: |
export PATH="/usr/local/opt/erlang@${{ matrix.otp }}/bin:$PATH"
ninja dialyzer

# Test
- name: "Test: test-erlang"
timeout-minutes: 10
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/build-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ jobs:
working-directory: build
run: make

- name: "Build: run dialyzer"
working-directory: build
run: make dialyzer

# Test
- name: "Test: test-erlang"
timeout-minutes: 10
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ option(AVM_VERBOSE_ABORT "Print module and line number on VM abort" OFF)
option(AVM_RELEASE "Build an AtomVM release" ON)
option(AVM_CREATE_STACKTRACES "Create stacktraces" ON)
option(COVERAGE "Build for code coverage" OFF)
option(RUN_DIALYZER "Run dialyzer on BEAM modules" ON)

if((${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") OR
(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") OR
Expand All @@ -48,6 +47,7 @@ add_subdirectory(tools/packbeam)
add_subdirectory(tools/uf2tool)

if (NOT "${CMAKE_GENERATOR}" MATCHES "Xcode")
add_custom_target(dialyzer COMMENT "Run dialyzer")
add_subdirectory(libs)
add_subdirectory(examples)
add_subdirectory(doc)
Expand Down
64 changes: 38 additions & 26 deletions CMakeModules/BuildErlang.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ macro(pack_archive avm_name)
COMMENT "Compiling ${module_name}.erl"
VERBATIM
)
set(BEAMS ${BEAMS} ${CMAKE_CURRENT_BINARY_DIR}/beams/${module_name}.beam)
set(pack_archive_${avm_name}_beams ${pack_archive_${avm_name}_beams} ${CMAKE_CURRENT_BINARY_DIR}/beams/${module_name}.beam)
endforeach()

add_custom_target(
${avm_name}_beams ALL
DEPENDS ${BEAMS}
DEPENDS ${pack_archive_${avm_name}_beams}
)

if(AVM_RELEASE)
Expand All @@ -45,8 +45,8 @@ macro(pack_archive avm_name)
add_custom_target(
${avm_name} ALL
DEPENDS ${avm_name}_beams PackBEAM
#DEPENDS ${BEAMS}
COMMAND ${CMAKE_BINARY_DIR}/tools/packbeam/PackBEAM -a ${INCLUDE_LINES} ${avm_name}.avm ${BEAMS}
#DEPENDS ${pack_archive_${avm_name}_beams}
COMMAND ${CMAKE_BINARY_DIR}/tools/packbeam/PackBEAM -a ${INCLUDE_LINES} ${avm_name}.avm ${pack_archive_${avm_name}_beams}
COMMENT "Packing archive ${avm_name}.avm"
VERBATIM
)
Expand All @@ -59,11 +59,11 @@ macro(pack_lib avm_name)

foreach(archive_name ${ARGN})
if(NOT ${archive_name} STREQUAL "exavmlib")
set(ARCHIVES ${ARCHIVES} ${CMAKE_BINARY_DIR}/libs/${archive_name}/src/${archive_name}.avm)
set(pack_lib_${avm_name}_archives ${pack_lib_${avm_name}_archives} ${CMAKE_BINARY_DIR}/libs/${archive_name}/src/${archive_name}.avm)
else()
set(ARCHIVES ${ARCHIVES} ${CMAKE_BINARY_DIR}/libs/${archive_name}/lib/${archive_name}.avm)
set(pack_lib_${avm_name}_archives ${pack_lib_${avm_name}_archives} ${CMAKE_BINARY_DIR}/libs/${archive_name}/lib/${archive_name}.avm)
endif()
set(ARCHIVE_TARGETS ${ARCHIVE_TARGETS} ${archive_name})
set(pack_lib_${avm_name}_archive_targets ${pack_lib_${avm_name}_archive_targets} ${archive_name})
endforeach()

if(AVM_RELEASE)
Expand All @@ -74,11 +74,11 @@ macro(pack_lib avm_name)

add_custom_target(
${avm_name} ALL
COMMAND ${CMAKE_BINARY_DIR}/tools/packbeam/PackBEAM -a ${INCLUDE_LINES} ${avm_name}.avm ${ARCHIVES}
COMMAND ${CMAKE_BINARY_DIR}/tools/packbeam/PackBEAM -a ${INCLUDE_LINES} ${avm_name}.avm ${pack_lib_${avm_name}_archives}
COMMENT "Packing runnable ${avm_name}.avm"
VERBATIM
)
add_dependencies(${avm_name} ${ARCHIVE_TARGETS} PackBEAM)
add_dependencies(${avm_name} ${pack_lib_${avm_name}_archive_targets} PackBEAM)
if(TARGET ${avm_name}_main)
add_dependencies(${avm_name} ${avm_name}_main)
endif()
Expand Down Expand Up @@ -111,13 +111,26 @@ macro(pack_runnable avm_name main)

foreach(archive_name ${ARGN})
if(NOT ${archive_name} STREQUAL "exavmlib")
set(ARCHIVES ${ARCHIVES} ${CMAKE_BINARY_DIR}/libs/${archive_name}/src/${archive_name}.avm)
set(pack_runnable_${avm_name}_archives ${pack_runnable_${avm_name}_archives} ${CMAKE_BINARY_DIR}/libs/${archive_name}/src/${archive_name}.avm)
if(NOT ${archive_name} MATCHES "^eavmlib|estdlib|alisp$")
set(${avm_name}_dialyzer_beams_opt ${${avm_name}_dialyzer_beams_opt} "-r" ${CMAKE_BINARY_DIR}/libs/${archive_name}/src/beams/)
endif()
else()
set(ARCHIVES ${ARCHIVES} ${CMAKE_BINARY_DIR}/libs/${archive_name}/lib/${archive_name}.avm)
set(pack_runnable_${avm_name}_archives ${pack_runnable_${avm_name}_archives} ${CMAKE_BINARY_DIR}/libs/${archive_name}/lib/${archive_name}.avm)
endif()
set(ARCHIVE_TARGETS ${ARCHIVE_TARGETS} ${archive_name})
set(pack_runnable_${avm_name}_archive_targets ${pack_runnable_${avm_name}_archive_targets} ${archive_name})
endforeach()

if (Dialyzer_FOUND)
add_custom_target(
${avm_name}_dialyzer
DEPENDS ${avm_name}_main
COMMAND dialyzer --plt ${CMAKE_BINARY_DIR}/libs/atomvmlib.plt -c ${main}.beam ${${avm_name}_dialyzer_beams_opt}
)
add_dependencies(${avm_name}_dialyzer atomvmlib_plt ${pack_runnable_${avm_name}_archive_targets})
add_dependencies(dialyzer ${avm_name}_dialyzer)
endif()

if(AVM_RELEASE)
set(INCLUDE_LINES "")
else()
Expand All @@ -126,22 +139,21 @@ macro(pack_runnable avm_name main)

add_custom_target(
${avm_name} ALL
COMMAND ${CMAKE_BINARY_DIR}/tools/packbeam/PackBEAM ${INCLUDE_LINES} ${avm_name}.avm ${main}.beam ${ARCHIVES}
COMMAND ${CMAKE_BINARY_DIR}/tools/packbeam/PackBEAM ${INCLUDE_LINES} ${avm_name}.avm ${main}.beam ${pack_runnable_${avm_name}_archives}
COMMENT "Packing runnable ${avm_name}.avm"
VERBATIM
)
add_dependencies(${avm_name} ${avm_name}_main ${ARCHIVE_TARGETS} PackBEAM)

add_dependencies(${avm_name} ${avm_name}_main ${pack_runnable_${avm_name}_archive_targets} PackBEAM)
endmacro()


macro(pack_test test_avm_name)

set(ARCHIVES ${CMAKE_CURRENT_BINARY_DIR}/${test_avm_name}_lib.avm)
set(ARCHIVE_TARGETS ${test_avm_name}_lib)
set(pack_test_${test_avm_name}_archives ${CMAKE_CURRENT_BINARY_DIR}/${test_avm_name}_lib.avm)
set(pack_test_${test_avm_name}_archive_targets ${test_avm_name}_lib)
foreach(archive_name ${ARGN})
set(ARCHIVES ${ARCHIVES} ${CMAKE_BINARY_DIR}/libs/${archive_name}/src/${archive_name}.avm)
set(ARCHIVE_TARGETS ${ARCHIVE_TARGETS} ${archive_name})
set(pack_test_${test_avm_name}_archives ${pack_test_${test_avm_name}_archives} ${CMAKE_BINARY_DIR}/libs/${archive_name}/src/${archive_name}.avm)
set(pack_test_${test_avm_name}_archive_targets ${pack_test_${test_avm_name}_archive_targets} ${archive_name})
endforeach()

if(AVM_RELEASE)
Expand All @@ -153,12 +165,12 @@ macro(pack_test test_avm_name)
add_custom_target(
${test_avm_name} ALL
COMMAND erlc +debug_info -I ${CMAKE_SOURCE_DIR}/libs/include ${CMAKE_CURRENT_SOURCE_DIR}/tests.erl
COMMAND ${CMAKE_BINARY_DIR}/tools/packbeam/PackBEAM ${INCLUDE_LINES} ${CMAKE_CURRENT_BINARY_DIR}/${test_avm_name}.avm ${CMAKE_CURRENT_BINARY_DIR}/tests.beam ${ARCHIVES}
COMMAND ${CMAKE_BINARY_DIR}/tools/packbeam/PackBEAM ${INCLUDE_LINES} ${CMAKE_CURRENT_BINARY_DIR}/${test_avm_name}.avm ${CMAKE_CURRENT_BINARY_DIR}/tests.beam ${pack_test_${test_avm_name}_archives}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tests.erl
COMMENT "Packing runnable ${test_avm_name}.avm"
VERBATIM
)
add_dependencies(${test_avm_name} ${ARCHIVE_TARGETS} PackBEAM)
add_dependencies(${test_avm_name} ${pack_test_${test_avm_name}_archive_targets} PackBEAM)

endmacro()

Expand All @@ -179,20 +191,20 @@ macro(pack_uf2 avm_name main)

foreach(archive_name ${ARGN})
if(NOT ${archive_name} STREQUAL "exavmlib")
set(ARCHIVES ${ARCHIVES} ${CMAKE_BINARY_DIR}/libs/${archive_name}/src/${archive_name}.avm)
set(pack_uf2_${avm_name}_archives ${pack_uf2_${avm_name}_archives} ${CMAKE_BINARY_DIR}/libs/${archive_name}/src/${archive_name}.avm)
else()
set(ARCHIVES ${ARCHIVES} ${CMAKE_BINARY_DIR}/libs/${archive_name}/lib/${archive_name}.avm)
set(pack_uf2_${avm_name}_archives ${pack_uf2_${avm_name}_archives} ${CMAKE_BINARY_DIR}/libs/${archive_name}/lib/${archive_name}.avm)
endif()
set(ARCHIVE_TARGETS ${ARCHIVE_TARGETS} ${archive_name})
set(pack_uf2_${avm_name}_archive_targets ${pack_uf2_${avm_name}_archive_targets} ${archive_name})
endforeach()

add_custom_target(
${avm_name}.avm ALL
COMMAND ${CMAKE_BINARY_DIR}/tools/packbeam/PackBEAM ${avm_name}.avm ${main}.beam ${ARCHIVES}
COMMAND ${CMAKE_BINARY_DIR}/tools/packbeam/PackBEAM ${avm_name}.avm ${main}.beam ${pack_uf2_${avm_name}_archives}
COMMENT "Packing runnable ${avm_name}.avm"
VERBATIM
)
add_dependencies(${avm_name}.avm ${avm_name}_main ${ARCHIVE_TARGETS} PackBEAM)
add_dependencies(${avm_name}.avm ${avm_name}_main ${pack_uf2_${avm_name}_archive_targets} PackBEAM)

add_custom_target(
${avm_name}.uf2 ALL
Expand Down
1 change: 1 addition & 0 deletions examples/emscripten/wasm_webserver.erl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

-export([start/0, handle_req/3]).

-spec start() -> no_return().
start() ->
Router = [
{"*", ?MODULE, []}
Expand Down
7 changes: 3 additions & 4 deletions libs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ else()
pack_lib(atomvmlib eavmlib estdlib alisp)
endif()

if (Dialyzer_FOUND AND RUN_DIALYZER)
if (Dialyzer_FOUND)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/atomvmlib.plt
DEPENDS atomvmlib
Expand All @@ -49,12 +49,11 @@ if (Dialyzer_FOUND AND RUN_DIALYZER)
-r ${CMAKE_CURRENT_BINARY_DIR}/eavmlib/src/beams
-r ${CMAKE_CURRENT_BINARY_DIR}/alisp/src/beams
)

add_custom_target(atomvmlib_plt ALL
add_custom_target(atomvmlib_plt
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/atomvmlib.plt
)
else()
message("Dialyzer is not enabled -- skipping PLT build")
message("Dialyzer was not found -- skipping PLT build")
endif()

install(
Expand Down
124 changes: 120 additions & 4 deletions libs/eavmlib/src/atomvm.erl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,18 @@
read_priv/2,
add_avm_pack_binary/2,
add_avm_pack_file/2,
close_avm_pack/2
close_avm_pack/2,
get_start_beam/1,
posix_open/2,
posix_open/3,
posix_close/1,
posix_read/2,
posix_write/2
]).

-export_type([
posix_fd/0,
posix_open_flag/0
]).

-type platform_name() ::
Expand All @@ -43,7 +54,30 @@
| pico
| stm32.

-type avm_path() :: string() | binary().
-type avm_path() :: iodata().

-opaque posix_fd() :: binary().
-type posix_open_flag() ::
o_exec
| o_rdonly
| o_rdwr
| o_search
| o_wronly
| o_append
| o_cloexec
| o_creat
| o_directory
| o_dsync
| o_excl
| o_noctty
| o_nofollow
| o_rsync
| o_sync
| o_trunc
| o_tty_atom.
-type posix_error() ::
atom()
| integer().

%%-----------------------------------------------------------------------------
%% @returns The platform name.
Expand Down Expand Up @@ -104,7 +138,8 @@ read_priv(_App, _Path) ->
%% Failure to properly load AVM data is result in a runtime `error'
%% @end
%%-----------------------------------------------------------------------------
-spec add_avm_pack_binary(AVMData :: binary(), Options :: [{name, Name :: atom()}]) -> ok.
-spec add_avm_pack_binary(AVMData :: binary(), Options :: [{name, Name :: atom()}]) ->
ok | {error, any()}.
add_avm_pack_binary(_AVMData, _Options) ->
erlang:nif_error(undefined).

Expand All @@ -131,7 +166,8 @@ add_avm_pack_binary(_AVMData, _Options) ->
%% Failure to properly load AVM path is result in a runtime `error'
%% @end
%%-----------------------------------------------------------------------------
-spec add_avm_pack_file(AVMPath :: avm_path(), Options :: []) -> ok.
-spec add_avm_pack_file(AVMPath :: avm_path(), Options :: [{name, Name :: atom()}]) ->
ok | {error, any()}.
add_avm_pack_file(_AVMPath, _Options) ->
erlang:nif_error(undefined).

Expand All @@ -151,3 +187,83 @@ add_avm_pack_file(_AVMPath, _Options) ->
-spec close_avm_pack(Name :: atom(), Options :: []) -> ok | error.
close_avm_pack(_Name, _Options) ->
erlang:nif_error(undefined).

%%-----------------------------------------------------------------------------
%% @param AVM Name of avm (atom)
%% @returns the name of the start module (with suffix)
%% @doc Get the start beam for a given avm
%% @end
%%-----------------------------------------------------------------------------
-spec get_start_beam(AVM :: atom()) -> {ok, binary()} | {error, not_found}.
get_start_beam(_AVM) ->
erlang:nif_error(undefined).

%%-----------------------------------------------------------------------------
%% @param Path Path to the file to open
%% @param Flags List of flags passed to `open(3)'.
%% @returns A tuple with a file descriptor or an error tuple.
%% @doc Open a file (on platforms that have `open(3)').
%% The file is automatically closed when the file descriptor is garbage
%% collected.
%%
%% Files are automatically opened with `O_NONBLOCK'. Other flags can be passed.
%% @end
%%-----------------------------------------------------------------------------
-spec posix_open(Path :: iodata(), Flags :: [posix_open_flag()]) ->
{ok, posix_fd()} | {error, posix_error()}.
posix_open(_Path, _Flags) ->
erlang:nif_error(undefined).

%%-----------------------------------------------------------------------------
%% @param Path Path to the file to open
%% @param Flags List of flags passed to `open(3)'.
%% @param Mode Mode passed to `open(3)' for created file.
%% @returns A tuple with a file descriptor or an error tuple.
%% @doc Open a file (on platforms that have `open(3)').
%% This variant can be used to specify the mode for new file.
%% @end
%%-----------------------------------------------------------------------------
-spec posix_open(Path :: iodata(), Flags :: [posix_open_flag()], Mode :: non_neg_integer()) ->
{ok, posix_fd()} | {error, posix_error()}.
posix_open(_Path, _Flags, _Mode) ->
erlang:nif_error(undefined).

%%-----------------------------------------------------------------------------
%% @param File Descriptor to a file to close
%% @returns `ok' or an error tuple
%% @doc Close a file that was opened with `posix_open/2,3'
%% @end
%%-----------------------------------------------------------------------------
-spec posix_close(File :: posix_fd()) -> ok | {error, posix_error()}.
posix_close(_File) ->
erlang:nif_error(undefined).

%%-----------------------------------------------------------------------------
%% @param File Descriptor to an open file
%% @param Count Maximum number of bytes to read
%% @returns a tuple with read bytes, `eof' or an error tuple
%% @doc Read at most `Count' bytes from a file.
%% Files are open non-blocking. ˋatomvm:posix_select_read/3' can be used to
%% determine if the file can be read.
%% `eof' is returned if no more data can be read because the file cursor
%% reached the end.
%% @end
%%-----------------------------------------------------------------------------
-spec posix_read(File :: posix_fd(), Count :: non_neg_integer()) ->
{ok, binary()} | eof | {error, posix_error()}.
posix_read(_File, _Count) ->
erlang:nif_error(undefined).

%%-----------------------------------------------------------------------------
%% @param File Descriptor to an open file
%% @param Data Data to write
%% @returns a tuple with the number of written bytes or an error tuple
%% @doc Write data to a file.
%% Files are open non-blocking. ˋatomvm:posix_select_write/3' can be used to
%% determine if the file can be written.
%% @end
%%-----------------------------------------------------------------------------
-spec posix_write(File :: posix_fd(), Data :: binary()) ->
{ok, non_neg_integer()} | {error, posix_error()}.
posix_write(_File, _Data) ->
erlang:nif_error(undefined).
Loading