build.c revision 275988
1/* Copyright (c) 2009 The NetBSD Foundation, Inc.
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
14 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */
25
26#include "atf-c/build.h"
27
28#include <stdlib.h>
29#include <string.h>
30
31#include "atf-c/detail/env.h"
32#include "atf-c/detail/sanity.h"
33#include "atf-c/detail/text.h"
34#include "atf-c/error.h"
35
36/* ---------------------------------------------------------------------
37 * Auxiliary functions.
38 * --------------------------------------------------------------------- */
39
40static
41atf_error_t
42append_config_var(const char *var, const char *default_value, atf_list_t *argv)
43{
44    atf_error_t err;
45    atf_list_t words;
46
47    err = atf_text_split(atf_env_get_with_default(var, default_value),
48                         " ", &words);
49    if (atf_is_error(err))
50        goto out;
51
52    atf_list_append_list(argv, &words);
53
54out:
55    return err;
56}
57
58static
59atf_error_t
60append_arg1(const char *arg, atf_list_t *argv)
61{
62    return atf_list_append(argv, strdup(arg), true);
63}
64
65static
66atf_error_t
67append_arg2(const char *flag, const char *arg, atf_list_t *argv)
68{
69    atf_error_t err;
70
71    err = append_arg1(flag, argv);
72    if (!atf_is_error(err))
73        err = append_arg1(arg, argv);
74
75    return err;
76}
77
78static
79atf_error_t
80append_optargs(const char *const optargs[], atf_list_t *argv)
81{
82    atf_error_t err;
83
84    err = atf_no_error();
85    while (*optargs != NULL && !atf_is_error(err)) {
86        err = append_arg1(strdup(*optargs), argv);
87        optargs++;
88    }
89
90    return err;
91}
92
93static
94atf_error_t
95append_src_out(const char *src, const char *obj, atf_list_t *argv)
96{
97    atf_error_t err;
98
99    err = append_arg2("-o", obj, argv);
100    if (atf_is_error(err))
101        goto out;
102
103    err = append_arg1("-c", argv);
104    if (atf_is_error(err))
105        goto out;
106
107    err = append_arg1(src, argv);
108
109out:
110    return err;
111}
112
113static
114atf_error_t
115list_to_array(const atf_list_t *l, char ***ap)
116{
117    atf_error_t err;
118    char **a;
119
120    a = (char **)malloc((atf_list_size(l) + 1) * sizeof(char *));
121    if (a == NULL)
122        err = atf_no_memory_error();
123    else {
124        char **aiter;
125        atf_list_citer_t liter;
126
127        aiter = a;
128        atf_list_for_each_c(liter, l) {
129            *aiter = strdup((const char *)atf_list_citer_data(liter));
130            aiter++;
131        }
132        *aiter = NULL;
133
134        err = atf_no_error();
135    }
136    *ap = a; /* Shut up warnings in the caller about uninitialized *ap. */
137
138    return err;
139}
140
141/* ---------------------------------------------------------------------
142 * Free functions.
143 * --------------------------------------------------------------------- */
144
145atf_error_t
146atf_build_c_o(const char *sfile,
147              const char *ofile,
148              const char *const optargs[],
149              char ***argv)
150{
151    atf_error_t err;
152    atf_list_t argv_list;
153
154    err = atf_list_init(&argv_list);
155    if (atf_is_error(err))
156        goto out;
157
158    err = append_config_var("ATF_BUILD_CC", ATF_BUILD_CC, &argv_list);
159    if (atf_is_error(err))
160        goto out_list;
161
162    err = append_config_var("ATF_BUILD_CPPFLAGS", ATF_BUILD_CPPFLAGS,
163                            &argv_list);
164    if (atf_is_error(err))
165        goto out_list;
166
167    err = append_config_var("ATF_BUILD_CFLAGS", ATF_BUILD_CFLAGS, &argv_list);
168    if (atf_is_error(err))
169        goto out_list;
170
171    if (optargs != NULL) {
172        err = append_optargs(optargs, &argv_list);
173        if (atf_is_error(err))
174            goto out_list;
175    }
176
177    err = append_src_out(sfile, ofile, &argv_list);
178    if (atf_is_error(err))
179        goto out_list;
180
181    err = list_to_array(&argv_list, argv);
182    if (atf_is_error(err))
183        goto out_list;
184
185out_list:
186    atf_list_fini(&argv_list);
187out:
188    return err;
189}
190
191atf_error_t
192atf_build_cpp(const char *sfile,
193              const char *ofile,
194              const char *const optargs[],
195              char ***argv)
196{
197    atf_error_t err;
198    atf_list_t argv_list;
199
200    err = atf_list_init(&argv_list);
201    if (atf_is_error(err))
202        goto out;
203
204    err = append_config_var("ATF_BUILD_CPP", ATF_BUILD_CPP, &argv_list);
205    if (atf_is_error(err))
206        goto out_list;
207
208    err = append_config_var("ATF_BUILD_CPPFLAGS", ATF_BUILD_CPPFLAGS,
209                            &argv_list);
210    if (atf_is_error(err))
211        goto out_list;
212
213    if (optargs != NULL) {
214        err = append_optargs(optargs, &argv_list);
215        if (atf_is_error(err))
216            goto out_list;
217    }
218
219    err = append_arg2("-o", ofile, &argv_list);
220    if (atf_is_error(err))
221        goto out_list;
222
223    err = append_arg1(sfile, &argv_list);
224    if (atf_is_error(err))
225        goto out_list;
226
227    err = list_to_array(&argv_list, argv);
228    if (atf_is_error(err))
229        goto out_list;
230
231out_list:
232    atf_list_fini(&argv_list);
233out:
234    return err;
235}
236
237atf_error_t
238atf_build_cxx_o(const char *sfile,
239                const char *ofile,
240                const char *const optargs[],
241                char ***argv)
242{
243    atf_error_t err;
244    atf_list_t argv_list;
245
246    err = atf_list_init(&argv_list);
247    if (atf_is_error(err))
248        goto out;
249
250    err = append_config_var("ATF_BUILD_CXX", ATF_BUILD_CXX, &argv_list);
251    if (atf_is_error(err))
252        goto out_list;
253
254    err = append_config_var("ATF_BUILD_CPPFLAGS", ATF_BUILD_CPPFLAGS,
255                            &argv_list);
256    if (atf_is_error(err))
257        goto out_list;
258
259    err = append_config_var("ATF_BUILD_CXXFLAGS", ATF_BUILD_CXXFLAGS,
260                            &argv_list);
261    if (atf_is_error(err))
262        goto out_list;
263
264    if (optargs != NULL) {
265        err = append_optargs(optargs, &argv_list);
266        if (atf_is_error(err))
267            goto out_list;
268    }
269
270    err = append_src_out(sfile, ofile, &argv_list);
271    if (atf_is_error(err))
272        goto out_list;
273
274    err = list_to_array(&argv_list, argv);
275    if (atf_is_error(err))
276        goto out_list;
277
278out_list:
279    atf_list_fini(&argv_list);
280out:
281    return err;
282}
283