-rw-r--r-- | include/sitecing/component_factory.h | 4 | ||||
-rw-r--r-- | lib/component_factory.cc | 25 |
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 | ||
15 | namespace sitecing { | 15 | namespace 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 | ||
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 | // 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 | } |