summaryrefslogtreecommitdiffabout
path: root/lib
authorMichael Krelin <hacker@klever.net>2005-03-29 21:03:31 (UTC)
committer Michael Krelin <hacker@klever.net>2005-03-29 21:03:31 (UTC)
commit642dc685bd0a3f1526e22827a4539aa0e06aeff7 (patch) (unidiff)
treef796be7c3093982f18dfd630a3f95c0a2c769eb3 /lib
parentb0e2dda829db4560e2c0ed7556803124a396b89f (diff)
downloadsitecing-642dc685bd0a3f1526e22827a4539aa0e06aeff7.zip
sitecing-642dc685bd0a3f1526e22827a4539aa0e06aeff7.tar.gz
sitecing-642dc685bd0a3f1526e22827a4539aa0e06aeff7.tar.bz2
split .so generation into compile and link stage
Diffstat (limited to 'lib') (more/less context) (show whitespace changes)
-rw-r--r--lib/component_factory.cc108
1 files changed, 77 insertions, 31 deletions
diff --git a/lib/component_factory.cc b/lib/component_factory.cc
index bcf19f2..f8666dc 100644
--- a/lib/component_factory.cc
+++ b/lib/component_factory.cc
@@ -1,226 +1,272 @@
1#ifdef USE_PCH 1#ifdef USE_PCH
2 #include "pch.h" 2 #include "pch.h"
3#else 3#else
4 #include <sys/types.h> 4 #include <sys/types.h>
5 #include <sys/stat.h> 5 #include <sys/stat.h>
6 #include <unistd.h> 6 #include <unistd.h>
7 #include <sys/wait.h> 7 #include <sys/wait.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <iostream> 9 #include <iostream>
10 #include <fstream> 10 #include <fstream>
11 #include <stdexcept> 11 #include <stdexcept>
12 #include <vector> 12 #include <vector>
13 using namespace std; 13 using namespace std;
14 #include "sitecing/component_factory.h" 14 #include "sitecing/component_factory.h"
15 #include "sitecing/sitecing_util.h" 15 #include "sitecing/sitecing_util.h"
16 #include "sitecing/sitecing_parser.h" 16 #include "sitecing/sitecing_parser.h"
17 #include "sitecing/sitecing_exception.h" 17 #include "sitecing/sitecing_exception.h"
18#endif 18#endif
19 19
20namespace sitecing { 20namespace sitecing {
21 21
22 static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors" }; 22 static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors" };
23 static const char *cc_targets[] = { ".o", ".d" };
23 24
24 component_factory::component_factory(configuration& c) 25 component_factory::component_factory(configuration& c)
25 : config(c), 26 : config(c),
26 root_source(normalize_path(c.root_source,strip_trailing_slash)+'/'), 27 root_source(normalize_path(c.root_source,strip_trailing_slash)+'/'),
27 root_intermediate(normalize_path(c.root_intermediate,strip_trailing_slash)+'/'), 28 root_intermediate(normalize_path(c.root_intermediate,strip_trailing_slash)+'/'),
28 root_so(normalize_path(c.root_so,strip_trailing_slash)+'/') { 29 root_so(normalize_path(c.root_so,strip_trailing_slash)+'/') {
29 } 30 }
30 31
31 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) {
32 deps.clear(); 33 deps.clear();
33 string dp = normalize_path(dst,strip_trailing_slash); 34 string dp = normalize_path(dst,strip_trailing_slash);
34 // source documents 35 // source documents
35 try { // XXX: or just compare it off? 36 try { // XXX: or just compare it off?
36 string noro = strip_prefix(dp,root_source); 37 string noro = strip_prefix(dp,root_source);
37 return; 38 return;
38 }catch(utility_no_affix& una) { 39 }catch(utility_no_affix& una) {
39 } 40 }
40 // .so binaries 41 // .so binaries
41 try { 42 try {
42 string noso = strip_suffix(dp,".so"); 43 string noso = strip_suffix(dp,".so");
43 string noro = strip_prefix(noso,root_so); 44 string noro = strip_prefix(noso,root_so);
44 deps.push_back(root_intermediate+noro+".cc"); 45 deps.push_back(root_intermediate+noro+".o");
45 config_options *co_cpp_deps = config.lookup_config(noro,config_options::flag_cpp_deps);
46 if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) {
47 ifstream df((root_intermediate+noro+".d").c_str(),ios::in);
48 if(df.good()) {
49 string str;
50 while(!df.eof()) {
51 df >> str;
52 if(str.find_first_of("\\:")==string::npos)
53 deps.push_back(combine_path(config.root_source+noro,str));
54 }
55 }
56 }
57 config_options *co_so_deps = config.lookup_config(noro,config_options::flag_so_deps); 46 config_options *co_so_deps = config.lookup_config(noro,config_options::flag_so_deps);
58 if(co_so_deps) { 47 if(co_so_deps) {
59 for(list<string>::const_iterator i=co_so_deps->so_deps.begin();i!=co_so_deps->so_deps.end();++i) 48 for(list<string>::const_iterator i=co_so_deps->so_deps.begin();i!=co_so_deps->so_deps.end();++i)
60 deps.push_back(*i); 49 deps.push_back(*i);
61 } 50 }
62 return; 51 return;
63 }catch(utility_no_prefix& unp) { 52 }catch(utility_no_prefix& unp) {
64 throw konforka::exception(CODEPOINT,"component is outside of component root"); 53 throw konforka::exception(CODEPOINT,"component is outside of component root");
65 }catch(utility_no_suffix& uns) { 54 }catch(utility_no_suffix& uns) {
66 } 55 }
67 // preprocessor targets 56 // preprocessor targets
68 for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { 57 for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) {
69 try { 58 try {
70 string nos = strip_suffix(dp,pp_targets[ppt]); 59 string nos = strip_suffix(dp,pp_targets[ppt]);
71 string noro = strip_prefix(nos,root_intermediate); 60 string noro = strip_prefix(nos,root_intermediate);
72 deps.push_back(root_source+noro); 61 deps.push_back(root_source+noro);
73 ifstream imports((root_intermediate+noro+".imports").c_str(),ios::in); 62 ifstream imports((root_intermediate+noro+".imports").c_str(),ios::in);
74 if(imports.good()) { 63 if(imports.good()) {
75 string str; 64 string str;
76 while(!imports.eof()) { 65 while(!imports.eof()) {
77 imports >> str; 66 imports >> str;
78 if(!str.empty()) 67 if(!str.empty())
79 deps.push_back(root_intermediate+str+".classname"); 68 deps.push_back(root_intermediate+str+".classname");
80 } 69 }
81 } 70 }
82 ifstream ancestors((root_intermediate+noro+".ancestors").c_str(),ios::in); 71 ifstream ancestors((root_intermediate+noro+".ancestors").c_str(),ios::in);
83 if(ancestors.good()) { 72 if(ancestors.good()) {
84 string str; 73 string str;
85 while(!ancestors.eof()) { 74 while(!ancestors.eof()) {
86 ancestors >> str; 75 ancestors >> str;
87 if(!str.empty()) 76 if(!str.empty())
88 deps.push_back(root_intermediate+str+".classname"); 77 deps.push_back(root_intermediate+str+".classname");
89 } 78 }
90 } 79 }
91 config_options *co_intermediate_deps = config.lookup_config(noro,config_options::flag_intermediate_deps); 80 config_options *co_intermediate_deps = config.lookup_config(noro,config_options::flag_intermediate_deps);
92 if(co_intermediate_deps) { 81 if(co_intermediate_deps) {
93 for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i) 82 for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i)
94 deps.push_back(*i); 83 deps.push_back(*i);
95 } 84 }
96 return; 85 return;
97 }catch(utility_no_affix& una) { 86 }catch(utility_no_affix& una) {
98 // do nothing. must be a cpp dependency. 87 // do nothing. must be a cpp dependency.
99 } 88 }
100 } 89 }
90 // compiler targets
91 for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) {
92 try {
93 string nos = strip_suffix(dp,cc_targets[cct]);
94 string noro = strip_prefix(nos,root_intermediate);
95 deps.push_back(root_intermediate+noro+".cc");
96 config_options *co_cpp_deps = config.lookup_config(noro,config_options::flag_cpp_deps);
97 if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) {
98 ifstream df((root_intermediate+noro+".d").c_str(),ios::in);
99 if(df.good()) {
100 string str;
101 while(!df.eof()) {
102 df >> str;
103 if(str.find_first_of("\\:")==string::npos)
104 deps.push_back(combine_path(config.root_source+noro,str));
105 }
106 }
107 }
108 // XXX: extra deps like IntermediateDeps?
109 }catch(utility_no_affix& una) {
110 // do nothing.
111 }
112 }
101 } 113 }
102 114
103 bool component_factory::is_uptodate(const string& dst,file_list_t *deps) { 115 bool component_factory::is_uptodate(const string& dst,file_list_t *deps) {
104 string dp = normalize_path(dst,strip_trailing_slash); 116 string dp = normalize_path(dst,strip_trailing_slash);
105 // XXX: or just compare it off, instead of throwing things around. 117 // XXX: or just compare it off, instead of throwing things around.
106 try { 118 try {
107 strip_prefix(dp,root_intermediate); 119 strip_prefix(dp,root_intermediate);
108 return file_factory::is_uptodate(dst,deps); 120 return file_factory::is_uptodate(dst,deps);
109 }catch(utility_no_prefix& unp) { 121 }catch(utility_no_prefix& unp) {
110 } 122 }
111 try { 123 try {
112 strip_prefix(dp,root_so); 124 strip_prefix(dp,root_so);
113 return file_factory::is_uptodate(dst,deps); 125 return file_factory::is_uptodate(dst,deps);
114 }catch(utility_no_prefix& unp) { 126 }catch(utility_no_prefix& unp) {
115 } 127 }
116 return true; 128 return true;
117 } 129 }
118 130
119 void component_factory::build(const string& dst) { 131 void component_factory::build(const string& dst) {
120 string dp = normalize_path(dst,strip_trailing_slash); 132 string dp = normalize_path(dst,strip_trailing_slash);
121 // sources 133 // sources
122 try { 134 try {
123 string noro = strip_prefix(dp,root_source); 135 string noro = strip_prefix(dp,root_source);
124 // building the sources is left up to developer 136 // building the sources is left up to developer
125 return; 137 return;
126 }catch(utility_no_prefix& unp) { 138 }catch(utility_no_prefix& unp) {
127 } 139 }
128 // .so files 140 // .so files
129 try { 141 try {
130 string noso = strip_suffix(dp,".so"); 142 string noso = strip_suffix(dp,".so");
131 string noro = strip_prefix(noso,root_so); 143 string noro = strip_prefix(noso,root_so);
144 string o = root_intermediate+noro+".o";
145 if(access(o.c_str(),R_OK))
146 throw konforka::exception(CODEPOINT,string("can't access compiled component code (")+o+")");
147 make_path(dir_name(root_so+noro),0755);
148 file_lock lock_cc(root_intermediate+noro+".o.lock");
149 file_lock lock_so(root_so+noro+".so.lock");
150 int stdO = open((root_intermediate+noro+".ld.stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664);
151 if(stdO<0)
152 throw konforka::exception(CODEPOINT,"failed to open/create linker stdout");
153 int stdE = open((root_intermediate+noro+".ld.stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664);
154 if(stdE<0) {
155 close(stdO);
156 throw konforka::exception(CODEPOINT,"failed to open/create linker stderr");
157 }
158 list<string> args;
159 config_options *co_ld_flags = config.lookup_config(noro,config_options::flag_ld_flags);
160 if(co_ld_flags) {
161 args.insert(args.end(),co_ld_flags->ld_flags.begin(),co_ld_flags->ld_flags.end());
162 }
163 args.push_back("-shared");
164 args.push_back(o);
165 file_list_t ancestors;
166 get_ancestors(noro,ancestors);
167 for(file_list_t::const_iterator i=ancestors.begin();i!=ancestors.end();++i) {
168 string aso=root_so+*i+".so";
169 make(aso);
170 args.push_back(aso);
171 }
172 args.push_back("-o"); args.push_back(dp);
173 // TODO: "g++" configurable
174 int rv = execute("g++",args,stdO,stdE);
175 if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) )
176 // TODO:TODO: linker_error
177 throw compile_error(CODEPOINT,"failed to link component",noro);
178 return;
179 }catch(utility_no_prefix& unp) {
180 throw konforka::exception(CODEPOINT,"component is outside of component root");
181 }catch(utility_no_suffix& uns) {
182 }
183 // compiler targets
184 for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) {
185 try {
186 string nos = strip_suffix(dp,cc_targets[cct]);
187 string noro = strip_prefix(nos,root_intermediate);
132 string cc = root_intermediate+noro+".cc"; 188 string cc = root_intermediate+noro+".cc";
189 string o = root_intermediate+noro+".o";
133 if(access(cc.c_str(),R_OK)) 190 if(access(cc.c_str(),R_OK))
134 throw konforka::exception(CODEPOINT,string("can't access preprocessed component code (")+cc+")"); 191 throw konforka::exception(CODEPOINT,string("can't access preprocessed component code (")+cc+")");
135 make_path(dir_name(root_so+noro),0755); 192 make_path(dir_name(cc),0755);
136 string pwd = dir_name(root_source+noro); 193 string pwd = dir_name(root_source+noro);
137 auto_chdir dir_changer(pwd); 194 auto_chdir dir_changer(pwd);
138 file_lock lock_source(root_intermediate+noro+".lock"); 195 file_lock lock_source(root_intermediate+noro+".lock");
139 file_lock lock_so(root_so+noro+".so.lock"); 196 file_lock lock_cc(root_intermediate+noro+".o.lock");
140 int stdO = open((root_intermediate+noro+".stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); 197 int stdO = open((root_intermediate+noro+".stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664);
141 if(stdO<0) 198 if(stdO<0)
142 throw konforka::exception(CODEPOINT,"failed to open/create compiler stdout"); 199 throw konforka::exception(CODEPOINT,"failed to open/create compiler stdout");
143 int stdE = open((root_intermediate+noro+".stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); 200 int stdE = open((root_intermediate+noro+".stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664);
144 if(stdE<0) { 201 if(stdE<0) {
145 close(stdO); 202 close(stdO);
146 throw konforka::exception(CODEPOINT,"failed to open/create compiler's stderr"); 203 throw konforka::exception(CODEPOINT,"failed to open/create compiler's stderr");
147 } 204 }
148 list<string> args; 205 list<string> args;
149 config_options *co_cpp_flags = config.lookup_config(noro,config_options::flag_cpp_flags); 206 config_options *co_cpp_flags = config.lookup_config(noro,config_options::flag_cpp_flags);
150 if(co_cpp_flags) { 207 if(co_cpp_flags) {
151 args.insert(args.end(),co_cpp_flags->cpp_flags.begin(),co_cpp_flags->cpp_flags.end()); 208 args.insert(args.end(),co_cpp_flags->cpp_flags.begin(),co_cpp_flags->cpp_flags.end());
152 } 209 }
153 config_options *co_ld_flags = config.lookup_config(noro,config_options::flag_ld_flags);
154 if(co_ld_flags) {
155 args.insert(args.end(),co_ld_flags->ld_flags.begin(),co_ld_flags->ld_flags.end());
156 }
157 // TODO: maybe move it to separare config option like CoreCPPFLags? 210 // TODO: maybe move it to separare config option like CoreCPPFLags?
158 args.push_back("-I"+root_intermediate); 211 args.push_back("-I"+root_intermediate);
159 args.push_back("-I"+root_source); 212 args.push_back("-I"+root_source);
160 args.push_back("-MD"); args.push_back("-MF"); args.push_back(root_intermediate+noro+".d"); 213 args.push_back("-MD"); args.push_back("-MF"); args.push_back(root_intermediate+noro+".d");
161 args.push_back("-shared"); 214 args.push_back("-c");
162 args.push_back("-o"); args.push_back(dp);
163 args.push_back(cc); 215 args.push_back(cc);
164 file_list_t ancestors; 216 args.push_back("-o"); args.push_back(o);
165 get_ancestors(noro,ancestors);
166 for(file_list_t::const_iterator i=ancestors.begin();i!=ancestors.end();++i) {
167 string aso=root_so+*i+".so";
168 make(aso);
169 args.push_back(aso);
170 }
171 // TODO: "g++" configurable 217 // TODO: "g++" configurable
172 int rv = execute("g++",args,stdO,stdE); 218 int rv = execute("g++",args,stdO,stdE);
173 if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) 219 if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) )
174 throw compile_error(CODEPOINT,"failed to compile component",noro); 220 throw compile_error(CODEPOINT,"failed to compile component",noro);
175 return; 221 return;
176 }catch(utility_no_prefix& unp) { 222 }catch(utility_no_affix& una) {
177 throw konforka::exception(CODEPOINT,"component is outside of component root"); 223 // do nothing, not a compiler target
178 }catch(utility_no_suffix& uns) { 224 }
179 } 225 }
180 // preprocessor targets 226 // preprocessor targets
181 for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { 227 for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) {
182 try { 228 try {
183 string nos = strip_suffix(dp,pp_targets[ppt]); 229 string nos = strip_suffix(dp,pp_targets[ppt]);
184 string noro = strip_prefix(nos,root_intermediate); 230 string noro = strip_prefix(nos,root_intermediate);
185 string src = root_source+noro; 231 string src = root_source+noro;
186 if(access(src.c_str(),R_OK)) 232 if(access(src.c_str(),R_OK))
187 throw konforka::exception(CODEPOINT,string("can't access component source (")+src+")"); 233 throw konforka::exception(CODEPOINT,string("can't access component source (")+src+")");
188 make_path(dir_name(root_intermediate+noro),0755); 234 make_path(dir_name(root_intermediate+noro),0755);
189 file_lock lock(root_intermediate+noro+".lock"); 235 file_lock lock(root_intermediate+noro+".lock");
190 sitecing_parser parser(*this); 236 sitecing_parser parser(*this);
191 config_options *co_skeleton = config.lookup_config(noro,config_options::flag_skeleton); 237 config_options *co_skeleton = config.lookup_config(noro,config_options::flag_skeleton);
192 if(co_skeleton) 238 if(co_skeleton)
193 parser.skeleton = co_skeleton->skeleton; 239 parser.skeleton = co_skeleton->skeleton;
194 static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 240 static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ";
195 parser.class_name = normalize_path(noro,strip_leading_slash|strip_trailing_slash); 241 parser.class_name = normalize_path(noro,strip_leading_slash|strip_trailing_slash);
196 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)) { 242 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)) {
197 string::size_type lc = parser.class_name.find_first_of(id_chars,illc); 243 string::size_type lc = parser.class_name.find_first_of(id_chars,illc);
198 int n = ((lc==string::npos)?parser.class_name.length():lc)-illc; 244 int n = ((lc==string::npos)?parser.class_name.length():lc)-illc;
199 parser.class_name.replace(illc,n,n,'_'); 245 parser.class_name.replace(illc,n,n,'_');
200 } 246 }
201 parser.class_name = "_SCC_"+parser.class_name; 247 parser.class_name = "_SCC_"+parser.class_name;
202 parser.output_basename = nos; 248 parser.output_basename = nos;
203 parser.component_basename = noro; 249 parser.component_basename = noro;
204 try { 250 try {
205 parser.preprocess(src); 251 parser.preprocess(src);
206 }catch(preprocessor_error& pe) { 252 }catch(preprocessor_error& pe) {
207 pe.component_name = noro; 253 pe.component_name = noro;
208 pe.see(CODEPOINT); 254 pe.see(CODEPOINT);
209 throw; 255 throw;
210 } 256 }
211 return; 257 return;
212 }catch(utility_no_affix& una) { 258 }catch(utility_no_affix& una) {
213 // must be a crap from .d file 259 // must be a crap from .d file
214 } 260 }
215 } 261 }
216 cerr << "ignoring build request for " << dp << endl; 262 cerr << "ignoring build request for " << dp << endl;
217 } 263 }
218 264
219 int component_factory::execute(const string& cmd, const list<string>& args,int stdo,int stde) { 265 int component_factory::execute(const string& cmd, const list<string>& args,int stdo,int stde) {
220 // XXX: is it right that we do stdio/stderr tricks outside of the function? 266 // XXX: is it right that we do stdio/stderr tricks outside of the function?
221 cerr << "executing: " << cmd; 267 cerr << "executing: " << cmd;
222 vector<const char*> argv(args.size()+2); 268 vector<const char*> argv(args.size()+2);
223 argv[0]=cmd.c_str(); 269 argv[0]=cmd.c_str();
224 int an = 1; 270 int an = 1;
225 for(list<string>::const_iterator i=args.begin();i!=args.end();i++) { 271 for(list<string>::const_iterator i=args.begin();i!=args.end();i++) {
226 cerr << " " << *i ; 272 cerr << " " << *i ;