From 7061375e3e7fad5823bfe37eba40f78827f2e740 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Thu, 29 Nov 2012 11:56:40 +0100 Subject: [PATCH] Fix compilation of mime_types.erl when working directory is not 'yaws' When mime_types.erl is generated, we must check if it is done during a Yaws compilation or a Yaws startup. In the first case, we must use a relative path for includes. Else include_lib must be used. This issue was reported by Andrei Zavada and avoid a compile error when the working directory is not 'yaws'. The mechanisms to generate and compile this file have also changed. Then, to centralize calls to yaws_generated:is_local_install/0, following functions was added in yaws.erl: get_app_dir/0, get_src_dir/0, get_ebin_dir/0, get_priv_dir/0, get_inc_dir/0 --- configure.in | 1 + known_dialyzer_warnings | 9 ++++---- priv/charset.def.in | 1 + scripts/rebar-pre-script | 24 +++++++++----------- src/Makefile | 37 ++++++++++++++----------------- src/mime_type_c.erl | 29 +++++++++++++++++++----- src/yaws.erl | 48 +++++++++++++++++++++++++++++++--------- src/yaws_config.erl | 30 +------------------------ src/yaws_sendfile.erl | 9 +------- src/yaws_soap12_lib.erl | 7 +----- src/yaws_soap_lib.erl | 7 +----- 11 files changed, 99 insertions(+), 103 deletions(-) create mode 100644 priv/charset.def.in diff --git a/configure.in b/configure.in index 8ba3aad28..2a4b4d650 100644 --- a/configure.in +++ b/configure.in @@ -333,6 +333,7 @@ AC_SUBST(HAVE_YAWS_SENDFILE) YTOP=`pwd` AC_SUBST(YTOP) AC_OUTPUT(include.mk) +AC_OUTPUT(priv/charset.def) AC_OUTPUT(test/support/include.mk) AC_OUTPUT(test/support/include.sh) diff --git a/known_dialyzer_warnings b/known_dialyzer_warnings index 020607eed..92a0391a0 100644 --- a/known_dialyzer_warnings +++ b/known_dialyzer_warnings @@ -1,8 +1,9 @@ -yaws.erl:1657: The pattern 'false' can never match the type 'true' -yaws.erl:2144: Guard test Ret::'file' == 'fd' can never succeed -yaws.erl:2152: Guard test Ret::'file' == 'binfd' can never succeed -yaws_config.erl:548: The pattern 'false' can never match the type 'true' +mime_type_c.erl:69: The variable _ can never match since previous clauses completely covered the type 'true' +yaws.erl:2138: Guard test Ret::'file' == 'fd' can never succeed +yaws.erl:2146: Guard test Ret::'file' == 'binfd' can never succeed +yaws.erl:2377: The pattern 'false' can never match the type 'true' +yaws.erl:2384: The pattern 'false' can never match the type 'true' yaws_ctl.erl:530: Function hup/1 has no local return yaws_ctl.erl:535: Function stop/1 has no local return yaws_ctl.erl:539: Function status/1 has no local return diff --git a/priv/charset.def.in b/priv/charset.def.in new file mode 100644 index 000000000..28ce5a021 --- /dev/null +++ b/priv/charset.def.in @@ -0,0 +1 @@ +@DEFAULT_CHARSET@ diff --git a/scripts/rebar-pre-script b/scripts/rebar-pre-script index 4562bd203..1918e98c2 100755 --- a/scripts/rebar-pre-script +++ b/scripts/rebar-pre-script @@ -34,22 +34,10 @@ keep_or_replace() { cd src || fail if [ "$1" = clean ]; then - rm -f mime_types.erl ../priv/charset.def yaws_configure.hrl yaws_generated.erl + rm -f mime_types.erl yaws_configure.hrl yaws_generated.erl exit 0 fi -CHARSET=${DEFAULT_CHARSET-""} -need_mime=yes -if [ -f mime_types.erl ]; then - need_mime=`find mime_type_c.erl -newer mime_types.erl -print` -fi -if [ -n "$need_mime" ]; then - echo ${CHARSET} > ../priv/charset.def || fail - erlc -o ../ebin mime_type_c.erl || fail ../priv/charset.def - erl -pa ../ebin -noshell -s mime_type_c generate || \ - fail ../priv/charset.def mime_types.erl -fi - if [ ! -f yaws_configure.hrl ]; then echo '%% rebar sets HAVE_YAWS_SENDFILE in erlc command line' \ > yaws_configure.hrl @@ -62,6 +50,16 @@ keep_or_replace yaws_generated.erl $tmpgen [ -d "$YAWS_VARDIR" ] || mkdir "$YAWS_VARDIR" || fail [ -d "$YAWS_ETCDIR" ] || mkdir "$YAWS_ETCDIR" || fail +need_mime=yes +if [ -f mime_types.erl ]; then + need_mime=`find mime_type_c.erl -newer mime_types.erl -print` +fi +if [ -n "$need_mime" ]; then + erlc -o ../ebin yaws_generated.erl || fail + erlc -o ../ebin mime_type_c.erl || fail + erl -pa ../ebin -noshell -s mime_type_c generate || fail mime_types.erl +fi + cd ../scripts tmpgen=`mktemp /tmp/${script}.XXXXXX` || fail diff --git a/src/Makefile b/src/Makefile index a47c38130..8b866fdf5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -69,7 +69,6 @@ ERLC_FLAGS+=-Werror $(DEBUG_FLAGS) -pa ../../yaws -I ../include # # Targets # - all: yaws_generated.erl yaws_configure.hrl $(EBIN_FILES) dav: @@ -80,39 +79,26 @@ $(EBIN_FILES) : ../include/yaws.hrl ../include/yaws_api.hrl ../ebin/yaws_sendfile.$(EMULATOR): yaws_configure.hrl yaws_generated.erl: yaws_generated.template ../vsn.mk - . ../vsn.mk ; \ - YAWS_VSN='$(YAWS_VSN)' VARDIR='$(VARDIR)' ETCDIR='$(ETCDIR)' \ - ../scripts/gen-yaws-generated true > yaws_generated.erl + $(MAKE) IS_LOCAL_INSTALL=true gen_yaws_generated yaws_configure.hrl: ../vsn.mk ../include.mk if [ $(HAVE_YAWS_SENDFILE) = "true" ]; then \ echo "-define(HAVE_YAWS_SENDFILE, true)." > yaws_configure.hrl; \ else touch yaws_configure.hrl; fi - -## need to differentiate between local install and not -.PHONY: regen -regen: - . ../vsn.mk ; \ - YAWS_VSN='$(YAWS_VSN)' VARDIR='$(VARDIR)' ETCDIR='$(ETCDIR)' \ - ../scripts/gen-yaws-generated false > yaws_generated.erl - -charset.def: - if [ -n "$(DEFAULT_CHARSET)" ]; then \ - echo $(DEFAULT_CHARSET) > ../priv/charset.def; \ - else rm -f ../priv/charset.def ; touch ../priv/charset.def; fi - -mime_types.erl: charset.def ../ebin/mime_type_c.beam +mime_types.erl: ../priv/charset.def ../priv/mime.types \ + ../ebin/yaws_generated.$(EMULATOR) ../ebin/mime_type_c.$(EMULATOR) $(ERL) -noshell -pa ../ebin -s mime_type_c generate + debug: $(MAKE) TYPE=debug clean: - rm -f $(EBIN_FILES) yaws_generated.erl yaws_configure.hrl \ - mime_types.erl ../priv/charset.def + rm -f $(EBIN_FILES) yaws_generated.erl yaws_configure.hrl mime_types.erl -install: regen all docsinstall +install: all docsinstall + $(MAKE) IS_LOCAL_INSTALL=false gen_yaws_generated $(INSTALL) -d $(DESTDIR)$(LIBDIR)/yaws/examples/ebin $(INSTALL) -d $(DESTDIR)$(LIBDIR)/yaws/examples/include $(INSTALL) -d $(DESTDIR)$(LIBDIR)/yaws/ebin @@ -123,6 +109,7 @@ install: regen all docsinstall (cd ..; tar cf - include ) | (cd $(DESTDIR)$(LIBDIR)/yaws; tar xf - ) (cd ..; tar cf - priv/*.xsd ) | (cd $(DESTDIR)$(LIBDIR)/yaws; tar xf - ) $(INSTALL) -m 644 ../priv/mime.types $(DESTDIR)$(LIBDIR)/yaws/priv + $(MAKE) IS_LOCAL_INSTALL=true gen_yaws_generated docsinstall: $(INSTALL) -d $(DESTDIR)$(VARDIR)/yaws/www @@ -135,3 +122,11 @@ xref: erl -noshell -pa ../ebin -s yaws_debug xref ../ebin + +## need to differentiate between local install and not +gen_yaws_generated: + rm -f yaws_generated.erl ../ebin/yaws_generated.$(EMULATOR) + YAWS_VSN='$(YAWS_VSN)' VARDIR='$(VARDIR)' ETCDIR='$(ETCDIR)' \ + ../scripts/gen-yaws-generated $(IS_LOCAL_INSTALL) > yaws_generated.erl + $(MAKE) ../ebin/yaws_generated.$(EMULATOR) + diff --git a/src/mime_type_c.erl b/src/mime_type_c.erl index 8c6feea38..400aace74 100644 --- a/src/mime_type_c.erl +++ b/src/mime_type_c.erl @@ -13,7 +13,7 @@ -include("../include/yaws.hrl"). --define(MIME_TYPES_FILE, filename:join(code:priv_dir(yaws), "mime.types")). +-define(MIME_TYPES_FILE, filename:join(yaws:get_priv_dir(), "mime.types")). -define(DEFAULT_MIME_TYPE, "text/plain"). %% This function is used during Yaws' compilation. To rebuild/reload mime_types @@ -25,13 +25,14 @@ generate() -> SrcDir = filename:dirname( proplists:get_value(source, ?MODULE:module_info(compile)) ), - PrivDir = filename:join(filename:dirname(SrcDir), "priv"), - Charset = read_charset_file(filename:join(PrivDir, "charset.def")), + EbinDir = filename:dirname(code:which(?MODULE)), + Charset = read_charset_file(filename:join(EbinDir, "../priv/charset.def")), GInfo = #mime_types_info{ - mime_types_file = filename:join(PrivDir, "mime.types"), + mime_types_file = filename:join(SrcDir, "../priv/mime.types"), default_charset = Charset }, ModFile = filename:join(SrcDir, "mime_types.erl"), + case generate(ModFile, GInfo, []) of ok -> erlang:halt(0); @@ -52,12 +53,29 @@ generate(ModFile, GInfo, SInfoMap) -> {Name, Info} <- [{global, GInfo}|SInfoMap] ], %% Generate module Header + %% + %% We must make the difference between generation during Yaws + %% compilation and generation during Yaws startup. + %% below, ignore dialyzer warning: + %% "The pattern 'false' can never match the type 'true'" + Inc = case yaws_generated:is_local_install() of + true -> + Info = ?MODULE:module_info(compile), + SrcDir = filename:dirname( + proplists:get_value(source, Info) + ), + F = filename:join([SrcDir, "../include/yaws.hrl"]), + "-include(\""++F++"\")."; + _ -> + "-include_lib(\"yaws/include/yaws.hrl\")." + end, io:format(Fd, "-module(mime_types).~n~n" "-export([default_type/0, default_type/1]).~n" "-export([t/1, revt/1]).~n" "-export([t/2, revt/2]).~n~n" - "-include_lib(\"yaws/include/yaws.hrl\").~n~n", []), + "~s~n~n", [Inc]), + %% Generate default_type/0, t/1 and revt/1 io:format(Fd, @@ -258,4 +276,3 @@ get_ext_type("cgi") -> cgi; get_ext_type("fcgi") -> fcgi; get_ext_type(_) -> regular. - diff --git a/src/yaws.erl b/src/yaws.erl index f93e131bf..308b6eb78 100644 --- a/src/yaws.erl +++ b/src/yaws.erl @@ -100,6 +100,9 @@ -export([parse_ipmask/1, match_ipmask/2]). +-export([get_app_dir/0, get_ebin_dir/0, get_priv_dir/0, + get_inc_dir/0, get_src_dir/0]). + %% Internal -export([local_time_as_gmt_string/1, universal_time_as_string/1, stringdate_to_datetime/1]). @@ -1649,16 +1652,7 @@ uid_to_name(Uid) -> end. load_setuid_drv() -> - %% below, ignore dialyzer warning: - %% "The pattern 'false' can never match the type 'true'" - Path = case yaws_generated:is_local_install() of - true -> - filename:dirname(code:which(?MODULE)) ++ "/../priv/lib"; - false -> - %% ignore dialyzer on this one - PrivDir = code:priv_dir(yaws), - filename:join(PrivDir,"lib") - end, + Path = filename:join(get_priv_dir(), "lib"), case erl_ddll:load_driver(Path, "setuid_drv") of ok -> ok; @@ -2370,3 +2364,37 @@ compare_ips({A,B1,_,_,_,_,_,_}, {A,B2,_,_,_,_,_,_}) when B1 > B2 -> greater; compare_ips({A1,_,_,_,_,_,_,_}, {A2,_,_,_,_,_,_,_}) when A1 < A2 -> less; compare_ips({A1,_,_,_,_,_,_,_}, {A2,_,_,_,_,_,_,_}) when A1 > A2 -> greater; compare_ips(_, _) -> error. + + +%% ---- +get_app_subdir(SubDir) when is_atom(SubDir) -> + %% below, ignore dialyzer warning: + %% "The pattern 'false' can never match the type 'true'" + case yaws_generated:is_local_install() of + true -> + EbinDir = get_ebin_dir(), + filename:join(filename:dirname(EbinDir), atom_to_list(SubDir)); + false -> + code:lib_dir(yaws, SubDir) + end. + +get_app_dir() -> + %% below, ignore dialyzer warning: + %% "The pattern 'false' can never match the type 'true'" + case yaws_generated:is_local_install() of + true -> filename:dirname(get_ebin_dir()); + false -> code:lib_dir(yaws) + end. + +get_src_dir() -> + Info = ?MODULE:module_info(compile), + filename:dirname(proplists:get_value(source, Info)). + +get_ebin_dir() -> + filename:dirname(code:which(?MODULE)). + +get_priv_dir() -> + get_app_subdir(priv). + +get_inc_dir() -> + get_app_subdir(include). diff --git a/src/yaws_config.erl b/src/yaws_config.erl index 5e8a09d4b..f27ebfe3c 100644 --- a/src/yaws_config.erl +++ b/src/yaws_config.erl @@ -538,35 +538,7 @@ make_default_sconf(DocRoot, Port) -> yaws_dir() -> - %% below, ignore dialyzer warning: - %% "The pattern 'false' can never match the type 'true'" - case yaws_generated:is_local_install() of - true -> - P = filename:split(code:which(?MODULE)), - P1 = del_tail(P), - filename:join(P1); - false -> - code:lib_dir(yaws) - end. - -del_tail(Parts) -> - del_tail(Parts,[]). -%% Initial ".." should be preserved -del_tail([".." |Tail], Acc) -> - del_tail(Tail, [".."|Acc]); -del_tail(Parts, Acc) -> - del_tail2(Parts, Acc). - -%% Embedded ".." should be removed together with preceding dir -del_tail2([_H, ".." |Tail], Acc) -> - del_tail2(Tail, Acc); -del_tail2([".." |Tail], [_P|Acc]) -> - del_tail2(Tail, Acc); -del_tail2([_X, _Y], Acc) -> - lists:reverse(Acc); -del_tail2([H|T], Acc) -> - del_tail2(T, [H|Acc]). - + yaws:get_app_dir(). string_to_host_and_port(String) -> case string:tokens(String, ":") of diff --git a/src/yaws_sendfile.erl b/src/yaws_sendfile.erl index 594963b7b..3b8287255 100644 --- a/src/yaws_sendfile.erl +++ b/src/yaws_sendfile.erl @@ -110,14 +110,7 @@ stop() -> init([]) -> process_flag(trap_exit, true), Shlib = "yaws_sendfile_drv", - Dir = case yaws_generated:is_local_install() of - true -> - filename:dirname(code:which(?MODULE)) ++ "/../priv/lib"; - false -> - %% ignore dialyzer on this one - PrivDir = code:priv_dir(yaws), - filename:join(PrivDir,"lib") - end, + Dir = filename:join(yaws:get_priv_dir(), "lib"), case erl_ddll:load_driver(Dir, Shlib) of ok -> ok; {error, already_loaded} -> ok; diff --git a/src/yaws_soap12_lib.erl b/src/yaws_soap12_lib.erl index 67b94931c..d266ece3c 100644 --- a/src/yaws_soap12_lib.erl +++ b/src/yaws_soap12_lib.erl @@ -347,12 +347,7 @@ initModelFile(ConfigFile) -> initModel2(WsdlFile, [{prefix, Prefix}], XsdPath, Import, AddFiles). priv_dir() -> - case code:priv_dir(yaws) of - {error, bad_name} -> - filename:join([filename:dirname(code:which(yaws)),"..", "priv"]); - A -> - A - end. + yaws:get_priv_dir(). initModel2(WsdlFile, ErlsomOptions, Path, Import, AddFiles) -> WsdlName = filename:join([Path, "wsdl.xsd"]), diff --git a/src/yaws_soap_lib.erl b/src/yaws_soap_lib.erl index e8f15f7a9..a5d94e1cb 100644 --- a/src/yaws_soap_lib.erl +++ b/src/yaws_soap_lib.erl @@ -307,12 +307,7 @@ initModelFile(ConfigFile) -> initModel2(WsdlFile, [{prefix, Prefix}], XsdPath, Import, AddFiles). priv_dir() -> - case code:priv_dir(yaws) of - {error, bad_name} -> - filename:join([filename:dirname(code:which(yaws)),"..", "priv"]); - A -> - A - end. + yaws:get_priv_dir(). initModel2(WsdlFile, ErlsomOptions, Path, Import, AddFiles) -> WsdlName = filename:join([Path, "wsdl.xsd"]),