1 /*******************************************************************/
2 /* slibtool: a skinny libtool implementation, written in C */
3 /* Copyright (C) 2016--2018 Z. Gilboa */
4 /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
5 /*******************************************************************/
6
7 #include <string.h>
8 #include <stdbool.h>
9 #include <fcntl.h>
10 #include <errno.h>
11 #include <sys/stat.h>
12
13 #include <slibtool/slibtool.h>
14 #include "slibtool_spawn_impl.h"
15 #include "slibtool_mkdir_impl.h"
16 #include "slibtool_errinfo_impl.h"
17 #include "slibtool_metafile_impl.h"
18
slbt_exec_compile_remove_file(const struct slbt_driver_ctx * dctx,struct slbt_exec_ctx * ectx,const char * target)19 static int slbt_exec_compile_remove_file(
20 const struct slbt_driver_ctx * dctx,
21 struct slbt_exec_ctx * ectx,
22 const char * target)
23 {
24 int fdcwd;
25
26 (void)ectx;
27
28 /* fdcwd */
29 fdcwd = slbt_driver_fdcwd(dctx);
30
31 /* remove target (if any) */
32 if (!unlinkat(fdcwd,target,0) || (errno == ENOENT))
33 return 0;
34
35 return SLBT_SYSTEM_ERROR(dctx,0);
36 }
37
slbt_exec_compile_finalize_argument_vector(const struct slbt_driver_ctx * dctx,struct slbt_exec_ctx * ectx)38 static int slbt_exec_compile_finalize_argument_vector(
39 const struct slbt_driver_ctx * dctx,
40 struct slbt_exec_ctx * ectx)
41 {
42 char * sargv[1024];
43 char ** sargvbuf;
44 char ** base;
45 char ** parg;
46 char ** aarg;
47 char ** aargv;
48 char ** cap;
49 char ** src;
50 char ** dst;
51 char * ccwrap;
52
53 /* vector size */
54 base = ectx->argv;
55 parg = ectx->argv;
56
57 for (; *parg; )
58 parg++;
59
60 /* buffer */
61 if (parg - base < 1024) {
62 aargv = sargv;
63 aarg = aargv;
64 sargvbuf = 0;
65
66 } else if (!(sargvbuf = calloc(parg-base+1,sizeof(char *)))) {
67 return SLBT_SYSTEM_ERROR(dctx,0);
68
69 } else {
70 aargv = sargvbuf;
71 aarg = aargv;
72 }
73
74 /* (program name) */
75 parg = &base[1];
76
77 /* split object args from all other args, record output */
78 /* annotation, and remove redundant -l arguments */
79 for (; *parg; ) {
80 if (ectx->lout[0] == parg) {
81 ectx->lout[0] = &aarg[0];
82 ectx->lout[1] = &aarg[1];
83 }
84
85 if (ectx->mout[0] == parg) {
86 ectx->mout[0] = &aarg[0];
87 ectx->mout[1] = &aarg[1];
88 }
89
90 /* placeholder argument? */
91 if (!strncmp(*parg,"-USLIBTOOL_PLACEHOLDER_",23)) {
92 parg++;
93 } else {
94 *aarg++ = *parg++;
95 }
96 }
97
98 /* program name, ccwrap */
99 if ((ccwrap = (char *)dctx->cctx->ccwrap)) {
100 base[1] = base[0];
101 base[0] = ccwrap;
102 base++;
103 }
104
105 /* join all other args */
106 src = aargv;
107 cap = aarg;
108 dst = &base[1];
109
110 for (; src<cap; )
111 *dst++ = *src++;
112
113 /* properly null-terminate argv, accounting for redundant arguments */
114 *dst = 0;
115
116 /* output annotation */
117 if (ectx->lout[0]) {
118 ectx->lout[0] = &base[1] + (ectx->lout[0] - aargv);
119 ectx->lout[1] = ectx->lout[0] + 1;
120 }
121
122 if (ectx->mout[0]) {
123 ectx->mout[0] = &base[1] + (ectx->mout[0] - aargv);
124 ectx->mout[1] = ectx->mout[0] + 1;
125 }
126
127 /* all done */
128 if (sargvbuf)
129 free(sargvbuf);
130
131 return 0;
132 }
133
slbt_exec_compile(const struct slbt_driver_ctx * dctx,struct slbt_exec_ctx * ectx)134 int slbt_exec_compile(
135 const struct slbt_driver_ctx * dctx,
136 struct slbt_exec_ctx * ectx)
137 {
138 int ret;
139 char * fpic;
140 char * ccwrap;
141 struct slbt_exec_ctx * actx = 0;
142 const struct slbt_common_ctx * cctx = dctx->cctx;
143
144 /* dry run */
145 if (cctx->drvflags & SLBT_DRIVER_DRY_RUN)
146 return 0;
147
148 /* context */
149 if (ectx)
150 slbt_reset_placeholders(ectx);
151 else if ((ret = slbt_get_exec_ctx(dctx,&ectx)))
152 return ret;
153 else
154 actx = ectx;
155
156 /* remove old .lo wrapper */
157 if (slbt_exec_compile_remove_file(dctx,ectx,ectx->ltobjname))
158 return SLBT_NESTED_ERROR(dctx);
159
160 /* .libs directory */
161 if (cctx->drvflags & SLBT_DRIVER_SHARED)
162 if (slbt_mkdir(dctx,ectx->ldirname)) {
163 ret = SLBT_SYSTEM_ERROR(dctx,ectx->ldirname);
164 slbt_free_exec_ctx(actx);
165 return ret;
166 }
167
168 /* compile mode */
169 ccwrap = (char *)cctx->ccwrap;
170 ectx->program = ccwrap ? ccwrap : ectx->compiler;
171 ectx->argv = ectx->cargv;
172
173 /* -fpic */
174 switch (cctx->tag) {
175 case SLBT_TAG_CC:
176 case SLBT_TAG_CXX:
177 case SLBT_TAG_F77:
178 fpic = cctx->settings.picswitch
179 ? cctx->settings.picswitch
180 : *ectx->fpic;
181 break;
182
183 default:
184 fpic = *ectx->fpic;
185 }
186
187 /* shared library object */
188 if (cctx->drvflags & SLBT_DRIVER_SHARED) {
189 if (!(cctx->drvflags & SLBT_DRIVER_ANTI_PIC)) {
190 *ectx->dpic = "-DPIC";
191 *ectx->fpic = fpic;
192 }
193
194 *ectx->lout[0] = "-o";
195 *ectx->lout[1] = ectx->lobjname;
196
197 if (slbt_exec_compile_finalize_argument_vector(dctx,ectx))
198 return SLBT_NESTED_ERROR(dctx);
199
200 if (!(cctx->drvflags & SLBT_DRIVER_SILENT)) {
201 if (slbt_output_compile(dctx,ectx)) {
202 slbt_free_exec_ctx(actx);
203 return SLBT_NESTED_ERROR(dctx);
204 }
205 }
206
207 if (((ret = slbt_spawn(ectx,true)) < 0) || ectx->exitcode) {
208 slbt_free_exec_ctx(actx);
209 return SLBT_SYSTEM_ERROR(dctx,0);
210 }
211
212 if (cctx->drvflags & SLBT_DRIVER_STATIC)
213 slbt_reset_argvector(ectx);
214 }
215
216 /* static archive object */
217 if (cctx->drvflags & SLBT_DRIVER_STATIC) {
218 slbt_reset_placeholders(ectx);
219
220 if (cctx->drvflags & SLBT_DRIVER_PRO_PIC) {
221 *ectx->dpic = "-DPIC";
222 *ectx->fpic = fpic;
223 }
224
225 *ectx->lout[0] = "-o";
226 *ectx->lout[1] = ectx->aobjname;
227
228 if (slbt_exec_compile_finalize_argument_vector(dctx,ectx))
229 return SLBT_NESTED_ERROR(dctx);
230
231 if (!(cctx->drvflags & SLBT_DRIVER_SILENT)) {
232 if (slbt_output_compile(dctx,ectx)) {
233 slbt_free_exec_ctx(actx);
234 return SLBT_NESTED_ERROR(dctx);
235 }
236 }
237
238 if (((ret = slbt_spawn(ectx,true)) < 0) || ectx->exitcode) {
239 slbt_free_exec_ctx(actx);
240 return SLBT_SYSTEM_ERROR(dctx,0);
241 }
242 }
243
244 ret = slbt_create_object_wrapper(dctx,ectx);
245 slbt_free_exec_ctx(actx);
246
247 return ret ? SLBT_NESTED_ERROR(dctx) : 0;
248 }
249