-rw-r--r-- | lib/component_factory.cc | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/lib/component_factory.cc b/lib/component_factory.cc index 2a2eefe..5c18bb7 100644 --- a/lib/component_factory.cc +++ b/lib/component_factory.cc | |||
@@ -1,200 +1,206 @@ | |||
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 | ||
20 | namespace sitecing { | 20 | namespace sitecing { |
21 | 21 | ||
22 | static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors", ".pp_stamp" }; | 22 | static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors", ".pp_stamp" }; |
23 | static const char *cc_targets[] = { ".o", ".d" }; | 23 | static const char *cc_targets[] = { ".o", ".d" }; |
24 | 24 | ||
25 | component_factory::component_factory(configuration& c) | 25 | component_factory::component_factory(configuration& c) |
26 | : config(c), | 26 | : config(c), |
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 | // .so binaries | 40 | // .so binaries |
41 | try { | 41 | try { |
42 | string noso = strip_suffix(dp,".so"); | 42 | string noso = strip_suffix(dp,".so"); |
43 | string noro = strip_prefix(noso,root_so); | 43 | string noro = strip_prefix(noso,root_so); |
44 | deps.push_back(root_intermediate+noro+".o"); | 44 | deps.push_back(root_intermediate+noro+".o"); |
45 | 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); |
46 | if(co_so_deps) { | 46 | if(co_so_deps) { |
47 | 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) |
48 | deps.push_back(*i); | 48 | deps.push_back(*i); |
49 | } | 49 | } |
50 | return; | 50 | return; |
51 | }catch(utility_no_prefix& unp) { | 51 | }catch(utility_no_prefix& unp) { |
52 | throw konforka::exception(CODEPOINT,"component is outside of component root"); | 52 | throw konforka::exception(CODEPOINT,"component is outside of component root"); |
53 | }catch(utility_no_suffix& uns) { } | 53 | }catch(utility_no_suffix& uns) { } |
54 | try { | 54 | try { |
55 | // preprocessor targets | 55 | // preprocessor targets |
56 | string noro = strip_prefix(dp,root_intermediate); | 56 | string noro = strip_prefix(dp,root_intermediate); |
57 | 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++) { |
58 | try { | 58 | try { |
59 | string nos = strip_suffix(noro,pp_targets[ppt]); | 59 | string nos = strip_suffix(noro,pp_targets[ppt]); |
60 | deps.push_back(root_source+nos); // depends on the source | 60 | deps.push_back(root_source+nos); // depends on the source |
61 | ifstream imports((root_intermediate+nos+".imports").c_str(),ios::in); | 61 | ifstream imports((root_intermediate+nos+".imports").c_str(),ios::in); |
62 | if(imports.good()) { | 62 | if(imports.good()) { |
63 | string str; | 63 | string str; |
64 | while(!imports.eof()) { | 64 | while(!imports.eof()) { |
65 | imports >> str; | 65 | imports >> str; |
66 | if(!str.empty()) | 66 | if(!str.empty()) |
67 | deps.push_back(root_intermediate+str+".classname"); | 67 | deps.push_back(root_intermediate+str+".classname"); |
68 | } | 68 | } |
69 | } | 69 | } |
70 | ifstream ancestors((root_intermediate+nos+".ancestors").c_str(),ios::in); | 70 | ifstream ancestors((root_intermediate+nos+".ancestors").c_str(),ios::in); |
71 | if(ancestors.good()) { | 71 | if(ancestors.good()) { |
72 | string str; | 72 | string str; |
73 | while(!ancestors.eof()) { | 73 | while(!ancestors.eof()) { |
74 | ancestors >> str; | 74 | ancestors >> str; |
75 | if(!str.empty()) | 75 | if(!str.empty()) |
76 | deps.push_back(root_intermediate+str+".classname"); | 76 | deps.push_back(root_intermediate+str+".classname"); |
77 | } | 77 | } |
78 | } | 78 | } |
79 | // XXX: intermediate_deps should be broken down | ||
79 | config_options *co_intermediate_deps = config.lookup_config(nos,config_options::flag_intermediate_deps); | 80 | config_options *co_intermediate_deps = config.lookup_config(nos,config_options::flag_intermediate_deps); |
80 | if(co_intermediate_deps) { | 81 | if(co_intermediate_deps) { |
81 | 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) |
82 | deps.push_back(*i); | 83 | deps.push_back(*i); |
83 | } | 84 | } |
84 | return; | 85 | return; |
85 | }catch(utility_no_suffix& uns) { } | 86 | }catch(utility_no_suffix& uns) { } |
86 | } | 87 | } |
87 | // compiler targets | 88 | // compiler targets |
88 | for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { | 89 | for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { |
89 | try { | 90 | try { |
90 | string nos = strip_suffix(noro,cc_targets[cct]); | 91 | string nos = strip_suffix(noro,cc_targets[cct]); |
91 | deps.push_back(root_intermediate+nos+".cc"); | 92 | deps.push_back(root_intermediate+nos+".cc"); |
92 | config_options *co_cpp_deps = config.lookup_config(noro,config_options::flag_cpp_deps); | 93 | config_options *co_cpp_deps = config.lookup_config(noro,config_options::flag_cpp_deps); |
93 | if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) { | 94 | if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) { |
94 | ifstream df((root_intermediate+noro+".d").c_str(),ios::in); | 95 | ifstream df((root_intermediate+noro+".d").c_str(),ios::in); |
95 | if(df.good()) { | 96 | if(df.good()) { |
96 | string str; | 97 | string str; |
97 | while(!df.eof()) { | 98 | while(!df.eof()) { |
98 | df >> str; | 99 | df >> str; |
99 | if(str.find_first_of("\\:")==string::npos) | 100 | if(str.find_first_of("\\:")==string::npos) |
100 | deps.push_back(combine_path(config.root_source+nos,str)); | 101 | deps.push_back(combine_path(config.root_source+nos,str)); |
101 | } | 102 | } |
102 | } | 103 | } |
103 | } | 104 | } |
104 | // XXX: extra deps like IntermediateDeps? | 105 | // XXX: intermediate_deps should be broken down |
106 | config_options *co_intermediate_deps = config.lookup_config(nos,config_options::flag_intermediate_deps); | ||
107 | if(co_intermediate_deps) { | ||
108 | for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i) | ||
109 | deps.push_back(*i); | ||
110 | } | ||
105 | }catch(utility_no_suffix& uns) { } | 111 | }catch(utility_no_suffix& uns) { } |
106 | } | 112 | } |
107 | }catch(utility_no_prefix& unp) { } | 113 | }catch(utility_no_prefix& unp) { } |
108 | } | 114 | } |
109 | 115 | ||
110 | bool component_factory::is_uptodate(const string& dst,file_list_t *deps) { | 116 | bool component_factory::is_uptodate(const string& dst,file_list_t *deps) { |
111 | string dp = normalize_path(dst,strip_trailing_slash); | 117 | string dp = normalize_path(dst,strip_trailing_slash); |
112 | // XXX: or just compare it off, instead of throwing things around. | 118 | // XXX: or just compare it off, instead of throwing things around. |
113 | try { | 119 | try { |
114 | string noro = strip_prefix(dp,root_intermediate); | 120 | string noro = strip_prefix(dp,root_intermediate); |
115 | for(int ppt=0;(ppt+1)<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { | 121 | for(int ppt=0;(ppt+1)<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { |
116 | try { | 122 | try { |
117 | string nos = strip_suffix(noro,pp_targets[ppt]); | 123 | string nos = strip_suffix(noro,pp_targets[ppt]); |
118 | return file_factory::is_uptodate(root_intermediate+nos+".pp_stamp",deps); | 124 | return file_factory::is_uptodate(root_intermediate+nos+".pp_stamp",deps); |
119 | }catch(utility_no_suffix& uns) { } | 125 | }catch(utility_no_suffix& uns) { } |
120 | } | 126 | } |
121 | bool rv = file_factory::is_uptodate(dst,deps); | 127 | bool rv = file_factory::is_uptodate(dst,deps); |
122 | return rv; | 128 | return rv; |
123 | }catch(utility_no_prefix& unp) { } | 129 | }catch(utility_no_prefix& unp) { } |
124 | try { | 130 | try { |
125 | strip_prefix(dp,root_so); | 131 | strip_prefix(dp,root_so); |
126 | return file_factory::is_uptodate(dst,deps); | 132 | return file_factory::is_uptodate(dst,deps); |
127 | }catch(utility_no_prefix& unp) { } | 133 | }catch(utility_no_prefix& unp) { } |
128 | return true; | 134 | return true; |
129 | } | 135 | } |
130 | 136 | ||
131 | void component_factory::build(const string& dst) { | 137 | void component_factory::build(const string& dst) { |
132 | string dp = normalize_path(dst,strip_trailing_slash); | 138 | string dp = normalize_path(dst,strip_trailing_slash); |
133 | // sources | 139 | // sources |
134 | try { | 140 | try { |
135 | string noro = strip_prefix(dp,root_source); | 141 | string noro = strip_prefix(dp,root_source); |
136 | // building the sources is left up to developer | 142 | // building the sources is left up to developer |
137 | return; | 143 | return; |
138 | }catch(utility_no_prefix& unp) { } | 144 | }catch(utility_no_prefix& unp) { } |
139 | // .so files | 145 | // .so files |
140 | try { | 146 | try { |
141 | string noso = strip_suffix(dp,".so"); | 147 | string noso = strip_suffix(dp,".so"); |
142 | string noro = strip_prefix(noso,root_so); | 148 | string noro = strip_prefix(noso,root_so); |
143 | string o = root_intermediate+noro+".o"; | 149 | string o = root_intermediate+noro+".o"; |
144 | if(access(o.c_str(),R_OK)) | 150 | if(access(o.c_str(),R_OK)) |
145 | throw konforka::exception(CODEPOINT,string("can't access compiled component code (")+o+")"); | 151 | throw konforka::exception(CODEPOINT,string("can't access compiled component code (")+o+")"); |
146 | make_path(dir_name(root_so+noro),0755); | 152 | make_path(dir_name(root_so+noro),0755); |
147 | file_lock lock_cc(root_intermediate+noro+".o.lock"); | 153 | file_lock lock_cc(root_intermediate+noro+".o.lock"); |
148 | file_lock lock_so(root_so+noro+".so.lock"); | 154 | file_lock lock_so(root_so+noro+".so.lock"); |
149 | int stdO = open((root_intermediate+noro+".ld.stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); | 155 | int stdO = open((root_intermediate+noro+".ld.stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); |
150 | if(stdO<0) | 156 | if(stdO<0) |
151 | throw konforka::exception(CODEPOINT,"failed to open/create linker stdout"); | 157 | throw konforka::exception(CODEPOINT,"failed to open/create linker stdout"); |
152 | int stdE = open((root_intermediate+noro+".ld.stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); | 158 | int stdE = open((root_intermediate+noro+".ld.stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); |
153 | if(stdE<0) { | 159 | if(stdE<0) { |
154 | close(stdO); | 160 | close(stdO); |
155 | throw konforka::exception(CODEPOINT,"failed to open/create linker stderr"); | 161 | throw konforka::exception(CODEPOINT,"failed to open/create linker stderr"); |
156 | } | 162 | } |
157 | list<string> args; | 163 | list<string> args; |
158 | config_options *co_ld_flags = config.lookup_config(noro,config_options::flag_ld_flags); | 164 | config_options *co_ld_flags = config.lookup_config(noro,config_options::flag_ld_flags); |
159 | if(co_ld_flags) { | 165 | if(co_ld_flags) { |
160 | args.insert(args.end(),co_ld_flags->ld_flags.begin(),co_ld_flags->ld_flags.end()); | 166 | args.insert(args.end(),co_ld_flags->ld_flags.begin(),co_ld_flags->ld_flags.end()); |
161 | } | 167 | } |
162 | args.push_back("-shared"); | 168 | args.push_back("-shared"); |
163 | args.push_back(o); | 169 | args.push_back(o); |
164 | file_list_t ancestors; | 170 | file_list_t ancestors; |
165 | get_ancestors(noro,ancestors); | 171 | get_ancestors(noro,ancestors); |
166 | for(file_list_t::const_iterator i=ancestors.begin();i!=ancestors.end();++i) { | 172 | for(file_list_t::const_iterator i=ancestors.begin();i!=ancestors.end();++i) { |
167 | string aso=root_so+*i+".so"; | 173 | string aso=root_so+*i+".so"; |
168 | make(aso); | 174 | make(aso); |
169 | args.push_back(aso); | 175 | args.push_back(aso); |
170 | } | 176 | } |
171 | args.push_back("-o"); args.push_back(dp); | 177 | args.push_back("-o"); args.push_back(dp); |
172 | // TODO: "g++" configurable | 178 | // TODO: "g++" configurable |
173 | int rv = execute("g++",args,stdO,stdE); | 179 | int rv = execute("g++",args,stdO,stdE); |
174 | if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) | 180 | if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) |
175 | throw link_error(CODEPOINT,"failed to link component",noro); | 181 | throw link_error(CODEPOINT,"failed to link component",noro); |
176 | return; | 182 | return; |
177 | }catch(utility_no_prefix& unp) { | 183 | }catch(utility_no_prefix& unp) { |
178 | throw konforka::exception(CODEPOINT,"component is outside of component root"); | 184 | throw konforka::exception(CODEPOINT,"component is outside of component root"); |
179 | }catch(utility_no_suffix& uns) { } | 185 | }catch(utility_no_suffix& uns) { } |
180 | try { | 186 | try { |
181 | string noro = strip_prefix(dp,root_intermediate); | 187 | string noro = strip_prefix(dp,root_intermediate); |
182 | // compiler targets | 188 | // compiler targets |
183 | for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { | 189 | for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { |
184 | try { | 190 | try { |
185 | string nos = strip_suffix(noro,cc_targets[cct]); | 191 | string nos = strip_suffix(noro,cc_targets[cct]); |
186 | string cc = root_intermediate+nos+".cc"; | 192 | string cc = root_intermediate+nos+".cc"; |
187 | string o = root_intermediate+nos+".o"; | 193 | string o = root_intermediate+nos+".o"; |
188 | if(access(cc.c_str(),R_OK)) | 194 | if(access(cc.c_str(),R_OK)) |
189 | throw konforka::exception(CODEPOINT,string("can't access preprocessed component code (")+cc+")"); | 195 | throw konforka::exception(CODEPOINT,string("can't access preprocessed component code (")+cc+")"); |
190 | make_path(dir_name(cc),0755); | 196 | make_path(dir_name(cc),0755); |
191 | string pwd = dir_name(root_source+nos); | 197 | string pwd = dir_name(root_source+nos); |
192 | auto_chdir dir_changer(pwd); | 198 | auto_chdir dir_changer(pwd); |
193 | file_lock lock_source(root_intermediate+nos+".lock"); | 199 | file_lock lock_source(root_intermediate+nos+".lock"); |
194 | file_lock lock_cc(root_intermediate+nos+".o.lock"); | 200 | file_lock lock_cc(root_intermediate+nos+".o.lock"); |
195 | int stdO = open((root_intermediate+nos+".stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); | 201 | int stdO = open((root_intermediate+nos+".stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); |
196 | if(stdO<0) | 202 | if(stdO<0) |
197 | throw konforka::exception(CODEPOINT,"failed to open/create compiler stdout"); | 203 | throw konforka::exception(CODEPOINT,"failed to open/create compiler stdout"); |
198 | int stdE = open((root_intermediate+nos+".stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); | 204 | int stdE = open((root_intermediate+nos+".stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); |
199 | if(stdE<0) { | 205 | if(stdE<0) { |
200 | close(stdO); | 206 | close(stdO); |