summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--include/sitecing/component_factory.h4
-rw-r--r--lib/component_factory.cc25
2 files changed, 25 insertions, 4 deletions
diff --git a/include/sitecing/component_factory.h b/include/sitecing/component_factory.h
index a208ed1..9ddf70d 100644
--- a/include/sitecing/component_factory.h
+++ b/include/sitecing/component_factory.h
@@ -1,84 +1,88 @@
1#ifndef __SITECING_COMPONENT_FACTORY_H 1#ifndef __SITECING_COMPONENT_FACTORY_H
2#define __SITECING_COMPONENT_FACTORY_H 2#define __SITECING_COMPONENT_FACTORY_H
3 3
4#include <string> 4#include <string>
5#include <list> 5#include <list>
6#include <stdexcept> 6#include <stdexcept>
7#include "sitecing/file_factory.h" 7#include "sitecing/file_factory.h"
8#include "sitecing/configuration.h" 8#include "sitecing/configuration.h"
9 9
10/** 10/**
11 * @file 11 * @file
12 * @brief The component_factory class declaration. 12 * @brief The component_factory class declaration.
13 */ 13 */
14 14
15namespace sitecing { 15namespace sitecing {
16 using namespace std; 16 using namespace std;
17 17
18 /** 18 /**
19 * @brief The components builder. 19 * @brief The components builder.
20 */ 20 */
21 class component_factory : public file_factory { 21 class component_factory : public file_factory {
22 public: 22 public:
23 /** 23 /**
24 * Path to the source files root. 24 * Path to the source files root.
25 */ 25 */
26 string root_source; 26 string root_source;
27 /** 27 /**
28 * Path to the root of the intermediate files storage. 28 * Path to the root of the intermediate files storage.
29 */ 29 */
30 string root_intermediate; 30 string root_intermediate;
31 /** 31 /**
32 * Output path for .so components. 32 * Output path for .so components.
33 */ 33 */
34 string root_so; 34 string root_so;
35 /** 35 /**
36 * Reference to the configuration container. 36 * Reference to the configuration container.
37 */ 37 */
38 configuration& config; 38 configuration& config;
39 39
40 /** 40 /**
41 * @param c reference to the configuration container. 41 * @param c reference to the configuration container.
42 */ 42 */
43 component_factory(configuration& c); 43 component_factory(configuration& c);
44 44
45 /** 45 /**
46 * @overload file_factory::get_dependencies() 46 * @overload file_factory::get_dependencies()
47 */ 47 */
48 virtual void get_dependencies(const string& dst,file_list_t& deps); 48 virtual void get_dependencies(const string& dst,file_list_t& deps);
49 /** 49 /**
50 * @overload file_factory::is_uptodate() 50 * @overload file_factory::is_uptodate()
51 */ 51 */
52 virtual bool is_uptodate(const string& dst,file_list_t *deps=NULL); 52 virtual bool is_uptodate(const string& dst,file_list_t *deps=NULL);
53 /** 53 /**
54 * @overload file_factory::build() 54 * @overload file_factory::build()
55 */ 55 */
56 virtual void build(const string& dst); 56 virtual void build(const string& dst);
57 /**
58 * @overload file_factory::make()
59 */
60 virtual void make(const string& dst);
57 61
58 /** 62 /**
59 * Helper function for executing external command. 63 * Helper function for executing external command.
60 * @param cmd the command to execute. 64 * @param cmd the command to execute.
61 * @param args the command line arguments. 65 * @param args the command line arguments.
62 * @param stdo stdout for the child process. 66 * @param stdo stdout for the child process.
63 * @param stde stderr for the child process. 67 * @param stde stderr for the child process.
64 * @return exit code. 68 * @return exit code.
65 */ 69 */
66 int execute(const string& cmd,const list<string>& args,int stdo,int stde); 70 int execute(const string& cmd,const list<string>& args,int stdo,int stde);
67 /** 71 /**
68 * Fetch the class name of the component. 72 * Fetch the class name of the component.
69 * @param component the component. 73 * @param component the component.
70 * @return the class name. 74 * @return the class name.
71 */ 75 */
72 string get_classname(const string& component); 76 string get_classname(const string& component);
73 /** 77 /**
74 * Get the components from which the target component has been 78 * Get the components from which the target component has been
75 * derived. 79 * derived.
76 * @param component the target component 80 * @param component the target component
77 * @param rv where to store the list of ancestors. 81 * @param rv where to store the list of ancestors.
78 */ 82 */
79 void get_ancestors(const string& component,file_list_t &rv); 83 void get_ancestors(const string& component,file_list_t &rv);
80 }; 84 };
81 85
82} 86}
83 87
84#endif /* __SITECING_COMPONENT_FACTORY_H */ 88#endif /* __SITECING_COMPONENT_FACTORY_H */
diff --git a/lib/component_factory.cc b/lib/component_factory.cc
index 5c18bb7..b5e95af 100644
--- a/lib/component_factory.cc
+++ b/lib/component_factory.cc
@@ -1,327 +1,344 @@
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", ".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 // XXX: intermediate_deps should be broken down
80 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);
81 if(co_intermediate_deps) { 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) 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); 83 deps.push_back(*i);
84 } 84 }
85 return; 85 return;
86 }catch(utility_no_suffix& uns) { } 86 }catch(utility_no_suffix& uns) { }
87 } 87 }
88 // compiler targets 88 // compiler targets
89 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++) {
90 try { 90 try {
91 string nos = strip_suffix(noro,cc_targets[cct]); 91 string nos = strip_suffix(noro,cc_targets[cct]);
92 deps.push_back(root_intermediate+nos+".cc"); 92 deps.push_back(root_intermediate+nos+".cc");
93 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);
94 if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) { 94 if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) {
95 ifstream df((root_intermediate+noro+".d").c_str(),ios::in); 95 ifstream df((root_intermediate+noro+".d").c_str(),ios::in);
96 if(df.good()) { 96 if(df.good()) {
97 string str; 97 string str;
98 while(!df.eof()) { 98 while(!df.eof()) {
99 df >> str; 99 df >> str;
100 if(str.find_first_of("\\:")==string::npos) 100 if(str.find_first_of("\\:")==string::npos)
101 deps.push_back(combine_path(config.root_source+nos,str)); 101 deps.push_back(combine_path(config.root_source+nos,str));
102 } 102 }
103 } 103 }
104 } 104 }
105 // XXX: intermediate_deps should be broken down 105 // XXX: intermediate_deps should be broken down
106 config_options *co_intermediate_deps = config.lookup_config(nos,config_options::flag_intermediate_deps); 106 config_options *co_intermediate_deps = config.lookup_config(nos,config_options::flag_intermediate_deps);
107 if(co_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) 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); 109 deps.push_back(*i);
110 } 110 }
111 }catch(utility_no_suffix& uns) { } 111 }catch(utility_no_suffix& uns) { }
112 } 112 }
113 }catch(utility_no_prefix& unp) { } 113 }catch(utility_no_prefix& unp) { }
114 } 114 }
115 115
116 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) {
117 string dp = normalize_path(dst,strip_trailing_slash); 117 string dp = normalize_path(dst,strip_trailing_slash);
118 // XXX: or just compare it off, instead of throwing things around.
119 try { 118 try {
120 string noro = strip_prefix(dp,root_intermediate); 119 string noro = strip_prefix(dp,root_intermediate);
121 for(int ppt=0;(ppt+1)<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { 120 for(int ppt=0;(ppt+1)<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) {
122 try { 121 try {
123 string nos = strip_suffix(noro,pp_targets[ppt]); 122 string nos = strip_suffix(noro,pp_targets[ppt]);
124 return file_factory::is_uptodate(root_intermediate+nos+".pp_stamp",deps); 123 return file_factory::is_uptodate(root_intermediate+nos+".pp_stamp",deps);
125 }catch(utility_no_suffix& uns) { } 124 }catch(utility_no_suffix& uns) { }
126 } 125 }
127 bool rv = file_factory::is_uptodate(dst,deps); 126 bool rv = file_factory::is_uptodate(dst,deps);
128 return rv; 127 return rv;
129 }catch(utility_no_prefix& unp) { } 128 }catch(utility_no_prefix& unp) { }
129 // XXX: or just compare it off, instead of throwing things around.
130 try { 130 try {
131 strip_prefix(dp,root_so); 131 strip_prefix(dp,root_so);
132 return file_factory::is_uptodate(dst,deps); 132 return file_factory::is_uptodate(dst,deps);
133 }catch(utility_no_prefix& unp) { } 133 }catch(utility_no_prefix& unp) { }
134 return true; 134 return true;
135 } 135 }
136 136
137 void component_factory::build(const string& dst) { 137 void component_factory::build(const string& dst) {
138 string dp = normalize_path(dst,strip_trailing_slash); 138 string dp = normalize_path(dst,strip_trailing_slash);
139 // sources 139 // sources
140 try { 140 try {
141 string noro = strip_prefix(dp,root_source); 141 string noro = strip_prefix(dp,root_source);
142 // building the sources is left up to developer 142 // building the sources is left up to developer
143 return; 143 return;
144 }catch(utility_no_prefix& unp) { } 144 }catch(utility_no_prefix& unp) { }
145 // .so files 145 // .so files
146 try { 146 try {
147 string noso = strip_suffix(dp,".so"); 147 string noso = strip_suffix(dp,".so");
148 string noro = strip_prefix(noso,root_so); 148 string noro = strip_prefix(noso,root_so);
149 string o = root_intermediate+noro+".o"; 149 string o = root_intermediate+noro+".o";
150 cerr << "Linking " << noro << endl;
150 if(access(o.c_str(),R_OK)) 151 if(access(o.c_str(),R_OK))
151 throw konforka::exception(CODEPOINT,string("can't access compiled component code (")+o+")"); 152 throw konforka::exception(CODEPOINT,string("can't access compiled component code (")+o+")");
152 make_path(dir_name(root_so+noro),0755); 153 make_path(dir_name(root_so+noro),0755);
153 file_lock lock_cc(root_intermediate+noro+".o.lock"); 154 file_lock lock_cc(root_intermediate+noro+".o.lock");
154 file_lock lock_so(root_so+noro+".so.lock"); 155 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); 156 int stdO = open((root_intermediate+noro+".ld.stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664);
156 if(stdO<0) 157 if(stdO<0)
157 throw konforka::exception(CODEPOINT,"failed to open/create linker stdout"); 158 throw konforka::exception(CODEPOINT,"failed to open/create linker stdout");
158 int stdE = open((root_intermediate+noro+".ld.stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); 159 int stdE = open((root_intermediate+noro+".ld.stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664);
159 if(stdE<0) { 160 if(stdE<0) {
160 close(stdO); 161 close(stdO);
161 throw konforka::exception(CODEPOINT,"failed to open/create linker stderr"); 162 throw konforka::exception(CODEPOINT,"failed to open/create linker stderr");
162 } 163 }
163 list<string> args; 164 list<string> args;
164 config_options *co_ld_flags = config.lookup_config(noro,config_options::flag_ld_flags); 165 config_options *co_ld_flags = config.lookup_config(noro,config_options::flag_ld_flags);
165 if(co_ld_flags) { 166 if(co_ld_flags) {
166 args.insert(args.end(),co_ld_flags->ld_flags.begin(),co_ld_flags->ld_flags.end()); 167 args.insert(args.end(),co_ld_flags->ld_flags.begin(),co_ld_flags->ld_flags.end());
167 } 168 }
168 args.push_back("-shared"); 169 args.push_back("-shared");
169 args.push_back(o); 170 args.push_back(o);
170 file_list_t ancestors; 171 file_list_t ancestors;
171 get_ancestors(noro,ancestors); 172 get_ancestors(noro,ancestors);
172 for(file_list_t::const_iterator i=ancestors.begin();i!=ancestors.end();++i) { 173 for(file_list_t::const_iterator i=ancestors.begin();i!=ancestors.end();++i) {
173 string aso=root_so+*i+".so"; 174 string aso=root_so+*i+".so";
174 make(aso); 175 make(aso);
175 args.push_back(aso); 176 args.push_back(aso);
176 } 177 }
177 args.push_back("-o"); args.push_back(dp); 178 args.push_back("-o"); args.push_back(dp);
178 // TODO: "g++" configurable 179 // TODO: "g++" configurable
179 int rv = execute("g++",args,stdO,stdE); 180 int rv = execute("g++",args,stdO,stdE);
180 if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) 181 if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) )
181 throw link_error(CODEPOINT,"failed to link component",noro); 182 throw link_error(CODEPOINT,"failed to link component",noro);
182 return; 183 return;
183 }catch(utility_no_prefix& unp) { 184 }catch(utility_no_prefix& unp) {
184 throw konforka::exception(CODEPOINT,"component is outside of component root"); 185 throw konforka::exception(CODEPOINT,"component is outside of component root");
185 }catch(utility_no_suffix& uns) { } 186 }catch(utility_no_suffix& uns) { }
186 try { 187 try {
187 string noro = strip_prefix(dp,root_intermediate); 188 string noro = strip_prefix(dp,root_intermediate);
188 // compiler targets 189 // compiler targets
189 for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { 190 for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) {
190 try { 191 try {
191 string nos = strip_suffix(noro,cc_targets[cct]); 192 string nos = strip_suffix(noro,cc_targets[cct]);
192 string cc = root_intermediate+nos+".cc"; 193 string cc = root_intermediate+nos+".cc";
193 string o = root_intermediate+nos+".o"; 194 string o = root_intermediate+nos+".o";
195 cerr << "Compiling " << nos << endl;
194 if(access(cc.c_str(),R_OK)) 196 if(access(cc.c_str(),R_OK))
195 throw konforka::exception(CODEPOINT,string("can't access preprocessed component code (")+cc+")"); 197 throw konforka::exception(CODEPOINT,string("can't access preprocessed component code (")+cc+")");
196 make_path(dir_name(cc),0755); 198 make_path(dir_name(cc),0755);
197 string pwd = dir_name(root_source+nos); 199 string pwd = dir_name(root_source+nos);
198 auto_chdir dir_changer(pwd); 200 auto_chdir dir_changer(pwd);
199 file_lock lock_source(root_intermediate+nos+".lock"); 201 file_lock lock_source(root_intermediate+nos+".lock");
200 file_lock lock_cc(root_intermediate+nos+".o.lock"); 202 file_lock lock_cc(root_intermediate+nos+".o.lock");
201 int stdO = open((root_intermediate+nos+".stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); 203 int stdO = open((root_intermediate+nos+".stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664);
202 if(stdO<0) 204 if(stdO<0)
203 throw konforka::exception(CODEPOINT,"failed to open/create compiler stdout"); 205 throw konforka::exception(CODEPOINT,"failed to open/create compiler stdout");
204 int stdE = open((root_intermediate+nos+".stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); 206 int stdE = open((root_intermediate+nos+".stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664);
205 if(stdE<0) { 207 if(stdE<0) {
206 close(stdO); 208 close(stdO);
207 throw konforka::exception(CODEPOINT,"failed to open/create compiler's stderr"); 209 throw konforka::exception(CODEPOINT,"failed to open/create compiler's stderr");
208 } 210 }
209 list<string> args; 211 list<string> args;
210 config_options *co_cpp_flags = config.lookup_config(nos,config_options::flag_cpp_flags); 212 config_options *co_cpp_flags = config.lookup_config(nos,config_options::flag_cpp_flags);
211 if(co_cpp_flags) { 213 if(co_cpp_flags) {
212 args.insert(args.end(),co_cpp_flags->cpp_flags.begin(),co_cpp_flags->cpp_flags.end()); 214 args.insert(args.end(),co_cpp_flags->cpp_flags.begin(),co_cpp_flags->cpp_flags.end());
213 } 215 }
214 // TODO: maybe move it to separare config option like CoreCPPFLags? 216 // TODO: maybe move it to separare config option like CoreCPPFLags?
215 args.push_back("-I"+root_intermediate); 217 args.push_back("-I"+root_intermediate);
216 args.push_back("-I"+root_source); 218 args.push_back("-I"+root_source);
217 args.push_back("-MD"); args.push_back("-MF"); args.push_back(root_intermediate+nos+".d"); 219 args.push_back("-MD"); args.push_back("-MF"); args.push_back(root_intermediate+nos+".d");
218 args.push_back("-c"); 220 args.push_back("-c");
219 args.push_back(cc); 221 args.push_back(cc);
220 args.push_back("-o"); args.push_back(o); 222 args.push_back("-o"); args.push_back(o);
221 // TODO: "g++" configurable 223 // TODO: "g++" configurable
222 int rv = execute("g++",args,stdO,stdE); 224 int rv = execute("g++",args,stdO,stdE);
223 if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) 225 if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) )
224 throw compile_error(CODEPOINT,"failed to compile component",nos); 226 throw compile_error(CODEPOINT,"failed to compile component",nos);
225 return; 227 return;
226 }catch(utility_no_suffix& uns) { } 228 }catch(utility_no_suffix& uns) { }
227 } 229 }
228 // preprocessor targets 230 // preprocessor targets
229 for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { 231 for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) {
230 try { 232 try {
231 string nos = strip_suffix(noro,pp_targets[ppt]); 233 string nos = strip_suffix(noro,pp_targets[ppt]);
232 string src = root_source+nos; 234 string src = root_source+nos;
235 cerr << "Preprocessing " << nos << endl;
233 if(access(src.c_str(),R_OK)) 236 if(access(src.c_str(),R_OK))
234 throw konforka::exception(CODEPOINT,string("can't access component source (")+src+")"); 237 throw konforka::exception(CODEPOINT,string("can't access component source (")+src+")");
235 make_path(dir_name(root_intermediate+nos),0755); 238 make_path(dir_name(root_intermediate+nos),0755);
236 file_lock lock(root_intermediate+nos+".lock"); 239 file_lock lock(root_intermediate+nos+".lock");
237 sitecing_parser parser(*this); 240 sitecing_parser parser(*this);
238 config_options *co_skeleton = config.lookup_config(nos,config_options::flag_skeleton); 241 config_options *co_skeleton = config.lookup_config(nos,config_options::flag_skeleton);
239 if(co_skeleton) 242 if(co_skeleton)
240 parser.skeleton = co_skeleton->skeleton; 243 parser.skeleton = co_skeleton->skeleton;
241 static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 244 static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ";
242 parser.class_name = normalize_path(nos,strip_leading_slash|strip_trailing_slash); 245 parser.class_name = normalize_path(nos,strip_leading_slash|strip_trailing_slash);
243 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)) { 246 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)) {
244 string::size_type lc = parser.class_name.find_first_of(id_chars,illc); 247 string::size_type lc = parser.class_name.find_first_of(id_chars,illc);
245 int n = ((lc==string::npos)?parser.class_name.length():lc)-illc; 248 int n = ((lc==string::npos)?parser.class_name.length():lc)-illc;
246 parser.class_name.replace(illc,n,n,'_'); 249 parser.class_name.replace(illc,n,n,'_');
247 } 250 }
248 parser.class_name = "_SCC_"+parser.class_name; 251 parser.class_name = "_SCC_"+parser.class_name;
249 parser.output_basename = root_intermediate+nos; 252 parser.output_basename = root_intermediate+nos;
250 parser.component_basename = nos; 253 parser.component_basename = nos;
251 try { 254 try {
252 parser.preprocess(src); 255 parser.preprocess(src);
253 string sf = root_intermediate+nos+".pp_stamp"; 256 string sf = root_intermediate+nos+".pp_stamp";
254 ofstream sfs(sf.c_str(),ios::trunc|ios::out); // touch .pp_stamp 257 ofstream sfs(sf.c_str(),ios::trunc|ios::out); // touch .pp_stamp
255 }catch(preprocessor_error& pe) { 258 }catch(preprocessor_error& pe) {
256 pe.component_name = nos; 259 pe.component_name = nos;
257 pe.see(CODEPOINT); 260 pe.see(CODEPOINT);
258 throw; 261 throw;
259 } 262 }
260 return; 263 return;
261 }catch(utility_no_suffix& uns) { } 264 }catch(utility_no_suffix& uns) { }
262 } 265 }
263 }catch(utility_no_prefix& unp) { } 266 }catch(utility_no_prefix& unp) { }
264 cerr << "ignoring build request for " << dp << endl; 267 cerr << "ignoring build request for " << dp << endl;
265 } 268 }
266 269
270 void component_factory::make(const string& dst) {
271 string dp = normalize_path(dst,strip_trailing_slash);
272 try {
273 string noso = strip_suffix(dp,".so");
274 string noro = strip_prefix(noso,root_so);
275 file_list_t a;
276 get_ancestors(noro,a);
277 for(file_list_t::const_iterator i=a.begin();i!=a.end();++i) {
278 make(root_so+*i+".so");
279 }
280 }catch(utility_no_affix& una) { }
281 file_factory::make(dst);
282 }
283
267 int component_factory::execute(const string& cmd, const list<string>& args,int stdo,int stde) { 284 int component_factory::execute(const string& cmd, const list<string>& args,int stdo,int stde) {
268 // XXX: is it right that we do stdio/stderr tricks outside of the function? 285 // XXX: is it right that we do stdio/stderr tricks outside of the function?
269 cerr << "executing: " << cmd; 286 // cerr << "executing: " << cmd;
270 vector<const char*> argv(args.size()+2); 287 vector<const char*> argv(args.size()+2);
271 argv[0]=cmd.c_str(); 288 argv[0]=cmd.c_str();
272 int an = 1; 289 int an = 1;
273 for(list<string>::const_iterator i=args.begin();i!=args.end();i++) { 290 for(list<string>::const_iterator i=args.begin();i!=args.end();i++) {
274 cerr << " " << *i ; 291 // cerr << " " << *i ;
275 argv[an++] = i->c_str(); 292 argv[an++] = i->c_str();
276 } 293 }
277 cerr << endl; 294 // cerr << endl;
278 argv[an++]=NULL; 295 argv[an++]=NULL;
279 pid_t pid = vfork(); 296 pid_t pid = vfork();
280 if(pid==-1) { 297 if(pid==-1) {
281 close(stdo); close(stde); 298 close(stdo); close(stde);
282 throw konforka::exception(CODEPOINT,"failed to vfork()"); 299 throw konforka::exception(CODEPOINT,"failed to vfork()");
283 } 300 }
284 if(!pid) { 301 if(!pid) {
285 // child 302 // child
286 if(dup2(stdo,1)!=1) 303 if(dup2(stdo,1)!=1)
287 _exit(-1); 304 _exit(-1);
288 if(dup2(stde,2)!=2) 305 if(dup2(stde,2)!=2)
289 _exit(-1); 306 _exit(-1);
290 close(0); 307 close(0);
291 execvp(cmd.c_str(),(char**)&argv.front()); 308 execvp(cmd.c_str(),(char**)&argv.front());
292 _exit(-1); 309 _exit(-1);
293 } 310 }
294 // parent 311 // parent
295 close(stdo); close(stde); 312 close(stdo); close(stde);
296 int rv; 313 int rv;
297 if(waitpid(pid,&rv,0)<0) 314 if(waitpid(pid,&rv,0)<0)
298 throw konforka::exception(CODEPOINT,"failed to waitpid()"); 315 throw konforka::exception(CODEPOINT,"failed to waitpid()");
299 return rv; 316 return rv;
300 } 317 }
301 318
302 string component_factory::get_classname(const string& component) { 319 string component_factory::get_classname(const string& component) {
303 string cn = root_intermediate+normalize_path(component,strip_trailing_slash|strip_leading_slash)+".classname"; 320 string cn = root_intermediate+normalize_path(component,strip_trailing_slash|strip_leading_slash)+".classname";
304 make(cn); 321 make(cn);
305 ifstream ifs(cn.c_str()); 322 ifstream ifs(cn.c_str());
306 if(!ifs.good()) 323 if(!ifs.good())
307 throw konforka::exception(CODEPOINT,"failed to access component .classname"); 324 throw konforka::exception(CODEPOINT,"failed to access component .classname");
308 ifs >> cn; 325 ifs >> cn;
309 return cn; 326 return cn;
310 } 327 }
311 328
312 void component_factory::get_ancestors(const string& component,file_list_t& rv) { 329 void component_factory::get_ancestors(const string& component,file_list_t& rv) {
313 string cn = root_intermediate+normalize_path(component,strip_trailing_slash|strip_leading_slash)+".ancestors"; 330 string cn = root_intermediate+normalize_path(component,strip_trailing_slash|strip_leading_slash)+".ancestors";
314 make(cn); 331 make(cn);
315 ifstream ifs(cn.c_str()); 332 ifstream ifs(cn.c_str());
316 if(!ifs.good()) 333 if(!ifs.good())
317 throw konforka::exception(CODEPOINT,string("failed to access component '")+component+"' .ancestors"); 334 throw konforka::exception(CODEPOINT,string("failed to access component '")+component+"' .ancestors");
318 rv.clear(); 335 rv.clear();
319 while(!ifs.eof()) { 336 while(!ifs.eof()) {
320 string a; 337 string a;
321 ifs >> a; 338 ifs >> a;
322 if(!a.empty()) 339 if(!a.empty())
323 rv.push_back(a); 340 rv.push_back(a);
324 } 341 }
325 } 342 }
326 343
327} 344}