summaryrefslogtreecommitdiffabout
path: root/lib
Unidiff
Diffstat (limited to 'lib') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/component_factory.cc264
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();