~ubuntu-branches/ubuntu/oneiric/dammit/oneiric

« back to all changes in this revision

Viewing changes to dammit/gnu_toolchain.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Simon Richter
  • Date: 2008-05-25 18:09:39 UTC
  • Revision ID: james.westby@ubuntu.com-20080525180939-iguzr0jb41w5s1oe
Tags: upstream-0~preview1
ImportĀ upstreamĀ versionĀ 0~preview1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2008 Simon Richter <Simon.Richter@hogyros.de>
 
2
 *
 
3
 * Released under the GNU General Public Licence version 3.
 
4
 */
 
5
 
 
6
#ifdef HAVE_CONFIG_H
 
7
#include <config.h>
 
8
#endif
 
9
 
 
10
#include "gnu_toolchain.hpp"
 
11
 
 
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"
 
21
 
 
22
#include "const_visitor.hpp"
 
23
 
 
24
#include "exceptions.hpp"
 
25
 
 
26
namespace dammit {
 
27
 
 
28
namespace {
 
29
 
 
30
enum preferred_type
 
31
{
 
32
        static_link
 
33
};
 
34
 
 
35
path get_filename(node const &, configuration_node const &, preferred_type);
 
36
 
 
37
}
 
38
 
 
39
intrusive_ptr<node> gnu_toolchain::visit(parallel_node &n)
 
40
{
 
41
        for(parallel_node::node_iterator i = n.nodes.begin();
 
42
                        i != n.nodes.end();)
 
43
        {
 
44
                if(*i = (**i).apply(*this))
 
45
                        ++i;
 
46
                else
 
47
                        i = n.nodes.erase(i);
 
48
        }
 
49
 
 
50
        return &n;
 
51
}
 
52
 
 
53
intrusive_ptr<node> gnu_toolchain::visit(project_node &n)
 
54
{
 
55
        gnu_toolchain tc;
 
56
 
 
57
        for(project_node::node_iterator i = n.nodes.begin();
 
58
                        i != n.nodes.end();)
 
59
        {
 
60
                if(*i = (**i).apply(tc))
 
61
                        ++i;
 
62
                else
 
63
                        i = n.nodes.erase(i);
 
64
        }
 
65
 
 
66
        return &n;
 
67
}
 
68
 
 
69
intrusive_ptr<node> gnu_toolchain::visit(configuration_node &n)
 
70
{
 
71
        gnu_toolchain tc;
 
72
        tc.configuration = &n;
 
73
 
 
74
        for(configuration_node::node_iterator i = n.nodes.begin();
 
75
                        i != n.nodes.end();)
 
76
        {
 
77
                if(*i = (**i).apply(tc))
 
78
                        ++i;
 
79
                else
 
80
                        i = n.nodes.erase(i);
 
81
        }
 
82
 
 
83
        return &n;
 
84
}
 
85
 
 
86
intrusive_ptr<node> gnu_toolchain::visit(input_node &n)
 
87
{
 
88
        if(!configuration)
 
89
                return &n;
 
90
 
 
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"))
 
94
        {
 
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());
 
110
                return temporary;
 
111
        }
 
112
        else if((extension == ".h") || (extension == ".hh") || (extension == ".hpp"))
 
113
                return 0;
 
114
        else
 
115
                return 0;
 
116
        return &n;
 
117
}
 
118
 
 
119
intrusive_ptr<node> gnu_toolchain::visit(temporary_node &n)
 
120
{
 
121
        return &n;
 
122
}
 
123
 
 
124
intrusive_ptr<node> gnu_toolchain::visit(output_node &n)
 
125
{
 
126
        if(!configuration)
 
127
                throw invalid_tree_state("output seen, but no configuration");
 
128
 
 
129
        if(n.action)
 
130
                return &n;
 
131
 
 
132
        intrusive_ptr<action_node> action(new action_node);
 
133
 
 
134
        switch(n.filetype)
 
135
        {
 
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());
 
144
                break;
 
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());
 
150
                break;
 
151
        }
 
152
 
 
153
        for(output_node::input_iterator i = n.inputs.begin();
 
154
                        i != n.inputs.end(); ++i)
 
155
        {
 
156
                intrusive_ptr<node> input = (**i).apply(*this);
 
157
                if(input)
 
158
                {
 
159
                        action->inputs.push_back(input);
 
160
                        action->cmd.arguments.push_back(get_filename(*input, *configuration, static_link).string());
 
161
                }
 
162
        }
 
163
        n.inputs.clear();
 
164
        n.action = action;
 
165
        return &n;
 
166
}
 
167
 
 
168
intrusive_ptr<node> gnu_toolchain::visit(tool_node &n)
 
169
{
 
170
        return &n;
 
171
}
 
172
 
 
173
intrusive_ptr<node> gnu_toolchain::visit(environment_node &n)
 
174
{
 
175
        return &n;
 
176
}
 
177
 
 
178
intrusive_ptr<node> gnu_toolchain::visit(action_node &n)
 
179
{
 
180
        // Stop traversing when we see an action node -- everything below here
 
181
        // is already done.
 
182
        return &n;
 
183
}
 
184
 
 
185
namespace {
 
186
 
 
187
class filename_getter :
 
188
        public const_visitor
 
189
{
 
190
public:
 
191
        filename_getter(configuration_node const &current_config,
 
192
                        preferred_type preferred) :
 
193
                current_config(current_config),
 
194
                preferred(preferred),
 
195
                looking_for_output(false)
 
196
        {
 
197
                return;
 
198
        }
 
199
 
 
200
        virtual ~filename_getter(void) throw() { }
 
201
 
 
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 &);
 
211
 
 
212
        configuration_node const &current_config;
 
213
 
 
214
        path filename;
 
215
        preferred_type preferred;
 
216
        bool looking_for_output;
 
217
};
 
218
 
 
219
void filename_getter::visit(parallel_node const &)
 
220
{
 
221
        throw invalid_tree_state("no filename here (parallel)");
 
222
}
 
223
 
 
224
void filename_getter::visit(project_node const &n)
 
225
{
 
226
        for(project_node::node_const_iterator i = n.nodes.begin();
 
227
                        i != n.nodes.end(); ++i)
 
228
        {
 
229
                (**i).apply(*this);
 
230
                if(!filename.empty())
 
231
                        break;
 
232
        }
 
233
}
 
234
 
 
235
void filename_getter::visit(configuration_node const &n)
 
236
{
 
237
        if(current_config != n)
 
238
                return;
 
239
 
 
240
        looking_for_output = true;
 
241
 
 
242
        for(configuration_node::node_const_iterator i = n.nodes.begin();
 
243
                        i != n.nodes.end(); ++i)
 
244
        {
 
245
                (**i).apply(*this);
 
246
                if(!filename.empty())
 
247
                        break;
 
248
        }
 
249
}
 
250
 
 
251
void filename_getter::visit(input_node const &n)
 
252
{
 
253
        if(!looking_for_output)
 
254
                filename = n.directory / n.filename;
 
255
}
 
256
 
 
257
void filename_getter::visit(temporary_node const &n)
 
258
{
 
259
        if(!looking_for_output)
 
260
                filename = n.directory / n.filename;
 
261
}
 
262
 
 
263
void filename_getter::visit(output_node const &n)
 
264
{
 
265
        filename = n.filename;
 
266
}
 
267
 
 
268
void filename_getter::visit(tool_node const &)
 
269
{
 
270
        throw invalid_tree_state("no filename here (tool)");
 
271
}
 
272
 
 
273
void filename_getter::visit(environment_node const &)
 
274
{
 
275
        throw invalid_tree_state("no filename here (environment)");
 
276
}
 
277
 
 
278
void filename_getter::visit(action_node const &)
 
279
{
 
280
        throw invalid_tree_state("no filename here (action)");
 
281
}
 
282
 
 
283
path get_filename(node const &n, configuration_node const &current_config, preferred_type preferred)
 
284
{
 
285
        filename_getter getter(current_config, preferred);
 
286
        n.apply(getter);
 
287
        return getter.filename;
 
288
}
 
289
 
 
290
}
 
291
 
 
292
}