|
View:
New views
5 Messages
—
Rating Filter:
Alert me
|
|
|
Producing dependencies Makefile for Erlang using erlc(1)-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1 Hello, When using erlc(1) and standard Makefiles to compile Erlang source files, there's currently no way to track header dependencies. Thus, if a header is modified, a module that depends on it will be recompiled only if the dependency is explicitly indicated in the Makefile. This becomes problematic when the header is external (for instance, a header from another application, such as xmerl.hrl). Attached is a patch that adds support for producing dependencies Makefiles to erlc(1) and compiler(3). It was modeled after GCC. For example, let's take the following module: -module(mod1). -include("header1.hrl"). ... The command "erlc -M mod1.erl" will output: mod1.beam: mod1.erl header1.hrl The patch adds the following options to erlc(1) and compiler(3): -M generate a rule describing dependencies; output on stdout. -MF File rule(s) is(are) written to `File'. -MT Target change the name of the rule emitted. -MQ Target same as -MT but quote special characters for make(1). -MG consider missing headers as generated files and add the to the dependencies -MP add a phony target for each dependency. -MD same as -M -MT file.Pbeam They're the same as GCC. The following options are not supported: -MM ignore system headers -MMD same as -MD but ignore system headers I choose to keep the same names as GCC because I'm working on Erlang support in Automake and it wants to use these options. Regarding compiler(3), options could have a more Erlang-fashion name. The patch, against R12B-4, includes the documentation updates. But I don't know how to make it, so it's untested. Thanks, PS: I already sent an older patch to erlang-questions@ more than a year ago. The attached patch obsoletes it. - -- Jean-Sébastien Pédron http://www.dumbbell.fr/ PGP Key: http://www.dumbbell.fr/pgp/pubkey.asc -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (FreeBSD) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkkIfWAACgkQa+xGJsFYOlP9swCdGsB6Ydsa6yTz3dLijCeyFAGh NzgAoMAsrNe2oEan+1ItXO+IuRVuSNwU =GOml -----END PGP SIGNATURE----- diff -Naur otp_src_R12B-4/erts/doc/src/erlc.xml otp_src_R12B-4-makedep/erts/doc/src/erlc.xml --- otp_src_R12B-4/erts/doc/src/erlc.xml 2008-02-05 14:37:24.000000000 +0100 +++ otp_src_R12B-4-makedep/erts/doc/src/erlc.xml 2008-10-29 15:50:58.000000000 +0100 @@ -135,6 +135,50 @@ for compiling native code, which needs to be compiled with the same run-time system that it should be run on.</p> </item> + <tag>-M</tag> + <item> + <p>Produces a Makefile rule to track headers dependencies. The + rule is sent to stdout. No object file is produced. + </p> + </item> + <tag>-MF <em>Makefile</em></tag> + <item> + <p>Like the <c><![CDATA[M]]></c> option above, except that the + Makefile is written to <em>Makefile</em>. No object + file is produced. + </p> + </item> + <tag>-MD</tag> + <item> + <p>Same as <c><![CDATA[-M -MF <File>.Pbeam]]></c>. + </p> + </item> + <tag>-MT <em>Target</em></tag> + <item> + <p>In conjunction with <c><![CDATA[-M]]></c> or + <c><![CDATA[-MF]]></c>, change the name of the rule emitted + to <em>Target</em>. + </p> + </item> + <tag>-MQ <em>Target</em></tag> + <item> + <p>Like the <c><![CDATA[-MT]]></c> option above, except that + characters special to make(1) or quoted. + </p> + </item> + <tag>-MP</tag> + <item> + <p>In conjunction with <c><![CDATA[-M]]></c> or + <c><![CDATA[-MF]]></c>, add a phony target for each dependency. + </p> + </item> + <tag>-MG</tag> + <item> + <p>In conjunction with <c><![CDATA[-M]]></c> or + <c><![CDATA[-MF]]></c>, consider missing headers as generated + files and add them to the dependencies. + </p> + </item> <tag>--</tag> <item> <p>Signals that no more options will follow. diff -Naur otp_src_R12B-4/erts/etc/common/erlc.c otp_src_R12B-4-makedep/erts/etc/common/erlc.c --- otp_src_R12B-4/erts/etc/common/erlc.c 2008-02-05 14:37:24.000000000 +0100 +++ otp_src_R12B-4-makedep/erts/etc/common/erlc.c 2008-10-29 11:53:03.000000000 +0100 @@ -255,6 +255,66 @@ case 'I': PUSH2("@i", process_opt(&argc, &argv, 0)); 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 */ + case 'G': /* -MG */ + 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 <target> */ + case 'Q': /* -MQ <target> */ + case 'F': /* -MF <file> */ + 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: + goto error; + } + } + } + break; case 'o': PUSH2("@outdir", process_opt(&argc, &argv, 0)); break; @@ -557,6 +617,15 @@ {"-hybrid", "compile using hybrid-heap emulator"}, {"-help", "shows this help text"}, {"-I path", "where to search for include files"}, + {"-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)"}, + {"-MG", "consider missing headers as generated files and add them to " + "the dependencies"}, + {"-MP", "add a phony target for each dependency"}, + {"-MD", "same as -M -MT file (with default `file')"}, {"-o name", "name output directory or file"}, {"-pa path", "add path to the front of Erlang's code path"}, {"-pz path", "add path to the end of Erlang's code path"}, diff -Naur otp_src_R12B-4/lib/compiler/doc/src/compile.xml otp_src_R12B-4-makedep/lib/compiler/doc/src/compile.xml --- otp_src_R12B-4/lib/compiler/doc/src/compile.xml 2008-10-29 15:29:03.000000000 +0100 +++ otp_src_R12B-4-makedep/lib/compiler/doc/src/compile.xml 2008-10-29 15:50:26.000000000 +0100 @@ -164,6 +164,55 @@ for details.</p> </item> + <tag><c>'M'</c></tag> + <item> + <p>Produces a Makefile rule to track headers dependencies. The + rule is sent to stdout. No object file is produced. + </p> + </item> + + <tag><c>{'MF',Makefile}</c></tag> + <item> + <p>Like the <c>'M'</c> option above, except that the Makefile + is written to <c>Makefile</c>. No object file is produced. + </p> + </item> + + <tag><c>'MD'</c></tag> + <item> + <p>Same as <c>['M', {'MF', <![CDATA[<File>.Pbeam]]>}]</c>. + </p> + </item> + + <tag><c>{'MT',Target}</c></tag> + <item> + <p>In conjunction with <c>'M'</c> or <c>'MF'</c>, change the + name of the rule emitted to <c>Target</c>. + </p> + </item> + + <tag><c>{'MQ',Target}</c></tag> + <item> + <p>Like the <c>{'MT',Target}</c> option above, except that + characters special to make(1) or quoted. + </p> + </item> + + <tag><c>'MP'</c></tag> + <item> + <p>In conjunction with <c>'M'</c> or <c>'MF'</c>, add a phony + target for each dependency. + </p> + </item> + + <tag><c>'MG'</c></tag> + <item> + <p>In conjunction with <c>'M'</c> or <c>'MF'</c>, consider + missing headers as generated files and add them to the + dependencies. + </p> + </item> + <tag><c>'P'</c></tag> <item> <p>Produces a listing of the parsed code after preprocessing diff -Naur otp_src_R12B-4/lib/compiler/src/compile.erl otp_src_R12B-4-makedep/lib/compiler/src/compile.erl --- otp_src_R12B-4/lib/compiler/src/compile.erl 2008-04-07 15:57:56.000000000 +0200 +++ otp_src_R12B-4-makedep/lib/compiler/src/compile.erl 2008-10-29 15:18:37.000000000 +0100 @@ -151,6 +151,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() @@ -398,6 +404,8 @@ %% file will be Ext. (Ext should not contain %% a period.) No more passes will be run. %% +%% done End compilation at this point. +%% %% {done,Ext} End compilation at this point. Produce a listing %% as with {listing,Ext}, unless 'binary' is %% specified, in which case the current @@ -431,6 +439,8 @@ [{listing,fun (St) -> src_listing(Ext, St) end}]; select_passes([{listing,Ext}|_], _Opts) -> [{listing,fun (St) -> listing(Ext, St) end}]; +select_passes([done|_], _Opts) -> + []; select_passes([{done,Ext}|_], Opts) -> select_passes([{unless,binary,{listing,Ext}}], Opts); select_passes([{iff,Flag,Pass}|Ps], Opts) -> @@ -513,6 +523,10 @@ standard_passes() -> [?pass(transform_module), + + {iff,'M',?pass(makedep)}, + {iff,'M',done}, + {iff,'dpp',{listing,"pp"}}, ?pass(lint_module), {iff,'P',{src_listing,"P"}}, @@ -852,6 +866,120 @@ errors=St#compile.errors ++ Es}} end. +makedep(#compile{options = Opts} = St) -> + Ifile = St#compile.ifile, + Ofile = St#compile.ofile, + % Get the target of the Makefile rule. + Target = case proplists:get_value('MT', Opts) of + undefined -> + % The target is derived from the output filename: eventually + % remove the current working directory to obtain a relative + % path. + Cwd = proplists:get_value(cwd, Opts), + case lists:prefix(Cwd, Ofile) of + true -> lists:nthtail(length(Cwd) + 1, Ofile); + false -> Ofile + end; + T -> + % The caller specified one with "-MT". + T + end, + Target1 = Target ++ ":", + % List the dependencies (includes) for this target. + {Main_Target, Phony} = makedep_add_headers(Ifile, St#compile.code, + [], length(Target1), Target1, "", Opts), + % Prepare the content of the Makefile. For instance: + % hello.erl: hello.hrl common.hrl + % + % Or if phony targets are enabled: + % hello.erl: hello.hrl common.hrl + % + % hello.hrl: + % + % common.hrl: + Makefile = case lists:member('MP', Opts) of + true -> Main_Target ++ Phony; + false -> Main_Target + end, + % Write this Makefile to the selected output. + case proplists:get_value('MF', Opts) of + undefined -> + % Output to stdout. + io:format("~s~n", [Makefile]); + O -> + % Output to a regular file. + 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 + end, + {ok, St}. + +makedep_add_headers(Ifile, [{attribute, _, file, {File, _}} | Rest], + Included, Line_Len, Main_Target, Phony, Opts) -> + {Included1, Line_Len1, Main_Target1, Phony1} = makedep_add_header( + Ifile, Included, Line_Len, Main_Target, Phony, File), + makedep_add_headers(Ifile, Rest, Included1, Line_Len1, + Main_Target1, Phony1, Opts); +makedep_add_headers(Ifile, [{error, {_, epp, {include, file, File}}} | Rest], + Included, Line_Len, Main_Target, Phony, Opts) -> + % The header doesn't exist, do we add it? + case lists:member('MG', Opts) of + true -> + {Included1, Line_Len1, Main_Target1, Phony1} = makedep_add_header( + Ifile, Included, Line_Len, Main_Target, Phony, File), + makedep_add_headers(Ifile, Rest, Included1, Line_Len1, + Main_Target1, Phony1, Opts); + false -> + makedep_add_headers(Ifile, Rest, Included, Line_Len, + Main_Target, Phony, Opts) + end; +makedep_add_headers(Ifile, [_ | Rest], Included, Line_Len, + Main_Target, Phony, Opts) -> + makedep_add_headers(Ifile, Rest, Included, + Line_Len, Main_Target, Phony, Opts); +makedep_add_headers(_Ifile, [], _Included, _Line_Len, + Main_Target, Phony, _Opts) -> + {Main_Target, Phony}. + +makedep_add_header(Ifile, Included, Line_Len, Main_Target, Phony, File) -> + case lists:member(File, Included) of + true -> + % This file was already listed in the dependencies, skip it. + {Included, Line_Len, Main_Target, Phony}; + false -> + Included1 = [File | Included], + % Remove "./" in front of the dependency filename. + File1 = case lists:prefix("./", File) of + true -> lists:nthtail(2, File); + false -> File + end, + % Prepare the phony target name. + Phony1 = case File of + Ifile -> Phony; + _ -> Phony ++ "\n\n" ++ File1 ++ ":" + end, + % Add the file to the dependencies. + if + Line_Len + 1 + length(File1) > 76 -> + Line_Len1 = 2 + length(File1), + Main_Target1 = Main_Target ++ " \\\n " ++ File1, + {Included1, Line_Len1, Main_Target1, Phony1}; + true -> + Line_Len1 = Line_Len + 1 + length(File1), + Main_Target1 = Main_Target ++ " " ++ File1, + {Included1, Line_Len1, Main_Target1, Phony1} + end + end. + %% expand_module(State) -> State' %% Do the common preprocessing of the input forms. _______________________________________________ erlang-patches mailing list erlang-patches@... http://www.erlang.org/mailman/listinfo/erlang-patches |
|
|
Re: Producing dependencies Makefile for Erlang using erlc(1)Hi,
How does this deal with header files included with -include_lib(). For our build purposes we use a small shellscript to generate dependencies, which also takes -include_lib directives into consideration. I must say that I really welcome this though :) Now we just support for pkg-config to be able to compile drivers without pain as well. Ofc, we have a erl-config script for this instead :/ ----- "Jean-Sébastien Pédron" <jean-sebastien.pedron@...> wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hello, > > When using erlc(1) and standard Makefiles to compile Erlang source > files, there's currently no way to track header dependencies. Thus, if > a > header is modified, a module that depends on it will be recompiled > only > if the dependency is explicitly indicated in the Makefile. This > becomes > problematic when the header is external (for instance, a header from > another application, such as xmerl.hrl). > > Attached is a patch that adds support for producing dependencies > Makefiles to erlc(1) and compiler(3). It was modeled after GCC. > > For example, let's take the following module: > -module(mod1). > -include("header1.hrl"). > ... > > The command "erlc -M mod1.erl" will output: > mod1.beam: mod1.erl header1.hrl > > The patch adds the following options to erlc(1) and compiler(3): > > -M generate a rule describing dependencies; output on > stdout. > -MF File rule(s) is(are) written to `File'. > -MT Target change the name of the rule emitted. > -MQ Target same as -MT but quote special characters for make(1). > -MG consider missing headers as generated files and add > the > to the dependencies > -MP add a phony target for each dependency. > -MD same as -M -MT file.Pbeam > > They're the same as GCC. The following options are not supported: > > -MM ignore system headers > -MMD same as -MD but ignore system headers > > I choose to keep the same names as GCC because I'm working on Erlang > support in Automake and it wants to use these options. Regarding > compiler(3), options could have a more Erlang-fashion name. > > The patch, against R12B-4, includes the documentation updates. But I > don't know how to make it, so it's untested. > > Thanks, > > PS: I already sent an older patch to erlang-questions@ more than a > year > ago. The attached patch obsoletes it. > > - -- > Jean-Sébastien Pédron > http://www.dumbbell.fr/ > > PGP Key: http://www.dumbbell.fr/pgp/pubkey.asc > > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.4.9 (FreeBSD) > Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org > > iEYEARECAAYFAkkIfWAACgkQa+xGJsFYOlP9swCdGsB6Ydsa6yTz3dLijCeyFAGh > NzgAoMAsrNe2oEan+1ItXO+IuRVuSNwU > =GOml > -----END PGP SIGNATURE----- > > diff -Naur otp_src_R12B-4/erts/doc/src/erlc.xml > otp_src_R12B-4-makedep/erts/doc/src/erlc.xml > --- otp_src_R12B-4/erts/doc/src/erlc.xml 2008-02-05 14:37:24.000000000 > +0100 > +++ otp_src_R12B-4-makedep/erts/doc/src/erlc.xml 2008-10-29 > 15:50:58.000000000 +0100 > @@ -135,6 +135,50 @@ > for compiling native code, which needs to be compiled with > the same > run-time system that it should be run on.</p> > </item> > + <tag>-M</tag> > + <item> > + <p>Produces a Makefile rule to track headers dependencies. > The > + rule is sent to stdout. No object file is produced. > + </p> > + </item> > + <tag>-MF <em>Makefile</em></tag> > + <item> > + <p>Like the <c><![CDATA[M]]></c> option above, except that > the > + Makefile is written to <em>Makefile</em>. No object > + file is produced. > + </p> > + </item> > + <tag>-MD</tag> > + <item> > + <p>Same as <c><![CDATA[-M -MF <File>.Pbeam]]></c>. > + </p> > + </item> > + <tag>-MT <em>Target</em></tag> > + <item> > + <p>In conjunction with <c><![CDATA[-M]]></c> or > + <c><![CDATA[-MF]]></c>, change the name of the rule emitted > + to <em>Target</em>. > + </p> > + </item> > + <tag>-MQ <em>Target</em></tag> > + <item> > + <p>Like the <c><![CDATA[-MT]]></c> option above, except that > + characters special to make(1) or quoted. > + </p> > + </item> > + <tag>-MP</tag> > + <item> > + <p>In conjunction with <c><![CDATA[-M]]></c> or > + <c><![CDATA[-MF]]></c>, add a phony target for each > dependency. > + </p> > + </item> > + <tag>-MG</tag> > + <item> > + <p>In conjunction with <c><![CDATA[-M]]></c> or > + <c><![CDATA[-MF]]></c>, consider missing headers as > generated > + files and add them to the dependencies. > + </p> > + </item> > <tag>--</tag> > <item> > <p>Signals that no more options will follow. > diff -Naur otp_src_R12B-4/erts/etc/common/erlc.c > otp_src_R12B-4-makedep/erts/etc/common/erlc.c > --- otp_src_R12B-4/erts/etc/common/erlc.c 2008-02-05 > 14:37:24.000000000 +0100 > +++ otp_src_R12B-4-makedep/erts/etc/common/erlc.c 2008-10-29 > 11:53:03.000000000 +0100 > @@ -255,6 +255,66 @@ > case 'I': > PUSH2("@i", process_opt(&argc, &argv, 0)); > 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 */ > + case 'G': /* -MG */ > + 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 <target> */ > + case 'Q': /* -MQ <target> */ > + case 'F': /* -MF <file> */ > + 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: > + goto error; > + } > + } > + } > + break; > case 'o': > PUSH2("@outdir", process_opt(&argc, &argv, 0)); > break; > @@ -557,6 +617,15 @@ > {"-hybrid", "compile using hybrid-heap emulator"}, > {"-help", "shows this help text"}, > {"-I path", "where to search for include files"}, > + {"-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)"}, > + {"-MG", "consider missing headers as generated files and add them to > " > + "the dependencies"}, > + {"-MP", "add a phony target for each dependency"}, > + {"-MD", "same as -M -MT file (with default `file')"}, > {"-o name", "name output directory or file"}, > {"-pa path", "add path to the front of Erlang's code path"}, > {"-pz path", "add path to the end of Erlang's code path"}, > diff -Naur otp_src_R12B-4/lib/compiler/doc/src/compile.xml > otp_src_R12B-4-makedep/lib/compiler/doc/src/compile.xml > --- otp_src_R12B-4/lib/compiler/doc/src/compile.xml 2008-10-29 > 15:29:03.000000000 +0100 > +++ otp_src_R12B-4-makedep/lib/compiler/doc/src/compile.xml 2008-10-29 > 15:50:26.000000000 +0100 > @@ -164,6 +164,55 @@ > for details.</p> > </item> > > + <tag><c>'M'</c></tag> > + <item> > + <p>Produces a Makefile rule to track headers > dependencies. The > + rule is sent to stdout. No object file is produced. > + </p> > + </item> > + > + <tag><c>{'MF',Makefile}</c></tag> > + <item> > + <p>Like the <c>'M'</c> option above, except that the > Makefile > + is written to <c>Makefile</c>. No object file is > produced. > + </p> > + </item> > + > + <tag><c>'MD'</c></tag> > + <item> > + <p>Same as <c>['M', {'MF', > <![CDATA[<File>.Pbeam]]>}]</c>. > + </p> > + </item> > + > + <tag><c>{'MT',Target}</c></tag> > + <item> > + <p>In conjunction with <c>'M'</c> or <c>'MF'</c>, change > the > + name of the rule emitted to <c>Target</c>. > + </p> > + </item> > + > + <tag><c>{'MQ',Target}</c></tag> > + <item> > + <p>Like the <c>{'MT',Target}</c> option above, except > that > + characters special to make(1) or quoted. > + </p> > + </item> > + > + <tag><c>'MP'</c></tag> > + <item> > + <p>In conjunction with <c>'M'</c> or <c>'MF'</c>, add a > phony > + target for each dependency. > + </p> > + </item> > + > + <tag><c>'MG'</c></tag> > + <item> > + <p>In conjunction with <c>'M'</c> or <c>'MF'</c>, > consider > + missing headers as generated files and add them to the > + dependencies. > + </p> > + </item> > + > <tag><c>'P'</c></tag> > <item> > <p>Produces a listing of the parsed code after > preprocessing > diff -Naur otp_src_R12B-4/lib/compiler/src/compile.erl > otp_src_R12B-4-makedep/lib/compiler/src/compile.erl > --- otp_src_R12B-4/lib/compiler/src/compile.erl 2008-04-07 > 15:57:56.000000000 +0200 > +++ otp_src_R12B-4-makedep/lib/compiler/src/compile.erl 2008-10-29 > 15:18:37.000000000 +0100 > @@ -151,6 +151,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() > @@ -398,6 +404,8 @@ > %% file will be Ext. (Ext should not contain > %% a period.) No more passes will be run. > %% > +%% done End compilation at this point. > +%% > %% {done,Ext} End compilation at this point. Produce a > listing > %% as with {listing,Ext}, unless 'binary' is > %% specified, in which case the current > @@ -431,6 +439,8 @@ > [{listing,fun (St) -> src_listing(Ext, St) end}]; > select_passes([{listing,Ext}|_], _Opts) -> > [{listing,fun (St) -> listing(Ext, St) end}]; > +select_passes([done|_], _Opts) -> > + []; > select_passes([{done,Ext}|_], Opts) -> > select_passes([{unless,binary,{listing,Ext}}], Opts); > select_passes([{iff,Flag,Pass}|Ps], Opts) -> > @@ -513,6 +523,10 @@ > > standard_passes() -> > [?pass(transform_module), > + > + {iff,'M',?pass(makedep)}, > + {iff,'M',done}, > + > {iff,'dpp',{listing,"pp"}}, > ?pass(lint_module), > {iff,'P',{src_listing,"P"}}, > @@ -852,6 +866,120 @@ > errors=St#compile.errors ++ Es}} > end. > > +makedep(#compile{options = Opts} = St) -> > + Ifile = St#compile.ifile, > + Ofile = St#compile.ofile, > + % Get the target of the Makefile rule. > + Target = case proplists:get_value('MT', Opts) of > + undefined -> > + % The target is derived from the output filename: eventually > + % remove the current working directory to obtain a relative > + % path. > + Cwd = proplists:get_value(cwd, Opts), > + case lists:prefix(Cwd, Ofile) of > + true -> lists:nthtail(length(Cwd) + 1, Ofile); > + false -> Ofile > + end; > + T -> > + % The caller specified one with "-MT". > + T > + end, > + Target1 = Target ++ ":", > + % List the dependencies (includes) for this target. > + {Main_Target, Phony} = makedep_add_headers(Ifile, > St#compile.code, > + [], length(Target1), Target1, "", Opts), > + % Prepare the content of the Makefile. For instance: > + % hello.erl: hello.hrl common.hrl > + % > + % Or if phony targets are enabled: > + % hello.erl: hello.hrl common.hrl > + % > + % hello.hrl: > + % > + % common.hrl: > + Makefile = case lists:member('MP', Opts) of > + true -> Main_Target ++ Phony; > + false -> Main_Target > + end, > + % Write this Makefile to the selected output. > + case proplists:get_value('MF', Opts) of > + undefined -> > + % Output to stdout. > + io:format("~s~n", [Makefile]); > + O -> > + % Output to a regular file. > + 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 > + end, > + {ok, St}. > + > +makedep_add_headers(Ifile, [{attribute, _, file, {File, _}} | Rest], > + Included, Line_Len, Main_Target, Phony, Opts) -> > + {Included1, Line_Len1, Main_Target1, Phony1} = > makedep_add_header( > + Ifile, Included, Line_Len, Main_Target, Phony, File), > + makedep_add_headers(Ifile, Rest, Included1, Line_Len1, > + Main_Target1, Phony1, Opts); > +makedep_add_headers(Ifile, [{error, {_, epp, {include, file, File}}} > | Rest], > + Included, Line_Len, Main_Target, Phony, Opts) -> > + % The header doesn't exist, do we add it? > + case lists:member('MG', Opts) of > + true -> > + {Included1, Line_Len1, Main_Target1, Phony1} = > makedep_add_header( > + Ifile, Included, Line_Len, Main_Target, Phony, File), > + makedep_add_headers(Ifile, Rest, Included1, Line_Len1, > + Main_Target1, Phony1, Opts); > + false -> > + makedep_add_headers(Ifile, Rest, Included, Line_Len, > + Main_Target, Phony, Opts) > + end; > +makedep_add_headers(Ifile, [_ | Rest], Included, Line_Len, > + Main_Target, Phony, Opts) -> > + makedep_add_headers(Ifile, Rest, Included, > + Line_Len, Main_Target, Phony, Opts); > +makedep_add_headers(_Ifile, [], _Included, _Line_Len, > + Main_Target, Phony, _Opts) -> > + {Main_Target, Phony}. > + > +makedep_add_header(Ifile, Included, Line_Len, Main_Target, Phony, > File) -> > + case lists:member(File, Included) of > + true -> > + % This file was already listed in the dependencies, skip it. > + {Included, Line_Len, Main_Target, Phony}; > + false -> > + Included1 = [File | Included], > + % Remove "./" in front of the dependency filename. > + File1 = case lists:prefix("./", File) of > + true -> lists:nthtail(2, File); > + false -> File > + end, > + % Prepare the phony target name. > + Phony1 = case File of > + Ifile -> Phony; > + _ -> Phony ++ "\n\n" ++ File1 ++ ":" > + end, > + % Add the file to the dependencies. > + if > + Line_Len + 1 + length(File1) > 76 -> > + Line_Len1 = 2 + length(File1), > + Main_Target1 = Main_Target ++ " \\\n " ++ File1, > + {Included1, Line_Len1, Main_Target1, Phony1}; > + true -> > + Line_Len1 = Line_Len + 1 + length(File1), > + Main_Target1 = Main_Target ++ " " ++ File1, > + {Included1, Line_Len1, Main_Target1, Phony1} > + end > + end. > + > %% expand_module(State) -> State' > %% Do the common preprocessing of the input forms. > > > _______________________________________________ > erlang-patches mailing list > erlang-patches@... > http://www.erlang.org/mailman/listinfo/erlang-patches Best regards -- Oscar Hellström, oscar@... Phone: +44 (0)798 45 44 773 Mobile: +44 (0)207 65 50 337 Web: http://www.erlang-consulting.com _______________________________________________ erlang-patches mailing list erlang-patches@... http://www.erlang.org/mailman/listinfo/erlang-patches |
|
|
Re: Producing dependencies Makefile for Erlang using erlc(1)-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1 On 29.10.2008 16:30, Oscar Hellström wrote: > How does this deal with header files included with -include_lib(). > For our build purposes we use a small shellscript to generate > dependencies, which also takes -include_lib directives into > consideration. "-include_lib" directives are expanded before the new options are treateed so it's supported. If we take the following module: -module(mod3). -include_lib("xmerl/include/xmerl.hrl"). ... The command "erlc -M mod3.erl" will output: mod3.beam: mod3.erl \ /usr/local/lib/erlang/lib/xmerl-1.1.10/include/xmerl.hrl > I must say that I really welcome this though :) Thanks! > Now we just support for pkg-config to be able to compile drivers > without pain as well. Yes, it would be great to have this :) - -- Jean-Sébastien Pédron http://www.dumbbell.fr/ PGP Key: http://www.dumbbell.fr/pgp/pubkey.asc -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (FreeBSD) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkkIhmwACgkQa+xGJsFYOlPvcQCfXK5XPNowRVxFocpjDeC1z3H0 Ae8AoKxxboK9brW2cohGJ9AxtZLySF4y =aaBI -----END PGP SIGNATURE----- _______________________________________________ erlang-patches mailing list erlang-patches@... http://www.erlang.org/mailman/listinfo/erlang-patches |
|
|
Re: Producing dependencies Makefile for Erlang using erlc(1)Did anything ever happen with this patch? I would love to see such a
thing added to erlc, since for better or worse, we do use .hrl files for record and guard definitions pretty heavily. -- paul Jean-Sébastien Pédron wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hello, > > When using erlc(1) and standard Makefiles to compile Erlang source > files, there's currently no way to track header dependencies. Thus, if a > header is modified, a module that depends on it will be recompiled only > if the dependency is explicitly indicated in the Makefile. This becomes > problematic when the header is external (for instance, a header from > another application, such as xmerl.hrl). > > Attached is a patch that adds support for producing dependencies > Makefiles to erlc(1) and compiler(3). It was modeled after GCC. > > For example, let's take the following module: > -module(mod1). > -include("header1.hrl"). > ... > > The command "erlc -M mod1.erl" will output: > mod1.beam: mod1.erl header1.hrl > > The patch adds the following options to erlc(1) and compiler(3): > > -M generate a rule describing dependencies; output on > stdout. > -MF File rule(s) is(are) written to `File'. > -MT Target change the name of the rule emitted. > -MQ Target same as -MT but quote special characters for make(1). > -MG consider missing headers as generated files and add the > to the dependencies > -MP add a phony target for each dependency. > -MD same as -M -MT file.Pbeam > > They're the same as GCC. The following options are not supported: > > -MM ignore system headers > -MMD same as -MD but ignore system headers > > I choose to keep the same names as GCC because I'm working on Erlang > support in Automake and it wants to use these options. Regarding > compiler(3), options could have a more Erlang-fashion name. > > The patch, against R12B-4, includes the documentation updates. But I > don't know how to make it, so it's untested. > > Thanks, > > PS: I already sent an older patch to erlang-questions@ more than a year > ago. The attached patch obsoletes it. > > - -- > Jean-Sébastien Pédron > http://www.dumbbell.fr/ > > PGP Key: http://www.dumbbell.fr/pgp/pubkey.asc > > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.4.9 (FreeBSD) > Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org > > iEYEARECAAYFAkkIfWAACgkQa+xGJsFYOlP9swCdGsB6Ydsa6yTz3dLijCeyFAGh > NzgAoMAsrNe2oEan+1ItXO+IuRVuSNwU > =GOml > -----END PGP SIGNATURE----- > _______________________________________________ erlang-patches mailing list erlang-patches@... http://www.erlang.org/mailman/listinfo/erlang-patches |
|
|
Re: Producing dependencies Makefile for Erlang using erlc(1)-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1 Paul Fisher wrote: > Did anything ever happen with this patch? I would love to see such a > thing added to erlc, since for better or worse, we do use .hrl files for > record and guard definitions pretty heavily. > > > -- > paul I would also like to see this functionality added. Currently I use grep+sed magic to create dependency rules. > Jean-Sébastien Pédron wrote: > Hello, > > When using erlc(1) and standard Makefiles to compile Erlang source > files, there's currently no way to track header dependencies. Thus, if a > header is modified, a module that depends on it will be recompiled only > if the dependency is explicitly indicated in the Makefile. This becomes > problematic when the header is external (for instance, a header from > another application, such as xmerl.hrl). > > Attached is a patch that adds support for producing dependencies > Makefiles to erlc(1) and compiler(3). It was modeled after GCC. > > For example, let's take the following module: > -module(mod1). > -include("header1.hrl"). > ... > > The command "erlc -M mod1.erl" will output: > mod1.beam: mod1.erl header1.hrl > > The patch adds the following options to erlc(1) and compiler(3): > > -M generate a rule describing dependencies; output on > stdout. > -MF File rule(s) is(are) written to `File'. > -MT Target change the name of the rule emitted. > -MQ Target same as -MT but quote special characters for make(1). > -MG consider missing headers as generated files and add the > to the dependencies > -MP add a phony target for each dependency. > -MD same as -M -MT file.Pbeam > > They're the same as GCC. The following options are not supported: > > -MM ignore system headers > -MMD same as -MD but ignore system headers > > I choose to keep the same names as GCC because I'm working on Erlang > support in Automake and it wants to use these options. Regarding > compiler(3), options could have a more Erlang-fashion name. > > The patch, against R12B-4, includes the documentation updates. But I > don't know how to make it, so it's untested. > > Thanks, > > PS: I already sent an older patch to erlang-questions@ more than a year > ago. The attached patch obsoletes it. > >> > _______________________________________________ > erlang-patches mailing list > erlang-patches@... > http://www.erlang.org/mailman/listinfo/erlang-patches -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.11 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkn1e4QACgkQ6pa1H/H5pqW7HACgqkP7+KjU/jyA9aWpWuiXcRzp VR4Anjc5ykYROfiJOpJ+NS82OkUrO0eg =C8ul -----END PGP SIGNATURE----- _______________________________________________ erlang-patches mailing list erlang-patches@... http://www.erlang.org/mailman/listinfo/erlang-patches |
| Free embeddable forum powered by Nabble | Forum Help |