gwenhywfar 5.10.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\n"
383 "e.g. gwbuild -s ..\n"
384 "\n"
385 "2. Prepare Buidling\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\n"
392 "typemaker2 generated types inside another typemaker2 generated type.\n"
393 "\n"
394 "3. Build All Targets\n"
395 "--------------------------\n"
396 " gwbuild\n"
397 "This command builds typemaker2 source files first (if needed) and then all\n"
398 "other targets.\n"
399 "A single process is used to compile and link the project files.\n"
400 "If you have multiple processor cores/threads you can build multiple files in\n"
401 "parallel:\n"
402 " gwbuild -j14\n"
403 "This command uses 14 processes in parallel.\n"
404 "The step can be repeated as often as needed. It will automatically check for\n"
405 "changed files and try to only re-compile/link those modified files and others\n"
406 "which depend on them.\n"
407 "If you change a 0BUILD file gwbuild will automatically call the setup step\n"
408 "using the same\n"
409 "arguments given to the last setup command (-s). This typically leads to all\n"
410 "files being re-build.\n"
411 "\n"
412 "Option List\n"
413 "-----------\n"
414 "-s FOLDER setup build environment (arg: source folder path)\n"
415 "-p run preparation commands (needed e.g. if typemaker2 is used)\n"
416 "-b build targets\n"
417 "-i install files\n"
418 "-c cleanup; delete generated files\n"
419 "-r repeat setup command using the same arguments given to last setup\n"
420 "-d make distribution folder (you need to run tar yourself for now)\n"
421 "-Oname=value specify options (can occur multiple times)\n"
422 "-Bname Only run commands for the given build (mostly used with\n"
423 " 'tm2builder')\n"
424 "-Lname Set loglevel (debug, info, notice, warn, error)\n"
425 "-Cname Crosscompile for given environment (e-g- 'x86_64-w64-mingw32')\n"
426 "-jvalue Use the given number of parallel process for building\n"
427 "--static Generate static libs for InstallLibrary targets\n"
428 );
429}
430
431
432
433
#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:74
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, args...)
Definition: debug.h:181
#define DBG_ERROR(dbg_logger, format, args...)
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:697
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
void GWEN_Logger_SetLevel(const char *logDomain, GWEN_LOGGER_LEVEL l)
Definition: logger.c:627
@ GWEN_LoggerType_Console
Definition: logger.h:44
@ GWEN_LoggerFacility_User
Definition: logger.h:58
GWEN_LOGGER_LEVEL
Definition: logger.h:64
@ GWEN_LoggerLevel_Unknown
Definition: logger.h:75
@ GWEN_LoggerLevel_Warning
Definition: logger.h:69
#define GWENHYWFAR_VERSION_FULL_STRING
Definition: version.h:38