Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gwenhywfar / tools / gwenbuild / main.c @ 4b609de5

History | View | Annotate | Download (11.5 KB)

1
/***************************************************************************
2
    begin       : Mon Feb 08 2021
3
    copyright   : (C) 2021 by Martin Preuss
4
    email       : martin@libchipcard.de
5

6
 ***************************************************************************
7
 *          Please see toplevel file COPYING for license details           *
8
 ***************************************************************************/
9

    
10
#ifdef HAVE_CONFIG_H
11
# include <config.h>
12
#endif
13

    
14

    
15
#include "gwenbuild/parser/parser.h"
16
#include "utils.h"
17
#include "c_setup.h"
18
#include "c_prepare.h"
19
#include "c_build.h"
20
#include "c_install.h"
21
#include "c_clean.h"
22
#include "c_dist.h"
23

    
24
#include <gwenhywfar/gwenhywfar.h>
25
#include <gwenhywfar/cgui.h>
26
#include <gwenhywfar/debug.h>
27
#include <gwenhywfar/args.h>
28
#include <gwenhywfar/i18n.h>
29
#include <gwenhywfar/text.h>
30
#include <gwenhywfar/directory.h>
31

    
32
#include <unistd.h>
33

    
34
#ifdef HAVE_SIGNAL_H
35
# include <signal.h>
36
#endif
37

    
38

    
39

    
40
#define I18N(msg) GWEN_I18N_Translate(PACKAGE, msg)
41
#define I18S(msg) msg
42

    
43

    
44
#define ARGS_COMMAND_SETUP          0x0001
45
#define ARGS_COMMAND_PREPARE        0x0002
46
#define ARGS_COMMAND_BUILD          0x0004
47
#define ARGS_COMMAND_REPEAT_SETUP   0x0008
48
#define ARGS_COMMAND_INSTALL        0x0010
49
#define ARGS_COMMAND_CLEAN          0x0020
50
#define ARGS_COMMAND_DIST           0x0040
51

    
52

    
53

    
54
static int _readArgsIntoDb(int argc, char **argv, GWEN_DB_NODE *db);
55
static int _handleStringArgument(int argc, char **argv, int *pIndex, const char *sArg, const char *sArgId,
56
                                 const char *sVarName, GWEN_DB_NODE *db);
57
static void _printHelpScreen();
58

    
59

    
60

    
61

    
62
#ifdef HAVE_SIGNAL_H
63

    
64
struct sigaction sigActionChild;
65

    
66

    
67
void _signalHandler(int s) {
68
  switch(s) {
69
  case SIGCHLD:
70
    //fprintf(stderr, "Child exited %d\n", s);
71
    break;
72
  default:
73
    fprintf(stderr, "Received unhandled signal %d\n", s);
74
    break;
75
  }
76
  signal(s, _signalHandler);
77
}
78

    
79

    
80

    
81
int _setSingleSignalHandler(struct sigaction *sa, int sig)
82
{
83
  sa->sa_handler=_signalHandler;
84
  sigemptyset(&sa->sa_mask);
85
  sa->sa_flags=0;
86
  if (sigaction(sig, sa, 0)) {
87
    DBG_ERROR(NULL, "Could not setup signal handler for signal %d", sig);
88
    return GWEN_ERROR_GENERIC;
89
  }
90
  return 0;
91
}
92

    
93

    
94

    
95
int _setSignalHandlers() {
96
  int rv;
97

    
98
  rv=_setSingleSignalHandler(&sigActionChild, SIGCHLD);
99
  if (rv<0) {
100
    DBG_INFO(NULL, "here (%d)", rv);
101
    return rv;
102
  }
103

    
104
  return 0;
105
}
106

    
107
#endif
108

    
109

    
110

    
111

    
112
int main(int argc, char **argv)
113
{
114
  GWEN_DB_NODE *dbArgs;
115
  int rv;
116
  int err;
117
  uint32_t commands=0;
118
  const char *s;
119
  GWEN_GUI *gui;
120

    
121
#ifdef HAVE_SIGNAL_H
122
  signal(SIGCHLD, _signalHandler);
123
  //_setSignalHandlers();
124
#endif
125

    
126
  err=GWEN_Init();
127
  if (err) {
128
    fprintf(stderr, "Could not initialize Gwenhywfar.\n");
129
    return 2;
130
  }
131

    
132
  gui=GWEN_Gui_CGui_new();
133
  GWEN_Gui_SetGui(gui);
134

    
135
  GWEN_Logger_Open(NULL, "gwenbuild", 0,
136
                   GWEN_LoggerType_Console,
137
                   GWEN_LoggerFacility_User);
138

    
139
  GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Warning);
140

    
141
  dbArgs=GWEN_DB_Group_new("args");
142
  rv=_readArgsIntoDb(argc, argv, dbArgs);
143
  if (rv<0 || rv==1) {
144
    return 1;
145
  }
146

    
147
  s=GWEN_DB_GetCharValue(dbArgs, "loglevel", 0, NULL);
148
  if (s && *s) {
149
    GWEN_LOGGER_LEVEL level;
150

    
151
    level=GWEN_Logger_Name2Level(s);
152
    if (level==GWEN_LoggerLevel_Unknown) {
153
    }
154
    else
155
      GWEN_Logger_SetLevel(NULL, level);
156
  }
157

    
158
  commands|=GWEN_DB_GetIntValue(dbArgs, "setup", 0, 0)?ARGS_COMMAND_SETUP:0;
159
  commands|=GWEN_DB_GetIntValue(dbArgs, "repeatSetup", 0, 0)?ARGS_COMMAND_REPEAT_SETUP:0;
160
  commands|=GWEN_DB_GetIntValue(dbArgs, "prepare", 0, 0)?ARGS_COMMAND_PREPARE:0;
161
  commands|=GWEN_DB_GetIntValue(dbArgs, "build", 0, 0)?ARGS_COMMAND_BUILD:0;
162
  commands|=GWEN_DB_GetIntValue(dbArgs, "install", 0, 0)?ARGS_COMMAND_INSTALL:0;
163
  commands|=GWEN_DB_GetIntValue(dbArgs, "clean", 0, 0)?ARGS_COMMAND_CLEAN:0;
164
  commands|=GWEN_DB_GetIntValue(dbArgs, "dist", 0, 0)?ARGS_COMMAND_DIST:0;
165

    
166
  if (commands & ARGS_COMMAND_SETUP) {
167
    rv=GWB_Setup(dbArgs);
168
    if (rv!=0) {
169
      fprintf(stderr, "ERROR: Error on setup build environment.\n");
170
      return rv;
171
    }
172
  }
173

    
174
  if (commands & ARGS_COMMAND_REPEAT_SETUP) {
175
    rv=GWB_RepeatLastSetup(".gwbuild.args");
176
    if (rv<0) {
177
      fprintf(stderr, "ERROR: Error on repeating setup.\n");
178
      return rv;
179
    }
180
  }
181

    
182
  if (commands & ARGS_COMMAND_PREPARE) {
183
    rv=GWB_Prepare(dbArgs);
184
    if (rv!=0) {
185
      fprintf(stderr, "ERROR: Error on preparing build environment.\n");
186
      return rv;
187
    }
188
  }
189

    
190
  if ((commands & ARGS_COMMAND_BUILD) || (commands==0)) {
191
    rv=GWB_Build(dbArgs);
192
    if (rv!=0) {
193
      fprintf(stderr, "ERROR: Error on building.\n");
194
      return rv;
195
    }
196
  }
197

    
198
  if (commands & ARGS_COMMAND_INSTALL) {
199
    rv=GWB_InstallFiles(".gwbuild.installfiles", getenv("DESTDIR"));
200
    if (rv!=0) {
201
      fprintf(stderr, "ERROR: Error on installing.\n");
202
      return rv;
203
    }
204
  }
205

    
206
  if (commands & ARGS_COMMAND_DIST) {
207
    rv=GWB_MkDist();
208
    if (rv!=0) {
209
      fprintf(stderr, "ERROR: Error on creating dist file.\n");
210
      return rv;
211
    }
212
  }
213

    
214
  if (commands & ARGS_COMMAND_CLEAN) {
215
    rv=GWB_Clean(".gwbuild.files");
216
    if (rv!=0) {
217
      fprintf(stderr, "ERROR: Error on cleaning generated files.\n");
218
      return rv;
219
    }
220
  }
221

    
222

    
223
  err=GWEN_Fini();
224
  if (err) {
225
    fprintf(stderr,
226
            "WARNING: Could not deinitialize Gwenhywfar.\n");
227
  }
228

    
229
  return 0;
230
}
231

    
232

    
233

    
234
int _handleStringArgument(int argc, char **argv, int *pIndex, const char *sArg, const char *sArgId, const char *sVarName, GWEN_DB_NODE *db)
235
{
236
  int i;
237

    
238
  i=*pIndex;
239
  if (*sArg==0) {
240
    i++;
241
    if (i>=argc) {
242
      DBG_ERROR(NULL, "Missing argument for \"%s\"", sArgId);
243
      return GWEN_ERROR_INVALID;
244
    }
245
    sArg=argv[i];
246
  }
247
  if (sArg && *sArg)
248
    GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_DEFAULT, sVarName, sArg);
249
  *pIndex=i;
250
  return 0;
251
}
252

    
253

    
254

    
255
int _readArgsIntoDb(int argc, char **argv, GWEN_DB_NODE *db)
256
{
257
  int i=1;
258
  int help=0;
259

    
260
  while(i<argc) {
261
    const char *s;
262
    int val;
263

    
264
    s=argv[i];
265
    if (s) {
266
      if (*s!='-') {
267
        /* no option, probably path to source folder */
268
        GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "folder", s);
269
        /* folder only needed in setup mode, assume that */
270
        GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "setup", 1);
271
      }
272
      else {
273
        int rv;
274

    
275
        if (strncmp(s, "-O", 2)==0) {
276
          rv=_handleStringArgument(argc, argv, &i, s+2, "-O", "option",db);
277
          if (rv<0)
278
            return rv;
279
        }
280
        if (strncmp(s, "-B", 2)==0) {
281
          rv=_handleStringArgument(argc, argv, &i, s+2, "-B", "builder",db);
282
          if (rv<0)
283
            return rv;
284
        }
285
        if (strncmp(s, "-L", 2)==0) {
286
          rv=_handleStringArgument(argc, argv, &i, s+2, "-L", "loglevel",db);
287
          if (rv<0)
288
            return rv;
289
        }
290
        if (strncmp(s, "-C", 2)==0) {
291
          rv=_handleStringArgument(argc, argv, &i, s+2, "-C", "crossCompileFor",db);
292
          if (rv<0)
293
            return rv;
294
        }
295
        else if (strcmp(s, "--dump")==0)
296
          GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "dump", 1);
297
        else if (strcmp(s, "--static")==0)
298
          GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "static", 1);
299
        else if (strcmp(s, "--help")==0) {
300
          GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "help", 1);
301
          help=1;
302
        }
303
        else if (strcmp(s, "-p")==0)
304
          GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "prepare", 1);
305
        else if (strcmp(s, "-s")==0)
306
          GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "setup", 1);
307
        else if (strcmp(s, "-r")==0)
308
          GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "repeatSetup", 1);
309
        else if (strcmp(s, "-b")==0)
310
          GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "build", 1);
311
        else if (strcmp(s, "-i")==0)
312
          GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "install", 1);
313
        else if (strcmp(s, "-c")==0)
314
          GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "clean", 1);
315
        else if (strcmp(s, "-d")==0)
316
          GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "dist", 1);
317
        else if (strncmp(s, "-j", 2)==0) {
318
          /* jobs */
319
          s+=2;
320
          if (*s==0) {
321
            i++;
322
            if (i>=argc) {
323
              DBG_ERROR(NULL, "Missing argument for \"-j\"");
324
              return GWEN_ERROR_INVALID;
325
            }
326
            s=argv[i];
327
          }
328
          if (1!=sscanf(s, "%d", &val)) {
329
            DBG_ERROR(NULL, "Non-integer argument for \"-j\"");
330
            return GWEN_ERROR_INVALID;
331
          }
332
          GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "jobs", val);
333
        }
334
      }
335
    }
336
    i++;
337
  } /* while */
338

    
339
  if (help) {
340
    _printHelpScreen();
341
    return 1;
342
  }
343

    
344
  return 0;
345
}
346

    
347

    
348

    
349
void _printHelpScreen()
350
{
351
  fprintf(stdout,
352
          "\n"
353
          "Gwenhywfar Build Tool " GWENHYWFAR_VERSION_FULL_STRING "\n"
354
          "\n"
355
          "Building a project (e.g. compiling and linking) is done in multiple steps.\n"
356
          "\n"
357
          "1. Setup Build Environment\n"
358
          "-------------------------\n"
359
          "A. Create files named 0BUILD inside your project (see project AqFinance for\n"
360
          "example files).\n"
361
          "B. Create an empty folder and change into it (all next commands are run\n"
362
          "from there).\n"
363
          "You might want to use a folder like 'build' inside the source tree of\n"
364
          "your project.\n"
365
          "3. run\n"
366
          "      gwbuild PATH_TO_SOURCE_TREE\n"
367
          "e.g.  gwbuild ..\n"
368
          "\n"
369
          "2. Prepare Buidling\n"
370
          "-------------------\n"
371
          "      gwbuild -p\n"
372
          "This is only needed if your project uses typemaker2 to generate c-sources from\n"
373
          "XML files.\n"
374
          "This command makes typemaker2 create its derived type description files needed\n"
375
          "when referencing\n"
376
          "typemaker2 generated types inside another typemaker2 generated type.\n"
377
          "\n"
378
          "3. Build Typemaker2 Files\n"
379
          "-------------------------\n"
380
          "     gwbuild -Btm2builder\n"
381
          "This also is only needed if typemaker2 files are used in your project.\n"
382
          "\n"
383
          "4. Build All Other Targets\n"
384
          "--------------------------\n"
385
          "     gwbuild\n"
386
          "This uses a single process to compile and link the project files.\n"
387
          "If you have multiple processor cores/threads you can build multiple files in\n"
388
          "parallel:\n"
389
          "     gwbuild -j14\n"
390
          "This command uses 14 processes in parallel.\n"
391
          "The step can be repeated as often as needed. It will automatically check for\n"
392
          "changed files and try to only re-compile/link those modified files and others\n"
393
          "which depend on them.\n"
394
          "If you change a 0BUILD file gwbuild will automatically call the setup step\n"
395
          "using the same\n"
396
          "arguments given to the last setup command (-s). This typically leads to all\n"
397
          "files being re-build.\n"
398
          "\n"
399
          "Option List\n"
400
          "-----------\n"
401
          "-s           setup build environment\n"
402
          "-p           run preparation commands (needed e.g. if typemaker2 is used)\n"
403
          "-b           build targets\n"
404
          "-i           install files\n"
405
          "-c           cleanup; delete generated files\n"
406
          "-r           repeat setup command using the same arguments given to last setup\n"
407
          "-d           make distribution folder (you need to run tar yourself for now)\n"
408
          "-Oname=value specify options (can occur multiple times)\n"
409
          "-Bname       Only run commands for the given build (mostly used with\n"
410
          "             'tm2builder')\n"
411
          "-Lname       Set loglevel (debug, info, notice, warn, error)\n"
412
          "-Cname       Crosscompile for given environment (e-g- 'x86_64-w64-mingw32')\n"
413
          "-jvalue      Use the given number of parallel process for building\n"
414
          "--static     Generate static libs for InstallLibrary targets\n"
415
         );
416
}
417

    
418

    
419

    
420