1 /*
2 Copyright (C) 2009 Justin Karneges
3
4 This file is free software; unlimited permission is given to copy and/or
5 distribute it, with or without modifications, as long as this notice is
6 preserved.
7 */
8
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <errno.h>
15 //#include <unistd.h>
16 #include <limits.h>
17 #include "embed.h"
18
19 #if defined(WIN32) || defined(_WIN32)
20 # define QC_OS_WIN
21 #endif
22
23 #ifdef QC_OS_WIN
24 #include <direct.h>
25 #endif
26
27 #ifdef QC_OS_WIN
28 static char *qconftemp_path = "qconftemp";
29 static char path_separator = ';';
30 #else
31 static char *qconftemp_path = ".qconftemp";
32 static char path_separator = ':';
33 #endif
34
35 static int qc_verbose = 0;
36 static char *ex_qtdir = NULL;
37 static char *qc_qtselect = NULL;
38 static char *qtsearchtext="4 or 5";
39
40 static char *prefix = NULL;
41 static char *bindir = NULL;
42 static char *includedir = NULL;
43 static char *libdir = NULL;
44 static char *datadir = NULL;
45
46 static int run_buffer_stdout(const char *command, char *out_buf, size_t buf_size);
47
48 enum ArgType
49 {
50 ArgValue,
51 ArgFlag
52 };
53
54 typedef struct qcarg
55 {
56 char *name;
57 char *envvar;
58 int type;
59 char *val; // we populate this later based on actual passed args
60 } qcarg_t;
61
62 typedef struct qcfile
63 {
64 char *name;
65 unsigned char *data;
66 unsigned int size;
67 } qcfile_t;
68
69 typedef struct qcdata
70 {
71 char *usage;
72
73 qcarg_t *args;
74 int args_count;
75
76 qcfile_t *files;
77 int files_count;
78
79 char *pro_name;
80 char *pro_file;
81
82 char *qtinfo;
83 } qcdata_t;
84
alloc_str(const unsigned char * src,int len)85 static char *alloc_str(const unsigned char *src, int len)
86 {
87 char *out;
88 out = (char *)malloc(len + 1);
89 memcpy(out, src, len);
90 out[len] = 0;
91 return out;
92 }
93
index_of(const char * in,char sub)94 static int index_of(const char *in, char sub)
95 {
96 int n;
97 for(n = 0; in[n]; ++n)
98 {
99 if(in[n] == sub)
100 return n;
101 }
102 return -1;
103 }
104
index_of_str(const char * in,const char * sub)105 static int index_of_str(const char *in, const char *sub)
106 {
107 char *p;
108 p = strstr(in, sub);
109 if(p)
110 return p - in;
111 else
112 return -1;
113 }
114
selection_insert(const char * in,int at,int len,const char * sub)115 static char *selection_insert(const char *in, int at, int len, const char *sub)
116 {
117 int ilen;
118 int slen;
119 int newsize;
120 char *out;
121
122 ilen = strlen(in);
123 slen = strlen(sub);
124 newsize = ilen - len + slen;
125 out = (char *)malloc(newsize + 1);
126 memcpy(out, in, at);
127 memcpy(out + at, sub, slen);
128 memcpy(out + at + slen, in + at + len, ilen - at - len);
129 out[newsize] = 0;
130
131 return out;
132 }
133
find_replace(const char * in,const char * old,const char * newv)134 static char *find_replace(const char *in, const char *old, const char *newv)
135 {
136 int at;
137 int olen;
138
139 olen = strlen(old);
140 at = index_of_str(in, old);
141 if(at != -1)
142 return selection_insert(in, at, olen, newv);
143 else
144 return strdup(in);
145 }
146
append_str(const char * in,const char * add)147 static char *append_str(const char *in, const char *add)
148 {
149 return selection_insert(in, strlen(in), 0, add);
150 }
151
152 // creates new string and frees old
append_free(char * in,const char * add)153 static char *append_free(char *in, const char *add)
154 {
155 char *out;
156 out = append_str(in, add);
157 free(in);
158 return out;
159 }
160
161 // FIXME: handle bad data, don't malloc 0, etc
parse_data(unsigned char * data,unsigned int size)162 static qcdata_t *parse_data(unsigned char *data, unsigned int size)
163 {
164 unsigned char *p;
165 qcdata_t *q;
166 unsigned int len;
167 int n;
168
169 (void)size;
170
171 q = (qcdata_t *)malloc(sizeof(qcdata_t));
172 p = data;
173 len = read32(p);
174 p += 4;
175 q->usage = alloc_str(p, len);
176 p += len;
177
178 q->args_count = read32(p);
179 p += 4;
180 q->args = (qcarg_t *)malloc(sizeof(qcarg_t) * q->args_count);
181 for(n = 0; n < q->args_count; ++n)
182 {
183 len = read32(p);
184 p += 4;
185 q->args[n].name = alloc_str(p, len);
186 p += len;
187
188 len = read32(p);
189 p += 4;
190 q->args[n].envvar = alloc_str(p, len);
191 p += len;
192
193 q->args[n].type = *(p++);
194
195 q->args[n].val = NULL;
196 }
197
198 q->files_count = read32(p);
199 p += 4;
200 q->files = (qcfile_t *)malloc(sizeof(qcfile_t) * q->files_count);
201 for(n = 0; n < q->files_count; ++n)
202 {
203 len = read32(p);
204 p += 4;
205 q->files[n].name = alloc_str(p, len);
206 p += len;
207
208 len = read32(p);
209 p += 4;
210 q->files[n].data = (unsigned char *)malloc(len);
211 memcpy(q->files[n].data, p, len);
212 q->files[n].size = len;
213 p += len;
214 }
215
216 len = read32(p);
217 p += 4;
218 q->pro_name = alloc_str(p, len);
219 p += len;
220
221 len = read32(p);
222 p += 4;
223 q->pro_file = alloc_str(p, len);
224 p += len;
225
226 len = read32(p);
227 p += 4;
228 q->qtinfo = alloc_str(p, len);
229 p += len;
230
231 return q;
232 }
233
qcdata_delete(qcdata_t * q)234 static void qcdata_delete(qcdata_t *q)
235 {
236 int n;
237
238 if(q->usage)
239 free(q->usage);
240
241 for(n = 0; n < q->args_count; ++n)
242 {
243 free(q->args[n].name);
244 free(q->args[n].envvar);
245 if(q->args[n].val)
246 free(q->args[n].val);
247 }
248
249 for(n = 0; n < q->files_count; ++n)
250 {
251 free(q->files[n].name);
252 free(q->files[n].data);
253 }
254
255 if(q->pro_name)
256 free(q->pro_name);
257 if(q->pro_file)
258 free(q->pro_file);
259
260 free(q);
261 }
262
find_arg(const qcarg_t * args,int count,const char * name)263 static int find_arg(const qcarg_t *args, int count, const char *name)
264 {
265 int n;
266 for(n = 0; n < count; ++n)
267 {
268 if(strcmp(args[n].name, name) == 0)
269 return n;
270 }
271 return -1;
272 }
273
find_file(const qcfile_t * files,int count,const char * name)274 static int find_file(const qcfile_t *files, int count, const char *name)
275 {
276 int n;
277 for(n = 0; n < count; ++n)
278 {
279 if(strcmp(files[n].name, name) == 0)
280 return n;
281 }
282 return -1;
283 }
284
285 // adapted from qt
set_envvar(const char * var,const char * val)286 static int set_envvar(const char *var, const char *val)
287 {
288 #if defined(_MSC_VER) && _MSC_VER >= 1400
289 return (_putenv_s(var, val) == 0 ? 1 : 0);
290 #else
291 char *str;
292 str = malloc(strlen(var) + 1 + strlen(val) + 1);
293 strcpy(str, var);
294 strcat(str, "=");
295 strcat(str, val);
296 return (putenv(str) == 0 ? 1 : 0);
297 #endif
298 }
299
get_envvar(const char * var)300 static char *get_envvar(const char *var)
301 {
302 return getenv(var);
303 }
304
separators_to_native(const char * in)305 static char *separators_to_native(const char *in)
306 {
307 char *out;
308
309 #ifdef QC_OS_WIN
310 int len;
311 int n;
312
313 out = strdup(in);
314 len = strlen(in);
315 for(n = 0; n < len; ++n)
316 {
317 if(out[n] == '/')
318 out[n] = '\\';
319 }
320 #else
321 out = strdup(in);
322 #endif
323
324 return out;
325 }
326
file_exists(const char * path)327 static int file_exists(const char *path)
328 {
329 char *npath;
330 int ret;
331 #ifdef QC_OS_WIN
332 struct _stat buf;
333 #else
334 struct stat buf;
335 #endif
336
337 npath = separators_to_native(path);
338
339 #ifdef QC_OS_WIN
340 ret = _stat(npath, &buf);
341 #else
342 ret = stat(npath, &buf);
343 #endif
344
345 free(npath);
346 if(ret == 0)
347 return 1;
348 else
349 return 0;
350 }
351
check_qmake_path(const char * qtdir)352 static char *check_qmake_path(const char *qtdir)
353 {
354 char *str;
355
356 str = separators_to_native(qtdir);
357 #ifdef QC_OS_WIN
358 str = append_free(str, "\\qmake.exe");
359 #else
360 str = append_free(str, "/qmake");
361 #endif
362 if (qc_verbose) {
363 printf("Check if \"%s\" exists\n", str);
364 }
365 if(file_exists(str))
366 {
367 return str;
368 }
369 else
370 {
371 free(str);
372 return NULL;
373 }
374 }
375
qmake_query(const char * qmake_path,const char * var,char * out_buf,size_t buf_size)376 static int qmake_query(const char *qmake_path, const char *var, char *out_buf, size_t buf_size)
377 {
378 char command[PATH_MAX];
379 int cnt = snprintf(command, sizeof(command) - 1, "%s -query %s", qmake_path, var);
380 if (cnt > 0 && cnt < (int)sizeof(command))
381 {
382 command[sizeof(command) - 1] = '\0'; // To be sure line has null-terminator
383 return run_buffer_stdout(command, out_buf, buf_size);
384 }
385 return 0; // fail
386 }
387
qmake_query_maj_ver(const char * qmake_path,char * out_buf,size_t buf_size)388 static int qmake_query_maj_ver(const char *qmake_path, char *out_buf, size_t buf_size)
389 {
390 if (qmake_query(qmake_path, "QT_VERSION", out_buf, buf_size)) {
391 int at = index_of(out_buf, '.');
392 if (at > 0)
393 {
394 out_buf[at] = '\0';
395 return 1;
396 }
397 }
398 return 0;
399 }
400
401 // modifies contents of spec_path and returns pointer to spec name
extract_spec_name(char * spec_path)402 char *extract_spec_name(char *spec_path)
403 {
404 char *end = spec_path;
405 while (!iscntrl(*end)) {
406 if (*end == '/') {
407 if (iscntrl(*(end+1))) { // next is end of line
408 break;
409 } else {
410 spec_path = end + 1;
411 end = spec_path + 1;
412 }
413 } else
414 end++;
415 }
416 *end = 0;
417 return spec_path;
418 }
419
check_qtversion(char * path,char * version)420 int check_qtversion(char *path, char *version)
421 {
422 int res = 0;
423
424 if (version)
425 {
426 char buf[20]; // version string output always small
427 if (qmake_query_maj_ver(path, buf, sizeof(buf))) {
428 res = !strcmp(version, buf);
429 if (!res && qc_verbose)
430 {
431 printf("Warning: %s not for Qt %s\n", path, qtsearchtext);
432 }
433 }
434 }
435 else
436 {
437 res = 1;
438 }
439
440 return res;
441 }
442
parse_qtselect(char * src)443 static char* parse_qtselect(char *src)
444 {
445 unsigned long int ver;
446 if (src) {
447 if (src[0] == 'q' && src[1] == 't')
448 src += 2;
449
450 ver = strtoul(src, NULL, 10);
451 if (ver > 0 && ver < ULONG_MAX) {
452 qc_qtselect = strdup(src);
453 qtsearchtext = qc_qtselect;
454 return qc_qtselect;
455 }
456 }
457 return NULL;
458 }
459
find_qmake()460 static char *find_qmake()
461 {
462 char *qtdir;
463 char *path;
464 char try_syspath = 1;
465
466 if (!qc_qtselect)
467 parse_qtselect(get_envvar("QT_SELECT"));
468
469
470 qtdir = ex_qtdir;
471 if(qtdir)
472 {
473 qtdir = append_free(strdup(qtdir), "\\bin");
474 path = check_qmake_path(qtdir);
475 free(qtdir);
476
477 if(path)
478 {
479 if (!check_qtversion(path, qc_qtselect))
480 return NULL;
481 return path;
482 }
483 try_syspath = 0;
484 }
485 if(qc_verbose)
486 printf("Warning: qmake not found via --qtdir\n");
487
488 qtdir = get_envvar("QTDIR");
489 if(qtdir)
490 {
491 qtdir = append_free(strdup(qtdir), "\\bin");
492 path = check_qmake_path(qtdir);
493 free(qtdir);
494
495 if(path)
496 {
497 if (!check_qtversion(path, qc_qtselect))
498 return NULL;
499 return path;
500 }
501 try_syspath = 0;
502 }
503 if(qc_verbose)
504 printf("Warning: qmake not found via %%QTDIR%%\n");
505
506 /* if not set explicitly try something implicit */
507 if (try_syspath) {
508 char *paths = strdup(get_envvar("PATH"));
509 qtdir = paths;
510 while (1)
511 {
512 int at = index_of(qtdir, path_separator);
513 if (at > 0)
514 qtdir[at] = '\0';
515 path = check_qmake_path(qtdir);
516 if (path && check_qtversion(path, qc_qtselect))
517 {
518 free(paths);
519 return path;
520 }
521
522 if (at > 0)
523 qtdir += at + 1;
524 else
525 break;
526 }
527 free(paths);
528 }
529
530 if(qc_verbose)
531 printf("Warning: qmake not found in PATH\n");
532
533 return NULL;
534 }
535
run_buffer_stdout(const char * command,char * out_buf,size_t buf_size)536 static int run_buffer_stdout(const char *command, char *out_buf, size_t buf_size)
537 {
538 FILE *file;
539
540 file = popen(command, "r");
541 if (file)
542 {
543 size_t bytes_left = buf_size - 1; // 1 for null terminator
544 size_t bytes_read;
545 while (bytes_left && (bytes_read = fread(out_buf, 1, bytes_left, file)) > 0)
546 bytes_left -= bytes_read;
547
548 out_buf[buf_size - bytes_left - 1] = '\0';
549 pclose(file);
550
551 return 1; // ok
552 }
553
554 out_buf[0] = 0; // just in case
555 return 0; // fail
556 }
557
run_silent_stdout(const char * cmd)558 static int run_silent_stdout(const char *cmd)
559 {
560 char *str;
561 int ret;
562
563 str = strdup(cmd);
564 #ifdef QC_OS_WIN
565 str = append_free(str, " >NUL");
566 #else
567 str = append_free(str, " >/dev/null");
568 #endif
569 ret = system(str);
570 free(str);
571
572 return ret;
573 }
574
run_silent_all(const char * cmd)575 static int run_silent_all(const char *cmd)
576 {
577 char *str;
578 int ret;
579
580 str = strdup(cmd);
581 #ifdef QC_OS_WIN
582 str = append_free(str, " >NUL 2>&1");
583 #else
584 str = append_free(str, " >/dev/null 2>&1");
585 #endif
586 ret = system(str);
587 free(str);
588
589 return ret;
590 }
591
run_conflog_all(const char * cmd)592 static int run_conflog_all(const char *cmd)
593 {
594 char *str;
595 int ret;
596
597 str = strdup(cmd);
598 #ifdef QC_OS_WIN
599 str = append_free(str, " >..\\conf.log 2>&1");
600 #else
601 str = append_free(str, " >../conf.log 2>&1");
602 #endif
603 if (qc_verbose)
604 printf("Starting \"%s\"\n", str);
605 ret = system(str);
606 free(str);
607
608 return ret;
609 }
610
qc_ensuredir(const char * path)611 static int qc_ensuredir(const char *path)
612 {
613 #ifdef QC_OS_WIN
614 if(_mkdir(path) == 0)
615 return 1;
616 else if(errno == EEXIST)
617 return 1;
618 else
619 return 0;
620 #else
621 if(mkdir(path, S_IRWXU | S_IRWXG) == 0)
622 return 1;
623 else if(errno == EEXIST)
624 return 1;
625 else
626 return 0;
627 #endif
628 }
629
qc_chdir(const char * path)630 static int qc_chdir(const char *path)
631 {
632 int ret;
633
634 #ifdef QC_OS_WIN
635 ret = _chdir(path);
636 #else
637 ret = chdir(path);
638 #endif
639
640 if(ret == 0)
641 return 1;
642 else
643 return 0;
644 }
645
qc_removedir(const char * path)646 static int qc_removedir(const char *path)
647 {
648 char *str;
649 int ret;
650
651 #ifdef QC_OS_WIN
652 str = strdup("deltree /y ");
653 str = append_free(str, path);
654 ret = run_silent_all(str);
655 free(str);
656 if(ret != 0)
657 {
658 str = strdup("rmdir /s /q ");
659 str = append_free(str, path);
660 ret = run_silent_all(str);
661 free(str);
662 }
663 #else
664 str = strdup("rm -rf ");
665 str = append_free(str, path);
666 ret = system(str);
667 free(str);
668 #endif
669
670 if(ret == 0)
671 return 1;
672 else
673 return 0;
674 }
675
gen_file(qcdata_t * q,const char * name,const char * dest)676 static int gen_file(qcdata_t *q, const char *name, const char *dest)
677 {
678 int at;
679 char *str, *npath;
680 FILE *fp;
681
682 at = find_file(q->files, q->files_count, name);
683 if(at == -1)
684 return 0;
685
686 str = strdup(dest);
687 str = append_free(str, "/");
688 str = append_free(str, name);
689 npath = separators_to_native(str);
690 free(str);
691 fp = fopen(npath, "wb");
692 free(npath);
693 if(!fp)
694 return 0;
695 /*if(*/fwrite(q->files[at].data, q->files[at].size, 1, fp);/* < 1)
696 {
697 fclose(fp);
698 return 0;
699 }*/
700 fclose(fp);
701 return 1;
702 }
703
gen_files(qcdata_t * q,const char * dest)704 static int gen_files(qcdata_t *q, const char *dest)
705 {
706 if(!gen_file(q, "modules.cpp", dest))
707 return 0;
708 if(!gen_file(q, "modules_new.cpp", dest))
709 return 0;
710 if(!gen_file(q, "conf4.h", dest))
711 return 0;
712 if(!gen_file(q, "conf4.cpp", dest))
713 return 0;
714 if(!gen_file(q, "conf4.pro", dest))
715 return 0;
716 return 1;
717 }
718
try_make(const char * makecmd,char ** maketool)719 static int try_make(const char *makecmd, char **maketool)
720 {
721 char *str;
722 int ret;
723
724 str = strdup(makecmd);
725 str = append_free(str, " clean");
726 ret = run_conflog_all(str);
727 free(str);
728 if(ret != 0)
729 return 0;
730
731 if(run_conflog_all(makecmd) != 0) {
732 if (qc_verbose)
733 printf("\"%s\" failed\n", makecmd);
734 return 0;
735 }
736
737 *maketool = strdup(makecmd);
738 return 1;
739 }
740
741 static char *maketool_list_common[] =
742 {
743 "mingw32-make",
744 "make",
745 "jom",
746 "nmake",
747 NULL
748 };
749
750 static char *maketool_list_mingw[] =
751 {
752 "make",
753 "mingw32-make",
754 NULL
755 };
756
757 static char *maketool_list_vs[] =
758 {
759 "jom",
760 "nmake",
761 NULL
762 };
763
do_conf_create(qcdata_t * q,const char * qmake_path,const char * spec,char ** maketool)764 static int do_conf_create(qcdata_t *q, const char *qmake_path, const char *spec, char **maketool)
765 {
766 char *str;
767 int n;
768 int at;
769 char **maketool_list;
770
771 if(!qc_ensuredir(qconftemp_path))
772 return 0;
773
774 if(!gen_files(q, qconftemp_path))
775 return 0;
776
777 if(!qc_chdir(qconftemp_path))
778 return 0;
779
780 // TODO: support -spec once QC_MAKESPEC matters
781 str = strdup(qmake_path);
782 str = append_free(str, " conf4.pro");
783 if(run_silent_stdout(str) != 0)
784 {
785 free(str);
786 qc_chdir("..");
787 return 0;
788 }
789 free(str);
790
791 at = -1;
792 if (strstr(spec, "win32-msvc")) {
793 maketool_list = maketool_list_vs;
794 } else if(strstr(spec, "win32-g++")) {
795 maketool_list = maketool_list_mingw;
796 } else {
797 maketool_list = maketool_list_common;
798 }
799 for(n = 0; maketool_list[n]; ++n)
800 {
801 if(qc_verbose)
802 printf("Trying \"%s\"\n", maketool_list[n]);
803 if(try_make(maketool_list[n], maketool))
804 {
805 at = n;
806 break;
807 }
808 }
809
810 qc_chdir("..");
811 if(at == -1)
812 return 0;
813
814 return 1;
815 }
816
do_conf_run()817 static int do_conf_run()
818 {
819 char *str, *npath;
820 int ret;
821
822 str = strdup(qconftemp_path);
823 str = append_free(str, "/conf");
824 npath = separators_to_native(str);
825 free(str);
826 ret = system(npath);
827 free(npath);
828
829 return ret;
830 }
831
cleanup_qconftemp()832 static void cleanup_qconftemp()
833 {
834 qc_removedir(qconftemp_path);
835 }
836
try_print_var(const char * var,const char * val)837 static void try_print_var(const char *var, const char *val)
838 {
839 printf("%s=", var);
840 if(val)
841 printf("%s", val);
842 printf("\n");
843 }
844
do_conf(qcdata_t * q,const char * argv0)845 static int do_conf(qcdata_t *q, const char *argv0)
846 {
847 char *qmake_path;
848 char *maketool;
849 int qt_maj_version = 0;
850 char *specs_name = NULL;
851 int n;
852 int ret;
853
854 printf("Configuring %s ...\n", q->pro_name);
855
856 if(qc_verbose)
857 {
858 printf("\n");
859 for(n = 0; n < q->args_count; ++n)
860 try_print_var(q->args[n].envvar, q->args[n].val);
861 }
862
863 printf("Verifying Qt build environment ... ");
864 fflush(stdout);
865
866 if(qc_verbose)
867 printf("\n");
868
869 qmake_path = find_qmake();
870 if(!qmake_path)
871 {
872 if(qc_verbose)
873 printf(" -> fail\n");
874 else
875 printf("fail\n");
876 printf("\n");
877 printf("Reason: Unable to find the 'qmake' tool for Qt %s.\n", qtsearchtext);
878 printf("\n");
879 printf("%s", q->qtinfo);
880 return 0;
881 }
882 if(qc_verbose)
883 printf("qmake found in %s\n", qmake_path);
884
885 // figure out what version it is.
886 {
887 char buf[20]; // version string output always small
888 if (qmake_query_maj_ver(qmake_path, buf, sizeof(buf))) {
889 qt_maj_version = strtoul(buf, NULL, 10);
890 if (qt_maj_version == ULONG_MAX)
891 qt_maj_version = 0;
892 }
893 if (qt_maj_version == 0) {
894 if(qc_verbose) {
895 printf(" -> fail\n");
896 printf("Qt major version is not parsable\n");
897 } else
898 printf("fail\n");
899 free(qmake_path);
900 return 0;
901 }
902 }
903
904 // find specc name
905 {
906 char *spec = get_envvar("QMAKESPEC");
907 if (!spec) {
908 // try to find default spec
909 if (qt_maj_version > 4) {
910 char buf[32];
911 if (qmake_query(qmake_path, "QMAKE_XSPEC", buf, sizeof(buf))) // or QMAKE_SPEC ?
912 specs_name = strdup(buf);
913 // it's possible to compute full path like QT_HOST_DATA/QMAKE_XSPEC
914 } else {
915 char *qmake_conf, buf[1024];
916 FILE *fp;
917 qmake_query(qmake_path, "QMAKE_MKSPECS", buf, sizeof(buf));
918 qmake_conf = append_free(strdup(buf), "/default/qmake.conf");
919 fp = fopen(qmake_conf, "r");
920 free(qmake_conf);
921 if (fp) {
922 size_t br;
923 if ((br = fread(buf, 1, sizeof(buf) - 1, fp)) > 0) {
924 char *str, *end;
925 buf[br] = 0;
926 str = strstr(buf, "QMAKESPEC_ORIGINAL=");
927 if (str) {
928 str = extract_spec_name(str);
929 if (str) {
930 specs_name = strdup(str);
931 }
932 }
933 }
934 fclose(fp);
935 }
936 }
937 } else {
938 char *s = strdup(spec);
939 specs_name = extract_spec_name(s);
940 if (specs_name) {
941 specs_name = strdup(specs_name);
942 }
943 free(s);
944 }
945 }
946
947 // TODO: in verbose mode, print out default makespec and what we're
948 // overriding the makespec to (if any). since at this time we don't
949 // ever override the makespec on windows, we don't need this yet.
950
951 cleanup_qconftemp();
952 maketool = NULL;
953 if(!do_conf_create(q, qmake_path, specs_name, &maketool))
954 {
955 cleanup_qconftemp();
956 if(qc_verbose)
957 printf(" -> fail\n");
958 else
959 printf("fail\n");
960 printf("\n");
961 printf("Reason: There was an error compiling 'conf'. See conf.log for details.\n");
962 printf("\n");
963 printf("%s", q->qtinfo);
964
965 if(qc_verbose)
966 {
967 printf("conf.log:\n");
968 system("type conf.log");
969 }
970
971 free(qmake_path);
972 return 0;
973 }
974
975 set_envvar("QC_COMMAND", argv0);
976 set_envvar("QC_PROFILE", q->pro_file);
977 set_envvar("QC_QMAKE", qmake_path);
978 // TODO: unix configure will set QC_MAKESPEC here if it needs to
979 // override the mkspec. currently, it only does this for macx-xcode
980 // so the behavior doesn't apply to windows yet.
981 set_envvar("QC_MAKETOOL", maketool);
982
983 free(qmake_path);
984
985 ret = do_conf_run();
986 if(ret == 1)
987 {
988 cleanup_qconftemp();
989 printf("\n");
990 free(maketool);
991 return 0;
992 }
993 else if(ret != 0)
994 {
995 cleanup_qconftemp();
996 if(qc_verbose)
997 printf(" -> fail\n");
998 else
999 printf("fail\n");
1000 printf("\n");
1001 printf("Reason: Unexpected error launching 'conf'\n");
1002 printf("\n");
1003 free(maketool);
1004 return 0;
1005 }
1006
1007 cleanup_qconftemp();
1008 printf("\n");
1009 printf("Good, your configure finished. Now run %s.\n", maketool);
1010 printf("\n");
1011 free(maketool);
1012
1013 return 1;
1014 }
1015
main(int argc,char ** argv)1016 int main(int argc, char **argv)
1017 {
1018 unsigned char *data;
1019 unsigned int size;
1020 qcdata_t *q;
1021 int n;
1022 int at;
1023 int quit;
1024 char *arg, *var, *val;
1025
1026 if(!embed_get_data(argv[0], &data, &size))
1027 {
1028 fprintf(stderr, "Error: Can't import data.\n");
1029 return 1;
1030 }
1031
1032 q = parse_data(data, size);
1033 if(!q)
1034 {
1035 fprintf(stderr, "Error: Can't parse internal data.\n");
1036 free(data);
1037 return 1;
1038 }
1039
1040 if(q->usage)
1041 {
1042 val = find_replace(q->usage, "$0", argv[0]);
1043 free(q->usage);
1044 q->usage = val;
1045 }
1046
1047 quit = 0;
1048 for(n = 1; n < argc && !quit; ++n)
1049 {
1050 arg = argv[n];
1051
1052 if(arg[0] != '-' || arg[1] != '-')
1053 {
1054 printf("%s", q->usage);
1055 quit = 1;
1056 break;
1057 }
1058
1059 at = index_of(arg + 2, '=');
1060 if(at != -1)
1061 {
1062 var = alloc_str((unsigned char *)arg + 2, at);
1063 val = strdup(arg + 2 + at + 1);
1064 }
1065 else
1066 {
1067 var = strdup(arg + 2);
1068 val = 0;
1069 }
1070
1071 if(strcmp(var, "help") == 0)
1072 {
1073 printf("%s", q->usage);
1074 quit = 1;
1075 }
1076 else if(strcmp(var, "verbose") == 0)
1077 {
1078 qc_verbose = 1;
1079 set_envvar("QC_VERBOSE", "Y");
1080 }
1081 else if(strcmp(var, "prefix") == 0)
1082 {
1083 prefix = strdup(val);
1084 }
1085 else if(strcmp(var, "bindir") == 0)
1086 {
1087 bindir = strdup(val);
1088 }
1089 else if(strcmp(var, "includedir") == 0)
1090 {
1091 includedir = strdup(val);
1092 }
1093 else if(strcmp(var, "datadir") == 0)
1094 {
1095 datadir = strdup(val);
1096 }
1097 else if(strcmp(var, "libdir") == 0)
1098 {
1099 libdir = strdup(val);
1100 }
1101 else if(strcmp(var, "qtselect") == 0)
1102 {
1103 if (val && strlen(val))
1104 qc_qtselect = parse_qtselect(val);
1105 }
1106 else
1107 {
1108 at = find_arg(q->args, q->args_count, var);
1109 if(at != -1)
1110 {
1111 // keep a stash of ex_qtdir
1112 if(strcmp(var, "qtdir") == 0)
1113 {
1114 if(ex_qtdir)
1115 free(ex_qtdir);
1116 ex_qtdir = strdup(val);
1117 }
1118
1119 if(q->args[at].val)
1120 free(q->args[at].val);
1121
1122 if(q->args[at].type == ArgValue)
1123 q->args[at].val = strdup(val);
1124 else // ArgFlag
1125 q->args[at].val = strdup("Y");
1126
1127 set_envvar(q->args[at].envvar, q->args[at].val);
1128 }
1129 else
1130 {
1131 printf("%s", q->usage);
1132 quit = 1;
1133 }
1134 }
1135
1136 free(var);
1137 if(val)
1138 free(val);
1139 }
1140
1141 if(quit)
1142 {
1143 qcdata_delete(q);
1144 if(ex_qtdir)
1145 free(ex_qtdir);
1146
1147 if(qc_qtselect)
1148 free(qc_qtselect);
1149
1150 if(prefix)
1151 free(prefix);
1152
1153 if(bindir)
1154 free(bindir);
1155
1156 if(includedir)
1157 free(includedir);
1158
1159 if(libdir)
1160 free(libdir);
1161
1162 if(datadir)
1163 free(datadir);
1164
1165 return 1;
1166 }
1167
1168 if(prefix)
1169 {
1170 set_envvar("PREFIX", prefix);
1171 if(!libdir)
1172 libdir = append_str(prefix, "/lib");
1173
1174 if(!bindir)
1175 bindir = append_str(prefix, "/bin");
1176
1177 if(!includedir)
1178 includedir = append_str(prefix, "/include");
1179
1180 if(!datadir)
1181 datadir = append_str(prefix, "/share");
1182 }
1183
1184 if(libdir)
1185 set_envvar("LIBDIR", libdir);
1186
1187 if(bindir)
1188 set_envvar("BINDIR", bindir);
1189
1190 if(includedir)
1191 set_envvar("INCLUDEDIR", includedir);
1192
1193 if(datadir)
1194 set_envvar("DATADIR", datadir);
1195
1196 if(libdir)
1197 set_envvar("LIBDIR", libdir);
1198
1199 n = do_conf(q, argv[0]);
1200 qcdata_delete(q);
1201 if(ex_qtdir)
1202 free(ex_qtdir);
1203
1204 if(qc_qtselect)
1205 free(qc_qtselect);
1206
1207 if(prefix)
1208 free(prefix);
1209
1210 if(bindir)
1211 free(bindir);
1212
1213 if(includedir)
1214 free(includedir);
1215
1216 if(libdir)
1217 free(libdir);
1218
1219 if(datadir)
1220 free(datadir);
1221
1222 if(n)
1223 return 0;
1224 else
1225 return 1;
1226 }
1227