-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 | |||
@@ -27,98 +27,93 @@ namespace sitecing { | |||
27 | root_source(normalize_path(c.root_source,strip_trailing_slash)+'/'), | 27 | root_source(normalize_path(c.root_source,strip_trailing_slash)+'/'), |
28 | root_intermediate(normalize_path(c.root_intermediate,strip_trailing_slash)+'/'), | 28 | root_intermediate(normalize_path(c.root_intermediate,strip_trailing_slash)+'/'), |
29 | root_so(normalize_path(c.root_so,strip_trailing_slash)+'/') { | 29 | root_so(normalize_path(c.root_so,strip_trailing_slash)+'/') { |
30 | } | 30 | } |
31 | 31 | ||
32 | void component_factory::get_dependencies(const string& dst,file_list_t& deps) { | 32 | void component_factory::get_dependencies(const string& dst,file_list_t& deps) { |
33 | deps.clear(); | 33 | deps.clear(); |
34 | string dp = normalize_path(dst,strip_trailing_slash); | 34 | string dp = normalize_path(dst,strip_trailing_slash); |
35 | // source documents | 35 | // source documents |
36 | try { // XXX: or just compare it off? | 36 | try { // XXX: or just compare it off? |
37 | string noro = strip_prefix(dp,root_source); | 37 | string noro = strip_prefix(dp,root_source); |
38 | return; | 38 | return; |
39 | }catch(utility_no_affix& una) { | 39 | }catch(utility_no_affix& una) { } |
40 | } | ||
41 | // .so binaries | 40 | // .so binaries |
42 | try { | 41 | try { |
43 | string noso = strip_suffix(dp,".so"); | 42 | string noso = strip_suffix(dp,".so"); |
44 | string noro = strip_prefix(noso,root_so); | 43 | string noro = strip_prefix(noso,root_so); |
45 | deps.push_back(root_intermediate+noro+".o"); | 44 | deps.push_back(root_intermediate+noro+".o"); |
46 | config_options *co_so_deps = config.lookup_config(noro,config_options::flag_so_deps); | 45 | config_options *co_so_deps = config.lookup_config(noro,config_options::flag_so_deps); |
47 | if(co_so_deps) { | 46 | if(co_so_deps) { |
48 | for(list<string>::const_iterator i=co_so_deps->so_deps.begin();i!=co_so_deps->so_deps.end();++i) | 47 | for(list<string>::const_iterator i=co_so_deps->so_deps.begin();i!=co_so_deps->so_deps.end();++i) |
49 | deps.push_back(*i); | 48 | deps.push_back(*i); |
50 | } | 49 | } |
51 | return; | 50 | return; |
52 | }catch(utility_no_prefix& unp) { | 51 | }catch(utility_no_prefix& unp) { |
53 | throw konforka::exception(CODEPOINT,"component is outside of component root"); | 52 | throw konforka::exception(CODEPOINT,"component is outside of component root"); |
54 | }catch(utility_no_suffix& uns) { | 53 | }catch(utility_no_suffix& uns) { } |
55 | } | 54 | try { |
56 | // preprocessor targets | 55 | // preprocessor targets |
57 | for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { | 56 | string noro = strip_prefix(dp,root_intermediate); |
58 | try { | 57 | for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { |
59 | string nos = strip_suffix(dp,pp_targets[ppt]); | 58 | try { |
60 | string noro = strip_prefix(nos,root_intermediate); | 59 | string nos = strip_suffix(noro,pp_targets[ppt]); |
61 | deps.push_back(root_source+noro); | 60 | deps.push_back(root_source+nos); // depends on the source |
62 | ifstream imports((root_intermediate+noro+".imports").c_str(),ios::in); | 61 | ifstream imports((root_intermediate+nos+".imports").c_str(),ios::in); |
63 | if(imports.good()) { | 62 | if(imports.good()) { |
64 | string str; | 63 | string str; |
65 | while(!imports.eof()) { | 64 | while(!imports.eof()) { |
66 | imports >> str; | 65 | imports >> str; |
67 | if(!str.empty()) | 66 | if(!str.empty()) |
68 | deps.push_back(root_intermediate+str+".classname"); | 67 | deps.push_back(root_intermediate+str+".classname"); |
68 | } | ||
69 | } | ||
70 | ifstream ancestors((root_intermediate+nos+".ancestors").c_str(),ios::in); | ||
71 | if(ancestors.good()) { | ||
72 | string str; | ||
73 | while(!ancestors.eof()) { | ||
74 | ancestors >> str; | ||
75 | if(!str.empty()) | ||
76 | deps.push_back(root_intermediate+str+".classname"); | ||
77 | } | ||
69 | } | 78 | } |
70 | } | 79 | config_options *co_intermediate_deps = config.lookup_config(nos,config_options::flag_intermediate_deps); |
71 | ifstream ancestors((root_intermediate+noro+".ancestors").c_str(),ios::in); | 80 | if(co_intermediate_deps) { |
72 | if(ancestors.good()) { | 81 | for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i) |
73 | string str; | 82 | deps.push_back(*i); |
74 | while(!ancestors.eof()) { | ||
75 | ancestors >> str; | ||
76 | if(!str.empty()) | ||
77 | deps.push_back(root_intermediate+str+".classname"); | ||
78 | } | 83 | } |
79 | } | 84 | return; |
80 | config_options *co_intermediate_deps = config.lookup_config(noro,config_options::flag_intermediate_deps); | 85 | }catch(utility_no_suffix& uns) { } |
81 | if(co_intermediate_deps) { | ||
82 | for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i) | ||
83 | deps.push_back(*i); | ||
84 | } | ||
85 | return; | ||
86 | }catch(utility_no_affix& una) { | ||
87 | // do nothing. must be a cpp dependency. | ||
88 | } | 86 | } |
89 | } | 87 | // compiler targets |
90 | // compiler targets | 88 | for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { |
91 | for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { | 89 | try { |
92 | try { | 90 | string nos = strip_suffix(noro,cc_targets[cct]); |
93 | string nos = strip_suffix(dp,cc_targets[cct]); | 91 | deps.push_back(root_intermediate+nos+".cc"); |
94 | string noro = strip_prefix(nos,root_intermediate); | 92 | config_options *co_cpp_deps = config.lookup_config(noro,config_options::flag_cpp_deps); |
95 | deps.push_back(root_intermediate+noro+".cc"); | 93 | if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) { |
96 | config_options *co_cpp_deps = config.lookup_config(noro,config_options::flag_cpp_deps); | 94 | ifstream df((root_intermediate+noro+".d").c_str(),ios::in); |
97 | if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) { | 95 | if(df.good()) { |
98 | ifstream df((root_intermediate+noro+".d").c_str(),ios::in); | 96 | string str; |
99 | if(df.good()) { | 97 | while(!df.eof()) { |
100 | string str; | 98 | df >> str; |
101 | while(!df.eof()) { | 99 | if(str.find_first_of("\\:")==string::npos) |
102 | df >> str; | 100 | deps.push_back(combine_path(config.root_source+nos,str)); |
103 | if(str.find_first_of("\\:")==string::npos) | 101 | } |
104 | deps.push_back(combine_path(config.root_source+noro,str)); | ||
105 | } | 102 | } |
106 | } | 103 | } |
107 | } | 104 | // XXX: extra deps like IntermediateDeps? |
108 | // XXX: extra deps like IntermediateDeps? | 105 | }catch(utility_no_suffix& uns) { } |
109 | }catch(utility_no_affix& una) { | ||
110 | // do nothing. | ||
111 | } | 106 | } |
112 | } | 107 | }catch(utility_no_prefix& unp) { } |
113 | } | 108 | } |
114 | 109 | ||
115 | bool component_factory::is_uptodate(const string& dst,file_list_t *deps) { | 110 | bool component_factory::is_uptodate(const string& dst,file_list_t *deps) { |
116 | string dp = normalize_path(dst,strip_trailing_slash); | 111 | string dp = normalize_path(dst,strip_trailing_slash); |
117 | // XXX: or just compare it off, instead of throwing things around. | 112 | // XXX: or just compare it off, instead of throwing things around. |
118 | try { | 113 | try { |
119 | string noro = strip_prefix(dp,root_intermediate); | 114 | string noro = strip_prefix(dp,root_intermediate); |
120 | for(int ppt=0;(ppt+1)<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { | 115 | for(int ppt=0;(ppt+1)<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { |
121 | try { | 116 | try { |
122 | string nos = strip_suffix(noro,pp_targets[ppt]); | 117 | string nos = strip_suffix(noro,pp_targets[ppt]); |
123 | return file_factory::is_uptodate(root_intermediate+nos+".pp_stamp",deps); | 118 | return file_factory::is_uptodate(root_intermediate+nos+".pp_stamp",deps); |
124 | }catch(utility_no_suffix& uns) { } | 119 | }catch(utility_no_suffix& uns) { } |
@@ -131,26 +126,25 @@ namespace sitecing { | |||
131 | return file_factory::is_uptodate(dst,deps); | 126 | return file_factory::is_uptodate(dst,deps); |
132 | }catch(utility_no_prefix& unp) { } | 127 | }catch(utility_no_prefix& unp) { } |
133 | return true; | 128 | return true; |
134 | } | 129 | } |
135 | 130 | ||
136 | void component_factory::build(const string& dst) { | 131 | void component_factory::build(const string& dst) { |
137 | string dp = normalize_path(dst,strip_trailing_slash); | 132 | string dp = normalize_path(dst,strip_trailing_slash); |
138 | // sources | 133 | // sources |
139 | try { | 134 | try { |
140 | string noro = strip_prefix(dp,root_source); | 135 | string noro = strip_prefix(dp,root_source); |
141 | // building the sources is left up to developer | 136 | // building the sources is left up to developer |
142 | return; | 137 | return; |
143 | }catch(utility_no_prefix& unp) { | 138 | }catch(utility_no_prefix& unp) { } |
144 | } | ||
145 | // .so files | 139 | // .so files |
146 | try { | 140 | try { |
147 | string noso = strip_suffix(dp,".so"); | 141 | string noso = strip_suffix(dp,".so"); |
148 | string noro = strip_prefix(noso,root_so); | 142 | string noro = strip_prefix(noso,root_so); |
149 | string o = root_intermediate+noro+".o"; | 143 | string o = root_intermediate+noro+".o"; |
150 | if(access(o.c_str(),R_OK)) | 144 | if(access(o.c_str(),R_OK)) |
151 | throw konforka::exception(CODEPOINT,string("can't access compiled component code (")+o+")"); | 145 | throw konforka::exception(CODEPOINT,string("can't access compiled component code (")+o+")"); |
152 | make_path(dir_name(root_so+noro),0755); | 146 | make_path(dir_name(root_so+noro),0755); |
153 | file_lock lock_cc(root_intermediate+noro+".o.lock"); | 147 | file_lock lock_cc(root_intermediate+noro+".o.lock"); |
154 | file_lock lock_so(root_so+noro+".so.lock"); | 148 | file_lock lock_so(root_so+noro+".so.lock"); |
155 | int stdO = open((root_intermediate+noro+".ld.stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); | 149 | int stdO = open((root_intermediate+noro+".ld.stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); |
156 | if(stdO<0) | 150 | if(stdO<0) |
@@ -174,107 +168,103 @@ namespace sitecing { | |||
174 | make(aso); | 168 | make(aso); |
175 | args.push_back(aso); | 169 | args.push_back(aso); |
176 | } | 170 | } |
177 | args.push_back("-o"); args.push_back(dp); | 171 | args.push_back("-o"); args.push_back(dp); |
178 | // TODO: "g++" configurable | 172 | // TODO: "g++" configurable |
179 | int rv = execute("g++",args,stdO,stdE); | 173 | int rv = execute("g++",args,stdO,stdE); |
180 | if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) | 174 | if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) |
181 | // TODO:TODO: linker_error | 175 | // TODO:TODO: linker_error |
182 | throw compile_error(CODEPOINT,"failed to link component",noro); | 176 | throw compile_error(CODEPOINT,"failed to link component",noro); |
183 | return; | 177 | return; |
184 | }catch(utility_no_prefix& unp) { | 178 | }catch(utility_no_prefix& unp) { |
185 | throw konforka::exception(CODEPOINT,"component is outside of component root"); | 179 | throw konforka::exception(CODEPOINT,"component is outside of component root"); |
186 | }catch(utility_no_suffix& uns) { | 180 | }catch(utility_no_suffix& uns) { } |
187 | } | 181 | try { |
188 | // compiler targets | 182 | string noro = strip_prefix(dp,root_intermediate); |
189 | for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { | 183 | // compiler targets |
190 | try { | 184 | for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { |
191 | string nos = strip_suffix(dp,cc_targets[cct]); | 185 | try { |
192 | string noro = strip_prefix(nos,root_intermediate); | 186 | string nos = strip_suffix(noro,cc_targets[cct]); |
193 | string cc = root_intermediate+noro+".cc"; | 187 | string cc = root_intermediate+nos+".cc"; |
194 | string o = root_intermediate+noro+".o"; | 188 | string o = root_intermediate+nos+".o"; |
195 | if(access(cc.c_str(),R_OK)) | 189 | if(access(cc.c_str(),R_OK)) |
196 | throw konforka::exception(CODEPOINT,string("can't access preprocessed component code (")+cc+")"); | 190 | throw konforka::exception(CODEPOINT,string("can't access preprocessed component code (")+cc+")"); |
197 | make_path(dir_name(cc),0755); | 191 | make_path(dir_name(cc),0755); |
198 | string pwd = dir_name(root_source+noro); | 192 | string pwd = dir_name(root_source+nos); |
199 | auto_chdir dir_changer(pwd); | 193 | auto_chdir dir_changer(pwd); |
200 | file_lock lock_source(root_intermediate+noro+".lock"); | 194 | file_lock lock_source(root_intermediate+nos+".lock"); |
201 | file_lock lock_cc(root_intermediate+noro+".o.lock"); | 195 | file_lock lock_cc(root_intermediate+nos+".o.lock"); |
202 | int stdO = open((root_intermediate+noro+".stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); | 196 | int stdO = open((root_intermediate+nos+".stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); |
203 | if(stdO<0) | 197 | if(stdO<0) |
204 | throw konforka::exception(CODEPOINT,"failed to open/create compiler stdout"); | 198 | throw konforka::exception(CODEPOINT,"failed to open/create compiler stdout"); |
205 | int stdE = open((root_intermediate+noro+".stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); | 199 | int stdE = open((root_intermediate+nos+".stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); |
206 | if(stdE<0) { | 200 | if(stdE<0) { |
207 | close(stdO); | 201 | close(stdO); |
208 | throw konforka::exception(CODEPOINT,"failed to open/create compiler's stderr"); | 202 | throw konforka::exception(CODEPOINT,"failed to open/create compiler's stderr"); |
209 | } | 203 | } |
210 | list<string> args; | 204 | list<string> args; |
211 | config_options *co_cpp_flags = config.lookup_config(noro,config_options::flag_cpp_flags); | 205 | config_options *co_cpp_flags = config.lookup_config(nos,config_options::flag_cpp_flags); |
212 | if(co_cpp_flags) { | 206 | if(co_cpp_flags) { |
213 | args.insert(args.end(),co_cpp_flags->cpp_flags.begin(),co_cpp_flags->cpp_flags.end()); | 207 | args.insert(args.end(),co_cpp_flags->cpp_flags.begin(),co_cpp_flags->cpp_flags.end()); |
214 | } | 208 | } |
215 | // TODO: maybe move it to separare config option like CoreCPPFLags? | 209 | // TODO: maybe move it to separare config option like CoreCPPFLags? |
216 | args.push_back("-I"+root_intermediate); | 210 | args.push_back("-I"+root_intermediate); |
217 | args.push_back("-I"+root_source); | 211 | args.push_back("-I"+root_source); |
218 | args.push_back("-MD"); args.push_back("-MF"); args.push_back(root_intermediate+noro+".d"); | 212 | args.push_back("-MD"); args.push_back("-MF"); args.push_back(root_intermediate+nos+".d"); |
219 | args.push_back("-c"); | 213 | args.push_back("-c"); |
220 | args.push_back(cc); | 214 | args.push_back(cc); |
221 | args.push_back("-o"); args.push_back(o); | 215 | args.push_back("-o"); args.push_back(o); |
222 | // TODO: "g++" configurable | 216 | // TODO: "g++" configurable |
223 | int rv = execute("g++",args,stdO,stdE); | 217 | int rv = execute("g++",args,stdO,stdE); |
224 | if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) | 218 | if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) |
225 | throw compile_error(CODEPOINT,"failed to compile component",noro); | 219 | throw compile_error(CODEPOINT,"failed to compile component",nos); |
226 | return; | 220 | return; |
227 | }catch(utility_no_affix& una) { | 221 | }catch(utility_no_suffix& uns) { } |
228 | // do nothing, not a compiler target | ||
229 | } | 222 | } |
230 | } | 223 | // preprocessor targets |
231 | // preprocessor targets | 224 | for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { |
232 | for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { | ||
233 | try { | ||
234 | string nos = strip_suffix(dp,pp_targets[ppt]); | ||
235 | string noro = strip_prefix(nos,root_intermediate); | ||
236 | string src = root_source+noro; | ||
237 | if(access(src.c_str(),R_OK)) | ||
238 | throw konforka::exception(CODEPOINT,string("can't access component source (")+src+")"); | ||
239 | make_path(dir_name(root_intermediate+noro),0755); | ||
240 | file_lock lock(root_intermediate+noro+".lock"); | ||
241 | sitecing_parser parser(*this); | ||
242 | config_options *co_skeleton = config.lookup_config(noro,config_options::flag_skeleton); | ||
243 | if(co_skeleton) | ||
244 | parser.skeleton = co_skeleton->skeleton; | ||
245 | static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | ||
246 | parser.class_name = normalize_path(noro,strip_leading_slash|strip_trailing_slash); | ||
247 | 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)) { | ||
248 | string::size_type lc = parser.class_name.find_first_of(id_chars,illc); | ||
249 | int n = ((lc==string::npos)?parser.class_name.length():lc)-illc; | ||
250 | parser.class_name.replace(illc,n,n,'_'); | ||
251 | } | ||
252 | parser.class_name = "_SCC_"+parser.class_name; | ||
253 | parser.output_basename = nos; | ||
254 | parser.component_basename = noro; | ||
255 | try { | 225 | try { |
256 | parser.preprocess(src); | 226 | string nos = strip_suffix(noro,pp_targets[ppt]); |
257 | string sf = root_intermediate+noro+".pp_stamp"; | 227 | string src = root_source+nos; |
258 | ofstream sfs(sf.c_str(),ios::trunc|ios::out); // touch .pp_stamp | 228 | if(access(src.c_str(),R_OK)) |
259 | }catch(preprocessor_error& pe) { | 229 | throw konforka::exception(CODEPOINT,string("can't access component source (")+src+")"); |
260 | pe.component_name = noro; | 230 | make_path(dir_name(root_intermediate+nos),0755); |
261 | pe.see(CODEPOINT); | 231 | file_lock lock(root_intermediate+nos+".lock"); |
262 | throw; | 232 | sitecing_parser parser(*this); |
263 | } | 233 | config_options *co_skeleton = config.lookup_config(nos,config_options::flag_skeleton); |
264 | return; | 234 | if(co_skeleton) |
265 | }catch(utility_no_affix& una) { | 235 | parser.skeleton = co_skeleton->skeleton; |
266 | // must be a crap from .d file | 236 | static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
237 | parser.class_name = normalize_path(nos,strip_leading_slash|strip_trailing_slash); | ||
238 | 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)) { | ||
239 | string::size_type lc = parser.class_name.find_first_of(id_chars,illc); | ||
240 | int n = ((lc==string::npos)?parser.class_name.length():lc)-illc; | ||
241 | parser.class_name.replace(illc,n,n,'_'); | ||
242 | } | ||
243 | parser.class_name = "_SCC_"+parser.class_name; | ||
244 | parser.output_basename = root_intermediate+nos; | ||
245 | parser.component_basename = nos; | ||
246 | try { | ||
247 | parser.preprocess(src); | ||
248 | string sf = root_intermediate+nos+".pp_stamp"; | ||
249 | ofstream sfs(sf.c_str(),ios::trunc|ios::out); // touch .pp_stamp | ||
250 | }catch(preprocessor_error& pe) { | ||
251 | pe.component_name = nos; | ||
252 | pe.see(CODEPOINT); | ||
253 | throw; | ||
254 | } | ||
255 | return; | ||
256 | }catch(utility_no_suffix& uns) { } | ||
267 | } | 257 | } |
268 | } | 258 | }catch(utility_no_prefix& unp) { } |
269 | cerr << "ignoring build request for " << dp << endl; | 259 | cerr << "ignoring build request for " << dp << endl; |
270 | } | 260 | } |
271 | 261 | ||
272 | int component_factory::execute(const string& cmd, const list<string>& args,int stdo,int stde) { | 262 | int component_factory::execute(const string& cmd, const list<string>& args,int stdo,int stde) { |
273 | // XXX: is it right that we do stdio/stderr tricks outside of the function? | 263 | // XXX: is it right that we do stdio/stderr tricks outside of the function? |
274 | cerr << "executing: " << cmd; | 264 | cerr << "executing: " << cmd; |
275 | vector<const char*> argv(args.size()+2); | 265 | vector<const char*> argv(args.size()+2); |
276 | argv[0]=cmd.c_str(); | 266 | argv[0]=cmd.c_str(); |
277 | int an = 1; | 267 | int an = 1; |
278 | for(list<string>::const_iterator i=args.begin();i!=args.end();i++) { | 268 | for(list<string>::const_iterator i=args.begin();i!=args.end();i++) { |
279 | cerr << " " << *i ; | 269 | cerr << " " << *i ; |
280 | argv[an++] = i->c_str(); | 270 | argv[an++] = i->c_str(); |