]> git.tdb.fi Git - builder.git/blobdiff - source/builder.cpp
Builder can build itself now.
[builder.git] / source / builder.cpp
index 3f93a672cfe46e8ef0de8c7e9c8ca5da8279ee3c..05ecf877c7f47265131491fa50f0e00189015c1d 100644 (file)
@@ -2,6 +2,8 @@
 #include <msp/strutils.h>
 #include <msp/parser/parser.h>
 #include <msp/path/utils.h>
+#include <msp/time/units.h>
+#include "action.h"
 #include "builder.h"
 #include "executable.h"
 #include "header.h"
@@ -18,7 +20,15 @@ Builder::Builder(int argc, char **argv):
        cwd(Path::getcwd())
 {
        for(int i=1; i<argc; ++i)
-               cmdline_targets.push_back(argv[i]);
+       {
+               string v(argv[i]);
+               unsigned equal=v.find('=');
+               if(equal!=string::npos)
+                       cmdline_options.insert(RawOptionMap::value_type(v.substr(0, equal), v.substr(equal+1)));
+               else
+                       cmdline_targets.push_back(argv[i]);
+       }
+
        if(cmdline_targets.empty())
                cmdline_targets.push_back("default");
 }
@@ -33,24 +43,33 @@ Package *Builder::get_package(const string &n)
        argv.push_back("pkg-config");
        argv.push_back("--variable=source");
        argv.push_back(n);
-       Path::Path srcdir=run_command(argv);
-       if(srcdir.empty())
-       {
-               string dirname=n;
-               if(dirname.compare(0, 3, "msp"))
-                       dirname.erase(0, 3);
-               if(Path::exists(cwd/dirname))
-                       srcdir=cwd/dirname;
-               else if(Path::exists(cwd/".."/dirname))
-                       srcdir=cwd/".."/dirname;
-       }
-       else
-               srcdir=strip(srcdir.str());
+       string srcdir=strip(run_command(argv));
+       cout<<srcdir;
        
+       list<Path::Path> dirs;
        if(!srcdir.empty())
-               load_build_file(srcdir/"Build");
+               dirs.push_back(srcdir);
 
-       return 0;
+       string dirname=n;
+       if(dirname.compare(0, 3, "msp"))
+               dirname.erase(0, 3);
+       dirs.push_back(cwd/dirname);
+       dirs.push_back(cwd/".."/dirname);
+
+       for(list<Path::Path>::iterator j=dirs.begin(); j!=dirs.end(); ++j)
+               if(!load_build_file(*j/"Build"))
+               {
+                       i=packages.find(n);
+                       if(i!=packages.end())
+                               return i->second;
+                       return 0;
+               }
+       
+       Package *pkg=Package::create(*this, n);
+       packages.insert(PackageMap::value_type(n, pkg));
+       new_pkgs.push_back(pkg);
+
+       return pkg;
 }
 
 Target *Builder::get_target(const string &n)
@@ -100,6 +119,27 @@ int Builder::main()
                pkg->resolve_refs();
        }
 
+       std::list<std::string> missing;
+       for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
+       {
+               const list<PackageRef> &requires=i->second->get_requires();
+               for(list<PackageRef>::const_iterator j=requires.begin(); j!=requires.end(); ++j)
+                       if(!j->get_package())
+                               missing.push_back(j->get_name());
+       }
+
+       if(!missing.empty())
+       {
+               missing.sort();
+               missing.unique();
+               cerr<<"The following packages were not found on the system:\n";
+               for(list<string>::iterator i=missing.begin(); i!=missing.end(); ++i)
+                       cerr<<"  "<<*i<<'\n';
+               cerr<<"Please install them and try again.\n";
+       }
+
+       default_pkg->create_build_info();
+
        cout<<"Active packages:";
        for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
        {
@@ -109,14 +149,17 @@ int Builder::main()
        }
        cout<<'\n';
        
-       create_targets();
+       if(create_targets())
+               return 1;
 
        for(TargetMap::iterator i=targets.begin(); i!=targets.end(); ++i)
-               cout<<i->second->get_name()<<' '<<i->second->get_type()<<'\n';
+               cout<<i->second->get_name()<<' '<<i->second->get_type()<<' '<<i->second->get_rebuild()<<' '<<i->second->get_rebuild_reason()<<'\n';
 
        cout<<"Active targets: "<<targets.size()<<'\n';
 
-       return 0;
+       build();
+
+       return exit_code;
 }
 
 int Builder::load_build_file(const Path::Path &fn)
@@ -132,28 +175,30 @@ int Builder::load_build_file(const Path::Path &fn)
        return 0;
 }
 
-void Builder::create_targets()
+int Builder::create_targets()
 {
        Target *world=new VirtualTarget(*this, "world");
        add_target(world);
+
        Target *def_tgt=new VirtualTarget(*this, "default");
        add_target(def_tgt);
+       world->add_depend(def_tgt);
 
        for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
        {
-               cout<<i->second->get_source()<<'\n';
+               if(!i->second->get_buildable())
+                       continue;
+
                const ComponentList &components=i->second->get_components();
                for(ComponentList::const_iterator j=components.begin(); j!=components.end(); ++j)
                {
                        Path::Path base=i->second->get_source()/j->get_source();
-                       cout<<base<<'\n';
                        list<string> files=list_files(base);
 
                        list<ObjectFile *> objs;
                        for(list<string>::iterator k=files.begin(); k!=files.end(); ++k)
                        {
                                Path::Path fn=base/ *k;
-                               //cout<<*k<<'\n';
                                string ext=Path::splitext(*k).ext;
                                if(ext==".cpp" || ext==".c")
                                {
@@ -172,6 +217,8 @@ void Builder::create_targets()
                        add_target(exe);
                        if(i->second==default_pkg)
                                def_tgt->add_depend(exe);
+                       else
+                               world->add_depend(exe);
                }
        }
 
@@ -181,6 +228,26 @@ void Builder::create_targets()
                new_tgts.erase(new_tgts.begin());
                tgt->find_depends();
        }
+
+       Target *cmdline=new VirtualTarget(*this, "cmdline");
+       add_target(cmdline);
+       world->add_depend(cmdline);
+       for(list<string>::iterator i=cmdline_targets.begin(); i!=cmdline_targets.end(); ++i)
+       {
+               Target *tgt=get_target(*i);
+               if(!tgt)
+                       tgt=get_target((cwd/ *i).str());
+               if(!tgt)
+               {
+                       cerr<<"I don't know anything about "<<*i<<'\n';
+                       return 1;
+               }
+               cmdline->add_depend(tgt);
+       }
+
+       world->prepare();
+
+       return 0;
 }
 
 Target *Builder::check_header(const Msp::Path::Path &fn)
@@ -202,6 +269,44 @@ void Builder::add_target(Target *t)
        new_tgts.push_back(t);
 }
 
+int Builder::build()
+{
+       Target *cmdline=get_target("cmdline");
+       list<Action *> actions;
+       bool fail=false;
+
+       while(cmdline->get_rebuild() && !fail)
+       {
+               if(actions.empty() && !fail)
+               {
+                       Target *tgt=cmdline->get_buildable_target();
+                       if(tgt)
+                       {
+                               cout<<"Build "<<tgt->get_name()<<'\n';
+                               Action *action=tgt->build();
+                               if(action)
+                                       actions.push_back(action);
+                       }
+               }
+               else
+                       sleep(10*Time::msec);
+
+               for(list<Action *>::iterator i=actions.begin(); i!=actions.end();)
+               {
+                       int status=(*i)->check();
+                       if(status>=0)
+                       {
+                               delete *i;
+                               i=actions.erase(i);
+                               if(status>0)
+                                       fail=true;
+                       }
+               }
+       }
+
+       return 0;
+}
+
 Application::RegApp<Builder> Builder::reg;
 
 Builder::Loader::Loader(Builder &b, const Path::Path &s):