-rw-r--r-- | lib/component_factory.cc | 264 |
1 files changed, 127 insertions, 137 deletions
diff --git a/lib/component_factory.cc b/lib/component_factory.cc index 1253111..a5ced6b 100644 --- a/lib/component_factory.cc +++ b/lib/component_factory.cc @@ -15,278 +15,268 @@ #include "sitecing/sitecing_util.h" #include "sitecing/sitecing_parser.h" #include "sitecing/sitecing_exception.h" #endif namespace sitecing { static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors", ".pp_stamp" }; static const char *cc_targets[] = { ".o", ".d" }; component_factory::component_factory(configuration& c) : config(c), root_source(normalize_path(c.root_source,strip_trailing_slash)+'/'), root_intermediate(normalize_path(c.root_intermediate,strip_trailing_slash)+'/'), root_so(normalize_path(c.root_so,strip_trailing_slash)+'/') { } void component_factory::get_dependencies(const string& dst,file_list_t& deps) { deps.clear(); string dp = normalize_path(dst,strip_trailing_slash); // source documents try { // XXX: or just compare it off? string noro = strip_prefix(dp,root_source); return; - }catch(utility_no_affix& una) { - } + }catch(utility_no_affix& una) { } // .so binaries try { string noso = strip_suffix(dp,".so"); string noro = strip_prefix(noso,root_so); deps.push_back(root_intermediate+noro+".o"); config_options *co_so_deps = config.lookup_config(noro,config_options::flag_so_deps); if(co_so_deps) { for(list<string>::const_iterator i=co_so_deps->so_deps.begin();i!=co_so_deps->so_deps.end();++i) deps.push_back(*i); } return; }catch(utility_no_prefix& unp) { throw konforka::exception(CODEPOINT,"component is outside of component root"); - }catch(utility_no_suffix& uns) { - } - // preprocessor targets - for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { - try { - string nos = strip_suffix(dp,pp_targets[ppt]); - string noro = strip_prefix(nos,root_intermediate); - deps.push_back(root_source+noro); - ifstream imports((root_intermediate+noro+".imports").c_str(),ios::in); - if(imports.good()) { - string str; - while(!imports.eof()) { - imports >> str; - if(!str.empty()) - deps.push_back(root_intermediate+str+".classname"); + }catch(utility_no_suffix& uns) { } + try { + // preprocessor targets + string noro = strip_prefix(dp,root_intermediate); + for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { + try { + string nos = strip_suffix(noro,pp_targets[ppt]); + deps.push_back(root_source+nos); // depends on the source + ifstream imports((root_intermediate+nos+".imports").c_str(),ios::in); + if(imports.good()) { + string str; + while(!imports.eof()) { + imports >> str; + if(!str.empty()) + deps.push_back(root_intermediate+str+".classname"); + } + } + ifstream ancestors((root_intermediate+nos+".ancestors").c_str(),ios::in); + if(ancestors.good()) { + string str; + while(!ancestors.eof()) { + ancestors >> str; + if(!str.empty()) + deps.push_back(root_intermediate+str+".classname"); + } } - } - ifstream ancestors((root_intermediate+noro+".ancestors").c_str(),ios::in); - if(ancestors.good()) { - string str; - while(!ancestors.eof()) { - ancestors >> str; - if(!str.empty()) - deps.push_back(root_intermediate+str+".classname"); + config_options *co_intermediate_deps = config.lookup_config(nos,config_options::flag_intermediate_deps); + if(co_intermediate_deps) { + for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i) + deps.push_back(*i); } - } - config_options *co_intermediate_deps = config.lookup_config(noro,config_options::flag_intermediate_deps); - if(co_intermediate_deps) { - for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i) - deps.push_back(*i); - } - return; - }catch(utility_no_affix& una) { - // do nothing. must be a cpp dependency. + return; + }catch(utility_no_suffix& uns) { } } - } - // compiler targets - for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { - try { - string nos = strip_suffix(dp,cc_targets[cct]); - string noro = strip_prefix(nos,root_intermediate); - deps.push_back(root_intermediate+noro+".cc"); - config_options *co_cpp_deps = config.lookup_config(noro,config_options::flag_cpp_deps); - if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) { - ifstream df((root_intermediate+noro+".d").c_str(),ios::in); - if(df.good()) { - string str; - while(!df.eof()) { - df >> str; - if(str.find_first_of("\\:")==string::npos) - deps.push_back(combine_path(config.root_source+noro,str)); + // compiler targets + for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { + try { + string nos = strip_suffix(noro,cc_targets[cct]); + deps.push_back(root_intermediate+nos+".cc"); + config_options *co_cpp_deps = config.lookup_config(noro,config_options::flag_cpp_deps); + if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) { + ifstream df((root_intermediate+noro+".d").c_str(),ios::in); + if(df.good()) { + string str; + while(!df.eof()) { + df >> str; + if(str.find_first_of("\\:")==string::npos) + deps.push_back(combine_path(config.root_source+nos,str)); + } } } - } - // XXX: extra deps like IntermediateDeps? - }catch(utility_no_affix& una) { - // do nothing. + // XXX: extra deps like IntermediateDeps? + }catch(utility_no_suffix& uns) { } } - } + }catch(utility_no_prefix& unp) { } } bool component_factory::is_uptodate(const string& dst,file_list_t *deps) { string dp = normalize_path(dst,strip_trailing_slash); // XXX: or just compare it off, instead of throwing things around. try { string noro = strip_prefix(dp,root_intermediate); for(int ppt=0;(ppt+1)<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { try { string nos = strip_suffix(noro,pp_targets[ppt]); return file_factory::is_uptodate(root_intermediate+nos+".pp_stamp",deps); }catch(utility_no_suffix& uns) { } } bool rv = file_factory::is_uptodate(dst,deps); return rv; }catch(utility_no_prefix& unp) { } try { strip_prefix(dp,root_so); return file_factory::is_uptodate(dst,deps); }catch(utility_no_prefix& unp) { } return true; } void component_factory::build(const string& dst) { string dp = normalize_path(dst,strip_trailing_slash); // sources try { string noro = strip_prefix(dp,root_source); // building the sources is left up to developer return; - }catch(utility_no_prefix& unp) { - } + }catch(utility_no_prefix& unp) { } // .so files try { string noso = strip_suffix(dp,".so"); string noro = strip_prefix(noso,root_so); string o = root_intermediate+noro+".o"; if(access(o.c_str(),R_OK)) throw konforka::exception(CODEPOINT,string("can't access compiled component code (")+o+")"); make_path(dir_name(root_so+noro),0755); file_lock lock_cc(root_intermediate+noro+".o.lock"); file_lock lock_so(root_so+noro+".so.lock"); int stdO = open((root_intermediate+noro+".ld.stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); if(stdO<0) throw konforka::exception(CODEPOINT,"failed to open/create linker stdout"); int stdE = open((root_intermediate+noro+".ld.stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); if(stdE<0) { close(stdO); throw konforka::exception(CODEPOINT,"failed to open/create linker stderr"); } list<string> args; config_options *co_ld_flags = config.lookup_config(noro,config_options::flag_ld_flags); if(co_ld_flags) { args.insert(args.end(),co_ld_flags->ld_flags.begin(),co_ld_flags->ld_flags.end()); } args.push_back("-shared"); args.push_back(o); file_list_t ancestors; get_ancestors(noro,ancestors); for(file_list_t::const_iterator i=ancestors.begin();i!=ancestors.end();++i) { string aso=root_so+*i+".so"; make(aso); args.push_back(aso); } args.push_back("-o"); args.push_back(dp); // TODO: "g++" configurable int rv = execute("g++",args,stdO,stdE); if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) // TODO:TODO: linker_error throw compile_error(CODEPOINT,"failed to link component",noro); return; }catch(utility_no_prefix& unp) { throw konforka::exception(CODEPOINT,"component is outside of component root"); - }catch(utility_no_suffix& uns) { - } - // compiler targets - for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { - try { - string nos = strip_suffix(dp,cc_targets[cct]); - string noro = strip_prefix(nos,root_intermediate); - string cc = root_intermediate+noro+".cc"; - string o = root_intermediate+noro+".o"; - if(access(cc.c_str(),R_OK)) - throw konforka::exception(CODEPOINT,string("can't access preprocessed component code (")+cc+")"); - make_path(dir_name(cc),0755); - string pwd = dir_name(root_source+noro); - auto_chdir dir_changer(pwd); - file_lock lock_source(root_intermediate+noro+".lock"); - file_lock lock_cc(root_intermediate+noro+".o.lock"); - int stdO = open((root_intermediate+noro+".stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); - if(stdO<0) - throw konforka::exception(CODEPOINT,"failed to open/create compiler stdout"); - int stdE = open((root_intermediate+noro+".stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); - if(stdE<0) { - close(stdO); - throw konforka::exception(CODEPOINT,"failed to open/create compiler's stderr"); - } - list<string> args; - config_options *co_cpp_flags = config.lookup_config(noro,config_options::flag_cpp_flags); - if(co_cpp_flags) { - args.insert(args.end(),co_cpp_flags->cpp_flags.begin(),co_cpp_flags->cpp_flags.end()); - } - // TODO: maybe move it to separare config option like CoreCPPFLags? - args.push_back("-I"+root_intermediate); - args.push_back("-I"+root_source); - args.push_back("-MD"); args.push_back("-MF"); args.push_back(root_intermediate+noro+".d"); - args.push_back("-c"); - args.push_back(cc); - args.push_back("-o"); args.push_back(o); - // TODO: "g++" configurable - int rv = execute("g++",args,stdO,stdE); - if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) - throw compile_error(CODEPOINT,"failed to compile component",noro); - return; - }catch(utility_no_affix& una) { - // do nothing, not a compiler target + }catch(utility_no_suffix& uns) { } + try { + string noro = strip_prefix(dp,root_intermediate); + // compiler targets + for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { + try { + string nos = strip_suffix(noro,cc_targets[cct]); + string cc = root_intermediate+nos+".cc"; + string o = root_intermediate+nos+".o"; + if(access(cc.c_str(),R_OK)) + throw konforka::exception(CODEPOINT,string("can't access preprocessed component code (")+cc+")"); + make_path(dir_name(cc),0755); + string pwd = dir_name(root_source+nos); + auto_chdir dir_changer(pwd); + file_lock lock_source(root_intermediate+nos+".lock"); + file_lock lock_cc(root_intermediate+nos+".o.lock"); + int stdO = open((root_intermediate+nos+".stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); + if(stdO<0) + throw konforka::exception(CODEPOINT,"failed to open/create compiler stdout"); + int stdE = open((root_intermediate+nos+".stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); + if(stdE<0) { + close(stdO); + throw konforka::exception(CODEPOINT,"failed to open/create compiler's stderr"); + } + list<string> args; + config_options *co_cpp_flags = config.lookup_config(nos,config_options::flag_cpp_flags); + if(co_cpp_flags) { + args.insert(args.end(),co_cpp_flags->cpp_flags.begin(),co_cpp_flags->cpp_flags.end()); + } + // TODO: maybe move it to separare config option like CoreCPPFLags? + args.push_back("-I"+root_intermediate); + args.push_back("-I"+root_source); + args.push_back("-MD"); args.push_back("-MF"); args.push_back(root_intermediate+nos+".d"); + args.push_back("-c"); + args.push_back(cc); + args.push_back("-o"); args.push_back(o); + // TODO: "g++" configurable + int rv = execute("g++",args,stdO,stdE); + if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) + throw compile_error(CODEPOINT,"failed to compile component",nos); + return; + }catch(utility_no_suffix& uns) { } } - } - // preprocessor targets - for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { - try { - string nos = strip_suffix(dp,pp_targets[ppt]); - string noro = strip_prefix(nos,root_intermediate); - string src = root_source+noro; - if(access(src.c_str(),R_OK)) - throw konforka::exception(CODEPOINT,string("can't access component source (")+src+")"); - make_path(dir_name(root_intermediate+noro),0755); - file_lock lock(root_intermediate+noro+".lock"); - sitecing_parser parser(*this); - config_options *co_skeleton = config.lookup_config(noro,config_options::flag_skeleton); - if(co_skeleton) - parser.skeleton = co_skeleton->skeleton; - static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - parser.class_name = normalize_path(noro,strip_leading_slash|strip_trailing_slash); - for(string::size_type illc = parser.class_name.find_first_not_of(id_chars);illc!=string::npos;illc=parser.class_name.find_first_not_of(id_chars,illc)) { - string::size_type lc = parser.class_name.find_first_of(id_chars,illc); - int n = ((lc==string::npos)?parser.class_name.length():lc)-illc; - parser.class_name.replace(illc,n,n,'_'); - } - parser.class_name = "_SCC_"+parser.class_name; - parser.output_basename = nos; - parser.component_basename = noro; + // preprocessor targets + for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { try { - parser.preprocess(src); - string sf = root_intermediate+noro+".pp_stamp"; - ofstream sfs(sf.c_str(),ios::trunc|ios::out); // touch .pp_stamp - }catch(preprocessor_error& pe) { - pe.component_name = noro; - pe.see(CODEPOINT); - throw; - } - return; - }catch(utility_no_affix& una) { - // must be a crap from .d file + string nos = strip_suffix(noro,pp_targets[ppt]); + string src = root_source+nos; + if(access(src.c_str(),R_OK)) + throw konforka::exception(CODEPOINT,string("can't access component source (")+src+")"); + make_path(dir_name(root_intermediate+nos),0755); + file_lock lock(root_intermediate+nos+".lock"); + sitecing_parser parser(*this); + config_options *co_skeleton = config.lookup_config(nos,config_options::flag_skeleton); + if(co_skeleton) + parser.skeleton = co_skeleton->skeleton; + static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + parser.class_name = normalize_path(nos,strip_leading_slash|strip_trailing_slash); + for(string::size_type illc = parser.class_name.find_first_not_of(id_chars);illc!=string::npos;illc=parser.class_name.find_first_not_of(id_chars,illc)) { + string::size_type lc = parser.class_name.find_first_of(id_chars,illc); + int n = ((lc==string::npos)?parser.class_name.length():lc)-illc; + parser.class_name.replace(illc,n,n,'_'); + } + parser.class_name = "_SCC_"+parser.class_name; + parser.output_basename = root_intermediate+nos; + parser.component_basename = nos; + try { + parser.preprocess(src); + string sf = root_intermediate+nos+".pp_stamp"; + ofstream sfs(sf.c_str(),ios::trunc|ios::out); // touch .pp_stamp + }catch(preprocessor_error& pe) { + pe.component_name = nos; + pe.see(CODEPOINT); + throw; + } + return; + }catch(utility_no_suffix& uns) { } } - } + }catch(utility_no_prefix& unp) { } cerr << "ignoring build request for " << dp << endl; } int component_factory::execute(const string& cmd, const list<string>& args,int stdo,int stde) { // XXX: is it right that we do stdio/stderr tricks outside of the function? cerr << "executing: " << cmd; vector<const char*> argv(args.size()+2); argv[0]=cmd.c_str(); int an = 1; for(list<string>::const_iterator i=args.begin();i!=args.end();i++) { cerr << " " << *i ; argv[an++] = i->c_str(); } cerr << endl; argv[an++]=NULL; pid_t pid = vfork(); if(pid==-1) { close(stdo); close(stde); throw konforka::exception(CODEPOINT,"failed to vfork()"); } if(!pid) { // child if(dup2(stdo,1)!=1) _exit(-1); |