%% CouchDB %% Copyright (C) 2006 Damien Katz %% %% This program is free software; you can redistribute it and/or %% modify it under the terms of the GNU General Public License %% as published by the Free Software Foundation; either version 2 %% of the License, or (at your option) any later version. %% %% This program is distributed in the hope that it will be useful, %% but WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. %% %% You should have received a copy of the GNU General Public License %% along with this program; if not, write to the Free Software %% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -module(build_couch). % % This library provides a way to make couch.app and couch.rel files and % also create a package a full erlang beam couch library, and dependencies % for kitting. % % To run from a command line, first compile: % > ERLC build_couch.erl % % To compile all erlang files: % > ERL -noshell -run build_couch compile_all % % To install the CouchDB lib files in a erlang installation: % run: % > ERL -noshell -run build_couch output_libs_to_erlang_lib_root % % Or to create a full couchdb application library directory % with all application beam files and dependencies satisfied, % run: % > ERL -noshell -run build_couch output_full_libs output/dir/ % -export([compile_all/0, output_full_libs/1, output_libs_to_erlang_lib_root/0]). compile_all() -> code:add_path("./couch_inets/"), code:add_path("./CouchDB/"), up_to_date = make:all(), make_app_and_boot_script_files(), shutdown_clean(). make_app_and_boot_script_files() -> CouchVersion = "@version@", {ok, CouchInetsAppSpec} = file:script("./couch_inets/couch_inets.app"), {_, _, CouchInetsKeyValues} = CouchInetsAppSpec, {value, {_, CouchInetsVsn}} = lists:keysearch(vsn, 1, CouchInetsKeyValues), {ok, CouchApp} = file:open("./CouchDB/couch.app", write), {ok, CouchRel} = file:open("./couch.rel", write), CouchRelData = {release, {"couch_rel", CouchVersion}, {erts, erlang:system_info(version)}, [app_version(kernel), app_version(stdlib), app_version(sasl), app_version(xmerl), {couch_inets, CouchInetsVsn}, {couch, CouchVersion}] }, CouchAppData = {application, couch, [{description, "CouchDB server"}, {vsn, CouchVersion}, {modules, [couch_btree, cjson, couch_db, couch_doc, couch_query_servers, couch_file, couch_server, couch_server_sup, couch_stream, couch_view_group, couch_util, mod_couch, couch_db_sup, couch_event_sup, couch_db_update_notifier, couch_ft_query, couch_log, couch_rep]}, {registered, [couch_server, couch_server_sup, couch_util, couch_query_servers, couch_ft_query]}, {applications, [kernel, stdlib, xmerl, couch_inets]}, {mod, {couch_server,[]}} ]}, io:format(CouchApp, "~p.", [CouchAppData]), io:format(CouchRel, "~p.", [CouchRelData]), file:close(CouchApp), file:close(CouchRel), ok = systools:make_script("couch", [{path, ["./CouchDB/", "./couch_inets/"]}]). output_libs_to_erlang_lib_root() -> output_libs(code:root_dir(), false). output_full_libs([OutputDir]) -> output_libs(OutputDir, true). output_libs(OutputDir, AllDependentsToo) -> % this is a call that causes Erlang to makes a "couch.tar.gz" % from the *.beam, couch.app, and couch.rel files ok = systools:make_tar("couch", [{path, ["./CouchDB/", "./couch_inets/"]}]), % get a list of all the files in the archive {ok, Filenames} = erl_tar:table("couch.tar.gz", [compressed]), % loop through and accumalate a list of all the files in the lib dir LibFilenames = lists:foldl( fun(Filename, AccFilenames) -> case Filename of "lib/couch" ++ _ -> [Filename | AccFilenames]; "lib/" ++ _ when (AllDependentsToo) -> [Filename | AccFilenames]; "lib/cjson" ++ _ -> [Filename | AccFilenames]; _ -> AccFilenames end end, [], Filenames), % now extract those files in the lib dir ok = erl_tar:extract("couch.tar.gz", [{cwd,OutputDir}, compressed, {files, LibFilenames}]), % delete the archive file:delete("couch.tar.gz"), shutdown_clean(). shutdown_clean() -> % this is the only way I could figure out to shut down cleanly % and be able to signal error if there's an error (uncaught errors % will cause the process to exit with an error code) spawn(fun() -> init:stop() end), ok. app_version(App) -> {ok, AppSpec} = file:script(code:lib_dir(App) ++ "/ebin/" ++ atom_to_list(App) ++ ".app"), {_, _, KeyValues} = AppSpec, {value, {_, Vsn}} = lists:keysearch(vsn, 1, KeyValues), {App, Vsn}.