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