Sync with 5.2.0
[deliverable/titan.core.git] / compiler2 / makefile.c
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdarg.h>
12 #include <unistd.h>
13 #include <errno.h>
14 #include <ctype.h>
15 #if defined SOLARIS || defined SOLARIS8
16 #include <sys/utsname.h>
17 #endif
18
19 #include "../common/memory.h"
20 #include "../common/path.h"
21 #include "../common/version_internal.h"
22 #include "../common/userinfo.h"
23 #include "ttcn3/ttcn3_preparser.h"
24 #include "asn1/asn1_preparser.h"
25
26 #ifdef LICENSE
27 #include "../common/license.h"
28 #endif
29
30 #include "xpather.h"
31
32 static const char *program_name = NULL;
33 static unsigned int error_count = 0;
34 static boolean suppress_warnings = FALSE;
35 void free_string2_list(struct string2_list* act_elem);
36 void free_string_list(struct string_list* act_elem);
37 void ERROR(const char *fmt, ...)
38 {
39 va_list parameters;
40 fprintf(stderr, "%s: error: ", program_name);
41 va_start(parameters, fmt);
42 vfprintf(stderr, fmt, parameters);
43 va_end(parameters);
44 fprintf(stderr, "\n");
45 fflush(stderr);
46 error_count++;
47 }
48
49 void WARNING(const char *fmt, ...)
50 {
51 va_list parameters;
52 if (suppress_warnings) return;
53 fprintf(stderr, "%s: warning: ", program_name);
54 va_start(parameters, fmt);
55 vfprintf(stderr, fmt, parameters);
56 va_end(parameters);
57 putc('\n', stderr);
58 fflush(stderr);
59 }
60
61 void NOTIFY(const char *fmt, ...)
62 {
63 va_list parameters;
64 va_start(parameters, fmt);
65 vfprintf(stderr, fmt, parameters);
66 va_end(parameters);
67 putc('\n', stderr);
68 fflush(stderr);
69 }
70
71 void DEBUG(unsigned level, const char *fmt, ...)
72 {
73 va_list parameters;
74 fprintf(stderr, "%*s", 2 * level, "");
75 va_start(parameters, fmt);
76 vfprintf(stderr, fmt, parameters);
77 va_end(parameters);
78 putc('\n', stderr);
79 fflush(stderr);
80 }
81
82 void path_error(const char *fmt, ...)
83 {
84 va_list ap;
85 char *err_msg;
86 va_start(ap, fmt);
87 err_msg = mprintf_va_list(fmt, ap);
88 va_end(ap);
89 ERROR("%s", err_msg);
90 Free(err_msg);
91 }
92
93
94 #if defined SOLARIS || defined SOLARIS8
95 /** Automatic detection of Solaris version based on uname() system call.
96 * Distinguishing is needed because some socket functions use socklen_t
97 * (which is an alias for unsigned int) as length arguments on Solaris 8.
98 * On Solaris 2.6 the argument type is simply int and no socklen_t or other
99 * alias exists.
100 * Note: It was discovered later that Solaris 7 (which is used rarely within
101 * Ericsson) already uses socklen_t thus the SOLARIS8 platform identifier is a
102 * bit misleading. */
103 static const char *get_platform_string(void)
104 {
105 struct utsname name;
106 int major, minor;
107 if (uname(&name) < 0) {
108 WARNING("System call uname() failed: %s", strerror(errno));
109 errno = 0;
110 return "SOLARIS";
111 }
112 if (sscanf(name.release, "%d.%d", &major, &minor) == 2 && major == 5) {
113 if (minor <= 6) return "SOLARIS";
114 else return "SOLARIS8";
115 } else {
116 ERROR("Invalid OS release: %s", name.release);
117 return "SOLARIS";
118 }
119 }
120 #elif defined LINUX
121 #define get_platform_string() "LINUX"
122 #elif defined FREEBSD
123 #define get_platform_string() "FREEBSD"
124 #elif defined WIN32
125 #define get_platform_string() "WIN32"
126 #elif defined INTERIX
127 #define get_platform_string() "INTERIX"
128 #else
129 #error Platform was not set.
130 #endif
131
132 /** structure for describing TTCN-3 and ASN.1 modules */
133 struct module_struct {
134 char *dir_name; /* directory of the TTCN-3 or ASN.1 file, it is NULL if the
135 file is in the current working directory */
136 char *file_name; /* name of the TTCN-3 or ASN.1 file */
137 char *module_name; /* name of the TTCN-3 or ASN.1 module */
138 boolean is_regular; /* indicates whether the name of the source file follows
139 the default naming convention */
140 };
141
142 /** structure for describing test ports and other C/C++ modules */
143 struct user_struct {
144 char *dir_name; /* directory of the C/C++ source files, it is NULL if the
145 files are in the current working directory */
146 char *file_prefix; /* the common prefix of the header and source file */
147 char *header_name; /* name of the C/C++ header file, which has .hh or .h or .hpp
148 suffix, it is NULL if there is no header file */
149 char *source_name; /* name of the C/C++ source file, which has .cc or .c or .cpp
150 suffix, it is NULL if there is no source file */
151 boolean has_hh_suffix; /* indicates whether the header file is present and
152 has .hh or .hpp suffix */
153 boolean has_cc_suffix; /* indicates whether the source file is present and
154 has .cc or .cpp suffix */
155 };
156
157 /** structure for directories that pre-compiled files are taken from */
158 struct base_dir_struct {
159 const char *dir_name; /* name of the directory */
160 boolean has_modules; /* indicates whether there are TTCN-3/ASN.1 modules in
161 the directory (it is set to FALSE if dir_name
162 contains user C/C++ files only */
163 };
164
165 /** data structure that describes the information needed for the Makefile */
166 struct makefile_struct {
167 char *project_name;
168 size_t nTTCN3Modules;
169 struct module_struct *TTCN3Modules;
170
171 boolean preprocess;
172 size_t nTTCN3PPModules;
173 struct module_struct *TTCN3PPModules;
174
175 boolean TTCN3ModulesRegular;
176 boolean BaseTTCN3ModulesRegular;
177 size_t nTTCN3IncludeFiles;
178 char **TTCN3IncludeFiles;
179
180 size_t nASN1Modules;
181 struct module_struct *ASN1Modules;
182 boolean ASN1ModulesRegular;
183 boolean BaseASN1ModulesRegular;
184
185 size_t nUserFiles;
186 struct user_struct *UserFiles;
187 boolean UserHeadersRegular;
188 boolean UserSourcesRegular;
189 boolean BaseUserHeadersRegular;
190 boolean BaseUserSourcesRegular;
191
192 size_t nOtherFiles;
193 char **OtherFiles;
194
195 boolean central_storage;
196 size_t nBaseDirs;
197 struct base_dir_struct *BaseDirs;
198 char *working_dir;
199 boolean gnu_make;
200 boolean single_mode;
201 char *output_file;
202 char *ets_name;
203 boolean force_overwrite;
204 boolean use_runtime_2;
205 boolean dynamic;
206 boolean gcc_dep;
207 char *code_splitting_mode;
208 boolean coverage;
209 char *tcov_file_name;
210 boolean library;
211 boolean linkingStrategy;
212 boolean hierarchical;
213 struct string_list* sub_project_dirs; /* not owned */
214 struct string_list* ttcn3_prep_includes; /* not owned */
215 struct string_list* ttcn3_prep_defines; /* not owned */
216 struct string_list* ttcn3_prep_undefines; /* not owned */
217 struct string_list* prep_includes; /* not owned */
218 struct string_list* prep_defines; /* not owned */
219 struct string_list* prep_undefines; /* not owned */
220 boolean codesplittpd;
221 boolean quietly;
222 boolean disablesubtypecheck;
223 const char *cxxcompiler;
224 const char *optlevel;
225 const char *optflags;
226 boolean disableber;
227 boolean disableraw;
228 boolean disabletext;
229 boolean disablexer;
230 boolean disablejson;
231 boolean forcexerinasn;
232 boolean defaultasomit;
233 boolean gccmsgformat;
234 boolean linenumbersonlymsg;
235 boolean includesourceinfo;
236 boolean addsourcelineinfo;
237 boolean suppresswarnings;
238 boolean outparamboundness;
239 struct string_list* solspeclibraries; /* not owned */
240 struct string_list* sol8speclibraries; /* not owned */
241 struct string_list* linuxspeclibraries; /* not owned */
242 struct string_list* freebsdspeclibraries; /* not owned */
243 struct string_list* win32speclibraries; /* not owned */
244 const char *ttcn3preprocessor;
245 struct string_list* linkerlibraries; /* not owned */
246 struct string_list* additionalObjects; /* not owned */
247 struct string_list* linkerlibsearchpath; /* not owned */
248 char* generatorCommandOutput; /* not owned */
249 struct string2_list* target_placement_list; /* not owned */
250 };
251
252 /** Initializes structure \a makefile with empty lists and default settings. */
253 static void init_makefile_struct(struct makefile_struct *makefile)
254 {
255 makefile->project_name = NULL;
256 makefile->nTTCN3Modules = 0;
257 makefile->TTCN3Modules = NULL;
258 makefile->preprocess = FALSE;
259 makefile->nTTCN3PPModules = 0;
260 makefile->TTCN3PPModules = NULL;
261 makefile->TTCN3ModulesRegular = TRUE;
262 makefile->BaseTTCN3ModulesRegular = TRUE;
263 makefile->nTTCN3IncludeFiles = 0;
264 makefile->TTCN3IncludeFiles = NULL;
265 makefile->nASN1Modules = 0;
266 makefile->ASN1Modules = NULL;
267 makefile->ASN1ModulesRegular = TRUE;
268 makefile->BaseASN1ModulesRegular = TRUE;
269 makefile->nUserFiles = 0;
270 makefile->UserFiles = NULL;
271 makefile->UserHeadersRegular = TRUE;
272 makefile->UserSourcesRegular = TRUE;
273 makefile->BaseUserHeadersRegular = TRUE;
274 makefile->BaseUserSourcesRegular = TRUE;
275 makefile->nOtherFiles = 0;
276 makefile->OtherFiles = NULL;
277 makefile->central_storage = FALSE;
278 makefile->nBaseDirs = 0;
279 makefile->BaseDirs = NULL;
280 makefile->working_dir = get_working_dir();
281 makefile->gnu_make = FALSE;
282 makefile->single_mode = FALSE;
283 makefile->ets_name = NULL;
284 makefile->output_file = NULL;
285 makefile->force_overwrite = FALSE;
286 makefile->use_runtime_2 = FALSE;
287 makefile->dynamic = FALSE;
288 makefile->gcc_dep = FALSE;
289 makefile->code_splitting_mode = NULL;
290 makefile->coverage = FALSE;
291 makefile->tcov_file_name = NULL;
292 makefile->library = FALSE;
293 makefile->linkingStrategy = FALSE;
294 makefile->hierarchical = FALSE;
295 makefile->sub_project_dirs = NULL;
296 makefile->ttcn3_prep_includes = NULL;
297 makefile->prep_includes = NULL;
298 makefile->prep_defines = NULL;
299 makefile->outparamboundness = FALSE;
300 makefile->solspeclibraries = NULL;
301 makefile->sol8speclibraries = NULL;
302 makefile->linuxspeclibraries = NULL;
303 makefile->freebsdspeclibraries = NULL;
304 makefile->win32speclibraries = NULL;
305 makefile->linkerlibraries = NULL;
306 makefile->additionalObjects = NULL;
307 makefile->linkerlibsearchpath = NULL;
308 makefile->generatorCommandOutput = NULL;
309 makefile->target_placement_list = NULL;
310 }
311
312 /** Deallocates all memory associated with structure \a makefile. */
313 static void free_makefile_struct(const struct makefile_struct *makefile)
314 {
315 Free(makefile->project_name);
316 size_t i;
317 for (i = 0; i < makefile->nTTCN3Modules; i++) {
318 Free(makefile->TTCN3Modules[i].dir_name);
319 Free(makefile->TTCN3Modules[i].file_name);
320 Free(makefile->TTCN3Modules[i].module_name);
321 }
322 Free(makefile->TTCN3Modules);
323 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
324 Free(makefile->TTCN3PPModules[i].dir_name);
325 Free(makefile->TTCN3PPModules[i].file_name);
326 Free(makefile->TTCN3PPModules[i].module_name);
327 }
328 Free(makefile->TTCN3PPModules);
329 for (i = 0; i < makefile->nTTCN3IncludeFiles; i++)
330 Free(makefile->TTCN3IncludeFiles[i]);
331 Free(makefile->TTCN3IncludeFiles);
332 for (i = 0; i < makefile->nASN1Modules; i++) {
333 Free(makefile->ASN1Modules[i].dir_name);
334 Free(makefile->ASN1Modules[i].file_name);
335 Free(makefile->ASN1Modules[i].module_name);
336 }
337 Free(makefile->ASN1Modules);
338 for (i = 0; i < makefile->nUserFiles; i++) {
339 Free(makefile->UserFiles[i].dir_name);
340 Free(makefile->UserFiles[i].file_prefix);
341 Free(makefile->UserFiles[i].header_name);
342 Free(makefile->UserFiles[i].source_name);
343 }
344 Free(makefile->UserFiles);
345 for (i = 0; i < makefile->nOtherFiles; i++) Free(makefile->OtherFiles[i]);
346 Free(makefile->OtherFiles);
347 Free(makefile->BaseDirs);
348 Free(makefile->working_dir);
349 Free(makefile->ets_name);
350 Free(makefile->output_file);
351 Free(makefile->code_splitting_mode);
352 Free(makefile->tcov_file_name);
353 }
354
355 /** Displays the contents of structure \a makefile as debug messages. */
356 static void dump_makefile_struct(const struct makefile_struct *makefile,
357 unsigned level)
358 {
359 size_t i;
360 DEBUG(level, "Data used for Makefile generation:");
361 DEBUG(level + 1, "TTCN-3 project name: %s", makefile->project_name);
362 DEBUG(level + 1, "TTCN-3 modules: (%u pcs.)", makefile->nTTCN3Modules);
363 for (i = 0; i < makefile->nTTCN3Modules; i++) {
364 const struct module_struct *module = makefile->TTCN3Modules + i;
365 DEBUG(level + 2, "Module name: %s", module->module_name);
366 if (module->dir_name != NULL)
367 DEBUG(level + 3, "Directory: %s", module->dir_name);
368 DEBUG(level + 3, "File name: %s", module->file_name);
369 DEBUG(level + 3, "Follows the naming convention: %s",
370 module->is_regular ? "yes" : "no");
371 }
372 DEBUG(level + 1, "TTCN-3 preprocessing: %s",
373 makefile->preprocess ? "yes" : "no");
374 if (makefile->preprocess) {
375 DEBUG(level + 1, "TTCN-3 modules to be preprocessed: (%u pcs.)",
376 makefile->nTTCN3PPModules);
377 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
378 const struct module_struct *module = makefile->TTCN3PPModules + i;
379 DEBUG(level + 2, "Module name: %s", module->module_name);
380 if (module->dir_name != NULL)
381 DEBUG(level + 3, "Directory: %s", module->dir_name);
382 DEBUG(level + 3, "File name: %s", module->file_name);
383 DEBUG(level + 3, "Follows the naming convention: %s",
384 module->is_regular ? "yes" : "no");
385 }
386 DEBUG(level + 1, "TTCN-3 include files: (%u pcs.)",
387 makefile->nTTCN3IncludeFiles);
388 for (i = 0; i < makefile->nTTCN3IncludeFiles; i++)
389 DEBUG(level + 2, "File name: %s", makefile->TTCN3IncludeFiles[i]);
390 }
391 DEBUG(level + 1, "All local TTCN-3 modules follow the naming convention: %s",
392 makefile->TTCN3ModulesRegular ? "yes" : "no");
393 if (makefile->central_storage) DEBUG(level + 1, "All TTCN-3 modules from other "
394 "directories follow the naming convention: %s",
395 makefile->BaseTTCN3ModulesRegular ? "yes" : "no");
396 DEBUG(level + 1, "ASN.1 modules: (%u pcs.)", makefile->nASN1Modules);
397 for (i = 0; i < makefile->nASN1Modules; i++) {
398 const struct module_struct *module = makefile->ASN1Modules + i;
399 DEBUG(level + 2, "Module name: %s", module->module_name);
400 if (module->dir_name != NULL)
401 DEBUG(level + 3, "Directory: %s", module->dir_name);
402 DEBUG(level + 3, "File name: %s", module->file_name);
403 DEBUG(level + 3, "Follows the naming convention: %s",
404 module->is_regular ? "yes" : "no");
405 }
406 DEBUG(level + 1, "All local ASN.1 modules follow the naming convention: %s",
407 makefile->ASN1ModulesRegular ? "yes" : "no");
408 if (makefile->central_storage) DEBUG(level + 1, "All ASN.1 modules from other "
409 "directories follow the naming convention: %s",
410 makefile->BaseASN1ModulesRegular ? "yes" : "no");
411 DEBUG(level + 1, "User C/C++ modules: (%u pcs.)", makefile->nUserFiles);
412 for (i = 0; i < makefile->nUserFiles; i++) {
413 const struct user_struct *user = makefile->UserFiles + i;
414 DEBUG(level + 2, "File prefix: %s", user->file_prefix);
415 if (user->dir_name != NULL)
416 DEBUG(level + 3, "Directory: %s", user->dir_name);
417 if (user->header_name != NULL) {
418 DEBUG(level + 3, "Header file: %s", user->header_name);
419 DEBUG(level + 3, "Header file has .hh or .hpp suffix: %s",
420 user->has_hh_suffix ? "yes" : "no");
421 }
422 if (user->source_name != NULL) {
423 DEBUG(level + 3, "Source file: %s", user->source_name);
424 DEBUG(level + 3, "Source file has .cc or .cpp suffix: %s",
425 user->has_cc_suffix ? "yes" : "no");
426 DEBUG(level + 3, "Object file: %s.o", user->file_prefix);
427 }
428 }
429 DEBUG(level + 1, "All local C/C++ header files follow the naming "
430 "convention: %s", makefile->UserHeadersRegular ? "yes" : "no");
431 DEBUG(level + 1, "All local C/C++ source files follow the naming "
432 "convention: %s", makefile->UserSourcesRegular ? "yes" : "no");
433 if (makefile->central_storage) {
434 DEBUG(level + 1, "All C/C++ header files from other directories follow the "
435 "naming convention: %s", makefile->BaseUserHeadersRegular ? "yes" : "no");
436 DEBUG(level + 1, "All C/C++ source files from other directories follow the "
437 "naming convention: %s", makefile->BaseUserSourcesRegular ? "yes" : "no");
438 }
439 DEBUG(level + 1, "Other files: (%u pcs.)", makefile->nOtherFiles);
440 for (i = 0; i < makefile->nOtherFiles; i++)
441 DEBUG(level + 2, "File name: %s", makefile->OtherFiles[i]);
442 DEBUG(level + 1, "Use pre-compiled files from central storage: %s",
443 makefile->central_storage ? "yes" : "no");
444 if (makefile->central_storage) {
445 DEBUG(level + 1, "Directories of pre-compiled files: (%u pcs.)",
446 makefile->nBaseDirs);
447 for (i = 0; i < makefile->nBaseDirs; i++) {
448 const struct base_dir_struct *base_dir = makefile->BaseDirs + i;
449 DEBUG(level + 2, "Directory: %s", base_dir->dir_name);
450 DEBUG(level + 3, "Has TTCN-3/ASN.1 modules: %s",
451 base_dir->has_modules ? "yes" : "no");
452 }
453 }
454 DEBUG(level + 1, "Working directory: %s",
455 makefile->working_dir != NULL ? makefile->working_dir : "<unknown>");
456 DEBUG(level + 1, "GNU make: %s", makefile->gnu_make ? "yes" : "no");
457 DEBUG(level + 1, "Execution mode: %s",
458 makefile->single_mode ? "single" : "parallel");
459 DEBUG(level + 1, "Name of executable: %s",
460 makefile->ets_name != NULL ? makefile->ets_name : "<unknown>");
461 DEBUG(level + 1, "Output file: %s",
462 makefile->output_file != NULL ? makefile->output_file : "<unknown>");
463 DEBUG(level + 1, "Force overwrite: %s",
464 makefile->force_overwrite ? "yes" : "no");
465 DEBUG(level + 1, "Use function test runtime: %s",
466 makefile->use_runtime_2 ? "yes" : "no");
467 DEBUG(level + 1, "Use dynamic linking: %s",
468 makefile->dynamic ? "yes" : "no");
469 DEBUG(level + 1, "Code splitting mode: %s",
470 makefile->code_splitting_mode != NULL ?
471 makefile->code_splitting_mode : "<unknown>");
472 DEBUG(level + 1, "Code coverage file: %s",
473 makefile->tcov_file_name != NULL ?
474 makefile->tcov_file_name : "<unknown>");
475 #ifdef COVERAGE_BUILD
476 DEBUG(level + 1, "Enable coverage: %s", makefile->coverage ? "yes" : "no");
477 #endif
478 }
479
480 /** Returns the name of an existing file that is related to command line
481 * argument \a argument. Tries the given list of suffixes. NULL pointer is
482 * returned if no file was found. The returned string shall be deallocated
483 * by the caller. */
484 static char *get_file_name_for_argument(const char *argument)
485 {
486 static const char * const suffix_list[] = {
487 "", ".ttcnpp", ".ttcnin", ".ttcn", ".ttcn3", ".3mp", ".asn", ".asn1",
488 ".cc", ".c", ".cpp", ".hh", ".h",".hpp", ".cfg", ".prj", NULL
489 };
490 const char * const *suffix_ptr;
491 for (suffix_ptr = suffix_list; *suffix_ptr != NULL; suffix_ptr++) {
492 char *file_name = mputstr(mcopystr(argument), *suffix_ptr);
493 if (get_path_status(file_name) == PS_FILE) return file_name;
494 Free(file_name);
495 }
496 return NULL;
497 }
498
499 /** Converts \a path_name to an absolute directory using \a working_dir.
500 * NULL pointer is returned if \a path_name does not contain a directory or
501 * the resulting absolute directory is identical to \a working_dir.
502 * The returned string shall be deallocated by the caller. */
503 static char *get_dir_name(const char *path_name, const char *working_dir)
504 {
505 char *dir_name = get_dir_from_path(path_name);
506 if (dir_name != NULL) {
507 char *absolute_dir = get_absolute_dir(dir_name, working_dir);
508 Free(dir_name);
509 if (absolute_dir == NULL || working_dir == NULL) {
510 /* an error occurred */
511 return NULL;
512 } else if (!strcmp(absolute_dir, working_dir)) {
513 /* the directory is identical to the working dir */
514 Free(absolute_dir);
515 return NULL;
516 } else return absolute_dir;
517 } else return NULL;
518 }
519
520 /** Returns whether \a dirname1 and \a dirname2 contain the same (canonized
521 * absolute) directories. NULL pointer is handled in a special way: it is
522 * identical only to itself. */
523 static boolean is_same_directory(const char *dirname1, const char *dirname2)
524 {
525 if (dirname1 == NULL) {
526 if (dirname2 == NULL) return TRUE;
527 else return FALSE;
528 } else {
529 if (dirname2 == NULL) return FALSE;
530 else if (strcmp(dirname1, dirname2)) return FALSE;
531 else return TRUE;
532 }
533 }
534
535 /** Returns whether the file \a filename1 in directory \a dirname1 is identical
536 * to file \a filename2 in directory \a dirname2. Only the directory names can
537 * be NULL. */
538 static boolean is_same_file(const char *dirname1, const char *filename1,
539 const char *dirname2, const char *filename2)
540 {
541 /* first examine the file names for efficiency reasons */
542 if (strcmp(filename1, filename2)) return FALSE;
543 else return is_same_directory(dirname1, dirname2);
544 }
545
546 /** Determines whether the TTCN-3 or ASN.1 module identifiers \a module1 and
547 * \a module2 are the same. Characters '-' and '_' in module names are not
548 * distinguished. */
549 static boolean is_same_module(const char *module1, const char *module2)
550 {
551 size_t i;
552 for (i = 0; ; i++) {
553 switch (module1[i]) {
554 case '\0':
555 if (module2[i] == '\0') return TRUE;
556 else return FALSE;
557 case '-':
558 case '_':
559 if (module2[i] != '-' && module2[i] != '_') return FALSE;
560 break;
561 default:
562 if (module1[i] != module2[i]) return FALSE;
563 break;
564 }
565 }
566 return FALSE; /* to avoid warnings */
567 }
568
569 /** Determines the suffix (i.e. the character sequence following the last dot)
570 * of file or path name \a file_name. NULL pointer is returned if \a file_name
571 * does not contain any dot character or the last character of it is a dot.
572 * The suffix is not copied, the returned pointer points to the tail of
573 * \a file_name. */
574 static const char *get_suffix(const char *file_name)
575 {
576 size_t last_dot = (size_t)-1;
577 size_t i;
578 for (i = 0; file_name[i] != '\0'; i++)
579 if (file_name[i] == '.') last_dot = i;
580 if (last_dot == (size_t)-1 || file_name[last_dot + 1] == '\0') return NULL;
581 else return file_name + last_dot + 1;
582 }
583
584 /** Truncates the suffix (i.e. the last dot and the characters following it)
585 * from \a file_name and returns a copy of the prefix of \a file_name.
586 * If \a file_name does not have a suffix an exact copy of it is returned.
587 * The returned string shall be deallocated by the caller. */
588 static char *cut_suffix(const char *file_name)
589 {
590 char *ret_val;
591 size_t last_dot = (size_t)-1;
592 size_t i;
593 for (i = 0; file_name[i] != '\0'; i++)
594 if (file_name[i] == '.') last_dot = i;
595 ret_val = mcopystr(file_name);
596 if (last_dot != (size_t)-1) ret_val = mtruncstr(ret_val, last_dot);
597 return ret_val;
598 }
599
600 /** Determines the name of the preprocessed file from \a file_name.
601 * It is assumed that \a file_name has ttcnpp suffix.
602 * The returned string shall be deallocated by the caller. */
603 static char *get_preprocessed_file_name(const char *file_name)
604 {
605 char *ret_val = cut_suffix(file_name);
606 ret_val = mputstr(ret_val, ".ttcn");
607 return ret_val;
608 }
609
610 /** Check if any of the preprocessed ttcn file names with the preprocessed
611 * (TTCN-3) suffix is equal to any other file given in the \a makefile */
612 static void check_preprocessed_filename_collision(
613 struct makefile_struct *makefile)
614 {
615 size_t i;
616 if (makefile->nTTCN3PPModules == 0) {
617 WARNING("TTCN-3 preprocessing (option `-p') is enabled, but no TTCN-3 "
618 "files to be preprocessed were given for the Makefile.");
619 }
620 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
621 const struct module_struct *pp_module = makefile->TTCN3PPModules + i;
622 /* name of the intermediate preprocessed file */
623 char *preprocessed_name = get_preprocessed_file_name(pp_module->file_name);
624 size_t j;
625 for (j = 0; j < makefile->nTTCN3Modules; j++) {
626 struct module_struct *module = makefile->TTCN3Modules + j;
627 if (is_same_file(pp_module->dir_name, preprocessed_name,
628 module->dir_name, module->file_name)) {
629 if (is_same_module(pp_module->module_name, module->module_name)) {
630 /* same file with the same module */
631 char *pp_pathname = compose_path_name(pp_module->dir_name,
632 pp_module->file_name);
633 char *m_pathname = compose_path_name(module->dir_name,
634 module->file_name);
635 WARNING("File `%s' containing TTCN-3 module `%s' is generated by "
636 "the preprocessor from `%s'. Removing the file from the list of "
637 "normal TTCN-3 modules.", m_pathname, module->module_name,
638 pp_pathname);
639 Free(pp_pathname);
640 Free(m_pathname);
641 Free(module->dir_name);
642 Free(module->file_name);
643 Free(module->module_name);
644 makefile->nTTCN3Modules--;
645 memmove(module, module + 1, (makefile->nTTCN3Modules - j) *
646 sizeof(*makefile->TTCN3Modules));
647 makefile->TTCN3Modules =
648 (struct module_struct*)Realloc(makefile->TTCN3Modules,
649 makefile->nTTCN3Modules * sizeof(*makefile->TTCN3Modules));
650 } else {
651 /* same file with different module */
652 char *pp_pathname = compose_path_name(pp_module->dir_name,
653 pp_module->file_name);
654 char *m_pathname = compose_path_name(module->dir_name,
655 module->file_name);
656 ERROR("Preprocessed intermediate file of `%s' (module `%s') clashes "
657 "with file `%s' containing TTCN-3 module `%s'.", pp_pathname,
658 pp_module->module_name, m_pathname, module->module_name);
659 Free(pp_pathname);
660 Free(m_pathname);
661 }
662 } else if (is_same_module(pp_module->module_name, module->module_name)) {
663 /* different file with the same module */
664 char *pp_pathname = compose_path_name(pp_module->dir_name,
665 pp_module->file_name);
666 char *m_pathname = compose_path_name(module->dir_name,
667 module->file_name);
668 ERROR("Both files `%s' and `%s' contain TTCN-3 module `%s'.",
669 pp_pathname, m_pathname, pp_module->module_name);
670 Free(pp_pathname);
671 Free(m_pathname);
672 }
673 }
674 for (j = 0; j < makefile->nASN1Modules; j++) {
675 struct module_struct *module = makefile->ASN1Modules + j;
676 if (is_same_file(pp_module->dir_name, preprocessed_name,
677 module->dir_name, module->file_name)) {
678 char *pp_pathname = compose_path_name(pp_module->dir_name,
679 pp_module->file_name);
680 char *m_pathname = compose_path_name(module->dir_name,
681 module->file_name);
682 ERROR("Preprocessed intermediate file of `%s' (module `%s') clashes "
683 "with file `%s' containing ASN.1 module `%s'.", pp_pathname,
684 pp_module->module_name, m_pathname, module->module_name);
685 Free(pp_pathname);
686 Free(m_pathname);
687 }
688 }
689 for (j = 0; j < makefile->nOtherFiles; j++) {
690 char *dir_name = get_dir_name(makefile->OtherFiles[j],
691 makefile->working_dir);
692 char *file_name = get_file_from_path(makefile->OtherFiles[j]);
693 if (is_same_file(pp_module->dir_name, preprocessed_name, dir_name,
694 file_name)) {
695 char *pp_pathname = compose_path_name(pp_module->dir_name,
696 pp_module->file_name);
697 ERROR("Preprocessed intermediate file of `%s' (module `%s') clashes "
698 "with other file `%s'.", pp_pathname, pp_module->module_name,
699 makefile->OtherFiles[j]);
700 Free(pp_pathname);
701 }
702 Free(dir_name);
703 Free(file_name);
704 }
705 Free(preprocessed_name);
706 }
707 }
708
709 /** Checks the name clash between existing module \a module and newly added
710 * module with parameters \a path_name, \a dir_name, \a file_name,
711 * \a module_name. Both the existing and the new module shall be of the same
712 * kind, parameter \a kind shall contain the respective string (either "ASN.1"
713 * or "TTCN-3"). If a clash is found the parameters of the new module except
714 * \a path_name are deallocated and TRUE is returned. Otherwise FALSE is
715 * returned. */
716 static boolean check_module_clash_same(const struct module_struct *module,
717 const char *kind, const char *path_name, char *dir_name, char *file_name,
718 char *module_name)
719 {
720 if (is_same_module(module_name, module->module_name)) {
721 if (is_same_file(dir_name, file_name,
722 module->dir_name, module->file_name)) {
723 /* the same file was given twice: just issue a warning */
724 WARNING("File `%s' was given more than once for the Makefile.",
725 path_name);
726 } else {
727 /* two different files contain the same module: this cannot be
728 * resolved as the generated C++ files will clash */
729 char *path_name1 = compose_path_name(module->dir_name,
730 module->file_name);
731 char *path_name2 = compose_path_name(dir_name, file_name);
732 ERROR("Both files `%s' and `%s' contain %s module `%s'.",
733 path_name1, path_name2, kind, module_name);
734 Free(path_name1);
735 Free(path_name2);
736 }
737 Free(file_name);
738 Free(dir_name);
739 Free(module_name);
740 return TRUE;
741 } else return FALSE;
742 }
743
744 /** Checks the name clash between existing module \a module and newly added
745 * module with parameters \a dir_name, \a file_name, \a module_name. The two
746 * modules shall be of different kinds (one is ASN.1, the other is TTCN-3).
747 * Parameters \a kind1 and \a kind2 shall contain the respective strings. If a
748 * clash is found the parameters of the new module are deallocated and TRUE is
749 * returned. Otherwise FALSE is returned. */
750 static boolean check_module_clash_different(const struct module_struct *module,
751 const char *kind1, char *dir_name, char *file_name, char *module_name,
752 const char *kind2)
753 {
754 if (is_same_module(module_name, module->module_name)) {
755 /* two different files contain the same module: this cannot be resolved
756 * as the generated C++ files will clash */
757 char *path_name1 = compose_path_name(module->dir_name, module->file_name);
758 char *path_name2 = compose_path_name(dir_name, file_name);
759 ERROR("File `%s' containing %s module `%s' and file `%s' containing "
760 "%s module `%s' cannot be used together in the same Makefile.",
761 path_name1, kind1, module->module_name, path_name2, kind2, module_name);
762 Free(path_name1);
763 Free(path_name2);
764 Free(file_name);
765 Free(dir_name);
766 Free(module_name);
767 return TRUE;
768 } else return FALSE;
769 }
770
771 /** Adds a TTCN-3 module to Makefile descriptor structure \a makefile.
772 * The name of the TTCN-3 source file is \a path_name, the module identifier
773 * is \a module_name. It is checked whether a file or module with the same name
774 * already exists in \a makefile and an appropriate warning or error is
775 * reported. */
776 static void add_ttcn3_module(struct makefile_struct *makefile,
777 const char *path_name, char *module_name)
778 {
779 struct module_struct *module;
780 char *dir_name = get_dir_name(path_name, makefile->working_dir);
781 char *file_name = get_file_from_path(path_name);
782 const char *suffix = get_suffix(file_name);
783 size_t i;
784 boolean is_preprocessed = FALSE;
785
786 if (suffix != NULL) {
787 if (!strcmp(suffix, "ttcnpp")) {
788 if (makefile->preprocess) is_preprocessed = TRUE;
789 else WARNING("The suffix of TTCN-3 file `%s' indicates that it should be "
790 "preprocessed, but TTCN-3 preprocessing is not enabled. The file "
791 "will be added to the list of normal TTCN-3 modules in the Makefile.",
792 path_name);
793 } else if (!strcmp(suffix, "ttcnin")) {
794 WARNING("The suffix of file `%s' indicates that it should be a "
795 "preprocessor include file, but it contains a TTCN-3 module named `%s'. "
796 "The file will be added to the list of normal TTCN-3 modules in the "
797 "Makefile.", path_name, module_name);
798 }
799 }
800
801 for (i = 0; i < makefile->nASN1Modules; i++) {
802 if (check_module_clash_different(makefile->ASN1Modules + i, "ASN.1",
803 dir_name, file_name, module_name, "TTCN-3")) return;
804 }
805 /* never entered if suffix is NULL */
806 if (is_preprocessed) {
807 char *file_prefix;
808 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
809 if (check_module_clash_same(makefile->TTCN3PPModules + i, "TTCN-3",
810 path_name, dir_name, file_name, module_name)) return;
811 }
812 /* clashes with normal TTCN-3 modules will be checked (and maybe resolved)
813 * in \a check_preprocessed_filename_collision() */
814 /* add it to the list of TTCN-3 modules to be preprocessed */
815 makefile->TTCN3PPModules = (struct module_struct*)
816 Realloc(makefile->TTCN3PPModules,
817 (makefile->nTTCN3PPModules + 1) * sizeof(*makefile->TTCN3PPModules));
818 module = makefile->TTCN3PPModules + makefile->nTTCN3PPModules;
819 makefile->nTTCN3PPModules++;
820 module->dir_name = dir_name;
821 module->file_name = file_name;
822 module->module_name = module_name;
823 file_prefix = cut_suffix(file_name);
824 if (!strcmp(file_prefix, module_name)) module->is_regular = TRUE;
825 else module->is_regular = FALSE;
826 Free(file_prefix);
827 } else {
828 /* the file is not preprocessed */
829 for (i = 0; i < makefile->nTTCN3Modules; i++) {
830 if (check_module_clash_same(makefile->TTCN3Modules + i, "TTCN-3",
831 path_name, dir_name, file_name, module_name)) return;
832 }
833 /* clashes with preprocessed TTCN-3 modules will be checked (and maybe
834 * resolved) in \a check_preprocessed_filename_collision() */
835 /* add it to the list of normal TTCN-3 modules */
836 makefile->TTCN3Modules = (struct module_struct*)
837 Realloc(makefile->TTCN3Modules,
838 (makefile->nTTCN3Modules + 1) * sizeof(*makefile->TTCN3Modules));
839 module = makefile->TTCN3Modules + makefile->nTTCN3Modules;
840 makefile->nTTCN3Modules++;
841 module->dir_name = dir_name;
842 module->file_name = file_name;
843 module->module_name = module_name;
844 if (suffix != NULL && !strcmp(suffix, "ttcn")) {
845 char *file_prefix = cut_suffix(file_name);
846 if (!strcmp(file_prefix, module_name)) module->is_regular = TRUE;
847 else module->is_regular = FALSE;
848 Free(file_prefix);
849 } else {
850 module->is_regular = FALSE;
851 }
852 }
853 }
854
855 /** ASN.1 filename shall contain no hyphen */
856 static boolean is_valid_asn1_filename(const char* file_name)
857 {
858 if (0 == strchr(file_name, '-')) {
859 return TRUE;
860 }
861 return FALSE;
862 }
863
864 /** Adds an ASN.1 module to Makefile descriptor structure \a makefile.
865 * The name of the ASN.1 source file is \a path_name, the module identifier
866 * is \a module_name. It is checked whether a file or module with the same name
867 * already exists in \a makefile and an appropriate warning or error is
868 * reported. */
869 static void add_asn1_module(struct makefile_struct *makefile,
870 const char *path_name, char *module_name)
871 {
872 struct module_struct *module;
873 char *dir_name = get_dir_name(path_name, makefile->working_dir);
874 char *file_name = get_file_from_path(path_name);
875 const char *suffix = get_suffix(file_name);
876 size_t i;
877 for (i = 0; i < makefile->nASN1Modules; i++) {
878 if (check_module_clash_same(makefile->ASN1Modules + i, "ASN.1", path_name,
879 dir_name, file_name, module_name)) return;
880 }
881 for (i = 0; i < makefile->nTTCN3Modules; i++) {
882 if (check_module_clash_different(makefile->TTCN3Modules + i, "TTCN-3",
883 dir_name, file_name, module_name, "ASN.1")) return;
884 }
885 if (makefile->preprocess) {
886 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
887 if (check_module_clash_different(makefile->TTCN3PPModules + i, "TTCN-3",
888 dir_name, file_name, module_name, "ASN.1")) return;
889 }
890 }
891 makefile->ASN1Modules = (struct module_struct*)
892 Realloc(makefile->ASN1Modules,
893 (makefile->nASN1Modules + 1) * sizeof(*makefile->ASN1Modules));
894 module = makefile->ASN1Modules + makefile->nASN1Modules;
895 makefile->nASN1Modules++;
896 module->dir_name = dir_name;
897 module->file_name = file_name;
898 module->module_name = module_name;
899 if (suffix != NULL && !strcmp(suffix, "asn")) {
900 char *file_prefix = cut_suffix(file_name);
901 /* replace all '_' with '-' in file name prefix */
902 for (i = 0; file_prefix[i] != '\0'; i++)
903 if (file_prefix[i] == '_') file_prefix[i] = '-';
904 if (!strcmp(file_prefix, module_name)) module->is_regular = TRUE;
905 else module->is_regular = FALSE;
906 Free(file_prefix);
907 } else {
908 module->is_regular = FALSE;
909 }
910 }
911
912 /** Adds the file named \a path_name to the list of files pointed by \a list_ptr
913 * and \a list_size. The suffix or contents of \a path_name are not examined,
914 * only duplicate entries are checked. In case of duplicate entries warning is
915 * reported only if argument \a report_warning is set to TRUE. */
916 static void add_path_to_list(size_t *list_size, char ***list_ptr,
917 const char *path_name, const char *working_dir, boolean report_warning)
918 {
919 size_t i;
920 char *dir_name = get_dir_name(path_name, working_dir);
921 char *file_name = get_file_from_path(path_name);
922 char *canonized_path_name = compose_path_name(dir_name, file_name);
923 Free(dir_name);
924 Free(file_name);
925 for (i = 0; i < *list_size; i++) {
926 if (!strcmp(canonized_path_name, (*list_ptr)[i])) {
927 if (report_warning) WARNING("File `%s' was given more than once for the "
928 "Makefile.", path_name);
929 Free(canonized_path_name);
930 return;
931 }
932 }
933 *list_ptr = (char**)Realloc(*list_ptr, (*list_size + 1) * sizeof(**list_ptr));
934 (*list_ptr)[*list_size] = canonized_path_name;
935 (*list_size)++;
936 }
937
938 /** Adds a C/C++ header or source file or an other file named \a path_name to
939 * Makefile descriptor structure \a makefile. The file is classified based on
940 * its suffix and not by content. If the file clashes with existing files or
941 * modules the appropriate warning or error is generated. */
942 static void add_user_file(struct makefile_struct *makefile,
943 const char *path_name)
944 {
945 const char *suffix = get_suffix(path_name);
946 if (suffix != NULL) {
947 if (!strcmp(suffix, "ttcn") || !strcmp(suffix, "ttcn3") ||
948 !strcmp(suffix, "3mp") || !strcmp(suffix, "ttcnpp")) {
949 /* The file content was already checked. Since it doesn't look like
950 * a valid TTCN-3 file, these suffixes are suspect */
951 WARNING("File `%s' does not contain a valid TTCN-3 module. "
952 "It will be added to the Makefile as other file.", path_name);
953 }
954 else if (!strcmp(suffix, "ttcnin")) {
955 /* this is a TTCN-3 include file */
956 if (makefile->preprocess) {
957 add_path_to_list(&makefile->nTTCN3IncludeFiles,
958 &makefile->TTCN3IncludeFiles, path_name, makefile->working_dir, TRUE);
959 return;
960 }
961 else {
962 WARNING("The suffix of file `%s' indicates that it is a TTCN-3 "
963 "include file, but TTCN-3 preprocessing is not enabled. The file "
964 "will be added to the Makefile as other file.", path_name);
965 }
966 }
967 else if (!strcmp(suffix, "asn") || !strcmp(suffix, "asn1")) {
968 /* The file content was already checked. Since it doesn't look like
969 * a valid ASN.1 file, these suffixes are suspect */
970 WARNING("File `%s' does not contain a valid ASN.1 module. "
971 "It will be added to the Makefile as other file.", path_name);
972 }
973 else if (!strcmp(suffix, "cc") || !strcmp(suffix, "c") || !strcmp(suffix, "cpp")) {
974 /* this is a source file */
975 char *dir_name = get_dir_name(path_name, makefile->working_dir);
976 char *file_name = get_file_from_path(path_name);
977 char *file_prefix = cut_suffix(file_name);
978 struct user_struct *user;
979 size_t i;
980 for (i = 0; i < makefile->nUserFiles; i++) {
981 user = makefile->UserFiles + i;
982 if (!strcmp(file_prefix, user->file_prefix)) {
983 if (user->source_name != NULL) {
984 /* the source file is already present */
985 if (is_same_file(dir_name, file_name,
986 user->dir_name, user->source_name)) {
987 WARNING("File `%s' was given more than once for the Makefile.", path_name);
988 }
989 else {
990 char *path_name1 = compose_path_name(user->dir_name, user->source_name);
991 char *path_name2 = compose_path_name(dir_name, file_name);
992 ERROR("C/C++ source files `%s' and `%s' cannot be used together "
993 "in the same Makefile.", path_name1, path_name2);
994 Free(path_name1);
995 Free(path_name2);
996 }
997 }
998 else {
999 /* a header file with the same prefix is already present */
1000 if (is_same_directory(dir_name, user->dir_name)) {
1001 user->source_name = file_name;
1002 file_name = NULL;
1003 if (!strcmp(suffix, "cc") || !strcmp(suffix, "cpp"))
1004 user->has_cc_suffix = TRUE;
1005 }
1006 else {
1007 char *path_name1 = compose_path_name(dir_name, file_name);
1008 char *path_name2 = compose_path_name(user->dir_name, user->header_name);
1009 ERROR("C/C++ source file `%s' cannot be used together with "
1010 "header file `%s' in the same Makefile.", path_name1,
1011 path_name2);
1012 Free(path_name1);
1013 Free(path_name2);
1014 }
1015 }
1016 Free(dir_name);
1017 Free(file_name);
1018 Free(file_prefix);
1019 return;
1020 }
1021 }
1022 makefile->UserFiles = (struct user_struct*)Realloc(makefile->UserFiles,
1023 (makefile->nUserFiles + 1) * sizeof(*makefile->UserFiles));
1024 user = makefile->UserFiles + makefile->nUserFiles;
1025 makefile->nUserFiles++;
1026 user->dir_name = dir_name;
1027 user->file_prefix = file_prefix;
1028 user->header_name = NULL;
1029 user->source_name = file_name;
1030 user->has_hh_suffix = FALSE;
1031 if (!strcmp(suffix, "cc") || !strcmp(suffix, "cpp")) user->has_cc_suffix = TRUE;
1032 else user->has_cc_suffix = FALSE;
1033 return;
1034 }
1035 else if (!strcmp(suffix, "hh") || !strcmp(suffix, "h")) {
1036 /* this is a header file */
1037 char *dir_name = get_dir_name(path_name, makefile->working_dir);
1038 char *file_name = get_file_from_path(path_name);
1039 char *file_prefix = cut_suffix(file_name);
1040 struct user_struct *user;
1041 size_t i;
1042 for (i = 0; i < makefile->nUserFiles; i++) {
1043 user = makefile->UserFiles + i;
1044 if (!strcmp(file_prefix, user->file_prefix)) {
1045 if (user->header_name != NULL) {
1046 /* the header file is already present */
1047 if (is_same_file(dir_name, file_name, user->dir_name, user->header_name)) {
1048 WARNING("File `%s' was given more than once for the Makefile.", path_name);
1049 }
1050 else {
1051 char *path_name1 = compose_path_name(user->dir_name, user->header_name);
1052 char *path_name2 = compose_path_name(dir_name, file_name);
1053 ERROR("C/C++ header files `%s' and `%s' cannot be used together "
1054 "in the same Makefile.", path_name1, path_name2);
1055 Free(path_name1);
1056 Free(path_name2);
1057 }
1058 }
1059 else {
1060 /* a source file with the same prefix is already present */
1061 if (is_same_directory(dir_name, user->dir_name)) {
1062 user->header_name = file_name;
1063 file_name = NULL;
1064 if (!strcmp(suffix, "hh") || !strcmp(suffix, "hpp"))
1065 user->has_hh_suffix = TRUE;
1066 }
1067 else {
1068 char *path_name1 = compose_path_name(dir_name, file_name);
1069 char *path_name2 = compose_path_name(user->dir_name, user->source_name);
1070 ERROR("C/C++ header file `%s' cannot be used together with "
1071 "source file `%s' in the same Makefile.", path_name1, path_name2);
1072 Free(path_name1);
1073 Free(path_name2);
1074 }
1075 }
1076 Free(dir_name);
1077 Free(file_name);
1078 Free(file_prefix);
1079 return;
1080 }
1081 }
1082 makefile->UserFiles = (struct user_struct*)Realloc(makefile->UserFiles,
1083 (makefile->nUserFiles + 1) * sizeof(*makefile->UserFiles));
1084 user = makefile->UserFiles + makefile->nUserFiles;
1085 makefile->nUserFiles++;
1086 user->dir_name = dir_name;
1087 user->file_prefix = file_prefix;
1088 user->header_name = file_name;
1089 user->source_name = NULL;
1090 if (!strcmp(suffix, "hh") || !strcmp(suffix, "hpp")) user->has_hh_suffix = TRUE;
1091 else user->has_hh_suffix = FALSE;
1092 user->has_cc_suffix = FALSE;
1093 return;
1094 }
1095 } /* end if (suffix != NULL) */
1096 /* treat the file as other file if it was not handled yet */
1097 add_path_to_list(&makefile->nOtherFiles, &makefile->OtherFiles, path_name,
1098 makefile->working_dir, TRUE);
1099 }
1100
1101 /** Removes the generated C++ header and/or source files of module \a module
1102 * from Makefile descriptor structure \a makefile. A warning is displayed if
1103 * such file is found. */
1104 static void drop_generated_files(struct makefile_struct *makefile,
1105 const struct module_struct *module)
1106 {
1107 char *module_name = mcopystr(module->module_name);
1108 size_t i;
1109 /* transform all '-' characters in ASN.1 module name to '_' */
1110 for (i = 0; module_name[i] != '\0'; i++)
1111 if (module_name[i] == '-') module_name[i] = '_';
1112 for (i = 0; i < makefile->nUserFiles; i++) {
1113 struct user_struct *user = makefile->UserFiles + i;
1114 if (!strcmp(module_name, user->file_prefix)) {
1115 char *m_pathname = compose_path_name(module->dir_name, module->file_name);
1116 /** Note: if central storage is used the generated C++ files are placed
1117 * into the same directory as the TTCN-3/ASN.1 modules, otherwise the
1118 * files are generated into the working directory. */
1119 boolean is_same_dir = is_same_directory(user->dir_name,
1120 makefile->central_storage ? module->dir_name : NULL);
1121 if (user->header_name != NULL) {
1122 char *u_pathname = compose_path_name(user->dir_name,
1123 user->header_name);
1124 if (is_same_dir && user->has_hh_suffix) {
1125 WARNING("Header file `%s' is generated from module `%s' (file `%s'). "
1126 "Removing it from the list of user files.", u_pathname,
1127 module->module_name, m_pathname);
1128 } else {
1129 ERROR("Header file `%s' cannot be used together with module `%s' "
1130 "(file `%s') in the same Makefile.", u_pathname,
1131 module->module_name, m_pathname);
1132 }
1133 Free(u_pathname);
1134 }
1135 if (user->source_name != NULL) {
1136 char *u_pathname = compose_path_name(user->dir_name,
1137 user->source_name);
1138 if (is_same_dir && user->has_cc_suffix) {
1139 WARNING("Source file `%s' is generated from module `%s' (file "
1140 "`%s'). Removing it from the list of user files.", u_pathname,
1141 module->module_name, m_pathname);
1142 } else {
1143 ERROR("Source file `%s' cannot be used together with module "
1144 "`%s' (file `%s') in the same Makefile.", u_pathname,
1145 module->module_name, m_pathname);
1146 }
1147 Free(u_pathname);
1148 }
1149 Free(m_pathname);
1150 Free(user->dir_name);
1151 Free(user->file_prefix);
1152 Free(user->header_name);
1153 Free(user->source_name);
1154 makefile->nUserFiles--;
1155 memmove(user, user + 1, (makefile->nUserFiles - i) *
1156 sizeof(*makefile->UserFiles));
1157 makefile->UserFiles = (struct user_struct*)Realloc(makefile->UserFiles,
1158 makefile->nUserFiles * sizeof(*makefile->UserFiles));
1159 break;
1160 }
1161 }
1162 Free(module_name);
1163 }
1164
1165 /** Drops all C++ header and source files of the Makefile descriptor structure
1166 * \a makefile that are generated from its TTCN-3 or ASN.1 modules. */
1167 static void filter_out_generated_files(struct makefile_struct *makefile)
1168 {
1169 size_t i;
1170 for (i = 0; i < makefile->nTTCN3Modules; i++) {
1171 drop_generated_files(makefile, makefile->TTCN3Modules + i);
1172 }
1173 if (makefile->preprocess) {
1174 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
1175 drop_generated_files(makefile, makefile->TTCN3PPModules + i);
1176 }
1177 }
1178 for (i = 0; i < makefile->nASN1Modules; i++) {
1179 drop_generated_files(makefile, makefile->ASN1Modules + i);
1180 }
1181 }
1182
1183 /** Completes the list of user C/C++ header and source files in \a makefile.
1184 * If only the source file was given the function looks for the corresponding
1185 * header file or vice versa. */
1186 static void complete_user_files(const struct makefile_struct *makefile)
1187 {
1188 size_t i;
1189 for (i = 0; i < makefile->nUserFiles; i++) {
1190 struct user_struct *user = makefile->UserFiles + i;
1191 if (user->header_name == NULL) {
1192 static const char * const suffix_list[] = { "hh", "h", "hpp", NULL };
1193 const char * const *suffix_ptr;
1194 for (suffix_ptr = suffix_list; *suffix_ptr != NULL; suffix_ptr++) {
1195 char *file_name = mprintf("%s.%s", user->file_prefix, *suffix_ptr);
1196 char *path_name = compose_path_name(user->dir_name, file_name);
1197 if (get_path_status(path_name) == PS_FILE) {
1198 Free(path_name);
1199 user->header_name = file_name;
1200 if (!strcmp(*suffix_ptr, "hh") || !strcmp(*suffix_ptr, "hpp"))
1201 user->has_hh_suffix = TRUE;
1202 break;
1203 }
1204 Free(file_name);
1205 Free(path_name);
1206 }
1207 }
1208 else if (user->source_name == NULL) {
1209 static const char * const suffix_list[] = { "cc", "c", "cpp", NULL };
1210 const char * const *suffix_ptr;
1211 for (suffix_ptr = suffix_list; *suffix_ptr != NULL; suffix_ptr++) {
1212 char *file_name = mprintf("%s.%s", user->file_prefix, *suffix_ptr);
1213 char *path_name = compose_path_name(user->dir_name, file_name);
1214 if (get_path_status(path_name) == PS_FILE) {
1215 Free(path_name);
1216 user->source_name = file_name;
1217 if (!strcmp(*suffix_ptr, "cc") || !strcmp(*suffix_ptr, "cpp"))
1218 user->has_cc_suffix = TRUE;
1219 break;
1220 }
1221 Free(file_name);
1222 Free(path_name);
1223 }
1224 }
1225 }
1226 }
1227
1228 /** Converts the directory name pointed by \a dir_ptr to a relative pathname
1229 * based on \a working_dir. The original directory name is deallocated and
1230 * replaced with a new string. Nothing happens if \a dir_ptr points to NULL. */
1231 static void replace_dir_with_relative(char **dir_ptr, const char *working_dir)
1232 {
1233 if (*dir_ptr != NULL) {
1234 char *rel_dir = get_relative_dir(*dir_ptr, working_dir);
1235 Free(*dir_ptr);
1236 *dir_ptr = rel_dir;
1237 }
1238 }
1239
1240 /** Converts the directory part of path name pointed by \a path_ptr to a relative
1241 * pathname based on \a working_dir. The original path name is deallocated and
1242 * replaced with a new string. */
1243 static void convert_path_to_relative(char **path_ptr, const char *working_dir)
1244 {
1245 char *dir_name = get_dir_name(*path_ptr, working_dir);
1246 if (dir_name != NULL) {
1247 char *file_name = get_file_from_path(*path_ptr);
1248 replace_dir_with_relative(&dir_name, working_dir);
1249 Free(*path_ptr);
1250 *path_ptr = compose_path_name(dir_name, file_name);
1251 Free(file_name);
1252 Free(dir_name);
1253 }
1254 }
1255
1256 /** Converts all directories used by the Makefile descriptor structure
1257 * \a makefile to relative pathnames based on the working directory stored in
1258 * \a makefile. */
1259 static void convert_dirs_to_relative(struct makefile_struct *makefile)
1260 {
1261 size_t i;
1262 for (i = 0; i < makefile->nTTCN3Modules; i++) {
1263 replace_dir_with_relative(&makefile->TTCN3Modules[i].dir_name,
1264 makefile->working_dir);
1265 }
1266 if (makefile->preprocess) {
1267 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
1268 replace_dir_with_relative(&makefile->TTCN3PPModules[i].dir_name,
1269 makefile->working_dir);
1270 }
1271 for (i = 0; i < makefile->nTTCN3IncludeFiles; i++) {
1272 convert_path_to_relative(makefile->TTCN3IncludeFiles + i,
1273 makefile->working_dir);
1274 }
1275 }
1276 for (i = 0; i < makefile->nASN1Modules; i++) {
1277 replace_dir_with_relative(&makefile->ASN1Modules[i].dir_name,
1278 makefile->working_dir);
1279 }
1280 for (i = 0; i < makefile->nUserFiles; i++) {
1281 replace_dir_with_relative(&makefile->UserFiles[i].dir_name,
1282 makefile->working_dir);
1283 }
1284 for (i = 0; i < makefile->nOtherFiles; i++) {
1285 convert_path_to_relative(makefile->OtherFiles + i, makefile->working_dir);
1286 }
1287 if (makefile->ets_name != NULL)
1288 convert_path_to_relative(&makefile->ets_name, makefile->working_dir);
1289 }
1290
1291 /* Returns whether the string \a file_name contains special characters. */
1292 static boolean has_special_chars(const char *file_name)
1293 {
1294 if (file_name != NULL) {
1295 size_t i;
1296 for (i = 0; ; i++) {
1297 int c = (unsigned char)file_name[i];
1298 switch (c) {
1299 case '\0':
1300 return FALSE;
1301 case ' ':
1302 case '*':
1303 case '?':
1304 case '[':
1305 case ']':
1306 case '<':
1307 case '=':
1308 case '>':
1309 case '|':
1310 case '&':
1311 case '$':
1312 case '%':
1313 case '{':
1314 case '}':
1315 case ';':
1316 case ':':
1317 case '(':
1318 case ')':
1319 case '#':
1320 case '!':
1321 case '\'':
1322 case '"':
1323 case '`':
1324 case '\\':
1325 return TRUE;
1326 default:
1327 if (!isascii(c) || !isprint(c)) return TRUE;
1328 break;
1329 }
1330 }
1331 }
1332 return FALSE;
1333 }
1334
1335 /** Checks whether the path name composed of \a dir_name and \a file_name
1336 * contains special characters that are not allowed in the Makefile. Parameter
1337 * \a what contains the description of the corresponding file. */
1338 static void check_special_chars_in_path(const char *dir_name,
1339 const char *file_name, const char *what)
1340 {
1341 if (has_special_chars(dir_name) || has_special_chars(file_name)) {
1342 char *path_name = compose_path_name(dir_name, file_name);
1343 ERROR("The name of %s `%s' contains special characters that cannot be "
1344 "handled properly by the `make' utility and/or the shell.", what,
1345 path_name);
1346 Free(path_name);
1347 }
1348 }
1349
1350 /** Checks whether the directory names or file names that will be used in the
1351 * generated Makefile contain special characters that cannot be handled by the
1352 * "make" utility. */
1353 static void check_special_chars(const struct makefile_struct *makefile)
1354 {
1355 size_t i;
1356 for (i = 0; i < makefile->nTTCN3Modules; i++) {
1357 check_special_chars_in_path(makefile->TTCN3Modules[i].dir_name,
1358 makefile->TTCN3Modules[i].file_name, "TTCN-3 file");
1359 }
1360 if (makefile->preprocess) {
1361 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
1362 check_special_chars_in_path(makefile->TTCN3PPModules[i].dir_name,
1363 makefile->TTCN3PPModules[i].file_name,
1364 "TTCN-3 file to be preprocessed");
1365 }
1366 }
1367 for (i = 0; i < makefile->nASN1Modules; i++) {
1368 check_special_chars_in_path(makefile->ASN1Modules[i].dir_name,
1369 makefile->ASN1Modules[i].file_name, "ASN.1 file");
1370 }
1371 for (i = 0; i < makefile->nUserFiles; i++) {
1372 const struct user_struct *user = makefile->UserFiles + i;
1373 if (user->source_name != NULL)
1374 check_special_chars_in_path(user->dir_name, user->source_name,
1375 "C/C++ source file");
1376 else check_special_chars_in_path(user->dir_name, user->header_name,
1377 "C/C++ header file");
1378 }
1379 for (i = 0; i < makefile->nOtherFiles; i++) {
1380 check_special_chars_in_path(NULL, makefile->OtherFiles[i], "other file");
1381 }
1382 }
1383
1384 /** Adds base directory \a dir_name to Makefile descriptor structure
1385 * \a makefile. Flag \a has_modules indicates whether \a dir_name contains
1386 * TTCN-3 and/or ASN.1 modules. The new directory is ignored if it is already
1387 * added to \a makefile. */
1388 static void add_base_dir(struct makefile_struct *makefile,
1389 const char *dir_name, boolean has_modules)
1390 {
1391 struct base_dir_struct *base_dir;
1392 if (dir_name != NULL) {
1393 size_t i;
1394 for (i = 0; i < makefile->nBaseDirs; i++) {
1395 base_dir = makefile->BaseDirs + i;
1396 if (!strcmp(dir_name, base_dir->dir_name)) {
1397 if (has_modules) base_dir->has_modules = TRUE;
1398 return;
1399 }
1400 }
1401 makefile->BaseDirs = (struct base_dir_struct*)Realloc(makefile->BaseDirs,
1402 (makefile->nBaseDirs + 1) * sizeof(*makefile->BaseDirs));
1403 base_dir = makefile->BaseDirs + makefile->nBaseDirs;
1404 makefile->nBaseDirs++;
1405 base_dir->dir_name = dir_name;
1406 base_dir->has_modules = has_modules;
1407 }
1408 }
1409
1410 /** Collects all directories that are used in the Makefile descriptor structure
1411 * \a makefile in order to use pre-compiled files from them. */
1412 static void collect_base_dirs(struct makefile_struct *makefile)
1413 {
1414 size_t i;
1415 for (i = 0; i < makefile->nTTCN3Modules; i++) {
1416 add_base_dir(makefile, makefile->TTCN3Modules[i].dir_name, TRUE);
1417 }
1418 if (makefile->preprocess) {
1419 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
1420 add_base_dir(makefile, makefile->TTCN3PPModules[i].dir_name, TRUE);
1421 }
1422 }
1423 for (i = 0; i < makefile->nASN1Modules; i++) {
1424 add_base_dir(makefile, makefile->ASN1Modules[i].dir_name, TRUE);
1425 }
1426 for (i = 0; i < makefile->nUserFiles; i++) {
1427 add_base_dir(makefile, makefile->UserFiles[i].dir_name, FALSE);
1428 }
1429 if (makefile->nBaseDirs == 0) {
1430 WARNING("Usage of pre-compiled files from central storage (option `-c') "
1431 "is enabled, but all given files are located in the current working "
1432 "directory.");
1433 }
1434 }
1435
1436 /** Checks whether the TTCN-3, ASN.1 and C++ files follow the default naming
1437 * convention and sets the appropriate flags accordingly. */
1438 static void check_naming_convention(struct makefile_struct *makefile)
1439 {
1440 /* initially set all flags to true */
1441 makefile->TTCN3ModulesRegular = TRUE;
1442 makefile->BaseTTCN3ModulesRegular = TRUE;
1443 makefile->ASN1ModulesRegular = TRUE;
1444 makefile->BaseASN1ModulesRegular = TRUE;
1445 makefile->UserHeadersRegular = TRUE;
1446 makefile->UserSourcesRegular = TRUE;
1447 makefile->BaseUserHeadersRegular = TRUE;
1448 makefile->BaseUserSourcesRegular = TRUE;
1449 if (makefile->central_storage) {
1450 /* this project (Makefile) will use pre-compiled files from other
1451 directories */
1452 size_t i;
1453 for (i = 0; i < makefile->nTTCN3Modules; i++) {
1454 const struct module_struct *module = makefile->TTCN3Modules + i;
1455 if (module->dir_name != NULL) {
1456 if (!module->is_regular) makefile->BaseTTCN3ModulesRegular = FALSE;
1457 }
1458 else {
1459 if (!module->is_regular) makefile->TTCN3ModulesRegular = FALSE;
1460 }
1461 if (!makefile->TTCN3ModulesRegular && !makefile->BaseTTCN3ModulesRegular)
1462 break;
1463 }
1464 /* ttcnpp files are ttcn files */
1465 if ((makefile->TTCN3ModulesRegular || makefile->BaseTTCN3ModulesRegular) &&
1466 makefile->preprocess) {
1467 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
1468 const struct module_struct *module = makefile->TTCN3PPModules + i;
1469 if (module->dir_name != NULL) {
1470 if (!module->is_regular) makefile->BaseTTCN3ModulesRegular = FALSE;
1471 } else {
1472 if (!module->is_regular) makefile->TTCN3ModulesRegular = FALSE;
1473 }
1474 if (!makefile->TTCN3ModulesRegular && !makefile->BaseTTCN3ModulesRegular)
1475 break;
1476 }
1477 }
1478 for (i = 0; i < makefile->nASN1Modules; i++) {
1479 const struct module_struct *module = makefile->ASN1Modules + i;
1480 if (module->dir_name != NULL) {
1481 if (!module->is_regular) makefile->BaseASN1ModulesRegular = FALSE;
1482 }
1483 else {
1484 if (!module->is_regular) makefile->ASN1ModulesRegular = FALSE;
1485 }
1486 if (!makefile->ASN1ModulesRegular && !makefile->BaseASN1ModulesRegular)
1487 break;
1488 }
1489 for (i = 0; i < makefile->nUserFiles; i++) {
1490 const struct user_struct *user = makefile->UserFiles + i;
1491 if (user->dir_name != NULL) {
1492 if (!user->has_cc_suffix)
1493 makefile->BaseUserSourcesRegular = FALSE;
1494 if (!user->has_cc_suffix || !user->has_hh_suffix)
1495 makefile->BaseUserHeadersRegular = FALSE;
1496 }
1497 else {
1498 if (!user->has_cc_suffix)
1499 makefile->UserSourcesRegular = FALSE;
1500 if (!user->has_cc_suffix || !user->has_hh_suffix)
1501 makefile->UserHeadersRegular = FALSE;
1502 }
1503 if (!makefile->UserHeadersRegular && !makefile->UserSourcesRegular &&
1504 !makefile->BaseUserHeadersRegular &&
1505 !makefile->BaseUserSourcesRegular) break;
1506 }
1507 } else {
1508 /* this project (Makefile) will-be stand-alone */
1509 size_t i;
1510 for (i = 0; i < makefile->nTTCN3Modules; i++) {
1511 const struct module_struct *module = makefile->TTCN3Modules + i;
1512 if (!module->is_regular || module->dir_name != NULL) {
1513 makefile->TTCN3ModulesRegular = FALSE;
1514 break;
1515 }
1516 }
1517 if (makefile->TTCN3ModulesRegular && makefile->preprocess) {
1518 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
1519 const struct module_struct *module = makefile->TTCN3PPModules + i;
1520 if (!module->is_regular || module->dir_name != NULL) {
1521 makefile->TTCN3ModulesRegular = FALSE;
1522 break;
1523 }
1524 }
1525 }
1526 for (i = 0; i < makefile->nASN1Modules; i++) {
1527 const struct module_struct *module = makefile->ASN1Modules + i;
1528 if (!module->is_regular || module->dir_name != NULL) {
1529 makefile->ASN1ModulesRegular = FALSE;
1530 break;
1531 }
1532 }
1533 for (i = 0; i < makefile->nUserFiles; i++) {
1534 const struct user_struct *user = makefile->UserFiles + i;
1535 if (!user->has_cc_suffix)
1536 makefile->UserSourcesRegular = FALSE;
1537 if (!user->has_cc_suffix || !user->has_hh_suffix)
1538 makefile->UserHeadersRegular = FALSE;
1539 if (!makefile->UserHeadersRegular && !makefile->UserSourcesRegular)
1540 break;
1541 }
1542 }
1543 }
1544
1545 /** Prints the name of the TTCN-3 or ASN.1 source file that belongs to module
1546 * \a module to file \a fp. */
1547 static void print_file_name(FILE *fp, const struct module_struct *module)
1548 {
1549 char *path_name = compose_path_name(module->dir_name, module->file_name);
1550 fprintf(fp, " %s", path_name);
1551 Free(path_name);
1552 }
1553
1554 /** Prints the name of the preprocessed TTCN-3 source file that belongs to
1555 * module \a module to file \a fp. */
1556 static void print_preprocessed_file_name(FILE *fp,
1557 const struct module_struct *module)
1558 {
1559 char *preprocessed_name = get_preprocessed_file_name(module->file_name);
1560 char *path_name = compose_path_name(module->dir_name, preprocessed_name);
1561 fprintf(fp, " %s", path_name);
1562 Free(path_name);
1563 Free(preprocessed_name);
1564 }
1565
1566 /** Prints the name of the generated header, source or object file of module
1567 * \a module to file \a fp. The name of the directory is added only if
1568 * \a add_directory is TRUE. Parameter \a suffix shall be "hh", "cc", "hpp", "cpp" or "o". */
1569 static void print_generated_file_name(FILE *fp,
1570 const struct module_struct *module, boolean add_directory, const char *suffix)
1571 {
1572 char *file_name = mcopystr(module->module_name);
1573 /* replace '-' with '_' */
1574 size_t i;
1575 for (i = 0; file_name[i] != '\0'; i++)
1576 if (file_name[i] == '-') file_name[i] = '_';
1577 /* append the suffix */
1578 file_name = mputprintf(file_name, "%s", suffix);
1579 /* add the directory name if necessary */
1580 if (add_directory) {
1581 char *path_name = compose_path_name(module->dir_name, file_name);
1582 Free(file_name);
1583 file_name = path_name;
1584 }
1585 fprintf(fp, " %s", file_name);
1586 Free(file_name);
1587 }
1588
1589 /** Prints the name of the user C/C++ header file of user module \a user if the
1590 * above file exists. */
1591 static void print_header_name(FILE *fp, const struct user_struct *user)
1592 {
1593 if (user->header_name != NULL) {
1594 char *path_name = compose_path_name(user->dir_name, user->header_name);
1595 fprintf(fp, " %s", path_name);
1596 Free(path_name);
1597 }
1598 }
1599
1600 /** Prints the name of the user C/C++ source file of user module \a user if the
1601 * above file exists. */
1602 static void print_source_name(FILE *fp, const struct user_struct *user)
1603 {
1604 if (user->source_name != NULL) {
1605 char *path_name = compose_path_name(user->dir_name, user->source_name);
1606 fprintf(fp, " %s", path_name);
1607 Free(path_name);
1608 }
1609 }
1610
1611 /** Prints the name of the user C/C++ object file of user module \a user if the
1612 * above file exists (i.e. the respective source file is present). */
1613 static void print_object_name(FILE *fp, const struct user_struct *user)
1614 {
1615 if (user->source_name != NULL) {
1616 char *file_name = mprintf("%s.o", user->file_prefix);
1617 char *path_name = compose_path_name(user->dir_name, file_name);
1618 Free(file_name);
1619 fprintf(fp, " %s", path_name);
1620 Free(path_name);
1621 }
1622 }
1623
1624 static void print_shared_object_name(FILE *fp, const struct user_struct *user)
1625 {
1626 if (user->source_name != NULL) {
1627 char *file_name = mprintf("%s.so", user->file_prefix);
1628 char *path_name = compose_path_name(user->dir_name, file_name);
1629 Free(file_name);
1630 fprintf(fp, " %s", path_name);
1631 Free(path_name);
1632 }
1633 }
1634 /** Prints the splitted files' names for a given module. */
1635 static void print_splitted_file_names(FILE *fp,
1636 const struct makefile_struct *makefile, const struct module_struct *module)
1637 {
1638 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
1639 print_generated_file_name(fp, module, FALSE, "_seq.cc");
1640 print_generated_file_name(fp, module, FALSE, "_set.cc");
1641 print_generated_file_name(fp, module, FALSE, "_seqof.cc");
1642 print_generated_file_name(fp, module, FALSE, "_setof.cc");
1643 print_generated_file_name(fp, module, FALSE, "_union.cc");
1644 }
1645 }
1646
1647 static void fprint_extra_targets(FILE* fp, struct string2_list* target_placement_list, const char* placement)
1648 {
1649 struct string2_list* act_elem = target_placement_list;
1650 while (act_elem) {
1651 if (act_elem->str1 && act_elem->str2 && (strcmp(act_elem->str2,placement)==0)) {
1652 fprintf(fp, " %s", act_elem->str1);
1653 }
1654 act_elem = act_elem->next;
1655 }
1656 }
1657
1658 #undef COMMENT_PREFIX
1659 #define COMMENT_PREFIX "# "
1660
1661 /** Prints the Makefile based on structure \a makefile. */
1662 static void print_makefile(struct makefile_struct *makefile)
1663 {
1664 boolean add_refd_prjs = FALSE;
1665 if (makefile->linkingStrategy && makefile->hierarchical) {
1666 add_refd_prjs = hasSubProject(makefile->project_name);
1667 }
1668 else {
1669 add_refd_prjs = makefile->sub_project_dirs && makefile->sub_project_dirs->str;
1670 }
1671 NOTIFY("Generating Makefile skeleton...");
1672
1673 if (makefile->force_overwrite ||
1674 get_path_status(makefile->output_file) == PS_NONEXISTENT) {
1675 size_t i;
1676 char *user_info;
1677 const char* cxx;
1678 const char* cpp;
1679 const char *rm_command = makefile->gnu_make ? "$(RM)" : "rm -f";
1680 FILE *fp;
1681 boolean run_compiler = (makefile->nASN1Modules > 0)
1682 || (makefile->nTTCN3Modules) || (makefile->nTTCN3PPModules > 0);
1683
1684 expstring_t titan_dir = 0;
1685 const char * last_slash = strrchr(program_name, '/');
1686 if (last_slash != NULL) {
1687 size_t path_len = last_slash - program_name;
1688 titan_dir = mcopystr(program_name);
1689 /* Chop off the program name, and the /bin before it (if any) */
1690 if (path_len >= 4
1691 && memcmp(titan_dir + path_len - 4, "/bin", 4) == 0) {
1692 titan_dir = mtruncstr(titan_dir, path_len - 4);
1693 }
1694 else {
1695 titan_dir = mtruncstr(titan_dir, path_len);
1696 }
1697 }
1698
1699
1700 fp = fopen(makefile->output_file, "w");
1701 if (fp == NULL){
1702 ERROR("Cannot open output file `%s' for writing: %s",
1703 makefile->output_file, strerror(errno));
1704 return;
1705 }
1706 user_info = get_user_info();
1707 fprintf(fp, "# This Makefile was generated by the Makefile Generator\n"
1708 "# of the TTCN-3 Test Executor version " PRODUCT_NUMBER "\n"
1709 "# for %s\n"
1710 COPYRIGHT_STRING "\n\n"
1711 "# The following make commands are available:\n"
1712 "# - make, make all Builds the %s.\n"
1713 "# - make archive Archives all source files.\n"
1714 "# - make check Checks the semantics of TTCN-3 and ASN.1 "
1715 "modules.\n"
1716 "%s" // clean:
1717 "%s" //clean-all
1718 "# - make compile Translates TTCN-3 and ASN.1 modules to C++.\n"
1719 "# - make dep Creates/updates dependency list.\n"
1720 "# - make executable Builds the executable test suite.\n"
1721 "# - make library Builds the library archive.\n"
1722 "# - make objects Builds the object files without linking the "
1723 "executable.\n", user_info,
1724 makefile->library ? "library archive." : "executable test suite",
1725 (makefile->linkingStrategy && makefile->hierarchical) ?
1726 "# - make clean Removes generated files from project.\n" :
1727 "# - make clean Removes all generated files.\n",
1728 (makefile->linkingStrategy && makefile->hierarchical) ?
1729 "# - make clean-all Removes all generated files from the project hierarchy.\n" : "");
1730 Free(user_info);
1731 if (makefile->dynamic)
1732 fprintf(fp, "# - make shared_objects Builds the shared object files "
1733 "without linking the executable.\n");
1734 if (makefile->preprocess)
1735 fputs("# - make preprocess Preprocess TTCN-3 files.\n", fp);
1736 if (makefile->central_storage) {
1737 fputs("# WARNING! This Makefile uses pre-compiled files from the "
1738 "following directories:\n", fp);
1739 for (i = 0; i < makefile->nBaseDirs; i++)
1740 fprintf(fp, "# %s\n", makefile->BaseDirs[i].dir_name);
1741 fputs("# The executable tests will be consistent only if all directories "
1742 "use\n"
1743 "# the same platform and the same version of TTCN-3 Test Executor "
1744 "and\n"
1745 "# C++ compiler with the same command line switches.\n\n", fp);
1746 }
1747 if (makefile->gnu_make) {
1748 fputs("# WARNING! This Makefile can be used with GNU make only.\n"
1749 "# Other versions of make may report syntax errors in it.\n\n"
1750 "#\n"
1751 "# Do NOT touch this line...\n"
1752 "#\n"
1753 ".PHONY: all shared_objects executable library objects check clean dep archive", fp);
1754 if (makefile->preprocess) fputs(" preprocess", fp);
1755 if (add_refd_prjs) {
1756 fprintf(fp, "\\\n referenced-all referenced-shared_objects referenced-executable referenced-library referenced-objects referenced-check"
1757 "\\\n referenced-clean%s",
1758 (makefile->linkingStrategy && makefile->hierarchical) ?
1759 "-all" : "");
1760 }
1761 fprint_extra_targets(fp, makefile->target_placement_list, "PHONY");
1762
1763 if (makefile->gcc_dep) {
1764 fputs("\n\n.SUFFIXES: .d", fp);
1765 }
1766 fputs("\n\n", fp);
1767 }
1768
1769 if (makefile->linkingStrategy) {
1770 const char* tpd_name = getTPDFileName(makefile->project_name);
1771 if (tpd_name) {
1772 fputs("# Titan Project Descriptor file what this Makefile is generated from.\n", fp);
1773 fprintf(fp, "TPD = %s\n\n", tpd_name);
1774 }
1775 const char* root_dir = getPathToRootDir(makefile->project_name);
1776 if (root_dir) {
1777 fputs("# Relative path to top directory at OS level.\n", fp);
1778 fprintf(fp, "ROOT_DIR = %s\n\n", root_dir);
1779 }
1780 }
1781
1782 if (add_refd_prjs) {
1783 struct string_list* act_elem = NULL;
1784 struct string_list* head = NULL;
1785 if (makefile->linkingStrategy && makefile->hierarchical) {// pair with free_string_list
1786 head = act_elem = getRefWorkingDirs(makefile->project_name);
1787 }
1788 else {
1789 act_elem = makefile->sub_project_dirs;
1790 }
1791 if (!makefile->linkingStrategy)
1792 fputs("# This is the top level makefile of a Makefile hierarchy generated from\n", fp);
1793 fputs("# Titan Project Descriptor hierarchy. List of referenced project\n"
1794 "# working directories (ordered by dependencies):\n", fp);
1795 while (act_elem) {
1796 if (act_elem->str) {
1797 fprintf(fp, "# %s\n", act_elem->str);
1798 }
1799 act_elem = act_elem->next;
1800 }
1801 if (makefile->linkingStrategy && makefile->hierarchical) { // pair with getRefWorkingDirs
1802 free_string_list(head);
1803 }
1804 fputs("REFERENCED_PROJECT_DIRS = ", fp);
1805 if (makefile->linkingStrategy && makefile->hierarchical) {
1806 head = act_elem = getRefWorkingDirs(makefile->project_name); // pair with free_string_list
1807 }
1808 else {
1809 act_elem = makefile->sub_project_dirs;
1810 }
1811 while (act_elem) {
1812 if (act_elem->str) {
1813 fprintf(fp, "%s ", act_elem->str);
1814 }
1815 act_elem = act_elem->next;
1816 }
1817 fputs("\n\n", fp);
1818 if (makefile->linkingStrategy && makefile->hierarchical) {// pair with getRefWorkingDirs
1819 free_string_list(head);
1820 }
1821 }
1822
1823 fprintf(fp, "#\n"
1824 "# Set these variables...\n"
1825 "#\n\n"
1826 "# The path of your TTCN-3 Test Executor installation:\n"
1827 "# Uncomment this line to override the environment variable.\n"
1828 "%s"
1829 "# TTCN3_DIR = %s\n"
1830 , titan_dir ?
1831 "# The value below points to the location of the TITAN version\n"
1832 "# that generated this makefile.\n" : ""
1833 , titan_dir ? titan_dir : "");
1834 if (titan_dir) Free(titan_dir);
1835
1836 if (makefile->cxxcompiler) {
1837 cxx = makefile->cxxcompiler;
1838 } else {
1839 cxx = "g++";
1840 }
1841
1842 fprintf(fp, "\n# Your platform: (SOLARIS, SOLARIS8, LINUX, FREEBSD or "
1843 "WIN32)\n"
1844 "PLATFORM = %s\n\n"
1845 "# Your C++ compiler:\n"
1846 "# (if you change the platform, you may need to change the compiler)\n"
1847 "CXX = %s \n\n", get_platform_string(), cxx);
1848
1849
1850 if (makefile->preprocess || makefile->ttcn3preprocessor) {
1851 if (makefile->ttcn3preprocessor) {
1852 cpp = makefile->ttcn3preprocessor;
1853 } else {
1854 cpp = "cpp";
1855 }
1856 fprintf(fp,"# C preprocessor used for TTCN-3 files:\n"
1857 "CPP = %s\n\n", cpp);
1858 }
1859
1860 fputs("# Flags for the C++ preprocessor (and makedepend as well):\n"
1861 "CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)/include", fp);
1862
1863 if (makefile->use_runtime_2) fputs(" -DTITAN_RUNTIME_2", fp);
1864
1865 for (i = 0; i < makefile->nBaseDirs; i++) {
1866 fprintf(fp, " -I%s", makefile->BaseDirs[i].dir_name);
1867 }
1868
1869 if (makefile->prep_includes) {
1870 struct string_list* act_elem = makefile->prep_includes;
1871 while (act_elem) {
1872 if (act_elem->str) {
1873 fprintf(fp, " -I%s", act_elem->str);
1874 }
1875 act_elem = act_elem->next;
1876 }
1877 }
1878
1879 if (makefile->prep_defines) {
1880 struct string_list* act_elem = makefile->prep_defines;
1881 while (act_elem) {
1882 if (act_elem->str) {
1883 fprintf(fp, " -D%s", act_elem->str);
1884 }
1885 act_elem = act_elem->next;
1886 }
1887 }
1888
1889 if (makefile->prep_undefines) {
1890 struct string_list* act_elem = makefile->prep_undefines;
1891 while (act_elem) {
1892 if (act_elem->str) {
1893 fprintf(fp, " -U%s", act_elem->str);
1894 }
1895 act_elem = act_elem->next;
1896 }
1897 }
1898
1899 fputs("\n\n", fp);
1900
1901 if (makefile->gcc_dep) {
1902 fprintf(fp, "# Flags for dependency generation\n"
1903 "CXXDEPFLAGS = -%s\n\n", strstr(cxx, "g++") ? "MM" : "xM1");
1904 }
1905
1906 if (makefile->preprocess || makefile->ttcn3_prep_includes || makefile->ttcn3_prep_defines) {
1907 fputs("# Flags for preprocessing TTCN-3 files:\n"
1908 "CPPFLAGS_TTCN3 =", fp);
1909
1910 if (makefile->preprocess) {
1911 for (i = 0; i < makefile->nBaseDirs; i++) {
1912 fprintf(fp, " -I%s", makefile->BaseDirs[i].dir_name);
1913 }
1914 }
1915 if (makefile->ttcn3_prep_includes) {
1916 struct string_list* act_elem = makefile->ttcn3_prep_includes;
1917 while (act_elem) {
1918 if (act_elem->str) {
1919 fprintf(fp, " -I%s", act_elem->str);
1920 }
1921 act_elem = act_elem->next;
1922 }
1923 }
1924 if (makefile->ttcn3_prep_defines) {
1925 struct string_list* act_elem = makefile->ttcn3_prep_defines;
1926 while (act_elem) {
1927 if (act_elem->str) {
1928 fprintf(fp, " -D%s", act_elem->str);
1929 }
1930 act_elem = act_elem->next;
1931 }
1932 }
1933 if (makefile->ttcn3_prep_undefines) {
1934 struct string_list* act_elem = makefile->ttcn3_prep_undefines;
1935 while (act_elem) {
1936 if (act_elem->str) {
1937 fprintf(fp, " -U%s", act_elem->str);
1938 }
1939 act_elem = act_elem->next;
1940 }
1941 }
1942 fputs("\n\n", fp);
1943 }
1944
1945 /* code splitting: command line argument wins */
1946 if (makefile->code_splitting_mode == NULL) {
1947 if (makefile->codesplittpd) {
1948 makefile->code_splitting_mode = mcopystr("-U type");
1949 }
1950 }
1951
1952 fprintf(fp, "# Flags for the C++ compiler:\n"
1953 "CXXFLAGS = %s%s %s %s\n\n"
1954 "# Flags for the linker:\n"
1955 "LDFLAGS = %s%s\n\n"
1956 "ifeq ($(PLATFORM), WIN32)\n"
1957 "# Silence linker warnings.\n"
1958 "LDFLAGS += -Wl,--enable-auto-import,--enable-runtime-pseudo-reloc\n"
1959 "endif\n\n"
1960 "# Utility to create library files\n"
1961 "AR = ar\n"
1962 "ARFLAGS = \n\n"
1963 "# Flags for the TTCN-3 and ASN.1 compiler:\n"
1964 "COMPILER_FLAGS =%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s %s\n\n"
1965 "# Execution mode: (either ttcn3 or ttcn3-parallel)\n"
1966 "TTCN3_LIB = ttcn3%s%s%s\n\n"
1967 #ifdef LICENSE
1968 "# The path of your OpenSSL installation:\n"
1969 "# If you do not have your own one, leave it unchanged.\n"
1970 "OPENSSL_DIR = $(TTCN3_DIR)\n\n"
1971 #endif
1972 "# The path of your libxml2 installation:\n"
1973 "# If you do not have your own one, leave it unchanged.\n"
1974 "XMLDIR = $(TTCN3_DIR)\n\n"
1975 "# Directory to store the archived source files:\n",
1976 makefile->dynamic ? "-Wall -fPIC" : "-Wall", /* CXXFLAGS */
1977 makefile->coverage ? " -fprofile-arcs -ftest-coverage -g" : "", /* CXXFLAGS COVERAGE */
1978 makefile->optlevel ? makefile->optlevel : "", /* CXXFLAGS optimization level */
1979 makefile->optflags ? makefile->optflags : "", /* CXXFLAGS optimization level */
1980 makefile->dynamic ? "-fPIC" : "", /* LDFLAGS */
1981 makefile->coverage ? " -fprofile-arcs -ftest-coverage -g -lgcov" : "", /* LDFLAGS COVERAGE */
1982 /* COMPILER_FLAGS */
1983 makefile->use_runtime_2 ? " -L -R " : " -L ",
1984 (makefile->code_splitting_mode ? makefile->code_splitting_mode : ""),
1985 (makefile->quietly ? " -q" : ""),
1986 (makefile->disablesubtypecheck ? " -y" : ""),
1987 (makefile->disableber ? " -b" : ""),
1988 (makefile->disableraw ? " -r" : ""),
1989 (makefile->disabletext ? " -x" : ""),
1990 (makefile->disablexer ? " -X" : ""),
1991 (makefile->disablejson ? " -j" : ""),
1992 (makefile->forcexerinasn ? " -a" : ""),
1993 (makefile->defaultasomit ? " -d" : ""),
1994 (makefile->gccmsgformat ? " -g" : ""),
1995 (makefile->linenumbersonlymsg ? " -i" : ""),
1996 (makefile->includesourceinfo ? " -l" : ""),
1997 /*(makefile->addsourcelineinfo ? " -L" : ""),*/
1998 (makefile->suppresswarnings ? " -w" : ""),
1999 (makefile->outparamboundness ? " -Y" : ""),
2000 (makefile->tcov_file_name ? makefile->tcov_file_name : ""),
2001 /* end of COMPILER FLAGS */
2002 (makefile->use_runtime_2 ? "-rt2" : ""), /* TTCN3_LIB */
2003 (makefile->single_mode ? "" : "-parallel"),
2004 (makefile->dynamic ? "-dynamic": "")
2005 );
2006 if (!makefile->gnu_make) {
2007 fputs("# Note: you can set any directory except ./archive\n", fp);
2008 }
2009 fputs("ARCHIVE_DIR = backup\n\n"
2010 "#\n"
2011 "# You may change these variables. Add your files if necessary...\n"
2012 "#\n\n"
2013 "# TTCN-3 modules of this project:\n"
2014 "TTCN3_MODULES =", fp);
2015 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2016 const struct module_struct *module = makefile->TTCN3Modules + i;
2017 if (module->dir_name == NULL || !makefile->central_storage)
2018 /* If the file is in the current directory or
2019 * is not in the current directory but central directory is not used,
2020 * it goes into TTCN3_MODULES */
2021 print_file_name(fp, module);
2022 }
2023 fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_MODULES");
2024 if (makefile->preprocess) {
2025 fputs("\n\n"
2026 "# TTCN-3 modules to preprocess:\n"
2027 "TTCN3_PP_MODULES =", fp);
2028 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2029 const struct module_struct *module = makefile->TTCN3PPModules + i;
2030 if (module->dir_name == NULL || !makefile->central_storage)
2031 print_file_name(fp, module);
2032 }
2033 fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_PP_MODULES");
2034 }
2035 if (makefile->central_storage) {
2036 fputs("\n\n"
2037 "# TTCN-3 modules used from central project(s):\n"
2038 "BASE_TTCN3_MODULES =", fp);
2039 if (!makefile->linkingStrategy) {
2040 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2041 const struct module_struct *module = makefile->TTCN3Modules + i;
2042 /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */
2043 if (module->dir_name != NULL) print_file_name(fp, module);
2044 }
2045 if (makefile->preprocess) {
2046 fputs("\n\n"
2047 "# TTCN-3 modules to preprocess used from central project(s):\n"
2048 "BASE_TTCN3_PP_MODULES =", fp);
2049 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2050 const struct module_struct *module = makefile->TTCN3PPModules + i;
2051 if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name))
2052 print_file_name(fp, module);
2053 }
2054 }
2055 }
2056 else { // new linking strategy
2057 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2058 const struct module_struct *module = makefile->TTCN3Modules + i;
2059 /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */
2060 if (module->dir_name != NULL && !isTtcn3ModuleInLibrary(module->module_name))
2061 print_file_name(fp, module);
2062 }
2063 fputs("\n\n"
2064 "# TTCN-3 library linked modules used from central project(s):\n"
2065 "BASE2_TTCN3_MODULES =", fp);
2066 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2067 const struct module_struct *module = makefile->TTCN3Modules + i;
2068 /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */
2069 if (module->dir_name != NULL && isTtcn3ModuleInLibrary(module->module_name))
2070 print_file_name(fp, module);
2071 }
2072 if (makefile->preprocess) {
2073 fputs("\n\n"
2074 "# TTCN-3 modules to preprocess used from central project(s):\n"
2075 "BASE_TTCN3_PP_MODULES =", fp);
2076 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2077 const struct module_struct *module = makefile->TTCN3PPModules + i;
2078 if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name))
2079 print_file_name(fp, module);
2080 }
2081 fputs("\n\n"
2082 "# TTCN-3 library linked modules to preprocess used from central project(s):\n"
2083 "BASE2_TTCN3_PP_MODULES =", fp);
2084 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2085 const struct module_struct *module = makefile->TTCN3PPModules + i;
2086 if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name))
2087 print_file_name(fp, module);
2088 }
2089 }
2090 }
2091 }
2092 if (makefile->preprocess) {
2093 fputs("\n\n"
2094 "# Files to include in TTCN-3 preprocessed modules:\n"
2095 "TTCN3_INCLUDES =", fp);
2096 for (i = 0; i < makefile->nTTCN3IncludeFiles; i++)
2097 fprintf(fp, " %s", makefile->TTCN3IncludeFiles[i]);
2098 fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_INCLUDES");
2099 }
2100 fputs("\n\n"
2101 "# ASN.1 modules of this project:\n"
2102 "ASN1_MODULES =", fp);
2103 for (i = 0; i < makefile->nASN1Modules; i++) {
2104 const struct module_struct *module = makefile->ASN1Modules + i;
2105 if (module->dir_name == NULL || !makefile->central_storage)
2106 print_file_name(fp, module);
2107 }
2108 fprint_extra_targets(fp, makefile->target_placement_list, "ASN1_MODULES");
2109 if (makefile->central_storage) {
2110 fputs("\n\n"
2111 "# ASN.1 modules used from central project(s):\n"
2112 "BASE_ASN1_MODULES =", fp);
2113 if (!makefile->linkingStrategy) {
2114 for (i = 0; i < makefile->nASN1Modules; i++) {
2115 const struct module_struct *module = makefile->ASN1Modules + i;
2116 if (module->dir_name != NULL) print_file_name(fp, module);
2117 }
2118 }
2119 else {
2120 for (i = 0; i < makefile->nASN1Modules; i++) {
2121 const struct module_struct *module = makefile->ASN1Modules + i;
2122 if (module->dir_name != NULL && !isAsn1ModuleInLibrary(module->module_name))
2123 print_file_name(fp, module);
2124 }
2125 fputs("\n\n"
2126 "# ASN.1 library linked modules used from central project(s):\n"
2127 "BASE2_ASN1_MODULES =", fp);
2128 for (i = 0; i < makefile->nASN1Modules; i++) {
2129 const struct module_struct *module = makefile->ASN1Modules + i;
2130 if (module->dir_name != NULL && isAsn1ModuleInLibrary(module->module_name))
2131 print_file_name(fp, module);
2132 }
2133 }
2134 }
2135 if (makefile->preprocess) {
2136 fputs("\n\n"
2137 "# TTCN-3 source files generated by the C preprocessor:\n"
2138 "PREPROCESSED_TTCN3_MODULES =", fp);
2139 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2140 const struct module_struct *module = makefile->TTCN3PPModules + i;
2141 if (module->dir_name == NULL || !makefile->central_storage)
2142 print_preprocessed_file_name(fp, module);
2143 }
2144 if (makefile->central_storage) {
2145 fputs("\n\n"
2146 "# TTCN-3 files generated by the CPP used from central project(s):\n"
2147 "BASE_PREPROCESSED_TTCN3_MODULES =", fp);
2148 if (!makefile->linkingStrategy) {
2149 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2150 const struct module_struct *module = makefile->TTCN3PPModules + i;
2151 if (module->dir_name != NULL)
2152 print_preprocessed_file_name(fp, module);
2153 }
2154 }
2155 else { // new linking strategy
2156 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2157 const struct module_struct *module = makefile->TTCN3PPModules + i;
2158 if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name))
2159 print_preprocessed_file_name(fp, module);
2160 }
2161 fputs("\n\n"
2162 "# TTCN-3 library linked files generated by the CPP used from central project(s):\n"
2163 "BASE2_PREPROCESSED_TTCN3_MODULES =", fp);
2164 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2165 const struct module_struct *module = makefile->TTCN3PPModules + i;
2166 if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name))
2167 print_preprocessed_file_name(fp, module);
2168 }
2169 }
2170 }
2171 }
2172 fputs("\n\n"
2173 "# C++ source & header files generated from the TTCN-3 & ASN.1 "
2174 "modules of\n"
2175 "# this project:\n"
2176 "GENERATED_SOURCES =", fp);
2177 if (makefile->gnu_make && makefile->TTCN3ModulesRegular) {
2178 fputs(" $(TTCN3_MODULES:.ttcn=.cc)", fp);
2179 if (makefile->code_splitting_mode) {
2180 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2181 const struct module_struct *module = makefile->TTCN3Modules + i;
2182 if (module->dir_name == NULL || !makefile->central_storage)
2183 print_splitted_file_names(fp, makefile, module);
2184 }
2185 }
2186 if (makefile->preprocess) {
2187 fputs(" $(TTCN3_PP_MODULES:.ttcnpp=.cc)", fp);
2188 if (makefile->code_splitting_mode) {
2189 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2190 const struct module_struct *module = makefile->TTCN3PPModules + i;
2191 if (module->dir_name == NULL || !makefile->central_storage)
2192 print_splitted_file_names(fp, makefile, module);
2193 }
2194 }
2195 }
2196 } else {
2197 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2198 const struct module_struct *module = makefile->TTCN3Modules + i;
2199 if (module->dir_name == NULL || !makefile->central_storage) {
2200 print_generated_file_name(fp, module, FALSE, ".cc");
2201 if (makefile->code_splitting_mode)
2202 print_splitted_file_names(fp, makefile, module);
2203 }
2204 }
2205 if (makefile->preprocess) {
2206 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2207 const struct module_struct *module = makefile->TTCN3PPModules + i;
2208 if (module->dir_name == NULL || !makefile->central_storage) {
2209 print_generated_file_name(fp, module, FALSE, ".cc");
2210 if (makefile->code_splitting_mode)
2211 print_splitted_file_names(fp, makefile, module);
2212 }
2213 }
2214 }
2215 }
2216 if (makefile->gnu_make && makefile->ASN1ModulesRegular) {
2217 fputs(" $(ASN1_MODULES:.asn=.cc)", fp);
2218 if (makefile->code_splitting_mode) {
2219 for (i = 0; i < makefile->nASN1Modules; i++) {
2220 const struct module_struct *module = makefile->ASN1Modules + i;
2221 if (module->dir_name == NULL || !makefile->central_storage) {
2222 print_splitted_file_names(fp, makefile, module);
2223 }
2224 }
2225 }
2226 } else {
2227 for (i = 0; i < makefile->nASN1Modules; i++) {
2228 const struct module_struct *module = makefile->ASN1Modules + i;
2229 if (module->dir_name == NULL || !makefile->central_storage) {
2230 print_generated_file_name(fp, module, FALSE, ".cc");
2231 if (makefile->code_splitting_mode)
2232 print_splitted_file_names(fp, makefile, module);
2233 }
2234 }
2235 }
2236
2237 fputs("\nGENERATED_HEADERS =", fp);
2238 if (makefile->gnu_make) {
2239 fputs(" $(GENERATED_SOURCES:.cc=.hh)", fp);
2240 }
2241 else {
2242 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2243 const struct module_struct *module = makefile->TTCN3Modules + i;
2244 if (module->dir_name == NULL || !makefile->central_storage)
2245 print_generated_file_name(fp, module, FALSE, ".hh");
2246 }
2247 if (makefile->preprocess) {
2248 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2249 const struct module_struct *module = makefile->TTCN3PPModules + i;
2250 if (module->dir_name == NULL || !makefile->central_storage)
2251 print_generated_file_name(fp, module, FALSE, ".hh");
2252 }
2253 }
2254 for (i = 0; i < makefile->nASN1Modules; i++) {
2255 const struct module_struct *module = makefile->ASN1Modules + i;
2256 if (module->dir_name == NULL || !makefile->central_storage)
2257 print_generated_file_name(fp, module, FALSE, ".hh");
2258 }
2259 }
2260 if (makefile->central_storage) {
2261 fputs("\n\n"
2262 "# C++ source & header files generated from the TTCN-3 & ASN.1 "
2263 "modules of\n"
2264 "# central project(s):\n"
2265 "BASE_GENERATED_SOURCES =", fp);
2266 if (makefile->gnu_make && makefile->BaseTTCN3ModulesRegular) {
2267 fputs(" $(BASE_TTCN3_MODULES:.ttcn=.cc)", fp);
2268 if (makefile->code_splitting_mode) {
2269 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2270 const struct module_struct *module = makefile->TTCN3Modules + i;
2271 if (module->dir_name != NULL) {
2272 print_splitted_file_names(fp, makefile, module);
2273 }
2274 }
2275 }
2276 if (makefile->preprocess) {
2277 fputs(" $(BASE_TTCN3_PP_MODULES:.ttcnpp=.cc)", fp);
2278 if (makefile->code_splitting_mode) {
2279 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2280 const struct module_struct *module = makefile->TTCN3PPModules + i;
2281 if (module->dir_name != NULL) {
2282 print_splitted_file_names(fp, makefile, module);
2283 }
2284 }
2285 }
2286 }
2287 } else {
2288 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2289 const struct module_struct *module = makefile->TTCN3Modules + i;
2290 if (module->dir_name != NULL) {
2291 print_generated_file_name(fp, module, TRUE, ".cc");
2292 if (makefile->code_splitting_mode)
2293 print_splitted_file_names(fp, makefile, module);
2294 }
2295 }
2296 if (makefile->preprocess) {
2297 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2298 const struct module_struct *module = makefile->TTCN3PPModules + i;
2299 if (module->dir_name != NULL) {
2300 print_generated_file_name(fp, module, TRUE, ".cc");
2301 if (makefile->code_splitting_mode)
2302 print_splitted_file_names(fp, makefile, module);
2303 }
2304 }
2305 }
2306 }
2307 if (makefile->gnu_make && makefile->BaseASN1ModulesRegular) {
2308 fputs(" $(BASE_ASN1_MODULES:.asn=.cc)", fp);
2309 if (makefile->code_splitting_mode) {
2310 for (i = 0; i < makefile->nASN1Modules; i++) {
2311 const struct module_struct *module = makefile->ASN1Modules + i;
2312 if (module->dir_name != NULL) {
2313 print_splitted_file_names(fp, makefile, module);
2314 }
2315 }
2316 }
2317 } else {
2318 for (i = 0; i < makefile->nASN1Modules; i++) {
2319 const struct module_struct *module = makefile->ASN1Modules + i;
2320 if (module->dir_name != NULL) {
2321 print_generated_file_name(fp, module, TRUE, ".cc");
2322 if (makefile->code_splitting_mode)
2323 print_splitted_file_names(fp, makefile, module);
2324 }
2325 }
2326 }
2327 fputs("\nBASE_GENERATED_HEADERS =", fp);
2328 if (makefile->gnu_make) {
2329 fputs(" $(BASE_GENERATED_SOURCES:.cc=.hh)", fp);
2330 } else {
2331 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2332 const struct module_struct *module = makefile->TTCN3Modules + i;
2333 if (module->dir_name != NULL)
2334 print_generated_file_name(fp, module, TRUE, ".hh");
2335 }
2336 if (makefile->preprocess) {
2337 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2338 const struct module_struct *module = makefile->TTCN3PPModules + i;
2339 if (module->dir_name != NULL)
2340 print_generated_file_name(fp, module, TRUE, ".hh");
2341 }
2342 }
2343 for (i = 0; i < makefile->nASN1Modules; i++) {
2344 const struct module_struct *module = makefile->ASN1Modules + i;
2345 if (module->dir_name != NULL)
2346 print_generated_file_name(fp, module, TRUE, ".hh");
2347 }
2348 }
2349 }
2350
2351 if (makefile->linkingStrategy) {
2352 fputs("\n\n"
2353 "# C++ source & header files generated from the TTCN-3 "
2354 " library linked modules of\n"
2355 "# central project(s):\n"
2356 "BASE2_GENERATED_SOURCES =", fp);
2357 if (makefile->gnu_make && makefile->BaseTTCN3ModulesRegular) {
2358 fputs(" $(BASE2_TTCN3_MODULES:.ttcn=.cc)", fp);
2359 fputs(" $(BASE2_ASN1_MODULES:.asn=.cc)", fp);
2360 if (makefile->preprocess)
2361 fputs(" $(BASE2_TTCN3_PP_MODULES:.ttcnpp=.cc)", fp);
2362 }
2363 else {
2364 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2365 const struct module_struct *module = makefile->TTCN3Modules + i;
2366 if (module->dir_name != NULL && isTtcn3ModuleInLibrary(module->module_name)) {
2367 print_generated_file_name(fp, module, TRUE, ".cc");
2368 }
2369 }
2370 if (makefile->preprocess) {
2371 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2372 const struct module_struct *module = makefile->TTCN3PPModules + i;
2373 if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name)) {
2374 print_generated_file_name(fp, module, TRUE, ".cc");
2375 }
2376 }
2377 }
2378 }
2379
2380 fputs("\nBASE2_GENERATED_HEADERS =", fp);
2381 if (makefile->gnu_make) {
2382 fputs(" $(BASE2_GENERATED_SOURCES:.cc=.hh)", fp);
2383 }
2384 else
2385 ERROR("the usage of 'Z' flag requires GNU make");
2386 }
2387
2388 fputs("\n\n"
2389 "# C/C++ Source & header files of Test Ports, external functions "
2390 "and\n"
2391 "# other modules:\n"
2392 "USER_SOURCES =", fp);
2393 for (i = 0; i < makefile->nUserFiles; i++) {
2394 const struct user_struct *user = makefile->UserFiles + i;
2395 if (user->dir_name == NULL || !makefile->central_storage)
2396 print_source_name(fp, user);
2397 }
2398 fprint_extra_targets(fp, makefile->target_placement_list, "USER_SOURCES");
2399 fputs("\nUSER_HEADERS =", fp);
2400 if (makefile->gnu_make && makefile->UserHeadersRegular) {
2401 fputs(" $(USER_SOURCES:.cc=.hh)", fp);
2402 } else {
2403 for (i = 0; i < makefile->nUserFiles; i++) {
2404 const struct user_struct *user = makefile->UserFiles + i;
2405 if (user->dir_name == NULL || !makefile->central_storage)
2406 print_header_name(fp, user);
2407 }
2408 }
2409 fprint_extra_targets(fp, makefile->target_placement_list, "USER_HEADERS");
2410 if (makefile->central_storage) {
2411 fputs("\n\n"
2412 "# C/C++ Source & header files of Test Ports, external functions "
2413 "and\n"
2414 "# other modules used from central project(s):\n"
2415 "BASE_USER_SOURCES =", fp);
2416 if (!makefile->linkingStrategy) {
2417 for (i = 0; i < makefile->nUserFiles; i++) {
2418 const struct user_struct *user = makefile->UserFiles + i;
2419 if (user->dir_name != NULL) {
2420 print_source_name(fp, user);
2421 }
2422 }
2423 fputs("\nBASE_USER_HEADERS =", fp);
2424 if (makefile->gnu_make && makefile->BaseUserHeadersRegular) {
2425 fputs(" $(BASE_USER_SOURCES:.cc=.hh)", fp);
2426 }
2427 else {
2428 for (i = 0; i < makefile->nUserFiles; i++) {
2429 const struct user_struct *user = makefile->UserFiles + i;
2430 if (user->dir_name != NULL)
2431 print_header_name(fp, user);
2432 }
2433 }
2434 }
2435 else {
2436 for (i = 0; i < makefile->nUserFiles; i++) {
2437 const struct user_struct *user = makefile->UserFiles + i;
2438 if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name)) {
2439 print_source_name(fp, user);
2440 }
2441 }
2442 fputs("\nBASE_USER_HEADERS =", fp);
2443 if (makefile->gnu_make && makefile->BaseUserHeadersRegular) {
2444 fputs(" $(BASE_USER_SOURCES:.cc=.hh)", fp);
2445 }
2446 else {
2447 for (i = 0; i < makefile->nUserFiles; i++) {
2448 const struct user_struct *user = makefile->UserFiles + i;
2449 if (user->dir_name != NULL && !isHeaderFileInLibrary(user->header_name))
2450 print_header_name(fp, user);
2451 }
2452 }
2453
2454 fputs("\n\n"
2455 "# C/C++ Source & header files of Test Ports, external functions "
2456 "and\n"
2457 "# other modules used from library linked central project(s):\n"
2458 "BASE2_USER_SOURCES =", fp);
2459 for (i = 0; i < makefile->nUserFiles; i++) {
2460 const struct user_struct *user = makefile->UserFiles + i;
2461 if (user->dir_name != NULL && isSourceFileInLibrary(user->source_name)) {
2462 print_source_name(fp, user);
2463 }
2464 }
2465 fputs("\nBASE2_USER_HEADERS =", fp);
2466 if (makefile->gnu_make && makefile->BaseUserHeadersRegular) {
2467 fputs(" $(BASE2_USER_SOURCES:.cc=.hh)", fp);
2468 }
2469 else {
2470 for (i = 0; i < makefile->nUserFiles; i++) {
2471 const struct user_struct *user = makefile->UserFiles + i;
2472 if (user->dir_name != NULL && isHeaderFileInLibrary(user->header_name))
2473 print_header_name(fp, user);
2474 }
2475 }
2476 }
2477 }
2478 if (makefile->dynamic) {
2479 fputs("\n\n"
2480 "# Shared object files of this project:\n"
2481 "SHARED_OBJECTS =", fp);
2482 if (makefile->gnu_make) {
2483 fputs(" $(GENERATED_SOURCES:.cc=.so)", fp);
2484 } else {
2485 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2486 const struct module_struct *module = makefile->TTCN3Modules + i;
2487 if (module->dir_name == NULL || !makefile->central_storage) {
2488 print_generated_file_name(fp, module, FALSE, ".so");
2489 if (makefile->code_splitting_mode != NULL)
2490 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2491 print_generated_file_name(fp, module, FALSE, "_seq.so");
2492 print_generated_file_name(fp, module, FALSE, "_set.so");
2493 print_generated_file_name(fp, module, FALSE, "_seqof.so");
2494 print_generated_file_name(fp, module, FALSE, "_setof.so");
2495 print_generated_file_name(fp, module, FALSE, "_union.so");
2496 }
2497 }
2498 }
2499 if (makefile->preprocess) {
2500 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2501 const struct module_struct *module = makefile->TTCN3PPModules + i;
2502 if (module->dir_name == NULL || !makefile->central_storage) {
2503 print_generated_file_name(fp, module, FALSE, ".so");
2504 if (makefile->code_splitting_mode != NULL)
2505 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2506 print_generated_file_name(fp, module, FALSE, "_seq.so");
2507 print_generated_file_name(fp, module, FALSE, "_set.so");
2508 print_generated_file_name(fp, module, FALSE, "_seqof.so");
2509 print_generated_file_name(fp, module, FALSE, "_setof.so");
2510 print_generated_file_name(fp, module, FALSE, "_union.so");
2511 }
2512 }
2513 }
2514 }
2515 for (i = 0; i < makefile->nASN1Modules; i++) {
2516 const struct module_struct *module = makefile->ASN1Modules + i;
2517 if (module->dir_name == NULL || !makefile->central_storage) {
2518 print_generated_file_name(fp, module, FALSE, ".so");
2519 if (makefile->code_splitting_mode != NULL)
2520 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2521 print_generated_file_name(fp, module, FALSE, "_seq.so");
2522 print_generated_file_name(fp, module, FALSE, "_set.so");
2523 print_generated_file_name(fp, module, FALSE, "_seqof.so");
2524 print_generated_file_name(fp, module, FALSE, "_setof.so");
2525 print_generated_file_name(fp, module, FALSE, "_union.so");
2526 }
2527 }
2528 }
2529 }
2530 if (makefile->gnu_make && makefile->UserSourcesRegular) {
2531 fputs(" $(USER_SOURCES:.cc=.so)", fp);
2532 } else {
2533 for (i = 0; i < makefile->nUserFiles; i++) {
2534 const struct user_struct *user = makefile->UserFiles + i;
2535 if (user->dir_name == NULL || !makefile->central_storage)
2536 print_shared_object_name(fp, user);
2537 }
2538 }
2539 }
2540
2541 fputs("\n\n"
2542 "# Object files of this project that are needed for the executable "
2543 "test suite:\n"
2544 "OBJECTS = $(GENERATED_OBJECTS) $(USER_OBJECTS)\n\n" /* never := */
2545 "GENERATED_OBJECTS =", fp);
2546 if (makefile->gnu_make) {
2547 fputs(" $(GENERATED_SOURCES:.cc=.o)", fp);
2548 } else {
2549 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2550 const struct module_struct *module = makefile->TTCN3Modules + i;
2551 if (module->dir_name == NULL || !makefile->central_storage) {
2552 print_generated_file_name(fp, module, FALSE, ".o");
2553 if (makefile->code_splitting_mode != NULL)
2554 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2555 print_generated_file_name(fp, module, FALSE, "_seq.o");
2556 print_generated_file_name(fp, module, FALSE, "_set.o");
2557 print_generated_file_name(fp, module, FALSE, "_seqof.o");
2558 print_generated_file_name(fp, module, FALSE, "_setof.o");
2559 print_generated_file_name(fp, module, FALSE, "_union.o");
2560 }
2561 }
2562 }
2563 if (makefile->preprocess) {
2564 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2565 const struct module_struct *module = makefile->TTCN3PPModules + i;
2566 if (module->dir_name == NULL || !makefile->central_storage) {
2567 print_generated_file_name(fp, module, FALSE, ".o");
2568 if (makefile->code_splitting_mode != NULL)
2569 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2570 print_generated_file_name(fp, module, FALSE, "_seq.o");
2571 print_generated_file_name(fp, module, FALSE, "_set.o");
2572 print_generated_file_name(fp, module, FALSE, "_seqof.o");
2573 print_generated_file_name(fp, module, FALSE, "_setof.o");
2574 print_generated_file_name(fp, module, FALSE, "_union.o");
2575 }
2576 }
2577 }
2578 }
2579 for (i = 0; i < makefile->nASN1Modules; i++) {
2580 const struct module_struct *module = makefile->ASN1Modules + i;
2581 if (module->dir_name == NULL || !makefile->central_storage) {
2582 print_generated_file_name(fp, module, FALSE, ".o");
2583 if (makefile->code_splitting_mode != NULL)
2584 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2585 print_generated_file_name(fp, module, FALSE, "_seq.o");
2586 print_generated_file_name(fp, module, FALSE, "_set.o");
2587 print_generated_file_name(fp, module, FALSE, "_seqof.o");
2588 print_generated_file_name(fp, module, FALSE, "_setof.o");
2589 print_generated_file_name(fp, module, FALSE, "_union.o");
2590 }
2591 }
2592 }
2593 }
2594
2595 fputs("\n\nUSER_OBJECTS =", fp);
2596 if (makefile->gnu_make && makefile->UserSourcesRegular) {
2597 fputs(" $(USER_SOURCES:.cc=.o)", fp);
2598 } else {
2599 for (i = 0; i < makefile->nUserFiles; i++) {
2600 const struct user_struct *user = makefile->UserFiles + i;
2601 if (user->dir_name == NULL || !makefile->central_storage)
2602 print_object_name(fp, user);
2603 }
2604 }
2605 fprint_extra_targets(fp, makefile->target_placement_list, "USER_OBJECTS");
2606
2607 if (makefile->gcc_dep) {
2608 /* GNU Make processes included makefiles in reverse order. By putting
2609 * user sources first, their .d will be generated last, after the
2610 * GENERATED_SOURCES (and GENERATED_HEADERS) have been created.
2611 * This avoid spurious errors during incremental dependency generation */
2612 fputs("\n\nDEPFILES = $(USER_OBJECTS:.o=.d) $(GENERATED_OBJECTS:.o=.d)", fp);
2613 }
2614
2615 if (makefile->central_storage) {
2616 if (makefile->dynamic) {
2617 fputs("\n\n"
2618 "# Shared object files of central project(s):\n"
2619 "BASE_SHARED_OBJECTS =", fp);
2620 if (!makefile->linkingStrategy) {
2621 if (makefile->gnu_make) {
2622 fputs(" $(BASE_GENERATED_SOURCES:.cc=.so)", fp);
2623 }
2624 else {
2625 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2626 const struct module_struct *module = makefile->TTCN3Modules + i;
2627 if (module->dir_name != NULL)
2628 print_generated_file_name(fp, module, TRUE, ".so");
2629 }
2630 if (makefile->preprocess) {
2631 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2632 const struct module_struct *module =
2633 makefile->TTCN3PPModules + i;
2634 if (module->dir_name != NULL)
2635 print_generated_file_name(fp, module, TRUE, ".so");
2636 }
2637 }
2638 for (i = 0; i < makefile->nASN1Modules; i++) {
2639 const struct module_struct *module = makefile->ASN1Modules + i;
2640 if (module->dir_name != NULL)
2641 print_generated_file_name(fp, module, TRUE, ".so");
2642 }
2643 }
2644 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
2645 fputs(" $(BASE_USER_SOURCES:.cc=.so)", fp);
2646 }
2647 else {
2648 for (i = 0; i < makefile->nUserFiles; i++) {
2649 const struct user_struct *user = makefile->UserFiles + i;
2650 if (user->dir_name != NULL)
2651 print_shared_object_name(fp, user);
2652 }
2653 }
2654 }
2655 else { // new linkingStrategy
2656 if (makefile->gnu_make) {
2657 fputs(" $(BASE_GENERATED_SOURCES:.cc=.so)", fp);
2658 }
2659 else
2660 ERROR("the usage of 'Z' flag requires GNU make");
2661
2662 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
2663 fputs(" $(BASE_USER_SOURCES:.cc=.so)", fp);
2664 }
2665 else {
2666 for (i = 0; i < makefile->nUserFiles; i++) {
2667 const struct user_struct *user = makefile->UserFiles + i;
2668 if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name))
2669 print_shared_object_name(fp, user);
2670 }
2671 }
2672 }
2673 } /* if dynamic */
2674 fputs("\n\n"
2675 "# Object files of central project(s) that are needed for the "
2676 "executable test suite:\n"
2677 "BASE_OBJECTS =", fp);
2678 if (!makefile->linkingStrategy) {
2679 if (makefile->gnu_make) {
2680 fputs(" $(BASE_GENERATED_SOURCES:.cc=.o)", fp);
2681 }
2682 else {
2683 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2684 const struct module_struct *module = makefile->TTCN3Modules + i;
2685 if (module->dir_name != NULL)
2686 print_generated_file_name(fp, module, TRUE, ".o");
2687 }
2688 if (makefile->preprocess) {
2689 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2690 const struct module_struct *module = makefile->TTCN3PPModules + i;
2691 if (module->dir_name != NULL)
2692 print_generated_file_name(fp, module, TRUE, ".o");
2693 }
2694 }
2695 for (i = 0; i < makefile->nASN1Modules; i++) {
2696 const struct module_struct *module = makefile->ASN1Modules + i;
2697 if (module->dir_name != NULL)
2698 print_generated_file_name(fp, module, TRUE, ".o");
2699 }
2700 }
2701 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
2702 fputs(" $(BASE_USER_SOURCES:.cc=.o)", fp);
2703 }
2704 else {
2705 for (i = 0; i < makefile->nUserFiles; i++) {
2706 const struct user_struct *user = makefile->UserFiles + i;
2707 if (user->dir_name != NULL)
2708 print_object_name(fp, user);
2709 }
2710 }
2711 }
2712 else { // new linkingStrategy
2713 if (makefile->gnu_make) {
2714 fputs(" $(BASE_GENERATED_SOURCES:.cc=.o)", fp);
2715 }
2716 else
2717 ERROR("the usage of 'Z' flag requires GNU make");
2718
2719 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
2720 fputs(" $(BASE_USER_SOURCES:.cc=.o)", fp);
2721 }
2722 else {
2723 for (i = 0; i < makefile->nUserFiles; i++) {
2724 const struct user_struct *user = makefile->UserFiles + i;
2725 if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name))
2726 print_object_name(fp, user);
2727 }
2728 }
2729 }
2730 }
2731 if (makefile->linkingStrategy) {
2732 fputs("\n\n"
2733 "# Object files of library linked central project(s) that are needed for the "
2734 "executable test suite:\n"
2735 "BASE2_OBJECTS =", fp);
2736 if (makefile->gnu_make) {
2737 if (makefile->dynamic)
2738 fputs(" $(BASE2_GENERATED_SOURCES:.cc=.so)", fp);
2739 else
2740 fputs(" $(BASE2_GENERATED_SOURCES:.cc=.o)", fp);
2741 }
2742 else ERROR("the usage of 'Z' flag requires GNU make");
2743
2744 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
2745 if (makefile->dynamic)
2746 fputs(" $(BASE2_USER_SOURCES:.cc=.so)", fp);
2747 else
2748 fputs(" $(BASE2_USER_SOURCES:.cc=.o)", fp);
2749 }
2750 else {
2751 for (i = 0; i < makefile->nUserFiles; i++) {
2752 const struct user_struct *user = makefile->UserFiles + i;
2753 if (user->dir_name != NULL && isSourceFileInLibrary(user->source_name)) {
2754 if (makefile->dynamic)
2755 print_shared_object_name(fp, user);
2756 else
2757 print_object_name(fp, user);
2758 }
2759 }
2760 }
2761 if (makefile->hierarchical) {
2762 fputs("\n\n"
2763 "#Libraries of referenced project(s) that are needed for the "
2764 "executable or library target:\n"
2765 "BASE2_LIBRARY =", fp);
2766 struct string2_list* head = getLinkerLibs(makefile->project_name);
2767 struct string2_list* act_elem = head;
2768 while (act_elem) {
2769 if (act_elem->str2) {
2770 fputs(" ", fp);
2771 fprintf(fp, "%s/lib%s.%s", act_elem->str1, act_elem->str2,
2772 isDynamicLibrary(act_elem->str2) ? "so" : "a");
2773 }
2774 act_elem = act_elem->next;
2775 }
2776 free_string2_list(head);
2777 }
2778 }
2779
2780 fputs("\n\n"
2781 "# Other files of the project (Makefile, configuration files, etc.)\n"
2782 "# that will be added to the archived source files:\n"
2783 "OTHER_FILES =", fp);
2784 for (i = 0; i < makefile->nOtherFiles; i++)
2785 fprintf(fp, " %s", makefile->OtherFiles[i]);
2786 fprint_extra_targets(fp, makefile->target_placement_list, "OTHER_FILES");
2787
2788 if (makefile->ets_name) {
2789 const char *ets_suffix = NULL;
2790 /* EXECUTABLE variable */
2791 fprintf(fp, "\n\n"
2792 "# The name of the executable test suite:\n"
2793 "EXECUTABLE = %s", makefile->ets_name);
2794 #ifdef WIN32
2795 {
2796 /* add the .exe suffix unless it is already present */
2797 ets_suffix = get_suffix(makefile->ets_name);
2798 if (ets_suffix == NULL || strcmp(ets_suffix, "exe"))
2799 fputs(".exe", fp);
2800 }
2801 #endif
2802 fputs("\n\n", fp);
2803 if (makefile->linkingStrategy) {
2804 #ifndef WIN32
2805 fputs("DYNAMIC_LIBRARY = lib$(EXECUTABLE).so\n", fp);
2806 fputs("STATIC_LIBRARY = lib$(EXECUTABLE).a\n", fp);
2807 #else
2808 char* name_prefix = cut_suffix(makefile->ets_name);
2809 fprintf(fp, "DYNAMIC_LIBRARY = lib%s.so\n", name_prefix);
2810 fprintf(fp, "STATIC_LIBRARY = lib%s.a\n", name_prefix);
2811 Free(name_prefix);
2812 #endif
2813 }
2814 /* LIBRARY variable */
2815 ets_suffix = get_suffix(makefile->ets_name);
2816 if (ets_suffix != NULL && !strcmp(ets_suffix, "exe")) {
2817 char* name_prefix = cut_suffix(makefile->ets_name);
2818 fprintf(fp, "\n\nLIBRARY = %s%s%s\n", "lib", name_prefix ? name_prefix : "library",
2819 makefile->dynamic ? ".so" : ".a");
2820 Free(name_prefix);
2821 }
2822 else {
2823 #ifndef WIN32
2824 fprintf(fp, "\n\nLIBRARY = lib$(EXECUTABLE)%s\n",
2825 makefile->dynamic ? ".so" : ".a");
2826 #else
2827 fprintf(fp, "\n\nLIBRARY = lib%s%s\n",
2828 makefile->ets_name, makefile->dynamic ? ".so" : ".a");
2829 #endif
2830 }
2831
2832 } else {
2833 fputs("\n\n"
2834 "# The name of the executable test suite:\n"
2835 "EXECUTABLE =\n"
2836 "LIBRARY =\n", fp);
2837 }
2838 if (!makefile->linkingStrategy || !buildObjects(makefile->project_name, add_refd_prjs)) {
2839 fprintf(fp, "\n"
2840 "TARGET = $(%s)", makefile->library ? "LIBRARY" : "EXECUTABLE");
2841 }
2842 else {
2843 if (makefile->dynamic) {
2844 fputs("\n"
2845 "TARGET = $(SHARED_OBJECTS)", fp);
2846 }
2847 else {
2848 fputs("\n"
2849 "TARGET = $(OBJECTS)", fp);
2850 }
2851 }
2852 fputs("\n\n"
2853 "#\n"
2854 "# Do not modify these unless you know what you are doing...\n"
2855 "# Platform specific additional libraries:\n"
2856 "#\n", fp);
2857
2858 fputs("SOLARIS_LIBS = -lsocket -lnsl -lxml2", fp);
2859 #ifdef USAGE_STATS
2860 fputs(" -lresolv", fp);
2861 #endif
2862 if (makefile->solspeclibraries) {
2863 struct string_list* act_elem = makefile->solspeclibraries;
2864 while (act_elem) {
2865 if (act_elem->str) {
2866 fprintf(fp, " -l%s", act_elem->str);
2867 }
2868 act_elem = act_elem->next;
2869 }
2870 }
2871 fputs("\n", fp);
2872
2873 fputs("SOLARIS8_LIBS = -lsocket -lnsl -lxml2", fp);
2874 #ifdef USAGE_STATS
2875 fputs(" -lresolv", fp);
2876 #endif
2877 if (makefile->sol8speclibraries) {
2878 struct string_list* act_elem = makefile->sol8speclibraries;
2879 while (act_elem) {
2880 if (act_elem->str) {
2881 fprintf(fp, " -l%s", act_elem->str);
2882 }
2883 act_elem = act_elem->next;
2884 }
2885 }
2886 fputs("\n", fp);
2887
2888 fputs("LINUX_LIBS = -lxml2", fp);
2889 #ifdef USAGE_STATS
2890 fputs(" -lpthread -lrt", fp);
2891 #endif
2892 if (makefile->linuxspeclibraries) {
2893 struct string_list* act_elem = makefile->linuxspeclibraries;
2894 while (act_elem) {
2895 if (act_elem->str) {
2896 fprintf(fp, " -l%s", act_elem->str);
2897 }
2898 act_elem = act_elem->next;
2899 }
2900 }
2901 fputs("\n", fp);
2902
2903 fputs("FREEBSD_LIBS = -lxml2", fp);
2904 if (makefile->freebsdspeclibraries) {
2905 struct string_list* act_elem = makefile->freebsdspeclibraries;
2906 while (act_elem) {
2907 if (act_elem->str) {
2908 fprintf(fp, " -l%s", act_elem->str);
2909 }
2910 act_elem = act_elem->next;
2911 }
2912 }
2913 fputs("\n", fp);
2914
2915 fputs("WIN32_LIBS = -lxml2", fp);
2916 if (makefile->win32speclibraries) {
2917 struct string_list* act_elem = makefile->win32speclibraries;
2918 while (act_elem) {
2919 if (act_elem->str) {
2920 fprintf(fp, " -l%s", act_elem->str);
2921 }
2922 act_elem = act_elem->next;
2923 }
2924 }
2925 fputs("\n\n", fp);
2926
2927 fputs("#\n"
2928 "# Rules for building the executable...\n"
2929 "#\n\n", fp);
2930 fprintf(fp, "all:%s $(TARGET) ;\n\n", add_refd_prjs?" referenced-all":"");
2931
2932 if (makefile->dynamic) {
2933 fprintf(fp, "shared_objects:%s $(SHARED_OBJECTS) ;\n\n", add_refd_prjs?" referenced-shared_objects":"");
2934 }
2935
2936 fprintf(fp,
2937 "executable:%s $(EXECUTABLE) ;\n\n"
2938 "library:%s $(LIBRARY) ;\n\n"
2939 "objects:%s $(OBJECTS) compile;\n\n", add_refd_prjs?" referenced-executable":"", add_refd_prjs?" referenced-library":"", add_refd_prjs?" referenced-objects":"");
2940
2941 /* target $(EXECUTABLE) */
2942 if (makefile->dynamic && makefile->library) {
2943 /* There is no need to create the .so for all the source files */
2944 fputs("$(EXECUTABLE): $(LIBRARY)\n"
2945 "\tif $(CXX) $(LDFLAGS) -o $@ $(LIBRARY)", fp);
2946 }
2947 else {
2948 fprintf(fp, "$(EXECUTABLE): %s", makefile->dynamic ? "$(SHARED_OBJECTS)" : "$(OBJECTS)");
2949 if (!makefile->linkingStrategy) { // use the old linking method
2950 if (makefile->central_storage) {
2951 if (makefile->dynamic) {
2952 fputs(" $(BASE_SHARED_OBJECTS)", fp);
2953 } else {
2954 fputs(" $(BASE_OBJECTS)", fp);
2955 }
2956 }
2957 }
2958 else {
2959 if (!makefile->library) {
2960 if (makefile->dynamic) {
2961 fputs(" $(BASE_SHARED_OBJECTS)", fp);
2962 }
2963 else {
2964 fputs(" $(BASE_OBJECTS)", fp);
2965 }
2966 if (makefile->hierarchical) {
2967 fputs(" $(BASE2_LIBRARY)", fp);
2968 }
2969 }
2970 }
2971 fprintf(fp, "\n"
2972 "\tif $(CXX) $(LDFLAGS) -o $@ %s",
2973 #if defined (SOLARIS) || defined (SOLARIS8)
2974 "");
2975 #else
2976 makefile->dynamic ? "-Wl,--no-as-needed " : ""); /* start writing the link step */
2977 #endif
2978 if (makefile->gnu_make) fputs("$^", fp);
2979 else {
2980 if (makefile->dynamic) {
2981 fputs("$(SHARED_OBJECTS)", fp);
2982 if (makefile->central_storage)
2983 fputs(" $(BASE_SHARED_OBJECTS)", fp);
2984 }
2985 else {
2986 fputs("$(OBJECTS)", fp);
2987 if (makefile->central_storage)
2988 fputs(" $(BASE_OBJECTS)", fp);
2989 }
2990 }
2991 }
2992
2993 if (makefile->additionalObjects) {
2994 struct string_list* act_elem = makefile->additionalObjects;
2995 while (act_elem) {
2996 if (act_elem->str) {
2997 fprintf(fp, " %s", act_elem->str);
2998 }
2999 act_elem = act_elem->next;
3000 }
3001 }
3002
3003 fprintf(fp, " \\\n"
3004 "\t-L$(TTCN3_DIR)/lib -l$(TTCN3_LIB)"
3005 " \\\n"
3006 "\t-L$(OPENSSL_DIR)/lib -lcrypto");
3007 if (!makefile->linkingStrategy) {
3008 if (makefile->linkerlibraries) {
3009 struct string_list* act_elem = makefile->linkerlibraries;
3010 while (act_elem) {
3011 if (act_elem->str) {
3012 fprintf(fp, " -l%s", act_elem->str);
3013 }
3014 act_elem = act_elem->next;
3015 }
3016 }
3017 if (makefile->linkerlibsearchpath) {
3018 struct string_list* act_elem = makefile->linkerlibsearchpath;
3019 while (act_elem) {
3020 if (act_elem->str) {
3021 fprintf(fp, " -L%s", act_elem->str);
3022 }
3023 act_elem = act_elem->next;
3024 }
3025 }
3026 fprintf(fp, " \\\n"
3027 "\t-L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \\\n"
3028 "\tthen : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi\n");
3029 }
3030 else { // new linking strategy
3031 fputs (" \\\n", fp);
3032 if (makefile->linkerlibraries && !makefile->library) {
3033 struct string2_list* head = getLinkerLibs(makefile->project_name);
3034 struct string2_list* act_elem = head;
3035 while (act_elem) {
3036 if (act_elem->str1 && act_elem->str2) {
3037 fprintf(fp, "\t-L%s -Wl,-rpath=%s -l%s \\\n", act_elem->str1, act_elem->str1, act_elem->str2);
3038 }
3039 act_elem = act_elem->next;
3040 }
3041 free_string2_list(head);
3042
3043 struct string_list* act_head = getExternalLibPathes(makefile->project_name);
3044 struct string_list* act_ext_elem = act_head;
3045 while (act_ext_elem) {
3046 if (act_ext_elem->str) {
3047 fprintf(fp, "\t-L%s \\\n", act_ext_elem->str);
3048 }
3049 act_ext_elem = act_ext_elem->next;
3050 }
3051 free_string_list(act_head);
3052 act_head = getExternalLibs(makefile->project_name);
3053 act_ext_elem = act_head;
3054 while (act_ext_elem) {
3055 if (act_ext_elem->str) {
3056 fprintf(fp, "\t-l%s \\\n", act_ext_elem->str);
3057 }
3058 act_ext_elem = act_ext_elem->next;
3059 }
3060 free_string_list(act_head);
3061 }
3062 fprintf(fp,
3063 "\t-L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \\\n"
3064 "\tthen : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi\n");
3065 }
3066 /* If the compiler will not be run because there are no TTCN(PP) or ASN.1
3067 * files, create the "compile" marker file which is checked by the
3068 * superior makefile if using this project as central storage */
3069 if (!run_compiler) fputs("\ttouch compile\n", fp);
3070 /* End of target $(EXECUTABLE) */
3071
3072 /* target $(LIBRARY) */
3073 if (makefile->dynamic) {
3074 fprintf(fp, "\n"
3075 "$(LIBRARY): $(OBJECTS)%s\n"
3076 "\t$(CXX) -shared -o $@ $(OBJECTS)",
3077 makefile->hierarchical ? " $(BASE2_LIBRARY)" : "");
3078 if (makefile->central_storage && !makefile->linkingStrategy) {
3079 fputs(" $(BASE_SHARED_OBJECTS) ;\n"
3080 "\tln -s $@ $(subst lib, ,$@) > /dev/null 2>&1 ;", fp);
3081 }
3082 if (makefile->linkingStrategy) {
3083 struct string2_list* head = getLinkerLibs(makefile->project_name);
3084 struct string2_list* act_elem = head;
3085 // If the project is Executable on Top Level the linker can link the *.a and *.so together
3086 while (act_elem && !isTopLevelExecutable(makefile->project_name)) {
3087 if (act_elem->str1 && act_elem->str2 && isDynamicLibrary(act_elem->str2)) {
3088 fputs(" \\\n", fp);
3089 fprintf(fp, "\t-L%s -Wl,-rpath=%s -l%s", act_elem->str1, act_elem->str1, act_elem->str2);
3090 }
3091 else {
3092 const char* mainLibName = getLibFromProject(makefile->project_name);
3093 ERROR("Library archive 'lib%s.a' cannot be linked to dynamic library 'lib%s.so' "
3094 "in project '%s' ",
3095 act_elem->str2, mainLibName ? mainLibName : "", makefile->project_name);
3096 free_string2_list(head);
3097 exit(EXIT_FAILURE);
3098 }
3099 act_elem = act_elem->next;
3100 }
3101 free_string2_list(head);
3102 struct string_list* act_head = getExternalLibPathes(makefile->project_name);
3103 struct string_list* act_ext_elem = act_head;
3104 while (act_ext_elem) {
3105 if (act_ext_elem->str) {
3106 fputs(" \\\n", fp);
3107 fprintf(fp, "\t-L%s", act_ext_elem->str);
3108 }
3109 act_ext_elem = act_ext_elem->next;
3110 }
3111 free_string_list(act_head);
3112 act_head = getExternalLibs(makefile->project_name);
3113 act_ext_elem = act_head;
3114 while (act_ext_elem) {
3115 if (act_ext_elem->str) {
3116 fputs(" \\\n", fp);
3117 fprintf(fp, "\t-l%s", act_ext_elem->str);
3118 }
3119 act_ext_elem = act_ext_elem->next;
3120 }
3121 free_string_list(act_head);
3122 }
3123 }
3124 else { // static linking
3125 fprintf(fp, "\n"
3126 "$(LIBRARY): $(OBJECTS)%s\n"
3127 "\t$(AR) -r%s $(ARFLAGS) $(LIBRARY) $(OBJECTS)",
3128 makefile->hierarchical ? " $(BASE2_LIBRARY)" : "",
3129 makefile->linkingStrategy ? "cT" : "");
3130 if (makefile->central_storage && !makefile->linkingStrategy) {
3131 fputs(" $(BASE_OBJECTS)", fp);
3132 }
3133 if (makefile->linkingStrategy) {
3134 if ( makefile->library) {
3135 struct string2_list* head = getLinkerLibs(makefile->project_name);
3136 struct string2_list* act_elem = head;
3137 while (act_elem) {
3138 if (act_elem->str2 && !isDynamicLibrary(act_elem->str2)) {
3139 fputs(" \\\n", fp);
3140 fprintf(fp, "\t%s/lib%s.a", act_elem->str1, act_elem->str2);
3141 }
3142 else {
3143 const char* mainLibName = getLibFromProject(makefile->project_name);
3144 if (act_elem->str2) {
3145 ERROR("Dynamic library 'lib%s.so' cannot be linked to static library 'lib%s.a' "
3146 "in project '%s' ",
3147 act_elem->str2, mainLibName ? mainLibName : "", makefile->project_name);
3148 exit(EXIT_FAILURE);
3149 }
3150 else {
3151 struct string_list* ext_libs = getExternalLibs(makefile->project_name);
3152 if (ext_libs && ext_libs->str) {
3153 ERROR("Third party dynamic library '%s' cannot be linked to static library 'lib%s.a' "
3154 "in project '%s' ", ext_libs->str,
3155 mainLibName ? mainLibName : "", makefile->project_name);
3156 free_string_list(ext_libs);
3157 exit(EXIT_FAILURE);
3158 }
3159 free_string_list(ext_libs);
3160 }
3161 }
3162 act_elem = act_elem->next;
3163 }
3164 free_string2_list(head);
3165
3166 struct string_list* act_head = getExternalLibs(makefile->project_name);
3167 struct string_list* act_ext_elem = act_head;
3168 while (act_ext_elem) {
3169 if (act_ext_elem->str && hasExternalLibrary(act_ext_elem->str, makefile->project_name)) {
3170 fputs(" \\\n", fp);
3171 fprintf(fp, "\tlib%s.a", act_ext_elem->str);
3172 ERROR("linking static 3d party or sytem library 'lib%s.a' to "
3173 "project library 'lib%s.a' is not supported ",
3174 act_ext_elem->str, makefile->ets_name);
3175 exit(EXIT_FAILURE);
3176 }
3177 act_ext_elem = act_ext_elem->next;
3178 }
3179 free_string_list(act_head);
3180 }
3181 }
3182 }
3183 fputs("\n\n.cc.o .c.o:\n"
3184 "\t$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $<\n\n", fp);
3185
3186 if (makefile->gcc_dep) {
3187 fputs(".cc.d .c.d:\n"
3188 "\t@echo Creating dependency file for '$<'; set -e; \\\n"
3189 "\t$(CXX) $(CXXDEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $< \\\n"
3190 "\t| sed 's/\\($*\\)\\.o[ :]*/\\1.o $@ : /g' > $@; \\\n"
3191 "\t[ -s $@ ] || rm -f $@\n\n", fp);
3192 /* "set -e" causes bash to exit the script if any statement
3193 * returns nonzero (failure).
3194 * The sed line transforms the first line of the dependency from
3195 * "x.o: x.cc" to "x.o x.d: x.cc", making the dependency file depend
3196 * on the source and headers.
3197 * [ -s x.d ] checks that the generated dependency is not empty;
3198 * otherwise it gets deleted.
3199 */
3200 }
3201
3202 if (makefile->dynamic) {
3203 fputs("%.so: %.o\n"
3204 "\t$(CXX) -shared -o $@ $<\n\n", fp);
3205 }
3206
3207 if (makefile->preprocess) {
3208 fputs("%.ttcn: %.ttcnpp $(TTCN3_INCLUDES)\n"
3209 "\t$(CPP) -x c -nostdinc $(CPPFLAGS_TTCN3) $< $@\n\n"
3210 "preprocess: $(PREPROCESSED_TTCN3_MODULES) ;\n\n", fp);
3211 }
3212
3213 if (makefile->central_storage) {
3214 boolean is_first = TRUE;
3215 fprintf(fp, "$(GENERATED_SOURCES) $(GENERATED_HEADERS):%s compile-all compile ",
3216 makefile->hierarchical ? " update" : "");
3217
3218 if (add_refd_prjs) fputs("referenced-dep", fp);
3219 /* These extra compile dependencies for the generated .cc are here to
3220 * check if all the referenced projects are up to date.
3221 * If the referenced projects are built too then they are not needed
3222 * (and cause problems as the included .d depends on the .cc).
3223 */
3224 if (!add_refd_prjs) for (i = 0; i < makefile->nBaseDirs; i++) {
3225 const struct base_dir_struct *base_dir = makefile->BaseDirs + i;
3226 if (base_dir->has_modules) {
3227 if (is_first) {
3228 fputs(" \\\n", fp);
3229 is_first = FALSE;
3230 }
3231 else putc(' ', fp);
3232 fprintf(fp, "%s/compile", base_dir->dir_name);
3233 }
3234 }
3235 if (makefile->preprocess) {
3236 fprintf(fp, "\n"
3237 "\t@if [ ! -f $@ ]; then %s compile-all; $(MAKE) compile-all; fi\n"
3238 "\n"
3239 "check:%s $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3240 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
3241 "%s\\\n"
3242 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n"
3243 "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ",
3244 rm_command, add_refd_prjs?" referenced-check":"",
3245 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3246 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
3247 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3248 if (makefile->gnu_make) {
3249 if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul
3250 fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3251 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
3252 "%s\\\n"
3253 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n",
3254 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3255 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
3256 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3257 else
3258 fputs("$^", fp);
3259 }
3260 else {
3261 fputs("\\\n"
3262 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n"
3263 "\t$(PREPROCESSED_TTCN3_MODULES) "
3264 "$(BASE_PREPROCESSED_TTCN3_MODULES) \\\n"
3265 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)", fp);
3266 }
3267 if (makefile->linkingStrategy && makefile->hierarchical) {
3268 fputs("\n\n"
3269 "update: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) \\\n"
3270 "\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) $(BASE2_PREPROCESSED_TTCN3_MODULES)\n"
3271 "ifneq ($(wildcard $(GENERATED_SOURCES)), ) \n"
3272 "ifeq ($(wildcard $?), ) \n"
3273 "\ttouch compile-all; \n"
3274 "\ttouch update; \n"
3275 "endif\n"
3276 "endif",fp);
3277 }
3278 fprintf(fp, "\n\n"
3279 "compile: $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) "
3280 "$(ASN1_MODULES)\n"
3281 "\t@echo \"compiling \"'$(patsubst %%.tpd, %%, $(TPD))';\n"
3282 "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
3283 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3284 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) %s\\\n"
3285 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s - $?\n"
3286 "\ttouch $@\n\n",
3287 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3288 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
3289 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES)":"");
3290 fprintf (fp,
3291 "compile-all: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
3292 "%s"
3293 "\t$(MAKE) preprocess\n"
3294 "\t@echo \"compiling all \"'$(patsubst %%.tpd, %%, $(TPD))';\n"
3295 "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
3296 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3297 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) %s"
3298 "\\\n"
3299 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
3300 "\t- $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES)\n"
3301 "\ttouch $@ compile\n\n",
3302 makefile->linkingStrategy ? "\\\n\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) "
3303 "$(BASE2_PREPROCESSED_TTCN3_MODULES) \n":"\n",
3304 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3305 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
3306 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3307 }
3308 else {
3309 fprintf(fp, "\n"
3310 "\t@if [ ! -f $@ ]; then %s compile-all; $(MAKE) compile-all; fi\n", rm_command);
3311 fprintf(fp, "\n"
3312 "check:%s $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3313 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n"
3314 "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ",
3315 add_refd_prjs?" referenced-check":"",
3316 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3317 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3318 if (makefile->gnu_make) {
3319 if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul
3320 fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3321 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n",
3322 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3323 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3324 else
3325 fputs("$^", fp);
3326 }
3327 else {
3328 fputs("\\\n"
3329 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n"
3330 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)", fp);
3331 }
3332
3333 if (makefile->linkingStrategy && makefile->hierarchical) {
3334 fputs("\n\n"
3335 "update: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) \\\n"
3336 "\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) $(BASE2_PREPROCESSED_TTCN3_MODULES)\n"
3337 "ifneq ($(wildcard $(GENERATED_SOURCES)), ) \n"
3338 "ifeq ($(wildcard $?), ) \n"
3339 "\ttouch compile-all; \n"
3340 "\ttouch update; \n"
3341 "endif\n"
3342 "endif",fp);
3343 }
3344
3345 fprintf(fp, "\n\n"
3346 "compile: $(TTCN3_MODULES) $(ASN1_MODULES)\n"
3347 "\t@echo \"compiling \"'$(patsubst %%.tpd, %%, $(TPD))';\n"
3348 "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
3349 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3350 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
3351 "\t- $?\n"
3352 "\ttouch $@\n\n",
3353 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "",
3354 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : "");
3355 fprintf(fp,
3356 "compile-all: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) %s\n",
3357 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES)" : "");
3358 fputs("\t@echo \"compiling all \"'$(patsubst %.tpd, %, $(TPD))';\n", fp);
3359 fprintf(fp,"\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
3360 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3361 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
3362 "\t- $(TTCN3_MODULES) $(ASN1_MODULES)\n"
3363 "\ttouch $@ compile\n\n",
3364 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "",
3365 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : "");
3366 }
3367 if (!makefile->hierarchical)
3368 for (i = 0; i < makefile->nBaseDirs; i++) {
3369 const struct base_dir_struct *base_dir = makefile->BaseDirs + i;
3370 if (base_dir->has_modules) {
3371 size_t j;
3372 fprintf(fp, "%s/compile:", base_dir->dir_name);
3373 for (j = 0; j < makefile->nTTCN3Modules; j++) {
3374 const struct module_struct *module = makefile->TTCN3Modules + j;
3375 if (module->dir_name != NULL &&
3376 !strcmp(base_dir->dir_name, module->dir_name))
3377 print_file_name(fp, module);
3378 }
3379 for (j = 0; j < makefile->nTTCN3PPModules; j++) {
3380 const struct module_struct *module = makefile->TTCN3PPModules + j;
3381 if (module->dir_name != NULL &&
3382 !strcmp(base_dir->dir_name, module->dir_name))
3383 print_file_name(fp, module);
3384 }
3385 for (j = 0; j < makefile->nASN1Modules; j++) {
3386 const struct module_struct *module = makefile->ASN1Modules + j;
3387 if (module->dir_name != NULL &&
3388 !strcmp(base_dir->dir_name, module->dir_name))
3389 print_file_name(fp, module);
3390 }
3391 fprintf(fp, "\n"
3392 "\t@echo 'Central directory %s is not up-to-date!'\n"
3393 "\t@exit 2\n\n", base_dir->dir_name);
3394 }
3395 }
3396 }
3397 else { /* not central storage */
3398 fprintf(fp, "$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile\n"
3399 "\t@if [ ! -f $@ ]; then %s compile; $(MAKE) compile; fi\n\n"
3400 "check: $(TTCN3_MODULES) ", rm_command);
3401 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3402 fputs("$(ASN1_MODULES)\n"
3403 "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ", fp);
3404 if (makefile->gnu_make) fputs("$^", fp);
3405 else {
3406 fputs("\\\n"
3407 "\t$(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES)",
3408 fp);
3409 }
3410 fputs("\n\n"
3411 "compile: $(TTCN3_MODULES) ", fp);
3412 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3413 fputs("$(ASN1_MODULES)\n"
3414 "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) ", fp);
3415 if (makefile->gnu_make) fputs("$^", fp);
3416 else {
3417 fputs("\\\n"
3418 "\t$(TTCN3_MODULES) ", fp);
3419 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3420 fputs("$(ASN1_MODULES)", fp);
3421 }
3422 fputs(" - $?\n"
3423 "\ttouch $@\n"
3424 "\n", fp);
3425 }
3426 // clean:
3427 if (makefile->linkingStrategy) {
3428 fprintf(fp, "clean:%s\n", (add_refd_prjs && !makefile->hierarchical) ?
3429 " referenced-clean" : "");
3430 if (makefile->dynamic && (makefile->central_storage || makefile->linkingStrategy)) {
3431 fprintf(fp,"\tfind . -type l -name \"*.so\" -exec unlink {} \\;\n");
3432 }
3433 fprintf(fp, "\t%s $(EXECUTABLE) $(DYNAMIC_LIBRARY) $(STATIC_LIBRARY) "
3434 "$(OBJECTS) $(GENERATED_HEADERS) \\\n"
3435 "\t$(GENERATED_SOURCES) ", rm_command);
3436 if (makefile->dynamic) fputs("$(SHARED_OBJECTS) ", fp);
3437 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3438 fputs("compile", fp);
3439 if (makefile->central_storage) fputs(" compile-all", fp);
3440 if (makefile->gcc_dep) fputs(" $(DEPFILES)", fp);
3441 fprintf(fp, " \\\n"
3442 "\ttags *.log%s%s\n\n",
3443 add_refd_prjs?" referenced*":"",
3444 makefile->hierarchical ? " update":"");
3445 }
3446 else {
3447 fprintf(fp, "clean:%s\n"
3448 "\t-%s $(EXECUTABLE) $(LIBRARY) $(OBJECTS) $(GENERATED_HEADERS) \\\n"
3449 "\t$(GENERATED_SOURCES) ", add_refd_prjs?" referenced-clean":"", rm_command);
3450 if (makefile->dynamic) fputs("$(SHARED_OBJECTS) ", fp);
3451 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3452 fputs("compile", fp);
3453 if (makefile->central_storage) fputs(" compile-all", fp);
3454 if (makefile->gcc_dep) fputs(" $(DEPFILES)", fp);
3455 fprintf(fp, " \\\n"
3456 "\ttags *.log%s",
3457 add_refd_prjs?" referenced*":"");
3458 }
3459
3460 // clean-all:
3461 if (makefile->linkingStrategy && makefile->hierarchical)
3462 fprintf(fp, "clean-all: %s clean\n", add_refd_prjs ? "referenced-clean-all":"");
3463
3464 // dep:
3465 fputs("\n\ndep: $(GENERATED_SOURCES) $(USER_SOURCES)",fp);
3466 if (add_refd_prjs) {
3467 fprintf(fp, "\n\t%s referenced-dep", rm_command);
3468 }
3469 else fputs(" ;",fp);
3470
3471 if (makefile->gcc_dep) {
3472 fprintf(fp, " \n\n"
3473 "ifeq ($(findstring n,$(MAKEFLAGS)),)\n"
3474 "ifeq ($(filter clean%s check compile archive diag%s,$(MAKECMDGOALS)),)\n"
3475 "-include $(DEPFILES)\n"
3476 "endif\n"
3477 "endif",
3478 (makefile->linkingStrategy && makefile->hierarchical) ? " clean-all" : "",
3479 (makefile->preprocess ? " preprocess" : ""));
3480 /* Don't include .d files when cleaning etc.; make will try to build them
3481 * and this involves running the Titan compiler. Same for preprocess.
3482 * The check target would be pointless if running the compiler
3483 * without generating code was always preceded by running the compiler
3484 * _and_ generating C++ code. */
3485 }
3486 else { /* old-style dep with makedepend. Do not check compiler version. */
3487 fputs("\n\tmakedepend $(CPPFLAGS) -DMAKEDEPEND_RUN ", fp);
3488 if (makefile->gnu_make) fputs("$^", fp);
3489 else fputs("$(GENERATED_SOURCES) $(USER_SOURCES)", fp);
3490 }
3491
3492 if (makefile->linkingStrategy) {
3493 fputs("\n\n"
3494 "archive:\n"
3495 "\t@perl $(TTCN3_DIR)/bin/ttcn3_archive.pl\n\n", fp);
3496 }
3497 else {
3498 fputs("\n\n"
3499 "archive:\n"
3500 "\tmkdir -p $(ARCHIVE_DIR)\n"
3501 "\ttar -cvhf - ", fp);
3502 if (makefile->central_storage) {
3503 fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n",
3504 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "");
3505 if (makefile->preprocess) {
3506 fprintf(fp, "\t$(TTCN3_PP_MODULES) $(BASE_TTCN3_PP_MODULES) "
3507 "%s $(TTCN3_INCLUDES) \\\n",
3508 makefile->linkingStrategy ? "$(BASE2_TTCN3_PP_MODULES)" : "");
3509 }
3510 fprintf(fp, "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
3511 "\t$(USER_HEADERS) $(BASE_USER_HEADERS) %s\\\n"
3512 "\t$(USER_SOURCES) $(BASE_USER_SOURCES) %s",
3513 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : "",
3514 makefile->linkingStrategy ? "$(BASE2_USER_HEADERS) " : "",
3515 makefile->linkingStrategy ? "$(BASE2_USER_SOURCES)" : "");
3516 }
3517 else {
3518 fputs("$(TTCN3_MODULES) ", fp);
3519 if (makefile->preprocess) {
3520 fputs("$(TTCN3_PP_MODULES) \\\n"
3521 "\t$(TTCN3_INCLUDES) ", fp);
3522 }
3523 fputs("$(ASN1_MODULES) \\\n"
3524 "\t$(USER_HEADERS) $(USER_SOURCES)", fp);
3525 }
3526 fputs(" $(OTHER_FILES) \\\n"
3527 "\t| gzip >$(ARCHIVE_DIR)/`basename $(TARGET) .exe`-"
3528 "`date '+%y%m%d-%H%M'`.tgz\n\n", fp);
3529 }
3530
3531 fprintf(fp, "diag:\n"
3532 "\t$(TTCN3_DIR)/bin/compiler -v 2>&1\n"
3533 "\t$(TTCN3_DIR)/bin/mctr_cli -v 2>&1\n"
3534 "\t$(CXX) -v 2>&1\n"
3535 "%s"
3536 "\t@echo TTCN3_DIR=$(TTCN3_DIR)\n"
3537 "\t@echo OPENSSL_DIR=$(OPENSSL_DIR)\n"
3538 "\t@echo XMLDIR=$(XMLDIR)\n"
3539 "\t@echo PLATFORM=$(PLATFORM)\n\n",
3540 makefile->dynamic ? "" : "\t$(AR) -V 2>&1\n");
3541
3542 if (add_refd_prjs) {
3543 fprintf(fp, "referenced-all referenced-shared_objects referenced-executable referenced-library \\\n"
3544 "referenced-objects referenced-check \\\n"
3545 "referenced-clean%s:\n"
3546 "\t@for dir in $(REFERENCED_PROJECT_DIRS); do \\\n"
3547 "\t $(MAKE) -C $$dir $(subst referenced-,,$@) || exit; \\\n"
3548 "\tdone; \n\n",
3549 (makefile->linkingStrategy && makefile->hierarchical) ? "-all" : "");
3550 fputs("referenced-dep:\n"
3551 "\t@for dir in $(REFERENCED_PROJECT_DIRS); do \\\n"
3552 "\t $(MAKE) -C $$dir $(subst referenced-,,$@) || exit; \\\n"
3553 "\tdone; \n"
3554 "\ttouch $@\n\n", fp);
3555 }
3556
3557 if (makefile->generatorCommandOutput) {
3558 fputs("### Project specific rules generated by user written script:\n\n", fp);
3559 fputs(makefile->generatorCommandOutput, fp);
3560 fputs("\n### End of project specific rules.\n\n", fp);
3561 }
3562
3563 fputs("#\n"
3564 "# Add your rules here if necessary...\n"
3565 "#\n\n", fp);
3566 fclose(fp);
3567 if (strcmp(makefile->output_file, "Makefile")) {
3568 NOTIFY("Makefile skeleton was written to `%s'.", makefile->output_file);
3569 } else {
3570 NOTIFY("Makefile skeleton was generated.");
3571 }
3572 }
3573 else {
3574 ERROR("Output file `%s' already exists. Use switch `%s' to force "
3575 "overwrite.",
3576 makefile->output_file,
3577 makefile->linkingStrategy ? "-F" : "-f");
3578 }
3579 }
3580
3581 #undef COMMENT_PREFIX
3582 #define COMMENT_PREFIX
3583
3584 /** run makefilegen commans for sub-projects */
3585 static void run_makefilegen_commands(struct string2_list* run_command_list)
3586 {
3587 struct string2_list* act_elem = run_command_list;
3588 while (act_elem) {
3589 struct string2_list* next_elem = act_elem->next;
3590 /* run commands if there were no ERRORs */
3591 if ((error_count == 0) && act_elem->str1 && act_elem->str2) {
3592 int rv;
3593 char* sub_proj_effective_work_dir = act_elem->str1;
3594 char* command = act_elem->str2;
3595 char* orig_dir = get_working_dir();
3596 rv = set_working_dir(sub_proj_effective_work_dir);
3597 if (rv) ERROR("Could not set working dir to `%s'", sub_proj_effective_work_dir);
3598 else {
3599 fprintf(stderr, "Executing `%s' in working directory `%s'...\n",
3600 command, sub_proj_effective_work_dir);
3601 rv = system(command);
3602 if (rv) ERROR("Execution failed with error code %d", rv); // TODO: it's not clear what system()'s return codes can be in different situations and platforms
3603 }
3604 rv = set_working_dir(orig_dir);
3605 if (rv) ERROR("Could not restore working dir to `%s'", orig_dir);
3606 Free(orig_dir);
3607 }
3608 Free(act_elem->str1);
3609 Free(act_elem->str2);
3610 Free(act_elem);
3611 act_elem = next_elem;
3612 }
3613 }
3614
3615 /** create symlinks and delete list */
3616 static void generate_symlinks(struct string2_list* create_symlink_list)
3617 {
3618 struct string2_list* act_elem = create_symlink_list;
3619 while (act_elem) {
3620 struct string2_list* next_elem = act_elem->next;
3621 /* create symlinks if there were no ERRORs */
3622 if ((error_count == 0) && act_elem->str1 && act_elem->str2) {
3623 int fail = symlink(act_elem->str1, act_elem->str2);
3624 if (fail) perror(act_elem->str2); /* complain but do not call ERROR() */
3625 }
3626 Free(act_elem->str1);
3627 Free(act_elem->str2);
3628 Free(act_elem);
3629 act_elem = next_elem;
3630 }
3631 }
3632
3633 /** Performs all tasks of Makefile generation based on the given list of
3634 * modules/files (taken from the command line) and options that represent
3635 * command line switches. */
3636 static void generate_makefile(size_t n_arguments, char *arguments[],
3637 size_t n_other_files, const char *other_files[], const char *output_file,
3638 const char *ets_name, char *project_name, boolean gnu_make, boolean single_mode,
3639 boolean central_storage, boolean absolute_paths, boolean preprocess,
3640 boolean dump_makefile_data, boolean force_overwrite, boolean use_runtime_2,
3641 boolean dynamic, boolean makedepend, boolean coverage,
3642 const char *code_splitting_mode, const char *tcov_file_name,
3643 boolean Lflag, boolean Zflag, boolean Hflag, struct string_list* sub_project_dirs, struct string_list* ttcn3_prep_includes,
3644 struct string_list* ttcn3_prep_defines, struct string_list* ttcn3_prep_undefines, struct string_list* prep_includes,
3645 struct string_list* prep_defines, struct string_list* prep_undefines, boolean codesplittpd, boolean quietly, boolean disablesubtypecheck,
3646 const char* cxxcompiler, const char* optlevel, const char* optflags, boolean disableber, boolean disableraw, boolean disabletext,
3647 boolean disablexer, boolean disablejson, boolean forcexerinasn, boolean defaultasomit, boolean gccmsgformat,
3648 boolean linenumbersonlymsg, boolean includesourceinfo, boolean addsourcelineinfo, boolean suppresswarnings,
3649 boolean outparamboundness, struct string_list* solspeclibraries, struct string_list* sol8speclibraries,
3650 struct string_list* linuxspeclibraries, struct string_list* freebsdspeclibraries,
3651 struct string_list* win32speclibraries, const char* ttcn3preprocessor, struct string_list* linkerlibraries,
3652 struct string_list* additionalObjects, struct string_list* linkerlibsearchpath, char* generatorCommandOutput,
3653 struct string2_list* target_placement_list)
3654 {
3655 size_t i;
3656
3657 struct makefile_struct makefile;
3658 init_makefile_struct(&makefile);
3659
3660 makefile.project_name = project_name;
3661 makefile.central_storage = central_storage;
3662 makefile.gnu_make = gnu_make;
3663 makefile.preprocess = preprocess;
3664 makefile.single_mode = single_mode;
3665 makefile.force_overwrite = force_overwrite;
3666 makefile.use_runtime_2 = use_runtime_2;
3667 makefile.dynamic = dynamic;
3668 makefile.gcc_dep = gnu_make && !makedepend;
3669 makefile.coverage = coverage;
3670 makefile.library = Lflag;
3671 makefile.linkingStrategy = Zflag;
3672 makefile.hierarchical = Hflag;
3673 makefile.sub_project_dirs = sub_project_dirs;
3674 makefile.ttcn3_prep_includes = ttcn3_prep_includes;
3675 makefile.ttcn3_prep_defines = ttcn3_prep_defines;
3676 makefile.ttcn3_prep_undefines = ttcn3_prep_undefines;
3677 makefile.prep_includes = prep_includes;
3678 makefile.prep_defines = prep_defines;
3679 makefile.prep_undefines = prep_undefines;
3680 makefile.codesplittpd = codesplittpd;
3681 makefile.quietly = quietly;
3682 makefile.disablesubtypecheck = disablesubtypecheck;
3683 makefile.cxxcompiler = cxxcompiler;
3684 makefile.optlevel = optlevel;
3685 makefile.optflags = optflags;
3686 makefile.disableber = disableber;
3687 makefile.disableraw = disableraw;
3688 makefile.disabletext = disabletext;
3689 makefile.disablexer = disablexer;
3690 makefile.disablejson = disablejson;
3691 makefile.forcexerinasn = forcexerinasn;
3692 makefile.defaultasomit = defaultasomit;
3693 makefile.gccmsgformat = gccmsgformat;
3694 makefile.linenumbersonlymsg = linenumbersonlymsg;
3695 makefile.includesourceinfo = includesourceinfo;
3696 makefile.addsourcelineinfo = addsourcelineinfo;
3697 makefile.suppresswarnings = suppresswarnings;
3698 makefile.outparamboundness = outparamboundness;
3699 makefile.solspeclibraries = solspeclibraries;
3700 makefile.sol8speclibraries = sol8speclibraries;
3701 makefile.linuxspeclibraries = linuxspeclibraries;
3702 makefile.freebsdspeclibraries = freebsdspeclibraries;
3703 makefile.win32speclibraries = win32speclibraries;
3704 makefile.ttcn3preprocessor = ttcn3preprocessor;
3705 makefile.linkerlibraries = linkerlibraries;
3706 makefile.additionalObjects = additionalObjects;
3707 makefile.linkerlibsearchpath = linkerlibsearchpath;
3708 makefile.generatorCommandOutput = generatorCommandOutput;
3709 makefile.target_placement_list = target_placement_list;
3710
3711 for (i = 0; i < n_arguments; i++) {
3712 char *file_name = get_file_name_for_argument(arguments[i]);
3713 if (file_name != NULL) {
3714 FILE *fp = fopen(file_name, "r");
3715 if (fp != NULL) {
3716 char *module_name;
3717 if (is_ttcn3_module(file_name, fp, &module_name)) {
3718 if (is_asn1_module(file_name, fp, NULL)) {
3719 ERROR("File `%s' looks so strange that it can be both ASN.1 and "
3720 "TTCN-3 module. Add it to the Makefile manually.", file_name);
3721 Free(module_name);
3722 } else {
3723 add_ttcn3_module(&makefile, file_name, module_name);
3724 }
3725 } else if (is_asn1_module(file_name, fp, &module_name)) {
3726 if (is_valid_asn1_filename(file_name)) {
3727 add_asn1_module(&makefile, file_name, module_name);
3728 } else {
3729 ERROR("The file name (without suffix) shall be identical to the module name.\n"
3730 "If the name of the ASN.1 module contains a hyphen, the corresponding "
3731 "file name shall contain an underscore character instead.");
3732 }
3733 } else {
3734 add_user_file(&makefile, file_name);
3735 }
3736 fclose(fp);
3737 } else {
3738 ERROR("Cannot open file `%s' for reading: %s", file_name,
3739 strerror(errno));
3740 errno = 0;
3741 }
3742 Free(file_name);
3743 } else if (get_path_status(arguments[i]) == PS_DIRECTORY) {
3744 ERROR("Argument `%s' is a directory.", arguments[i]);
3745 } else {
3746 ERROR("Cannot find any source file for argument `%s'.", arguments[i]);
3747 }
3748 }
3749 for (i = 0; i < n_other_files; i++) {
3750 char *file_name = get_file_name_for_argument(other_files[i]);
3751 if (file_name != NULL) {
3752 add_path_to_list(&makefile.nOtherFiles, &makefile.OtherFiles, file_name,
3753 makefile.working_dir, TRUE);
3754 Free(file_name);
3755 } else if (get_path_status(other_files[i]) == PS_DIRECTORY) {
3756 ERROR("Argument `%s' given as other file is a directory.",
3757 other_files[i]);
3758 } else {
3759 ERROR("Cannot find any other file for argument `%s'.", other_files[i]);
3760 }
3761 }
3762
3763 if (ets_name != NULL) {
3764 char *dir_name = get_dir_name(ets_name, makefile.working_dir);
3765 char *file_name = get_file_from_path(ets_name);
3766 makefile.ets_name = compose_path_name(dir_name, file_name);
3767 Free(dir_name);
3768 Free(file_name);
3769 }
3770
3771 if (code_splitting_mode != NULL) {
3772 makefile.code_splitting_mode = mputprintf(makefile.code_splitting_mode, "-U %s", code_splitting_mode);
3773 }
3774
3775 if (tcov_file_name != NULL) {
3776 makefile.tcov_file_name = mputprintf(makefile.tcov_file_name, "-K %s", tcov_file_name);
3777 }
3778
3779 if (makefile.nTTCN3Modules >= 1) {
3780 if (makefile.ets_name == NULL)
3781 makefile.ets_name = mcopystr(makefile.TTCN3Modules[0].module_name);
3782 } else if (preprocess && (makefile.nTTCN3PPModules >= 1)) {
3783 if (makefile.ets_name == NULL)
3784 makefile.ets_name = mcopystr(makefile.TTCN3PPModules[0].module_name);
3785 } else if (makefile.nASN1Modules >= 1) {
3786 WARNING("No TTCN-3 module was given for the Makefile.");
3787 if (makefile.ets_name == NULL)
3788 makefile.ets_name = mcopystr(makefile.ASN1Modules[0].module_name);
3789 } else if (makefile.nUserFiles > 0) {
3790 WARNING("No TTCN-3 or ASN.1 module was given for the Makefile.");
3791 if (makefile.ets_name == NULL)
3792 makefile.ets_name = mcopystr(makefile.UserFiles[0].file_prefix);
3793 } else {
3794 WARNING("No source files were given for the Makefile");
3795 }
3796
3797 if (output_file != NULL) {
3798 if (get_path_status(output_file) == PS_DIRECTORY)
3799 makefile.output_file = mprintf("%s/Makefile", output_file);
3800 else makefile.output_file = mcopystr(output_file);
3801 } else makefile.output_file = mcopystr("Makefile");
3802 add_path_to_list(&makefile.nOtherFiles, &makefile.OtherFiles,
3803 makefile.output_file, makefile.working_dir, FALSE);
3804
3805 if (preprocess) check_preprocessed_filename_collision(&makefile);
3806 filter_out_generated_files(&makefile);
3807 complete_user_files(&makefile);
3808 if (!absolute_paths) convert_dirs_to_relative(&makefile);
3809 check_special_chars(&makefile);
3810 if (central_storage) collect_base_dirs(&makefile);
3811 check_naming_convention(&makefile);
3812
3813 if (dump_makefile_data) dump_makefile_struct(&makefile, 0);
3814
3815 if (error_count == 0) print_makefile(&makefile);
3816 free_makefile_struct(&makefile);
3817 }
3818
3819 #ifdef COVERAGE_BUILD
3820 #define C_flag "C"
3821 #else
3822 #define C_flag
3823 #endif
3824
3825
3826 static void usage(void)
3827 {
3828 fprintf(stderr, "\n"
3829 "usage: %s [-abc" C_flag "dDfFglLmprRstTVwWXZ] [-K file] [-P dir]"
3830 " [-U none|type] [-e ets_name] [-o dir|file]\n"
3831 " [-t project_descriptor.tpd [-b buildconfig]]\n"
3832 " [-O file] ... module_name ... testport_name ...\n"
3833 " or %s -v\n"
3834 "\n"
3835 "OPTIONS:\n"
3836 " -a: use absolute pathnames in the generated Makefile\n"
3837 " -c: use the pre-compiled files from central directories\n"
3838 #ifdef COVERAGE_BUILD
3839 " -C: enable coverage of generated C++ code\n"
3840 #endif
3841 " -d: dump the data used for Makefile generation\n"
3842 " -e ets_name: name of the target executable\n"
3843 " -f: force overwriting of the output Makefile\n"
3844 " -g: generate Makefile for use with GNU make\n"
3845 " -l: use dynamic linking\n"
3846 " -L: create makefile with library archive as the default target\n"
3847 " -m: always use makedepend for dependencies\n"
3848 " -K file: enable selective code coverage\n"
3849 " -o dir|file: write the Makefile to the given directory or file\n"
3850 " -O file: add the given file to the Makefile as other file\n"
3851 " -p: generate Makefile with TTCN-3 preprocessing\n"
3852 " -R: use function test runtime (TITAN_RUNTIME_2)\n"
3853 " -s: generate Makefile for single mode\n"
3854 " -U none|type: split generated code\n"
3855 " -v: show version\n"
3856 " -w: suppress warnings\n"
3857 " -Y: Enforces legacy behaviour of the \"out\" function parameters (see refguide)\n"
3858 "Options for processing the Titan Project Descriptor file(s):\n"
3859 " -t tpd: read project descriptor file\n"
3860 " -b buildconfig: use the specified build config instead of the default\n"
3861 " -D: use current directory as working directory\n"
3862 " -V: disable validation of TPD file with schema\n"
3863 " -r: generate Makefile hierarchy for TPD hierarchy (recursive)\n"
3864 " -F: force overwriting of all generated Makefiles, use with -r\n"
3865 " -T: generate only top-level Makefile of the hierarchy, use with -r\n"
3866 " -P dir: prints out a file list found in a given TPD relative to the given directory\n"
3867 " -X: generate XML file that describes the TPD hierarchy, use with -r\n"
3868 " -W: prefix working directories with project name\n"
3869 " -Z: recursive Makefile generation from TPD using object files and dynamic libraries too\n"
3870 " -H: hierachical Makefile generation from TPD use with -Z\n"
3871 , program_name, program_name);
3872 }
3873
3874 #define SET_FLAG(x) if (x##flag) {\
3875 ERROR("Flag -" #x " was specified more than once.");\
3876 error_flag = TRUE;\
3877 } else x##flag = TRUE
3878
3879 void free_string_list(struct string_list* act_elem)
3880 {
3881 while (act_elem) {
3882 struct string_list* next_elem = act_elem->next;
3883 Free(act_elem->str);
3884 Free(act_elem);
3885 act_elem = next_elem;
3886 }
3887 }
3888
3889 void free_string2_list(struct string2_list* act_elem)
3890 {
3891 while (act_elem) {
3892 struct string2_list* next_elem = act_elem->next;
3893 Free(act_elem->str1);
3894 Free(act_elem->str2);
3895 Free(act_elem);
3896 act_elem = next_elem;
3897 }
3898 }
3899
3900 int main(int argc, char *argv[])
3901 {
3902 boolean
3903 aflag = FALSE, bflag = FALSE, cflag = FALSE, Cflag = FALSE,
3904 dflag = FALSE, eflag = FALSE, fflag = FALSE, gflag = FALSE,
3905 oflag = FALSE, Kflag = FALSE, lflag = FALSE, pflag = FALSE,
3906 Pflag = FALSE, Rflag = FALSE, sflag = FALSE, tflag = FALSE,
3907 wflag = FALSE, vflag = FALSE, mflag = FALSE, Uflag = FALSE,
3908 Lflag = FALSE, rflag = FALSE, Fflag = FALSE, Xflag = FALSE,
3909 Tflag = FALSE, Yflag = FALSE, csflag = FALSE, quflag = FALSE,
3910 dsflag = FALSE, dbflag = FALSE, drflag = FALSE, dtflag = FALSE,
3911 dxflag = FALSE, fxflag = FALSE, doflag = FALSE,
3912 gfflag = FALSE, lnflag = FALSE, isflag = FALSE, asflag = FALSE,
3913 swflag = FALSE, Vflag = FALSE, Dflag = FALSE, Wflag = FALSE,
3914 djflag = FALSE, Zflag = FALSE, Hflag = FALSE;
3915 boolean error_flag = FALSE;
3916 char *output_file = NULL;
3917 char *ets_name = NULL;
3918 char *project_name = NULL;
3919 size_t n_other_files = 0;
3920 const char **other_files = NULL;
3921 const char *code_splitting_mode = NULL;
3922 const char *tpd_file_name = NULL;
3923 const char *tpd_build_config = NULL;
3924 const char *tcov_file_name = NULL;
3925 const char *file_list_path = NULL;
3926 enum tpd_result tpd_processed = FALSE;
3927 struct string_list* sub_project_dirs = NULL;
3928 struct string2_list* create_symlink_list = NULL;
3929 struct string_list* ttcn3_prep_includes = NULL;
3930 struct string_list* ttcn3_prep_defines = NULL;
3931 struct string_list* ttcn3_prep_undefines = NULL;
3932 struct string_list* prep_includes = NULL;
3933 struct string_list* prep_defines = NULL;
3934 struct string_list* prep_undefines = NULL;
3935 char *cxxcompiler = NULL;
3936 char *optlevel = NULL;
3937 char *optflags = NULL;
3938 struct string_list* solspeclibraries = NULL;
3939 struct string_list* sol8speclibraries = NULL;
3940 struct string_list* linuxspeclibraries = NULL;
3941 struct string_list* freebsdspeclibraries = NULL;
3942 struct string_list* win32speclibraries = NULL;
3943 char *ttcn3prep = NULL;
3944 struct string_list* linkerlibraries = NULL;
3945 struct string_list* additionalObjects = NULL;
3946 struct string_list* linkerlibsearchpath = NULL;
3947 char* generatorCommandOutput = NULL;
3948 struct string2_list* target_placement_list = NULL;
3949 struct string2_list* run_command_list = NULL;
3950 struct string2_list* required_configs = NULL;
3951
3952 #ifdef LICENSE
3953 license_struct lstr;
3954 int valid_license;
3955 #endif
3956
3957 program_name = argv[0];
3958
3959 if (argc == 1) {
3960 fputs("Makefile Generator for the TTCN-3 Test Executor, version "
3961 PRODUCT_NUMBER "\n", stderr);
3962 usage();
3963 return EXIT_FAILURE;
3964 }
3965
3966 for ( ; ; ) {
3967 int c = getopt(argc, argv, "O:ab:c" C_flag "dDe:fFgK:o:lLmpP:rRst:TU:vVwWXYZH");
3968 if (c == -1) break;
3969 switch (c) {
3970 case 'O':
3971 n_other_files++;
3972 other_files = (const char**)
3973 Realloc(other_files, n_other_files * sizeof(*other_files));
3974 other_files[n_other_files - 1] = optarg;
3975 break;
3976 case 'a':
3977 SET_FLAG(a);
3978 break;
3979 case 'b':
3980 SET_FLAG(b);
3981 tpd_build_config = optarg;
3982 break;
3983 case 'c':
3984 SET_FLAG(c);
3985 break;
3986 case 'K':
3987 SET_FLAG(K);
3988 tcov_file_name = optarg;
3989 break;
3990 #ifdef COVERAGE_BUILD
3991 case 'C':
3992 SET_FLAG(C);
3993 break;
3994 #endif
3995 case 'd':
3996 SET_FLAG(d);
3997 break;
3998 case 'D':
3999 SET_FLAG(D);
4000 break;
4001 case 'e':
4002 SET_FLAG(e);
4003 ets_name = optarg;
4004 break;
4005 case 'f':
4006 SET_FLAG(f);
4007 break;
4008 case 'F':
4009 SET_FLAG(F);
4010 break;
4011 case 'g':
4012 SET_FLAG(g);
4013 break;
4014 case 'H':
4015 SET_FLAG(H);
4016 break;
4017 case 'o':
4018 SET_FLAG(o);
4019 output_file = optarg;
4020 break;
4021 case 'l':
4022 SET_FLAG(l);
4023 break;
4024 case 'L':
4025 SET_FLAG(L);
4026 break;
4027 case 'm':
4028 SET_FLAG(m);
4029 break;
4030 case 'p':
4031 SET_FLAG(p);
4032 break;
4033 case 'P':
4034 SET_FLAG(P);
4035 /* Optional arguments with `::' are GNU specific... */
4036 if (get_path_status(optarg) == PS_DIRECTORY) {
4037 file_list_path = optarg;
4038 } else {
4039 ERROR("The -P flag requires a valid directory as its argument "
4040 "instead of `%s'", optarg);
4041 error_flag = TRUE;
4042 }
4043 break;
4044 case 'r':
4045 SET_FLAG(r);
4046 break;
4047 case 'R':
4048 SET_FLAG(R);
4049 break;
4050 case 's':
4051 SET_FLAG(s);
4052 break;
4053 case 't':
4054 SET_FLAG(t);
4055 tpd_file_name = optarg;
4056 break;
4057 case 'T':
4058 SET_FLAG(T);
4059 break;
4060 case 'Y':
4061 SET_FLAG(Y);
4062 break;
4063 case 'U':
4064 SET_FLAG(U);
4065 code_splitting_mode = optarg;
4066 if (strcmp(optarg, "none") != 0 &&
4067 strcmp(optarg, "type") != 0)
4068 ERROR("Unrecognizable argument: '%s'. Valid options for -U switch are: "
4069 "'none', 'type'", optarg);
4070 break;
4071 case 'v':
4072 SET_FLAG(v);
4073 break;
4074 case 'V':
4075 SET_FLAG(V);
4076 break;
4077 case 'w':
4078 SET_FLAG(w);
4079 suppress_warnings = TRUE;
4080 break;
4081 case 'W':
4082 SET_FLAG(W);
4083 break;
4084 case 'X':
4085 SET_FLAG(X);
4086 break;
4087 case 'Z':
4088 SET_FLAG(Z);
4089 break;
4090 default:
4091 error_flag = TRUE;
4092 break;
4093 }
4094 }
4095
4096 /* Checking incompatible options */
4097 if (vflag) {
4098 /* -v prints the version and exits, it's pointless to specify other flags */
4099 if ( aflag || bflag || cflag || Cflag || dflag || eflag || fflag || Fflag || gflag
4100 || mflag || oflag || lflag || pflag || Pflag || rflag || Rflag || sflag
4101 || tflag || Tflag || Vflag || wflag || Xflag || Kflag || Dflag || Wflag || Yflag
4102 || Zflag || Hflag || n_other_files > 0)
4103 error_flag = TRUE;
4104 }
4105
4106 if (Zflag) {
4107 if (!gflag) gflag = TRUE; // GNU make
4108 if (!cflag) cflag = TRUE; // central sorage
4109 }
4110
4111 if ((bflag || Dflag || Pflag || Vflag || rflag || Wflag || Zflag) && !tflag) {
4112 ERROR("Using the '-b', '-D', '-P', '-V', '-r' 'Z' or '-W' option requires the use of the -t' option.");
4113 error_flag = TRUE;
4114 }
4115
4116 if (rflag && !cflag) {
4117 ERROR("Using the '-r' option requires use of the '-c' option. Recursive makefile hierarchy uses the central directory feature.");
4118 error_flag = TRUE;
4119 }
4120
4121 if (Fflag && !rflag) {
4122 ERROR("Using the '-F' option requires use of the '-r' option.");
4123 error_flag = TRUE;
4124 }
4125
4126 if (Xflag && !rflag) {
4127 ERROR("Using the '-X' option requires use of the '-r' option.");
4128 error_flag = TRUE;
4129 }
4130
4131 if (Tflag && !rflag) {
4132 ERROR("Using the '-T' option requires use of the '-r' option.");
4133 error_flag = TRUE;
4134 }
4135
4136 if (!Zflag && Hflag) {
4137 ERROR("Using the '-H' option requires use of the '-Z' option.");
4138 error_flag = TRUE;
4139 }
4140
4141 if (Zflag && !Fflag && !fflag) {
4142 ERROR("Using the '-Z' option requires use of the '-F' option.");
4143 error_flag = TRUE;
4144 }
4145
4146 if (lflag && !strncmp(get_platform_string(), "WIN32", 5)) {
4147 ERROR("Generating Makefile with dynamic linking enabled is not supported "
4148 "on Windows platform");
4149 error_flag = TRUE;
4150 }
4151
4152 if (error_flag) {
4153 usage();
4154 return EXIT_FAILURE;
4155 }
4156
4157 if (vflag) {
4158 fputs("Makefile Generator for the TTCN-3 Test Executor\n"
4159 "Product number: " PRODUCT_NUMBER "\n"
4160 "Build date: " __DATE__ " " __TIME__ "\n"
4161 "Compiled with: " C_COMPILER_VERSION "\n\n"
4162 COPYRIGHT_STRING "\n\n", stderr);
4163 #ifdef LICENSE
4164 print_license_info();
4165 #endif
4166 return EXIT_SUCCESS;
4167 }
4168
4169 #ifdef LICENSE
4170 init_openssl();
4171 load_license(&lstr);
4172 valid_license = verify_license(&lstr);
4173 free_openssl();
4174 if (!valid_license) {
4175 free_license(&lstr);
4176 exit(EXIT_FAILURE);
4177 }
4178 if (!check_feature(&lstr, FEATURE_TPGEN)) {
4179 ERROR("The license key does not allow the generation of "
4180 "Makefile skeletons.");
4181 return EXIT_FAILURE;
4182 }
4183 free_license(&lstr);
4184 #endif
4185
4186 if (tflag) {
4187 char* abs_work_dir = NULL;
4188 FILE* prj_graph_fp = NULL;
4189 sub_project_dirs = (struct string_list*)Malloc(sizeof(struct string_list));
4190 sub_project_dirs->str = NULL;
4191 sub_project_dirs->next = NULL;
4192 ttcn3_prep_includes = (struct string_list*)Malloc(sizeof(struct string_list));
4193 ttcn3_prep_includes->str = NULL;
4194 ttcn3_prep_includes->next = NULL;
4195 ttcn3_prep_defines = (struct string_list*)Malloc(sizeof(struct string_list));
4196 ttcn3_prep_defines->str = NULL;
4197 ttcn3_prep_defines->next = NULL;
4198 ttcn3_prep_undefines = (struct string_list*)Malloc(sizeof(struct string_list));
4199 ttcn3_prep_undefines->str = NULL;
4200 ttcn3_prep_undefines->next = NULL;
4201 prep_includes = (struct string_list*)Malloc(sizeof(struct string_list));
4202 prep_includes->str = NULL;
4203 prep_includes->next = NULL;
4204 prep_defines = (struct string_list*)Malloc(sizeof(struct string_list));
4205 prep_defines->str = NULL;
4206 prep_defines->next = NULL;
4207 prep_undefines = (struct string_list*)Malloc(sizeof(struct string_list));
4208 prep_undefines->str = NULL;
4209 prep_undefines->next = NULL;
4210 solspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4211 solspeclibraries->str = NULL;
4212 solspeclibraries->next = NULL;
4213 sol8speclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4214 sol8speclibraries->str = NULL;
4215 sol8speclibraries->next = NULL;
4216 linuxspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4217 linuxspeclibraries->str = NULL;
4218 linuxspeclibraries->next = NULL;
4219 freebsdspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4220 freebsdspeclibraries->str = NULL;
4221 freebsdspeclibraries->next = NULL;
4222 win32speclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4223 win32speclibraries->str = NULL;
4224 win32speclibraries->next = NULL;
4225 linkerlibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4226 linkerlibraries->str = NULL;
4227 linkerlibraries->next = NULL;
4228 additionalObjects = (struct string_list*)Malloc(sizeof(struct string_list));
4229 additionalObjects->str = NULL;
4230 additionalObjects->next = NULL;
4231 linkerlibsearchpath = (struct string_list*)Malloc(sizeof(struct string_list));
4232 linkerlibsearchpath->str = NULL;
4233 linkerlibsearchpath->next = NULL;
4234
4235 if (Xflag) {
4236 const char* prj_graph_filename = "project_hierarchy_graph.xml";
4237 prj_graph_fp = fopen(prj_graph_filename, "w");
4238 if (prj_graph_fp==NULL) WARNING("Cannot open output file `%s' for writing: %s", prj_graph_filename, strerror(errno));
4239 if (prj_graph_fp) fprintf(prj_graph_fp, "<project_hierarchy_graph top_level_tpd=\"%s\">\n", tpd_file_name);
4240 }
4241 create_symlink_list = (struct string2_list*)Malloc(sizeof(struct string2_list));
4242 create_symlink_list->str1 = NULL;
4243 create_symlink_list->str2 = NULL;
4244 create_symlink_list->next = NULL;
4245 target_placement_list = (struct string2_list*)Malloc(sizeof(struct string2_list));
4246 target_placement_list->str1 = NULL;
4247 target_placement_list->str2 = NULL;
4248 target_placement_list->next = NULL;
4249 run_command_list = (struct string2_list*)Malloc(sizeof(struct string2_list));
4250 run_command_list->str1 = NULL;
4251 run_command_list->str2 = NULL;
4252 run_command_list->next = NULL;
4253 required_configs = (struct string2_list*)Malloc(sizeof(struct string2_list));
4254 required_configs->str1 = NULL;
4255 required_configs->str2 = NULL;
4256 required_configs->next = NULL;
4257
4258 tpd_processed = process_tpd(tpd_file_name, tpd_build_config, file_list_path,
4259 &argc, &argv, &optind, &ets_name, &project_name,
4260 &gflag, &sflag, &cflag, &aflag, &pflag,
4261 &Rflag, &lflag, &mflag, &Pflag, &Lflag, rflag, Fflag, Tflag, output_file, &abs_work_dir, sub_project_dirs, program_name, prj_graph_fp,
4262 create_symlink_list,ttcn3_prep_includes, ttcn3_prep_defines,ttcn3_prep_undefines, prep_includes, prep_defines, prep_undefines, &csflag,
4263 &quflag, &dsflag, &cxxcompiler, &optlevel, &optflags, &dbflag, &drflag, &dtflag, &dxflag, &djflag, &fxflag, &doflag, &gfflag, &lnflag, &isflag,
4264 &asflag, &swflag, &Yflag, solspeclibraries, sol8speclibraries, linuxspeclibraries, freebsdspeclibraries, win32speclibraries, &ttcn3prep,
4265 linkerlibraries, additionalObjects, linkerlibsearchpath, Vflag, Dflag, &Zflag, &Hflag,
4266 &generatorCommandOutput, target_placement_list, Wflag, run_command_list, required_configs);
4267
4268 Free(abs_work_dir);
4269 if (prj_graph_fp) {
4270 fprintf(prj_graph_fp, "</project_hierarchy_graph>\n");
4271 fclose(prj_graph_fp);
4272 }
4273 if (tpd_processed == TPD_FAILED) {
4274 ERROR("Failed to process %s", tpd_file_name);
4275 exit(EXIT_FAILURE);
4276 }
4277 }
4278
4279 if (!Pflag) {
4280 run_makefilegen_commands(run_command_list);
4281 generate_symlinks(create_symlink_list);
4282 if (Zflag) {
4283 if (Fflag)
4284 NOTIFY("Makefile generation from top-level TPD: %s", tpd_file_name);
4285 if (!Fflag && fflag)
4286 NOTIFY("Makefile generation from lower level TPD: %s", tpd_file_name);
4287 }
4288 generate_makefile(argc - optind, argv + optind, n_other_files, other_files,
4289 output_file, ets_name, project_name, gflag, sflag, cflag, aflag, pflag, dflag, fflag||Fflag,
4290 Rflag, lflag, mflag, Cflag, code_splitting_mode, tcov_file_name, Lflag, Zflag, Hflag, rflag ? sub_project_dirs : NULL, ttcn3_prep_includes,
4291 ttcn3_prep_defines, ttcn3_prep_undefines, prep_includes, prep_defines, prep_undefines, csflag, quflag, dsflag, cxxcompiler, optlevel, optflags, dbflag,
4292 drflag, dtflag, dxflag, djflag, fxflag, doflag, gfflag, lnflag, isflag, asflag, swflag, Yflag, solspeclibraries,
4293 sol8speclibraries, linuxspeclibraries, freebsdspeclibraries, win32speclibraries, ttcn3prep, linkerlibraries, additionalObjects,
4294 linkerlibsearchpath, generatorCommandOutput, target_placement_list);
4295 }
4296
4297 free_string_list(sub_project_dirs);
4298 free_string_list(ttcn3_prep_includes);
4299 free_string_list(ttcn3_prep_defines);
4300 free_string_list(ttcn3_prep_undefines);
4301 free_string_list(prep_includes);
4302 free_string_list(prep_defines);
4303 free_string_list(prep_undefines);
4304 free_string_list(solspeclibraries);
4305 free_string_list(sol8speclibraries);
4306 free_string_list(linuxspeclibraries);
4307 free_string_list(freebsdspeclibraries);
4308 free_string_list(win32speclibraries);
4309 free_string_list(linkerlibraries);
4310 free_string_list(additionalObjects);
4311 free_string_list(linkerlibsearchpath);
4312
4313 Free(generatorCommandOutput);
4314 free_string2_list(target_placement_list);
4315 free_string2_list(required_configs);
4316
4317 Free(other_files);
4318 if (tpd_processed == TPD_SUCCESS) {
4319 int E;
4320 if (!(eflag && ets_name))
4321 Free(ets_name);
4322 if (cxxcompiler)
4323 Free(cxxcompiler);
4324 if (optlevel)
4325 Free(optlevel);
4326 if (optflags)
4327 Free(optflags);
4328 if (ttcn3prep)
4329 Free(ttcn3prep);
4330 /* Free(output_file); */
4331 for (E = 0; E < argc; ++E) Free(argv[E]);
4332 Free(argv);
4333 }
4334 /* check_mem_leak(program_name); not needed when linked to new.cc */
4335 return error_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
4336 }
4337
This page took 0.175441 seconds and 6 git commands to generate.