Attached is a little C++ program to extract global dependency info
from the .deps database.

Compile with the equivalent of:
$ SRCTREE=../devel; BUILDTREE=../devel/build; 
$ g++ -I${SRCTREE}/boost -I${SRCTREE}/src -o collect_deps collect_deps.C 
-L${BUILDTREE}/src/support/.libs -lsupport -L${BUILDTREE}/boost/libs/regex/src/.libs 
-lboostregex

Run like:
$ ./collect_deps `find ${BUILDTREE}/src/ -name "*.o"` | sort -n -r | less

Gives the output below. I think it is fair to say that 88 object files
really _shouldn't_ depend on Bullets.h...

625 dependencies on support/std_string.h
535 dependencies on config.h
277 dependencies on LColor.h
274 dependencies on support/std_ostream.h
253 dependencies on support/DebugStream.h
253 dependencies on debug.h
248 dependencies on lyxlength.h
229 dependencies on gettext.h
217 dependencies on insets/insetbase.h
215 dependencies on dimension.h
214 dependencies on lyxfont.h
154 dependencies on support/lstrings.h
151 dependencies on ParagraphList_fwd.h
150 dependencies on insets/inset.h
140 dependencies on support/types.h
131 dependencies on layout.h
130 dependencies on frontends/qt2/qt_helpers.h
129 dependencies on frontends/controllers/Kernel.h
128 dependencies on frontends/controllers/Dialog.h
119 dependencies on paper.h
111 dependencies on graphics/GraphicsTypes.h
109 dependencies on lyxlayout_ptr_fwd.h
106 dependencies on lfuns.h
105 dependencies on frontends/xforms/forms_fwd.h
104 dependencies on lyxgluelength.h
104 dependencies on frontends/mouse_state.h
101 dependencies on vspace.h
97 dependencies on frontends/controllers/ButtonPolicies.h
92 dependencies on Spacing.h
92 dependencies on frontends/controllers/BCView.tmpl
92 dependencies on frontends/controllers/BCView.h
89 dependencies on lyxlayout.h
89 dependencies on InsetList.h
88 dependencies on Bullet.h
87 dependencies on metricsinfo.h
87 dependencies on lyxtextclass.h
87 dependencies on frontends/xforms/fdesign_base.h
87 dependencies on BranchList.h
86 dependencies on support/filetools.h
85 dependencies on support/LAssert.h
85 dependencies on author.h
84 dependencies on insets/insetquotes.h
84 dependencies on bufferparams.h
81 dependencies on RowList_fwd.h
77 dependencies on texrow.h
74 dependencies on support/limited_stack.h
74 dependencies on mathed/math_inset.h
73 dependencies on lyxvc.h
73 dependencies on buffer.h
72 dependencies on lyxcursor.h
72 dependencies on funcrequest.h
71 dependencies on bufferview_funcs.h
71 dependencies on box.h

-- 
Angus--nextPart6146248.53BEXn27C3
Content-Type: text/x-csrc; name="collect_deps.C"
Content-Transfer-Encoding: 8Bit
Content-Disposition: attachment; filename="collect_deps.C"

#include "lyx_main.h"
#include "support/FileInfo.h"
#include "support/filetools.h"
#include "support/lstrings.h"

#include <boost/tuple/tuple.hpp>

#include <cassert>
#include <exception>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <utility>
#include <vector>

std::ostream & lyxerr = std::cerr;

using std::make_pair;

using std::map;
using std::pair;
using std::string;
using std::vector;

namespace support = lyx::support;

int usage(char const * name);

pair<string, string> const
get_dependency_file(string const & obj_file);

vector<string> const
extract_dependencies(string const & dep_file, string const & obj_file);

typedef map<string, int> DepMap;
void build_local_dependency_map(vector<string> const & data, DepMap & dep_map);

int main(int argc, char * argv[])
{
        if (argc < 2)
                return usage(argv[0]);

        typedef char const * const * const_charstring_iterator;
        const_charstring_iterator obj_files_begin = &argv[1];
        const_charstring_iterator obj_files_end   = &argv[0] + argc;

        DepMap dep_map;

        for (const_charstring_iterator it = obj_files_begin;
             it != obj_files_end; ++it) {
                string dep_file;
                string obj_file;
                boost::tie(dep_file, obj_file) = get_dependency_file(*it);
                if (dep_file.empty())
                        continue;

                vector<string> const data =
                        extract_dependencies(dep_file, obj_file);

                if (data.empty())
                        continue;

                build_local_dependency_map(data, dep_map);
        }

        DepMap::const_iterator dit  = dep_map.begin();
        DepMap::const_iterator dend = dep_map.end();
        for (; dit != dend; ++dit) {
                std::cout << dit->second << " dependencies on "
                          << dit->first << '\n';
        }

        std::flush(std::cout);

        return 0;
}


int usage(char const * name)
{
        std::cerr << "Usage: " << name << " <list of object files>\n";
        return 1;
}


pair<string, string> const get_dependency_file(string const & obj_file)
{
        pair<string, string> const empty;

        if (!support::IsFileReadable(obj_file)) {
                std::cerr << "Cannot find \"" << obj_file << "\".\n";
                return empty;
        }

        string const ext = support::GetExtension(obj_file);
        string const filename = support::OnlyFilename(obj_file);
        if (ext != "o") {
                std::cerr << "Expecting .o files, not " <<  filename << ".\n";
                return empty;
        }

        string const dir = support::OnlyPath(obj_file);
        if (!support::FileInfo(dir).isDir()) {
                std::cerr << '"' << dir << "\" is not a directory.\n";
                return empty;
        }

        string const deps_dir = support::AddPath(dir, ".deps");
        if (!support::FileInfo(deps_dir).isDir()) {
                std::cerr << '"' << deps_dir << "\" is not a directory.\n";
                return empty;
        }

        string const filebase = support::ChangeExtension(obj_file, string());
        string const lo_file = filebase + ".lo";

        string obj_file_out;
        string dep_file;
        if (support::IsFileReadable(lo_file)) {
                obj_file_out = support::OnlyFilename(lo_file);
                dep_file = support::ChangeExtension(filename, ".Plo");
        } else {
                obj_file_out = filename;
                dep_file = support::ChangeExtension(filename, ".Po");
        }
        dep_file = support::AddName(deps_dir, dep_file);
        return make_pair(dep_file, obj_file_out);
}


vector<string> const
extract_dependencies(string const & dep_file, string const & obj_file)
{
        using std::getline;
        using support::ltrim;
        using support::prefixIs;
        using support::split;

        vector<string> data;

        std::ifstream ifs(dep_file.c_str());
        if (!ifs.good()) {
                std::cerr << "Unable to open \"" << dep_file << "\".\n";
                return data;
        }

        bool found_start = false;
        bool the_end = false;
        while (ifs.good()) {
                string line;
                std::getline(ifs, line);
                ltrim(line);
                if (prefixIs(line, obj_file)) {
                        found_start = true;
                        line = ltrim(split(line, ':'));
                }
                if (found_start) {
                        while (1) {
                                string entry;
                                line = ltrim(split(line, entry, ' '));
                                if (!entry.empty() && entry != "\\")
                                        data.push_back(entry);
                                if (line.empty()) {
                                        if (entry != "\\")
                                                the_end = true;
                                        break;
                                }
                        }
                }
                if (the_end)
                        break;
        }
        return data;
}


void build_local_dependency_map(vector<string> const & data, DepMap & dep_map)
{
        using support::contains;
        using support::prefixIs;

        vector<string>::const_iterator it  = data.begin();
        vector<string>::const_iterator end = data.end();
        for (; it != end; ++it) {
                if (!prefixIs(*it, "."))
                        continue;
                if (contains(*it, "boost/"))
                        continue;
                string::size_type const pos = it->find("src/");
                string const entry = pos == string::npos ? *it : it->substr(pos+4);

                DepMap::iterator mit = dep_map.find(entry);
                if (mit == dep_map.end())
                        dep_map[entry] = 1;
                else
                        mit->second += 1;
        }
}


namespace boost {

void throw_exception(std::exception const & e)
{
        std::cerr << "Exception caught:\n" << e.what() << std::endl;
        assert(false);
}

}


string const _(string const & str)
{
        return str;
}


void LyX::emergencyCleanup() {}

Reply via email to