1#include "ninqu.h"
2
3#include <limits.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <unistd.h>
8
9static void
10usage(void)
11{
12 eprintf(
13 "usage: %s [-jN] [-f manifest] [-C dir] [-Dvar=val]... [-S] [-F] [-G ninja] "
14 "[target|meta.target ...]\n"
15 " %s query (features|groups|metas|rules|graph) [arg]\n",
16 argv0,
17 argv0
18 );
19}
20
21int
22main(int argc, char *argv[])
23{
24 const char *manifest = "ninqu.rules";
25 int features_mode = 0;
26 int query_mode = 0;
27 const char *query_sub = NULL;
28 const char *query_arg = NULL;
29 const char *generator = NULL;
30 int i;
31 struct StrList wanted = {0};
32
33 /* detect query before ARGBEGIN so it is not parsed as a target */
34 if (argc >= 2 && strcmp(argv[1], "query") == 0) {
35 query_mode = 1;
36 if (argc < 3)
37 usage();
38 query_sub = argv[2];
39 query_arg = (argc >= 4) ? argv[3] : NULL;
40 for (i = 3; i < argc; i++) {
41 if (argv[i][0] == '-' && argv[i][1] == 'f')
42 manifest = argv[i][2] ? argv[i] + 2 : argv[++i];
43 else if (argv[i][0] == '-' && argv[i][1] == 'C') {
44 if (chdir(argv[i][2] ? argv[i] + 2 : argv[++i]) != 0)
45 eprintf("chdir:");
46 } else if (argv[i][0] == '-' && argv[i][1] == 'D') {
47 char *spec = argv[i][2] ? argv[i] + 2 : argv[++i];
48 char *eq = strchr(spec, '=');
49 if (!eq)
50 usage();
51 *eq = '\0';
52 kv_set_cli(spec, eq + 1);
53 }
54 }
55 } else {
56 ARGBEGIN
57 {
58 case 'j':
59 jobs_n = (int)estrtonum(EARGF(usage()), 1, INT_MAX);
60 break;
61 case 'f':
62 manifest = EARGF(usage());
63 break;
64 case 'C':
65 if (chdir(EARGF(usage())) != 0)
66 eprintf("chdir:");
67 break;
68 case 'D': {
69 char *spec = EARGF(usage());
70 char *eq = strchr(spec, '=');
71 if (!eq)
72 usage();
73 *eq = '\0';
74 kv_set_cli(spec, eq + 1);
75 break;
76 }
77 case 'S':
78 summary_mode = 1;
79 break;
80 case 'F':
81 features_mode = 1;
82 break;
83 case 'G':
84 generator = EARGF(usage());
85 break;
86 default:
87 usage();
88 }
89 ARGEND
90
91 for (i = 0; i < argc; i++)
92 sl_push(&wanted, argv[i]);
93 }
94
95 load_file(manifest);
96 resolve_all_bareword_deps();
97
98 if (query_mode) {
99 do_query(query_sub, query_arg);
100 return 0;
101 }
102 if (features_mode) {
103 do_features();
104 return 0;
105 }
106
107 if (wanted.n == 0)
108 build_default_group();
109 else
110 for (i = 0; i < wanted.n; i++)
111 resolve_wanted(wanted.v[i]);
112
113 resolve_deps();
114
115 if (generator) {
116 const struct Backend *be = backend_by_name(generator);
117 if (!be)
118 eprintf("ninqu: unknown generator '%s'\n", generator);
119 be->emit(be->file, &wanted);
120 return failed_any ? 1 : 0;
121 }
122
123 /* BACKEND=internal forces executor. otherwise generate file and exec backend binary */
124 if (strcmp(kv_get_or("BACKEND", "auto"), "internal") != 0) {
125 char *bin;
126 const struct Backend *be = backend_resolve(&bin);
127 if (be) {
128 be->emit(be->file, &wanted);
129 if (failed_any)
130 return 1;
131 backend_exec(be, bin, &wanted);
132 }
133 }
134
135 schedule_and_run();
136
137 return failed_any ? 1 : 0;
138}