//
// aegis - project change supervisor
// Copyright (C) 2007-2012, 2014 Peter Miller
//
// 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 3 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, see .
//
#include
#include
#include
#include
#include
#include
target_make_automake::~target_make_automake()
{
trace(("%s\n", __PRETTY_FUNCTION__));
}
target_make_automake::target_make_automake(change_identifier &a_cid) :
target_make(a_cid)
{
trace(("%s\n", __PRETTY_FUNCTION__));
op = output_filter_wrap_make::create(op);
}
target::pointer
target_make_automake::create(change_identifier &a_cid)
{
trace(("%s\n", __PRETTY_FUNCTION__));
return pointer(new target_make_automake(a_cid));
}
void
target_make_automake::process3_begin(void)
{
trace(("%s\n", __PRETTY_FUNCTION__));
warning_this_file_is_generated();
print_comment
(
"\n"
"Tell automake to put the object file for foo/bar.cc in "
"directory foo/\n"
"\n"
);
print_assignment("AUTOMAKE_OPTIONS", "subdir-objects");
}
void
target_make_automake::process_item_uudecode(const nstring &fn)
{
trace(("%s\n", __PRETTY_FUNCTION__));
nstring fn2 = nstring(fn.c_str(), fn.size() - 4);
// this isn't automatic in automake (?)
nstring_list lhs;
lhs.push_back(fn2);
nstring_list rhs;
rhs.push_back(fn);
nstring_list body;
body.push_back("uudecode -o " + fn2 + " " + fn);
location_comment(__FILE__, __LINE__);
print_rule(lhs, rhs, body);
// now process the result of the rule.
// it could be just about anything.
processing.run_process(fn2);
}
void
target_make_automake::process_item_scripts(const nstring &fn)
{
trace(("%s\n", __PRETTY_FUNCTION__));
//
// The logic here *must* match the logic in
// aemakegen/target/debian/process.cc
//
assert(filename_implies_is_a_script(fn));
if (fn.starts_with("test/"))
return;
nstring prog = fn.basename().trim_extension();
nstring bin_prog = "bin/" + prog;
nstring_list lhs;
lhs.push_back(bin_prog);
nstring_list rhs;
rhs.push_back(fn);
nstring_list body;
body.push_back("@mkdir -p " + bin_prog.dirname());
body.push_back("cp " + fn + " $@");
body.push_back("chmod a+rx $@");
location_comment(__FILE__, __LINE__);
print_rule(lhs, rhs, body);
}
void
target_make_automake::process_item_aegis_lib_doc(const nstring &fn)
{
trace(("%s\n", __PRETTY_FUNCTION__));
nstring macros = fn.get_extension();
if (macros == "roff")
macros = "";
else if (macros == "mm")
macros = "-m$(MM)";
else if (macros == "ms")
macros = "-m$(MS)";
else
{
if (!macros.starts_with("m"))
macros = "m" + macros;
macros = "-" + macros;
}
nstring src = fn.dirname() + ".pdf";
nstring ps = fn.dirname() + ".ps";
nstring_list lhs;
lhs.push_back(src);
nstring_list rhs;
rhs.push_back(fn);
rhs.push_back_unique(roff_include_dependencies(fn));
nstring_list body;
body.push_back
(
"$(GROFF) -Tps -I. -R -t -p " + macros + " -mpic -mpspic " + fn +
" > " + ps
);
body.push_back("ps2pdf " + ps + " $@");
body.push_back("rm " + ps);
location_comment(__FILE__, __LINE__);
print_rule(lhs, rhs, body);
}
void
target_make_automake::process3_end(void)
{
trace(("%s\n", __PRETTY_FUNCTION__));
if (data.have_yacc() || data.need_yacc())
{
print_comment("\nWhich yacc flags to use.\n\n");
location_comment(__FILE__, __LINE__);
print_assignment("AM_YFLAGS", "-d");
}
if (data.seen_install_mandir())
{
print_comment("manual pages");
location_comment(__FILE__, __LINE__);
print_assignment_sorted("man_MANS", data.get_man_sources());
}
if (data.seen_all_bin())
{
nstring_list programs = data.get_all_bin();
programs.sort();
nstring_list bin_programs;
nstring_list noinst_programs;
nstring_list check_programs;
nstring_list bin_scripts;
nstring_list noinst_scripts;
nstring_list check_scripts;
for (size_t j = 0; j < programs.size(); ++j)
{
nstring bin_program = programs[j];
assert(bin_program.starts_with("bin/"));
nstring program = bin_program.substr(4, bin_program.size() - 4);
nstring progdir = data.progdir_from_progname(program);
bool is_a_script = data.get_object_files_by_dir(progdir).empty();
if (is_a_script)
{
if (data.is_explicit_noinst(program))
noinst_scripts.push_back(bin_program);
else
bin_scripts.push_back(bin_program);
if (program.starts_with("test"))
check_scripts.push_back(bin_program);
}
else
{
if (data.is_explicit_noinst(program))
noinst_programs.push_back(bin_program);
else
bin_programs.push_back(bin_program);
if (program.starts_with("test"))
check_programs.push_back(bin_program);
}
}
if (!bin_programs.empty())
{
print_comment("executables to be installed");
print_assignment_sorted("bin_PROGRAMS", bin_programs);
}
if (!noinst_programs.empty())
{
print_comment("executables not to be installed");
print_assignment_sorted("noinst_PROGRAMS", noinst_programs);
}
if (!check_programs.empty())
{
print_comment("executables needed to run tests");
print_assignment_sorted("check_PROGRAMS", check_programs);
}
if (!bin_scripts.empty())
{
print_comment("scripts to be installed");
print_assignment_sorted("bin_SCRIPTS", bin_scripts);
}
if (!noinst_scripts.empty())
{
print_comment("scripts not to be installed");
print_assignment_sorted("noinst_SCRIPTS", noinst_scripts);
}
if (!check_scripts.empty())
{
print_comment("scripts needed to run tests");
print_assignment_sorted("check_SCRIPTS", check_scripts);
}
}
if (data.seen_pkgconfig_source())
{
op->fputc('\n');
print_assignment("pkgconfigdir", "$(libdir)/pkgconfig");
print_comment("Data files to be installed in $(pkgconfigdir)");
print_assignment_sorted("pkgconfig_DATA", data.get_pkgconfig_sources());
}
// Emit the definitions for the library or libraries.
{
nstring_list lib_ltlibraries;
nstring_list noinst_libraries;
nstring_list lib_dirs = data.get_list_of_library_directories();
lib_dirs.sort();
for (size_t j = 0; j < lib_dirs.size(); ++j)
{
nstring library_dirname = lib_dirs[j];
nstring library_libname = library_dirname;
if (library_libname == "lib")
library_libname = get_project_name();
if (!library_libname.starts_with("lib"))
library_libname = "lib" + library_libname;
nstring path =
library_dirname + "/" + library_libname + "." + data.libext();
bool shared =
(
data.use_libtool()
&&
library_libname == get_library_libname()
);
print_comment("The " + path + " library.");
print_assignment_sorted
(
path.identifier() + "_includes",
data.get_include_files_by_dir(library_dirname)
);
print_assignment_sorted
(
path.identifier() + "_SOURCES",
data.get_source_files_by_dir(library_dirname)
);
if (shared)
{
print_assignment
(
path.identifier() + "_LDFLAGS",
"-version-info " + data.get_version_info()
);
lib_ltlibraries.push_back(path);
}
else
noinst_libraries.push_back(path);
}
if (!lib_ltlibraries.empty())
{
print_comment("Shared libraries, to be installed.");
print_assignment_sorted("lib_LTLIBRARIES", lib_ltlibraries);
}
if (!noinst_libraries.empty())
{
print_comment("Static libraries, not to be installed.");
print_assignment_sorted("noinst_LIBRARIES", noinst_libraries);
}
}
if (data.seen_datadir() || data.seen_datarootdir())
{
nstring_list files = data.get_install_datadir();
nstring_list pkgdatadir;
nstring_list datadir;
nstring_list datarootdir;
nstring projname = get_project_name() + "/";
for (size_t j = 0; j < files.size(); ++j)
{
nstring file = files[j];
if (file.starts_with("$(datarootdir)/"))
{
file = file.trim_first_directory();
datarootdir.push_back(file);
}
else if (file.starts_with("$(datadir)/"))
{
file = file.trim_first_directory();
if (file.starts_with(projname))
{
file = file.trim_first_directory();
pkgdatadir.push_back(file);
}
else
{
datadir.push_back(file);
}
}
else if (file.starts_with("$(sysconfdir)/"))
{
// FIXME: this is wrong, but I don't know how to force
// Automake to change the name of a file when it is
// installed.
datarootdir.push_back(file);
}
else
{
print_comment
(
"Don't know what to do with the " +
file.quote_c() + " file."
);
}
}
if (!pkgdatadir.empty())
{
print_comment
(
"Data files to be installed in $(datadir)/" + projname
);
location_comment(__FILE__, __LINE__);
print_assignment_sorted("dist_pkgdatadir_DATA", pkgdatadir);
}
if (!datadir.empty())
{
print_comment("Data files to be installed in $(datadir)");
location_comment(__FILE__, __LINE__);
print_assignment_sorted("dist_datadir_DATA", pkgdatadir);
}
if (!datarootdir.empty())
{
print_comment("Data files to be installed in $(datarootdir)");
location_comment(__FILE__, __LINE__);
print_assignment_sorted("dist_datarootdir_DATA", datarootdir);
}
}
{
nstring_list drd;
drd.push_back(data.get_am_data_data());
drd.push_back(data.get_install_i18n());
if (!drd.empty())
{
print_comment("Data to be installed below $(datarootdir)/");
location_comment(__FILE__, __LINE__);
print_assignment_sorted("data_DATA", drd);
}
}
if (!data.get_install_include_sources().empty())
{
print_comment("header files to be installed");
print_assignment_sorted
(
(
data.get_library_directory() == "lib"
?
"include_HEADERS"
:
"nobase_include_HEADERS"
),
data.get_install_include_sources()
);
}
if (data.seen_dist_clean_files())
{
print_comment("Files to be removed by the \"distclean\" make target.");
print_assignment_sorted("DISTCLEANFILES", data.get_dist_clean_files());
}
if (data.seen_programs())
{
bool package_library = !data.get_library_name().empty();
nstring_list programs = data.get_programs();
programs.sort();
for (size_t j = 0; j < programs.size(); ++j)
{
nstring prog = programs[j];
nstring iprog = prog.identifier();
print_comment("The " + prog + " program.");
print_assignment_sorted
(
"bin_" + iprog + "_includes",
data.get_include_files_by_dir(prog)
);
print_assignment_sorted
(
"bin_" + iprog + "_SOURCES",
data.get_source_files_by_dir(prog)
);
{
nstring_list ldadd = data.get_library_list_by_program(prog);
if (ldadd.empty() && package_library)
{
ldadd.push_back
(
data.get_library_directory() + "/" +
get_library_libname() + "." + data.libext()
);
}
print_assignment_sorted("bin_" + iprog + "_LDADD", ldadd);
}
}
}
if (data.seen_test_files())
{
//
// FIXME: this needs to be smarter about the test_command field
// of the aegis.conf project configuration file.
//
print_comment("How to run the test scripts.");
nstring_list rhs;
if (data.seen_etc_test_sh())
rhs.push_back("$(SHELL) etc/test.sh");
else
rhs.push_back("PATH=`pwd`/bin:$$PATH $(SHELL)");
print_assignment("TESTS_ENVIRONMENT", rhs);
print_comment("The test scripts to be run.");
print_assignment_sorted("TESTS", data.get_test_sources());
}
// These files don't appear in any other list of files,
// but are to be included in tarballs.
if (data.seen_extra_dist())
{
print_comment("Additional source files to be included in the tarball.");
print_assignment_sorted("EXTRA_DIST", data.get_extra_dist());
}
if (data.use_libtool())
{
//
// Libtool makes executables that have to be writable. Sheesh. This
// makes baseline testing and regression testing impossible, when
// you are using Aegis. So we have to execute thm once at build
// time to get all the crap resolved into an executable that
// doesn't need to be writable.
//
// (It doesn't matter if the program doesn't understand the -V option,
// it still has the effect of making the program the way we want it.)
//
op->fprintf("\n");
op->fprintf("all-am: goose-libtool-writable-crap\n");
op->fprintf("goose-libtool-writable-crap: $(PROGRAMS)\n");
nstring_list programs = data.get_programs();
programs.sort();
for (size_t j = 0; j < programs.size(); ++j)
{
nstring prog = programs[j];
op->fprintf("\t-bin/%s -V\n", prog.c_str());
}
}
//
// BUILT_SOURCES is how automake handles catch-22 include dependencies.
//
if (data.seen_built_sources())
{
print_comment("Catch-22 when building dependencies.");
location_comment(__FILE__, __LINE__);
print_assignment_sorted("BUILT_SOURCES", data.get_built_sources());
}
print_comment("vi" "m: set ts=8 sw=8 noet :");
}
// vim: set ts=8 sw=4 et :