gwenhywfar 5.14.1
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 "gwenbuild/filenames.h"
17#include "utils.h"
18#include "c_setup.h"
19#include "c_prepare.h"
20#include "c_build.h"
21#include "c_install.h"
22#include "c_clean.h"
23#include "c_dist.h"
24
25#include <gwenhywfar/gwenhywfar.h>
26#include <gwenhywfar/cgui.h>
27#include <gwenhywfar/debug.h>
28#include <gwenhywfar/args.h>
29#include <gwenhywfar/i18n.h>
30#include <gwenhywfar/text.h>
31#include <gwenhywfar/directory.h>
32
33#include <unistd.h>
34
35#ifdef HAVE_SIGNAL_H
36# include <signal.h>
37#endif
38
39
40
41#define I18N(msg) GWEN_I18N_Translate(PACKAGE, msg)
42#define I18S(msg) msg
43
44
45#define ARGS_COMMAND_SETUP 0x0001
46#define ARGS_COMMAND_PREPARE 0x0002
47#define ARGS_COMMAND_BUILD 0x0004
48#define ARGS_COMMAND_REPEAT_SETUP 0x0008
49#define ARGS_COMMAND_INSTALL 0x0010
50#define ARGS_COMMAND_CLEAN 0x0020
51#define ARGS_COMMAND_DIST 0x0040
52
53
54
55static int _readArgsIntoDb(int argc, char **argv, GWEN_DB_NODE *db);
56static int _handleStringArgument(int argc, char **argv, int *pIndex, const char *sArg, const char *sArgId,
57 const char *sVarName, GWEN_DB_NODE *db);
58static void _printHelpScreen();
59
60
61
62
63#ifdef HAVE_SIGNAL_H
64
65# ifdef _POSIX_C_SOURCE
66struct sigaction sigActionChild;
67# endif
68
69
70void _signalHandler(int s) {
71 switch(s) {
72#ifdef _POSIX_C_SOURCE
73 case SIGCHLD:
74 //fprintf(stderr, "Child exited %d\n", s);
75 break;
76#endif
77 default:
78 fprintf(stderr, "Received unhandled signal %d\n", s);
79 break;
80 }
81 signal(s, _signalHandler);
82}
83
84
85
86#if _POSIX_C_SOURCE
87int _setSingleSignalHandler(struct sigaction *sa, int sig)
88{
89 sa->sa_handler=_signalHandler;
90 sigemptyset(&sa->sa_mask);
91 sa->sa_flags=0;
92 if (sigaction(sig, sa, 0)) {
93 DBG_ERROR(NULL, "Could not setup signal handler for signal %d", sig);
94 return GWEN_ERROR_GENERIC;
95 }
96 return 0;
97}
98#endif
99
100
101
102int _setSignalHandlers() {
103#ifdef _POSIX_C_SOURCE
104 int rv;
105
106 rv=_setSingleSignalHandler(&sigActionChild, SIGCHLD);
107 if (rv<0) {
108 DBG_INFO(NULL, "here (%d)", rv);
109 return rv;
110 }
111#endif
112
113 return 0;
114}
115
116#endif
117
118
119
120
121int main(int argc, char **argv)
122{
123 GWEN_DB_NODE *dbArgs;
124 int rv;
125 int err;
126 uint32_t commands=0;
127 const char *s;
128 GWEN_GUI *gui;
129
130#if defined(HAVE_SIGNAL_H) && defined(_POSIX_C_SOURCE)
131 signal(SIGCHLD, _signalHandler);
132 //_setSignalHandlers();
133#endif
134
135 err=GWEN_Init();
136 if (err) {
137 fprintf(stderr, "Could not initialize Gwenhywfar.\n");
138 return 2;
139 }
140
141 gui=GWEN_Gui_CGui_new();
142 GWEN_Gui_SetGui(gui);
143
144 GWEN_Logger_Open(NULL, "gwenbuild", 0,
147
149
150 dbArgs=GWEN_DB_Group_new("args");
151 rv=_readArgsIntoDb(argc, argv, dbArgs);
152 if (rv<0 || rv==1) {
153 return 1;
154 }
155
156 s=GWEN_DB_GetCharValue(dbArgs, "loglevel", 0, NULL);
157 if (s && *s) {
158 GWEN_LOGGER_LEVEL level;
159
160 level=GWEN_Logger_Name2Level(s);
161 if (level==GWEN_LoggerLevel_Unknown) {
162 }
163 else
165 }
166
167 commands|=GWEN_DB_GetIntValue(dbArgs, "setup", 0, 0)?ARGS_COMMAND_SETUP:0; /* -s */
168 commands|=GWEN_DB_GetIntValue(dbArgs, "repeatSetup", 0, 0)?ARGS_COMMAND_REPEAT_SETUP:0; /* -r */
169 commands|=GWEN_DB_GetIntValue(dbArgs, "prepare", 0, 0)?ARGS_COMMAND_PREPARE:0; /* -p */
170 commands|=GWEN_DB_GetIntValue(dbArgs, "build", 0, 0)?ARGS_COMMAND_BUILD:0; /* -b or no opts */
171 commands|=GWEN_DB_GetIntValue(dbArgs, "install", 0, 0)?ARGS_COMMAND_INSTALL:0; /* -i */
172 commands|=GWEN_DB_GetIntValue(dbArgs, "clean", 0, 0)?ARGS_COMMAND_CLEAN:0; /* -c */
173 commands|=GWEN_DB_GetIntValue(dbArgs, "dist", 0, 0)?ARGS_COMMAND_DIST:0; /* -d */
174
175 if (commands & ARGS_COMMAND_SETUP) {
176 rv=GWB_Setup(dbArgs);
177 if (rv!=0) {
178 fprintf(stderr, "ERROR: Error on setup build environment.\n");
179 return rv;
180 }
181 }
182
183 if (commands & ARGS_COMMAND_REPEAT_SETUP) {
185 if (rv<0) {
186 fprintf(stderr, "ERROR: Error on repeating setup.\n");
187 return rv;
188 }
189 }
190
191 if (commands & ARGS_COMMAND_PREPARE) {
192 rv=GWB_Prepare(dbArgs);
193 if (rv!=0) {
194 fprintf(stderr, "ERROR: Error on preparing build environment.\n");
195 return rv;
196 }
197 }
198
199 if ((commands & ARGS_COMMAND_BUILD) || (commands==0)) {
200 rv=GWB_Build(dbArgs);
201 if (rv!=0) {
202 fprintf(stderr, "ERROR: Error on building.\n");
203 return rv;
204 }
205 }
206
207 if (commands & ARGS_COMMAND_INSTALL) {
208 rv=GWB_InstallFiles(GWBUILD_FILE_INSTALLFILES, getenv("DESTDIR"));
209 if (rv!=0) {
210 fprintf(stderr, "ERROR: Error on installing.\n");
211 return rv;
212 }
213 }
214
215 if (commands & ARGS_COMMAND_DIST) {
216 rv=GWB_MkDist();
217 if (rv!=0) {
218 fprintf(stderr, "ERROR: Error on creating dist file.\n");
219 return rv;
220 }
221 }
222
223 if (commands & ARGS_COMMAND_CLEAN) {
225 if (rv!=0) {
226 fprintf(stderr, "ERROR: Error on cleaning generated files.\n");
227 return rv;
228 }
229 }
230
231
232 err=GWEN_Fini();
233 if (err) {
234 fprintf(stderr,
235 "WARNING: Could not deinitialize Gwenhywfar.\n");
236 }
237
238 return 0;
239}
240
241
242
243int _handleStringArgument(int argc, char **argv, int *pIndex, const char *sArg, const char *sArgId, const char *sVarName, GWEN_DB_NODE *db)
244{
245 int i;
246
247 i=*pIndex;
248 if (*sArg==0) {
249 i++;
250 if (i>=argc) {
251 DBG_ERROR(NULL, "Missing argument for \"%s\"", sArgId);
252 return GWEN_ERROR_INVALID;
253 }
254 sArg=argv[i];
255 }
256 if (sArg && *sArg)
257 GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_DEFAULT, sVarName, sArg);
258 *pIndex=i;
259 return 0;
260}
261
262
263
264int _readArgsIntoDb(int argc, char **argv, GWEN_DB_NODE *db)
265{
266 int i=1;
267 int help=0;
268
269 while(i<argc) {
270 const char *s;
271 int val;
272
273 s=argv[i];
274 if (s) {
275 if (*s!='-') {
276#if 0
277 /* no option, probably gwbuild target */
278 GWEN_DB_SetCharValue(db, 0, "target", s);
279#else
280 fprintf(stderr, "Specifying build target not yet supported.\n");
281 return GWEN_ERROR_GENERIC;
282#endif
283 }
284 else {
285 int rv;
286
287 if (strncmp(s, "-O", 2)==0) {
288 rv=_handleStringArgument(argc, argv, &i, s+2, "-O", "option",db);
289 if (rv<0)
290 return rv;
291 }
292 if (strncmp(s, "-B", 2)==0) {
293 rv=_handleStringArgument(argc, argv, &i, s+2, "-B", "builder",db);
294 if (rv<0)
295 return rv;
296 }
297 if (strncmp(s, "-L", 2)==0) {
298 rv=_handleStringArgument(argc, argv, &i, s+2, "-L", "loglevel",db);
299 if (rv<0)
300 return rv;
301 }
302 if (strncmp(s, "-C", 2)==0) {
303 rv=_handleStringArgument(argc, argv, &i, s+2, "-C", "crossCompileFor",db);
304 if (rv<0)
305 return rv;
306 }
307 else if (strcmp(s, "--dump")==0)
309 else if (strcmp(s, "--static")==0)
311 else if (strcmp(s, "--help")==0) {
313 help=1;
314 }
315 else if (strcmp(s, "-p")==0)
317 else if (strcmp(s, "-s")==0) {
319 rv=_handleStringArgument(argc, argv, &i, s+2, "-s", "folder", db);
320 if (rv<0)
321 return rv;
322 }
323 else if (strcmp(s, "-r")==0)
325 else if (strcmp(s, "-b")==0)
327 else if (strcmp(s, "-i")==0)
329 else if (strcmp(s, "-c")==0)
331 else if (strcmp(s, "-d")==0)
333 else if (strncmp(s, "-j", 2)==0) {
334 /* jobs */
335 s+=2;
336 if (*s==0) {
337 i++;
338 if (i>=argc) {
339 DBG_ERROR(NULL, "Missing argument for \"-j\"");
340 return GWEN_ERROR_INVALID;
341 }
342 s=argv[i];
343 }
344 if (1!=sscanf(s, "%d", &val)) {
345 DBG_ERROR(NULL, "Non-integer argument for \"-j\"");
346 return GWEN_ERROR_INVALID;
347 }
349 }
350 }
351 }
352 i++;
353 } /* while */
354
355 if (help) {
357 return 1;
358 }
359
360 return 0;
361}
362
363
364
366{
367 fprintf(stdout,
368 "\n"
369 "Gwenhywfar Build Tool " GWENHYWFAR_VERSION_FULL_STRING "\n"
370 "\n"
371 "Building a project (e.g. compiling and linking) is done in multiple steps.\n"
372 "\n"
373 "1. Setup Build Environment\n"
374 "-------------------------\n"
375 "A. Create files named 0BUILD inside your project (see project AqFinance for\n"
376 "example files).\n"
377 "B. Create an empty folder and change into it (all next commands are run\n"
378 "from there).\n"
379 "You might want to use a folder like 'build' inside the source tree of\n"
380 "your project.\n"
381 "C. run\n"
382 " gwbuild -s PATH_TO_SOURCE_TREE [-OOPTIONS]\n"
383 "e.g. gwbuild -s .. -Oprefix=/usr/local\n"
384 "\n"
385 "2. Prepare Building\n"
386 "-------------------\n"
387 " gwbuild -p\n"
388 "This is only needed if your project uses typemaker2 to generate c-sources from\n"
389 "XML files.\n"
390 "This command makes typemaker2 create its derived type description files needed\n"
391 "when referencing typemaker2 generated types inside another typemaker2 generated\n"
392 "type.\n"
393 "\n"
394 "3. Build Typemaker2 Files\n"
395 "--------------------------\n"
396 " gwbuild -Btm2builder\n"
397 "This step is only needed once after the previous step and before compiling source files.\n"
398 "The reason is that compiling source files involves creating dependency files.\n"
399 "But for that to work at least for GCC all the headers which are included by source\n"
400 "files need to exist; this also means source files to be generated by typemaker2.\n"
401 "So if you have typemaker2 input files you need to run this step once.\n"
402 "After that gwbuild keeps track of changes made to the input files and calls typemaker2\n"
403 "again if necessary.\n"
404 "\n"
405 "4. Build All Targets\n"
406 "--------------------\n"
407 " gwbuild\n"
408 "This command builds typemaker2 source files first (if needed) and then all\n"
409 "other targets.\n"
410 "A single process is used to compile and link the project files.\n"
411 "If you have multiple processor cores/threads you can build multiple files in\n"
412 "parallel:\n"
413 " gwbuild -j14\n"
414 "This command uses 14 processes in parallel.\n"
415 "The step can be repeated as often as needed. It will automatically check for\n"
416 "changed files and try to only re-compile/link those modified files and others\n"
417 "which depend on them.\n"
418 "If you change a 0BUILD file gwbuild will automatically call the setup step\n"
419 "using the same\n"
420 "arguments given to the last setup command (-s). This typically leads to all\n"
421 "files being re-build.\n"
422 "\n"
423 "Complete Option List\n"
424 "--------------------\n"
425 "-s FOLDER setup build environment (arg: source folder path)\n"
426 "-p run preparation commands (needed e.g. if typemaker2 is used)\n"
427 "-b build targets\n"
428 "-i install files\n"
429 "-c cleanup; delete generated files\n"
430 "-r repeat setup command using the same arguments given to last setup\n"
431 "-d make distribution folder (you need to run tar yourself for now)\n"
432 "-Oname=value specify options (uppercase o, can occur multiple times)\n"
433 "-Bname Only run commands for the given build (mostly used with\n"
434 " 'tm2builder')\n"
435 "-Lname Set loglevel (debug, info, notice, warn, error)\n"
436 "-Cname Crosscompile for given environment (e-g- 'x86_64-w64-mingw32')\n"
437 "-jvalue Use the given number of parallel process for building\n"
438 "--static Generate static libs for InstallLibrary targets\n"
439 "\n"
440 "Please see https://www.aquamaniac.de/rdm/projects/aqbanking/wiki/Gwbuild for\n"
441 "more info and tutorials.\n"
442 );
443}
444
445
446
447
#define NULL
Definition binreloc.c:300
int GWB_Build(GWEN_DB_NODE *dbArgs)
Definition c_build.c:26
int GWB_Clean(const char *fname)
Definition c_clean.c:27
int GWB_MkDist()
Definition c_dist.c:37
int GWB_InstallFiles(const char *fileName, const char *destDir)
Definition c_install.c:25
int GWB_Prepare(GWEN_UNUSED GWEN_DB_NODE *dbArgs)
Definition c_prepare.c:27
int GWB_Setup(GWEN_DB_NODE *dbArgs)
Definition c_setup.c:45
int GWB_RepeatLastSetup(const char *fileName)
Definition c_setup.c:159
GWEN_GUI * GWEN_Gui_CGui_new(void)
Definition cgui.c:77
const char * GWEN_DB_GetCharValue(GWEN_DB_NODE *n, const char *path, int idx, const char *defVal)
Definition db.c:971
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
int GWEN_DB_SetCharValue(GWEN_DB_NODE *n, uint32_t flags, const char *path, const char *val)
Definition db.c:997
int GWEN_DB_GetIntValue(GWEN_DB_NODE *n, const char *path, int idx, int defVal)
Definition db.c:1163
#define GWEN_DB_FLAGS_DEFAULT
Definition db.h:168
#define GWEN_DB_FLAGS_OVERWRITE_VARS
Definition db.h:121
struct GWEN_DB_NODE GWEN_DB_NODE
Definition db.h:228
#define DBG_INFO(dbg_logger, format,...)
Definition debug.h:181
#define DBG_ERROR(dbg_logger, format,...)
Definition debug.h:97
#define GWEN_ERROR_INVALID
Definition error.h:67
#define GWEN_ERROR_GENERIC
Definition error.h:62
#define GWBUILD_FILE_INSTALLFILES
Definition filenames.h:19
#define GWBUILD_FILE_FILES
Definition filenames.h:16
#define GWBUILD_FILE_ARGS
Definition filenames.h:20
void GWEN_Gui_SetGui(GWEN_GUI *gui)
Definition gui.c:170
struct GWEN_GUI GWEN_GUI
Definition gui.h:176
static int _readArgsIntoDb(int argc, char **argv, GWEN_DB_NODE *db)
int main(int argc, char **argv)
#define ARGS_COMMAND_SETUP
#define ARGS_COMMAND_DIST
#define ARGS_COMMAND_PREPARE
#define ARGS_COMMAND_BUILD
#define ARGS_COMMAND_REPEAT_SETUP
#define ARGS_COMMAND_INSTALL
static int _handleStringArgument(int argc, char **argv, int *pIndex, const char *sArg, const char *sArgId, const char *sVarName, GWEN_DB_NODE *db)
static void _printHelpScreen()
#define ARGS_COMMAND_CLEAN
int GWEN_Init(void)
Definition gwenhywfar.c:92
int GWEN_Fini(void)
Definition gwenhywfar.c:303
GWEN_LOGGER_LEVEL GWEN_Logger_Name2Level(const char *name)
Definition logger.c:542
int GWEN_Logger_Open(const char *logDomain, const char *ident, const char *file, GWEN_LOGGER_LOGTYPE logtype, GWEN_LOGGER_FACILITY facility)
Definition logger.c:281
void GWEN_Logger_SetLevel(const char *logDomain, GWEN_LOGGER_LEVEL l)
Definition logger.c:472
@ GWEN_LoggerType_Console
Definition logger.h:41
@ GWEN_LoggerFacility_User
Definition logger.h:55
GWEN_LOGGER_LEVEL
Definition logger.h:61
@ GWEN_LoggerLevel_Unknown
Definition logger.h:72
@ GWEN_LoggerLevel_Warning
Definition logger.h:66
#define GWENHYWFAR_VERSION_FULL_STRING
Definition version.h:38