gwenhywfar  5.7.2
gwenbuild/main.c
Go to the documentation of this file.
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 
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,
138 
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 */
269  /* folder only needed in setup mode, assume that */
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)
297  else if (strcmp(s, "--static")==0)
299  else if (strcmp(s, "--help")==0) {
301  help=1;
302  }
303  else if (strcmp(s, "-p")==0)
305  else if (strcmp(s, "-s")==0)
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)
311  else if (strcmp(s, "-i")==0)
313  else if (strcmp(s, "-c")==0)
315  else if (strcmp(s, "-d")==0)
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  }
333  }
334  }
335  }
336  i++;
337  } /* while */
338 
339  if (help) {
341  return 1;
342  }
343 
344  return 0;
345 }
346 
347 
348 
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 
#define GWEN_DB_FLAGS_OVERWRITE_VARS
Definition: db.h:121
#define ARGS_COMMAND_CLEAN
int GWB_Setup(GWEN_DB_NODE *dbArgs)
Definition: c_setup.c:44
struct GWEN_DB_NODE GWEN_DB_NODE
Definition: db.h:228
int GWB_RepeatLastSetup(const char *fileName)
Definition: c_setup.c:159
#define GWEN_ERROR_INVALID
Definition: error.h:67
void GWEN_Logger_SetLevel(const char *logDomain, GWEN_LOGGER_LEVEL l)
Definition: logger.c:627
#define ARGS_COMMAND_REPEAT_SETUP
GWEN_LOGGER_LEVEL
Definition: logger.h:64
#define NULL
Definition: binreloc.c:300
#define ARGS_COMMAND_SETUP
GWEN_LOGGER_LEVEL GWEN_Logger_Name2Level(const char *name)
Definition: logger.c:697
#define ARGS_COMMAND_DIST
#define ARGS_COMMAND_INSTALL
int GWB_Build(GWEN_DB_NODE *dbArgs)
Definition: c_build.c:25
int GWB_Clean(const char *fname)
Definition: c_clean.c:26
#define GWEN_ERROR_GENERIC
Definition: error.h:62
const char * GWEN_DB_GetCharValue(GWEN_DB_NODE *n, const char *path, int idx, const char *defVal)
Definition: db.c:971
int GWEN_Fini(void)
Definition: gwenhywfar.c:303
int GWEN_Logger_Open(const char *logDomain, const char *ident, const char *file, GWEN_LOGGER_LOGTYPE logtype, GWEN_LOGGER_FACILITY facility)
Definition: logger.c:225
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
int GWB_Prepare(GWEN_UNUSED GWEN_DB_NODE *dbArgs)
Definition: c_prepare.c:26
int GWB_MkDist()
Definition: c_dist.c:36
#define ARGS_COMMAND_PREPARE
int GWEN_DB_SetCharValue(GWEN_DB_NODE *n, uint32_t flags, const char *path, const char *val)
Definition: db.c:997
#define ARGS_COMMAND_BUILD
int main(int argc, char **argv)
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:178
static int _readArgsIntoDb(int argc, char **argv, GWEN_DB_NODE *db)
struct GWEN_GUI GWEN_GUI
Definition: gui.h:176
int GWEN_DB_GetIntValue(GWEN_DB_NODE *n, const char *path, int idx, int defVal)
Definition: db.c:1163
GWEN_DB_NODE * GWEN_DB_Group_new(const char *name)
Definition: db.c:173
int GWEN_DB_SetIntValue(GWEN_DB_NODE *n, uint32_t flags, const char *path, int val)
Definition: db.c:1202
#define GWENHYWFAR_VERSION_FULL_STRING
Definition: version.h:38
void GWEN_Gui_SetGui(GWEN_GUI *gui)
Definition: gui.c:170
int GWEN_Init(void)
Definition: gwenhywfar.c:92
GWEN_GUI * GWEN_Gui_CGui_new(void)
Definition: cgui.c:74
int GWB_InstallFiles(const char *fileName, const char *destDir)
Definition: c_install.c:24
static void _printHelpScreen()
static int _handleStringArgument(int argc, char **argv, int *pIndex, const char *sArg, const char *sArgId, const char *sVarName, GWEN_DB_NODE *db)
#define GWEN_DB_FLAGS_DEFAULT
Definition: db.h:168