diff -Naur otp_src_R11B-5/erts/etc/common/erlc.c otp_src_R11B-5-makedep/erts/etc/common/erlc.c --- otp_src_R11B-5/erts/etc/common/erlc.c 2007-03-27 15:28:26.000000000 +0200 +++ otp_src_R11B-5-makedep/erts/etc/common/erlc.c 2007-07-06 18:37:02.000000000 +0200 @@ -298,6 +298,67 @@ } break; + case 'M': + { + char *buf, *key, *val; + size_t buf_len, key_len, val_len; + + if (argv[1][2] == '\0') { /* -M */ + buf = emalloc(4); + buf[0] = '\''; + buf[1] = argv[1][1]; + buf[2] = '\''; + buf[3] = '\0'; + + PUSH2("@option", buf); + } else { + switch(argv[1][2]) { + case 'P': /* -MP */ + case 'D': /* -MD */ + buf = emalloc(5); + buf[0] = '\''; + buf[1] = argv[1][1]; + buf[2] = argv[1][2]; + buf[3] = '\''; + buf[4] = '\0'; + + PUSH2("@option", buf); + break; + case 'T': /* -MT */ + case 'Q': /* -MQ */ + case 'F': /* -MF */ + switch (argv[1][2]) { + case 'T': + key = "'MT'"; + break; + case 'Q': + key = "'MQ'"; + break; + case 'F': + key = "'MF'"; + break; + default: + key = "'M?'"; + break; + } + key_len = strlen(key); + val = process_opt(&argc, &argv, 1); + val_len = strlen(val); + + buf_len = 1 + key_len + 2 + val_len + 2 + 1; + buf = emalloc(buf_len); + snprintf(buf, buf_len, "{%s,\"%s\"}", key, val); + + PUSH2("@option", buf); + break; + default: + usage(); + break; + } + } + } + break; + case '-': goto no_more_options; @@ -532,6 +593,13 @@ {"-E", "generate listing of expanded code (Erlang compiler)"}, {"-S", "generate assembly listing (Erlang compiler)"}, {"-P", "generate listing of preprocessed code (Erlang compiler)"}, + {"-M", "generate a rule for make(1) describing the dependencies"}, + {"-MF file", "write the dependencies to `file'"}, + {"-MT target", "change the target of the rule emitted by dependency " + "generation"}, + {"-MQ target", "same as -MT but quote characters special to make(1)"}, + {"-MP", "add a phony target for each dependency"}, + {"-MD", "same as -M -MT file (with default `file')"}, {"+term", "pass the Erlang term unchanged to the compiler"}, }; int i; diff -Naur otp_src_R11B-5/lib/compiler/src/compile.erl otp_src_R11B-5-makedep/lib/compiler/src/compile.erl --- otp_src_R11B-5/lib/compiler/src/compile.erl 2007-06-11 14:52:59.000000000 +0200 +++ otp_src_R11B-5-makedep/lib/compiler/src/compile.erl 2007-07-06 18:37:02.000000000 +0200 @@ -128,6 +128,12 @@ expand_opt(no_float_opt, Os) -> %%Turn off the entire type optimization pass. [no_topt|Os]; +expand_opt('MD', Os) -> + ['M', {'MF', default} | Os]; +expand_opt({'MQ', T}, Os) -> + Fun = fun($$) -> "$$"; (C) -> C end, + T1 = lists:flatten(lists:map(Fun, T)), + [{'MT', T1} | Os]; expand_opt(O, Os) -> [O|Os]. %% format_error(ErrorDescriptor) -> string() @@ -488,6 +494,8 @@ {iff,'P',{src_listing,"P"}}, {iff,'to_pp',{done,"P"}}, + {iff,'M',?pass(makedep)}, + {iff,'dabstr',{listing,"abstr"}}, {iff,debug_info,?pass(save_abstract_code)}, @@ -824,6 +832,77 @@ errors=St#compile.errors ++ Es}} end. +makedep(#compile{options = Opts} = St) -> + Ifile = St#compile.ifile, + Ofile = St#compile.ofile, + Target = case lists:keysearch('MT', 1, Opts) of + {value, {_, T}} -> + T; + false -> + {value, {_, Cwd}} = lists:keysearch(cwd, 1, Opts), + case lists:prefix(Cwd, Ofile) of + true -> lists:nthtail(length(Cwd) + 1, Ofile); + false -> Ofile + end + end, + Target1 = Target ++ ":", + {Main_Target, Phony} = makedep_add_includes(Ifile, St#compile.code, + [], length(Target1), Target1, ""), + Makefile = case lists:member('MP', Opts) of + true -> Main_Target ++ Phony; + false -> Main_Target + end, + case lists:keysearch('MF', 1, Opts) of + {value, {_, O}} -> + Output = case O of + default -> filename:basename(Ofile, ".beam") ++ ".Pbeam"; + _ -> O + end, + case file:open(Output, write) of + {ok, Io_Dev} -> + io:fwrite(Io_Dev, "~s~n", [Makefile]), + file:close(Io_Dev); + {error, Reason} -> + io:format("Couldn't open makefile `~s': ~p~n", + [Output, Reason]) + end; + false -> + io:format("~s~n", [Makefile]) + end, + {ok, St}. + +makedep_add_includes(Ifile, [{attribute, _, file, {File, _}} | Rest], + Included, Line_Len, Main_Target, Phony) -> + case lists:member(File, Included) of + true -> + makedep_add_includes(Ifile, Rest, Included, Line_Len, + Main_Target, Phony); + false -> + File1 = case lists:prefix("./", File) of + true -> lists:nthtail(2, File); + false -> File + end, + Phony1 = case File of + Ifile -> Phony; + _ -> Phony ++ "\n\n" ++ File1 ++ ":" + end, + if + Line_Len + 1 + length(File1) > 76 -> + makedep_add_includes(Ifile, Rest, [File | Included], + 2 + length(File1), + Main_Target ++ " \\\n " ++ File1, Phony1); + true -> + makedep_add_includes(Ifile, Rest, [File | Included], + Line_Len + 1 + length(File1), + Main_Target ++ " " ++ File1, Phony1) + end + end; +makedep_add_includes(Ifile, [_ | Rest], Included, Line_Len, + Main_Target, Phony) -> + makedep_add_includes(Ifile, Rest, Included, Line_Len, Main_Target, Phony); +makedep_add_includes(_Ifile, [], _Included, _Line_Len, Main_Target, Phony) -> + {Main_Target, Phony}. + %% expand_module(State) -> State' %% Do the common preprocessing of the input forms.