1
/* Copyright 2008 Simon Richter <Simon.Richter@hogyros.de>
3
* Released under the GNU General Public Licence version 3.
10
#include "gnu_toolchain.hpp"
12
#include "parallel_node.hpp"
13
#include "project_node.hpp"
14
#include "configuration_node.hpp"
15
#include "input_node.hpp"
16
#include "temporary_node.hpp"
17
#include "output_node.hpp"
18
#include "tool_node.hpp"
19
#include "environment_node.hpp"
20
#include "action_node.hpp"
22
#include "const_visitor.hpp"
24
#include "exceptions.hpp"
35
path get_filename(node const &, configuration_node const &, preferred_type);
39
intrusive_ptr<node> gnu_toolchain::visit(parallel_node &n)
41
for(parallel_node::node_iterator i = n.nodes.begin();
44
if(*i = (**i).apply(*this))
53
intrusive_ptr<node> gnu_toolchain::visit(project_node &n)
57
for(project_node::node_iterator i = n.nodes.begin();
60
if(*i = (**i).apply(tc))
69
intrusive_ptr<node> gnu_toolchain::visit(configuration_node &n)
72
tc.configuration = &n;
74
for(configuration_node::node_iterator i = n.nodes.begin();
77
if(*i = (**i).apply(tc))
86
intrusive_ptr<node> gnu_toolchain::visit(input_node &n)
91
path::string_type basename = boost::filesystem::basename(n.filename);
92
path::string_type extension = boost::filesystem::extension(n.filename);
93
if((extension == ".cc") || (extension == ".cpp"))
95
intrusive_ptr<action_node> action(new action_node);
96
action->inputs.push_back(&n);
97
intrusive_ptr<temporary_node> temporary(new temporary_node);
98
temporary->directory = configuration->temporary_dir;
99
temporary->filename = basename + ".o";
100
temporary->action = action;
101
action->cmd.executable = "g++";
102
action->cmd.workingdir = configuration->temporary_dir;
103
action->cmd.arguments.push_back("-W");
104
action->cmd.arguments.push_back("-Wall");
105
action->cmd.arguments.push_back("-g");
106
action->cmd.arguments.push_back("-o");
107
action->cmd.arguments.push_back(temporary->filename.string());
108
action->cmd.arguments.push_back("-c");
109
action->cmd.arguments.push_back((n.directory / n.filename).string());
112
else if((extension == ".h") || (extension == ".hh") || (extension == ".hpp"))
119
intrusive_ptr<node> gnu_toolchain::visit(temporary_node &n)
124
intrusive_ptr<node> gnu_toolchain::visit(output_node &n)
127
throw invalid_tree_state("output seen, but no configuration");
132
intrusive_ptr<action_node> action(new action_node);
136
case output_node::executable:
137
action->cmd.workingdir = configuration->output_dir;
138
action->cmd.executable = "g++";
139
action->cmd.arguments.push_back("-W");
140
action->cmd.arguments.push_back("-Wall");
141
action->cmd.arguments.push_back("-g");
142
action->cmd.arguments.push_back("-o");
143
action->cmd.arguments.push_back(n.filename.string());
145
case output_node::static_library:
146
action->cmd.workingdir = configuration->output_dir;
147
action->cmd.executable = "ar";
148
action->cmd.arguments.push_back("-cru");
149
action->cmd.arguments.push_back(n.filename.string());
153
for(output_node::input_iterator i = n.inputs.begin();
154
i != n.inputs.end(); ++i)
156
intrusive_ptr<node> input = (**i).apply(*this);
159
action->inputs.push_back(input);
160
action->cmd.arguments.push_back(get_filename(*input, *configuration, static_link).string());
168
intrusive_ptr<node> gnu_toolchain::visit(tool_node &n)
173
intrusive_ptr<node> gnu_toolchain::visit(environment_node &n)
178
intrusive_ptr<node> gnu_toolchain::visit(action_node &n)
180
// Stop traversing when we see an action node -- everything below here
187
class filename_getter :
191
filename_getter(configuration_node const ¤t_config,
192
preferred_type preferred) :
193
current_config(current_config),
194
preferred(preferred),
195
looking_for_output(false)
200
virtual ~filename_getter(void) throw() { }
202
virtual void visit(parallel_node const &);
203
virtual void visit(project_node const &);
204
virtual void visit(configuration_node const &);
205
virtual void visit(input_node const &);
206
virtual void visit(temporary_node const &);
207
virtual void visit(output_node const &);
208
virtual void visit(tool_node const &);
209
virtual void visit(environment_node const &);
210
virtual void visit(action_node const &);
212
configuration_node const ¤t_config;
215
preferred_type preferred;
216
bool looking_for_output;
219
void filename_getter::visit(parallel_node const &)
221
throw invalid_tree_state("no filename here (parallel)");
224
void filename_getter::visit(project_node const &n)
226
for(project_node::node_const_iterator i = n.nodes.begin();
227
i != n.nodes.end(); ++i)
230
if(!filename.empty())
235
void filename_getter::visit(configuration_node const &n)
237
if(current_config != n)
240
looking_for_output = true;
242
for(configuration_node::node_const_iterator i = n.nodes.begin();
243
i != n.nodes.end(); ++i)
246
if(!filename.empty())
251
void filename_getter::visit(input_node const &n)
253
if(!looking_for_output)
254
filename = n.directory / n.filename;
257
void filename_getter::visit(temporary_node const &n)
259
if(!looking_for_output)
260
filename = n.directory / n.filename;
263
void filename_getter::visit(output_node const &n)
265
filename = n.filename;
268
void filename_getter::visit(tool_node const &)
270
throw invalid_tree_state("no filename here (tool)");
273
void filename_getter::visit(environment_node const &)
275
throw invalid_tree_state("no filename here (environment)");
278
void filename_getter::visit(action_node const &)
280
throw invalid_tree_state("no filename here (action)");
283
path get_filename(node const &n, configuration_node const ¤t_config, preferred_type preferred)
285
filename_getter getter(current_config, preferred);
287
return getter.filename;