Wang Zhijun
Wang Zhijun

Reputation: 67

Can not compile Erlang file using file module

When I want to compile a simple file.erl file, I got the error message.

$ erlc file.erl
/opt/erlang17.5/lib/kernel-3.2/include/file.hrl:34: type date_time() undefined

Below is the content of file.erl

-module(file).
-include_lib("kernel/include/file.hrl").

-export([file_info/1]).

file_info(Dir) ->
    {ok, F} = file:read_file_info(Dir),
    io:format("~p~n", [F#file_info.type]).

It seems nobody reported this kind of issue, is there anything wrong with what I did?

Upvotes: 0

Views: 695

Answers (2)

Steve Vinoski
Steve Vinoski

Reputation: 20004

It's instructive to investigate the root cause of the compilation problem. The compiler emits this error:

/opt/erlang17.5/lib/kernel-3.2/include/file.hrl:34: type date_time() undefined

Looking at line 34 of file.hrl we see:

ctime  :: file:date_time() | non_neg_integer(),

This is a type specifier for the ctime field of the #file_info{} record. It states that ctime can hold a value of either the file:date_time() type or of the non_neg_integer() type.

The error message complains specifically about the date_time() type because its scope indicates that it's defined in the file module. In this case, the file module is the one being defined and compiled, and it's hiding the standard one provided by the Erlang/OTP kernel application. The standard file module defines its date_time() type as follows:

-type date_time() :: calendar:datetime().

The file module we're trying to compile, though, does not. What happens if we add this type definition?

-module(file).
-type date_time() :: calendar:datetime().
-include_lib("kernel/include/file.hrl").

-export([file_info/1]).

file_info(Dir) ->
    {ok, F} = file:read_file_info(Dir),
    io:format("~p~n", [F#file_info.type]).

Compiling this version containing the added type definition now works:

$ erlc file.erl
$

We've fixed the compilation error, so let's try to use our compiled module. We start an Erlang shell:

$ erl
Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false]

{"init terminating in do_boot",{undef,[{file,path_eval,[[".","/Users/user"],".erlang"],[]},{c,f_p_e,2,[{file,"c.erl"},{line,481}]},{init,eval_script,8,[]},{init,do_boot,3,[]}]}}

Crash dump is being written to: erl_crash.dump...done
init terminating in do_boot ()

We can see in the error message that an attempt to call file:path_eval/2 failed because it's not defined. Because our file module hides the standard one but doesn't supply all the same functions, we can't even start up an Erlang shell as long as our file module hides the standard one.

Clearly, choosing a different name for the module is necessary for more than just fixing the original compilation error.

Upvotes: 6

Dzej Bi
Dzej Bi

Reputation: 116

Your code is right, the problem is with filename. Erlang has library "file", so you cannot use this filename. Change it (don't forget to modify source) and everything should be fine.

Upvotes: 1

Related Questions