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