clang compatibility
[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 boolean cxx_free = FALSE;
1878 if (makefile->cxxcompiler) {
1879 cxx = makefile->cxxcompiler;
1880 } else {
1881 #ifdef __clang__
1882 unsigned int
1883 compiler_major = __clang_major__,
1884 compiler_minor = __clang_minor__;
1885 cxx = mprintf("clang++-%u.%u", compiler_major, compiler_minor);
1886 cxx_free = TRUE;
1887 #else
1888 cxx = "g++";
1889 #endif
1890 }
1891
1892 fprintf(fp, "\n# Your platform: (SOLARIS, SOLARIS8, LINUX, FREEBSD or "
1893 "WIN32)\n"
1894 "PLATFORM = %s\n\n"
1895 "# Your C++ compiler:\n"
1896 "# (if you change the platform, you may need to change the compiler)\n"
1897 "CXX = %s \n\n", get_platform_string(), cxx);
1898
1899
1900 if (makefile->preprocess || makefile->ttcn3preprocessor) {
1901 if (makefile->ttcn3preprocessor) {
1902 cpp = makefile->ttcn3preprocessor;
1903 } else {
1904 cpp = "cpp";
1905 }
1906 fprintf(fp,"# C preprocessor used for TTCN-3 files:\n"
1907 "CPP = %s\n\n", cpp);
1908 }
1909
1910 fputs("# Flags for the C++ preprocessor (and makedepend as well):\n"
1911 "CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)/include", fp);
1912
1913 if (makefile->use_runtime_2) fputs(" -DTITAN_RUNTIME_2", fp);
1914
1915 for (i = 0; i < makefile->nBaseDirs; i++) {
1916 fprintf(fp, " -I%s", makefile->BaseDirs[i].dir_name);
1917 }
1918
1919 if (makefile->prep_includes) {
1920 struct string_list* act_elem = makefile->prep_includes;
1921 while (act_elem) {
1922 if (act_elem->str) {
1923 fprintf(fp, " -I%s", act_elem->str);
1924 }
1925 act_elem = act_elem->next;
1926 }
1927 }
1928
1929 if (makefile->prep_defines) {
1930 struct string_list* act_elem = makefile->prep_defines;
1931 while (act_elem) {
1932 if (act_elem->str) {
1933 fprintf(fp, " -D%s", act_elem->str);
1934 }
1935 act_elem = act_elem->next;
1936 }
1937 }
1938
1939 if (makefile->prep_undefines) {
1940 struct string_list* act_elem = makefile->prep_undefines;
1941 while (act_elem) {
1942 if (act_elem->str) {
1943 fprintf(fp, " -U%s", act_elem->str);
1944 }
1945 act_elem = act_elem->next;
1946 }
1947 }
1948
1949 fputs("\n\n", fp);
1950
1951 if (makefile->gcc_dep) {
1952 fprintf(fp, "# Flags for dependency generation\n"
1953 "CXXDEPFLAGS = -%s\n\n", strstr(cxx, "g++") ? "MM" : "xM1");
1954 }
1955
1956 if (cxx_free) {
1957 Free((char*)cxx);
1958 cxx = NULL;
1959 }
1960
1961 if (makefile->preprocess || makefile->ttcn3_prep_includes || makefile->ttcn3_prep_defines) {
1962 fputs("# Flags for preprocessing TTCN-3 files:\n"
1963 "CPPFLAGS_TTCN3 =", fp);
1964
1965 if (makefile->preprocess) {
1966 for (i = 0; i < makefile->nBaseDirs; i++) {
1967 fprintf(fp, " -I%s", makefile->BaseDirs[i].dir_name);
1968 }
1969 }
1970 if (makefile->ttcn3_prep_includes) {
1971 struct string_list* act_elem = makefile->ttcn3_prep_includes;
1972 while (act_elem) {
1973 if (act_elem->str) {
1974 fprintf(fp, " -I%s", act_elem->str);
1975 }
1976 act_elem = act_elem->next;
1977 }
1978 }
1979 if (makefile->ttcn3_prep_defines) {
1980 struct string_list* act_elem = makefile->ttcn3_prep_defines;
1981 while (act_elem) {
1982 if (act_elem->str) {
1983 fprintf(fp, " -D%s", act_elem->str);
1984 }
1985 act_elem = act_elem->next;
1986 }
1987 }
1988 if (makefile->ttcn3_prep_undefines) {
1989 struct string_list* act_elem = makefile->ttcn3_prep_undefines;
1990 while (act_elem) {
1991 if (act_elem->str) {
1992 fprintf(fp, " -U%s", act_elem->str);
1993 }
1994 act_elem = act_elem->next;
1995 }
1996 }
1997 fputs("\n\n", fp);
1998 }
1999
2000 /* code splitting: command line argument wins */
2001 if (makefile->code_splitting_mode == NULL) {
2002 if (makefile->codesplittpd) {
2003 makefile->code_splitting_mode = mcopystr("-U type");
2004 }
2005 }
2006
2007 fprintf(fp, "# Flags for the C++ compiler:\n"
2008 "CXXFLAGS = %s%s %s %s\n\n"
2009 "# Flags for the linker:\n"
2010 "LDFLAGS = %s%s\n\n"
2011 "ifeq ($(PLATFORM), WIN32)\n"
2012 "# Silence linker warnings.\n"
2013 "LDFLAGS += -Wl,--enable-auto-import,--enable-runtime-pseudo-reloc\n"
2014 "endif\n\n"
2015 "# Utility to create library files\n"
2016 "AR = ar\n"
2017 "ARFLAGS = \n\n"
2018 "# Flags for the TTCN-3 and ASN.1 compiler:\n"
2019 "COMPILER_FLAGS =%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n\n"
2020 "# Execution mode: (either ttcn3 or ttcn3-parallel)\n"
2021 "TTCN3_LIB = ttcn3%s%s%s\n\n"
2022 #ifdef LICENSE
2023 "# The path of your OpenSSL installation:\n"
2024 "# If you do not have your own one, leave it unchanged.\n"
2025 "%sOPENSSL_DIR = $(TTCN3_DIR)\n\n"
2026 #endif
2027 "# The path of your libxml2 installation:\n"
2028 "# If you do not have your own one, leave it unchanged.\n"
2029 "XMLDIR = $(TTCN3_DIR)\n\n"
2030 "# Directory to store the archived source files:\n",
2031 makefile->dynamic ? "-Wall -fPIC" : "-Wall", /* CXXFLAGS */
2032 makefile->coverage ? " -fprofile-arcs -ftest-coverage -g" : "", /* CXXFLAGS COVERAGE */
2033 makefile->optlevel ? makefile->optlevel : "", /* CXXFLAGS optimization level */
2034 makefile->optflags ? makefile->optflags : "", /* CXXFLAGS optimization level */
2035 makefile->dynamic ? "-fPIC" : "", /* LDFLAGS */
2036 makefile->coverage ? " -fprofile-arcs -ftest-coverage -g -lgcov" : "", /* LDFLAGS COVERAGE */
2037 /* COMPILER_FLAGS */
2038 makefile->use_runtime_2 ? " -L -R " : " -L ",
2039 (makefile->code_splitting_mode ? makefile->code_splitting_mode : ""),
2040 (makefile->quietly ? " -q" : ""),
2041 (makefile->disablesubtypecheck ? " -y" : ""),
2042 (makefile->disableber ? " -b" : ""),
2043 (makefile->disableraw ? " -r" : ""),
2044 (makefile->disabletext ? " -x" : ""),
2045 (makefile->disablexer ? " -X" : ""),
2046 (makefile->disablejson ? " -j" : ""),
2047 (makefile->forcexerinasn ? " -a" : ""),
2048 (makefile->defaultasomit ? " -d" : ""),
2049 (makefile->gccmsgformat ? " -g" : ""),
2050 (makefile->linenumbersonlymsg ? " -i" : ""),
2051 (makefile->includesourceinfo ? " -l" : ""),
2052 /*(makefile->addsourcelineinfo ? " -L" : ""),*/
2053 (makefile->suppresswarnings ? " -w" : ""),
2054 (makefile->outparamboundness ? " -Y" : ""),
2055 (makefile->omit_in_value_list ? " -M" : ""),
2056 (makefile->warnings_for_bad_variants ? " -E" : ""),
2057 (makefile->tcov_file_name ? makefile->tcov_file_name : ""),
2058 (makefile->profiled_file_list ? " -z $(PROFILED_FILE_LIST)" : ""),
2059 /* end of COMPILER FLAGS */
2060 (makefile->use_runtime_2 ? "-rt2" : ""), /* TTCN3_LIB */
2061 (makefile->single_mode ? "" : "-parallel"),
2062 (makefile->dynamic ? "-dynamic": "")
2063 #ifdef LICENSE
2064 ,(makefile->disable_predef_ext_folder ? "# " : "")
2065 #endif
2066 );
2067 if (!makefile->gnu_make) {
2068 fputs("# Note: you can set any directory except ./archive\n", fp);
2069 }
2070 fputs("ARCHIVE_DIR = backup\n\n"
2071 "#\n"
2072 "# You may change these variables. Add your files if necessary...\n"
2073 "#\n\n"
2074 "# TTCN-3 modules of this project:\n"
2075 "TTCN3_MODULES =", fp);
2076 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2077 const struct module_struct *module = makefile->TTCN3Modules + i;
2078 if (module->dir_name == NULL || !makefile->central_storage)
2079 /* If the file is in the current directory or
2080 * is not in the current directory but central directory is not used,
2081 * it goes into TTCN3_MODULES */
2082 print_file_name(fp, module);
2083 }
2084 fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_MODULES");
2085 if (makefile->preprocess) {
2086 fputs("\n\n"
2087 "# TTCN-3 modules to preprocess:\n"
2088 "TTCN3_PP_MODULES =", fp);
2089 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2090 const struct module_struct *module = makefile->TTCN3PPModules + i;
2091 if (module->dir_name == NULL || !makefile->central_storage)
2092 print_file_name(fp, module);
2093 }
2094 fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_PP_MODULES");
2095 }
2096 if (makefile->central_storage) {
2097 fputs("\n\n"
2098 "# TTCN-3 modules used from central project(s):\n"
2099 "BASE_TTCN3_MODULES =", fp);
2100 if (!makefile->linkingStrategy) {
2101 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2102 const struct module_struct *module = makefile->TTCN3Modules + i;
2103 /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */
2104 if (module->dir_name != NULL) print_file_name(fp, module);
2105 }
2106 if (makefile->preprocess) {
2107 fputs("\n\n"
2108 "# TTCN-3 modules to preprocess used from central project(s):\n"
2109 "BASE_TTCN3_PP_MODULES =", fp);
2110 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2111 const struct module_struct *module = makefile->TTCN3PPModules + i;
2112 if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name))
2113 print_file_name(fp, module);
2114 }
2115 }
2116 }
2117 else { // new linking strategy
2118 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2119 const struct module_struct *module = makefile->TTCN3Modules + i;
2120 /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */
2121 if (module->dir_name != NULL && !isTtcn3ModuleInLibrary(module->module_name))
2122 print_file_name(fp, module);
2123 }
2124 fputs("\n\n"
2125 "# TTCN-3 library linked modules used from central project(s):\n"
2126 "BASE2_TTCN3_MODULES =", fp);
2127 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2128 const struct module_struct *module = makefile->TTCN3Modules + i;
2129 /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */
2130 if (module->dir_name != NULL && isTtcn3ModuleInLibrary(module->module_name))
2131 print_file_name(fp, module);
2132 }
2133 if (makefile->preprocess) {
2134 fputs("\n\n"
2135 "# TTCN-3 modules to preprocess used from central project(s):\n"
2136 "BASE_TTCN3_PP_MODULES =", fp);
2137 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2138 const struct module_struct *module = makefile->TTCN3PPModules + i;
2139 if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name))
2140 print_file_name(fp, module);
2141 }
2142 fputs("\n\n"
2143 "# TTCN-3 library linked modules to preprocess used from central project(s):\n"
2144 "BASE2_TTCN3_PP_MODULES =", fp);
2145 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2146 const struct module_struct *module = makefile->TTCN3PPModules + i;
2147 if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name))
2148 print_file_name(fp, module);
2149 }
2150 }
2151 }
2152 }
2153 if (makefile->preprocess) {
2154 fputs("\n\n"
2155 "# Files to include in TTCN-3 preprocessed modules:\n"
2156 "TTCN3_INCLUDES =", fp);
2157 for (i = 0; i < makefile->nTTCN3IncludeFiles; i++)
2158 fprintf(fp, " %s", makefile->TTCN3IncludeFiles[i]);
2159 fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_INCLUDES");
2160 }
2161 fputs("\n\n"
2162 "# ASN.1 modules of this project:\n"
2163 "ASN1_MODULES =", fp);
2164 for (i = 0; i < makefile->nASN1Modules; i++) {
2165 const struct module_struct *module = makefile->ASN1Modules + i;
2166 if (module->dir_name == NULL || !makefile->central_storage)
2167 print_file_name(fp, module);
2168 }
2169 fprint_extra_targets(fp, makefile->target_placement_list, "ASN1_MODULES");
2170 if (makefile->central_storage) {
2171 fputs("\n\n"
2172 "# ASN.1 modules used from central project(s):\n"
2173 "BASE_ASN1_MODULES =", fp);
2174 if (!makefile->linkingStrategy) {
2175 for (i = 0; i < makefile->nASN1Modules; i++) {
2176 const struct module_struct *module = makefile->ASN1Modules + i;
2177 if (module->dir_name != NULL) print_file_name(fp, module);
2178 }
2179 }
2180 else {
2181 for (i = 0; i < makefile->nASN1Modules; i++) {
2182 const struct module_struct *module = makefile->ASN1Modules + i;
2183 if (module->dir_name != NULL && !isAsn1ModuleInLibrary(module->module_name))
2184 print_file_name(fp, module);
2185 }
2186 fputs("\n\n"
2187 "# ASN.1 library linked modules used from central project(s):\n"
2188 "BASE2_ASN1_MODULES =", fp);
2189 for (i = 0; i < makefile->nASN1Modules; i++) {
2190 const struct module_struct *module = makefile->ASN1Modules + i;
2191 if (module->dir_name != NULL && isAsn1ModuleInLibrary(module->module_name))
2192 print_file_name(fp, module);
2193 }
2194 }
2195 }
2196 if (makefile->preprocess) {
2197 fputs("\n\n"
2198 "# TTCN-3 source files generated by the C preprocessor:\n"
2199 "PREPROCESSED_TTCN3_MODULES =", fp);
2200 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2201 const struct module_struct *module = makefile->TTCN3PPModules + i;
2202 if (module->dir_name == NULL || !makefile->central_storage)
2203 print_preprocessed_file_name(fp, module);
2204 }
2205 if (makefile->central_storage) {
2206 fputs("\n\n"
2207 "# TTCN-3 files generated by the CPP used from central project(s):\n"
2208 "BASE_PREPROCESSED_TTCN3_MODULES =", fp);
2209 if (!makefile->linkingStrategy) {
2210 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2211 const struct module_struct *module = makefile->TTCN3PPModules + i;
2212 if (module->dir_name != NULL)
2213 print_preprocessed_file_name(fp, module);
2214 }
2215 }
2216 else { // new linking strategy
2217 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2218 const struct module_struct *module = makefile->TTCN3PPModules + i;
2219 if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name))
2220 print_preprocessed_file_name(fp, module);
2221 }
2222 fputs("\n\n"
2223 "# TTCN-3 library linked files generated by the CPP used from central project(s):\n"
2224 "BASE2_PREPROCESSED_TTCN3_MODULES =", fp);
2225 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2226 const struct module_struct *module = makefile->TTCN3PPModules + i;
2227 if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name))
2228 print_preprocessed_file_name(fp, module);
2229 }
2230 }
2231 }
2232 }
2233 if (makefile->profiled_file_list) {
2234 if (makefile->profiled_file_list->next && !makefile->central_storage) {
2235 // merge all profiled file lists into one list
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.merged\n"
2240 "PROFILED_FILE_LIST_SEGMENTS =",
2241 makefile->profiled_file_list->str);
2242 struct string_list* iter = makefile->profiled_file_list;
2243 while(iter != NULL) {
2244 fprintf(fp, " %s", iter->str);
2245 iter = iter->next;
2246 }
2247 }
2248 else {
2249 // only one profiled file list is needed
2250 fprintf(fp, "\n\n"
2251 "# Text file containing the list of profiled TTCN-3 files of "
2252 "this project:\n"
2253 "PROFILED_FILE_LIST = %s", makefile->profiled_file_list->str);
2254 }
2255 }
2256 fputs("\n\n"
2257 "# C++ source & header files generated from the TTCN-3 & ASN.1 "
2258 "modules of\n"
2259 "# this project:\n"
2260 "GENERATED_SOURCES =", fp);
2261 if (makefile->gnu_make && makefile->TTCN3ModulesRegular) {
2262 fputs(" $(TTCN3_MODULES:.ttcn=.cc)", fp);
2263 if (makefile->code_splitting_mode) {
2264 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2265 const struct module_struct *module = makefile->TTCN3Modules + i;
2266 if (module->dir_name == NULL || !makefile->central_storage)
2267 print_splitted_file_names(fp, makefile, module);
2268 }
2269 }
2270 if (makefile->preprocess) {
2271 fputs(" $(TTCN3_PP_MODULES:.ttcnpp=.cc)", fp);
2272 if (makefile->code_splitting_mode) {
2273 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2274 const struct module_struct *module = makefile->TTCN3PPModules + i;
2275 if (module->dir_name == NULL || !makefile->central_storage)
2276 print_splitted_file_names(fp, makefile, module);
2277 }
2278 }
2279 }
2280 } else {
2281 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2282 const struct module_struct *module = makefile->TTCN3Modules + i;
2283 if (module->dir_name == NULL || !makefile->central_storage) {
2284 print_generated_file_name(fp, module, FALSE, ".cc");
2285 if (makefile->code_splitting_mode)
2286 print_splitted_file_names(fp, makefile, module);
2287 }
2288 }
2289 if (makefile->preprocess) {
2290 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2291 const struct module_struct *module = makefile->TTCN3PPModules + i;
2292 if (module->dir_name == NULL || !makefile->central_storage) {
2293 print_generated_file_name(fp, module, FALSE, ".cc");
2294 if (makefile->code_splitting_mode)
2295 print_splitted_file_names(fp, makefile, module);
2296 }
2297 }
2298 }
2299 }
2300 if (makefile->gnu_make && makefile->ASN1ModulesRegular) {
2301 fputs(" $(ASN1_MODULES:.asn=.cc)", fp);
2302 if (makefile->code_splitting_mode) {
2303 for (i = 0; i < makefile->nASN1Modules; i++) {
2304 const struct module_struct *module = makefile->ASN1Modules + i;
2305 if (module->dir_name == NULL || !makefile->central_storage) {
2306 print_splitted_file_names(fp, makefile, module);
2307 }
2308 }
2309 }
2310 } else {
2311 for (i = 0; i < makefile->nASN1Modules; i++) {
2312 const struct module_struct *module = makefile->ASN1Modules + i;
2313 if (module->dir_name == NULL || !makefile->central_storage) {
2314 print_generated_file_name(fp, module, FALSE, ".cc");
2315 if (makefile->code_splitting_mode)
2316 print_splitted_file_names(fp, makefile, module);
2317 }
2318 }
2319 }
2320
2321 fputs("\nGENERATED_HEADERS =", fp);
2322 if (makefile->gnu_make) {
2323 fputs(" $(GENERATED_SOURCES:.cc=.hh)", fp);
2324 }
2325 else {
2326 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2327 const struct module_struct *module = makefile->TTCN3Modules + i;
2328 if (module->dir_name == NULL || !makefile->central_storage)
2329 print_generated_file_name(fp, module, FALSE, ".hh");
2330 }
2331 if (makefile->preprocess) {
2332 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2333 const struct module_struct *module = makefile->TTCN3PPModules + i;
2334 if (module->dir_name == NULL || !makefile->central_storage)
2335 print_generated_file_name(fp, module, FALSE, ".hh");
2336 }
2337 }
2338 for (i = 0; i < makefile->nASN1Modules; i++) {
2339 const struct module_struct *module = makefile->ASN1Modules + i;
2340 if (module->dir_name == NULL || !makefile->central_storage)
2341 print_generated_file_name(fp, module, FALSE, ".hh");
2342 }
2343 }
2344 if (makefile->central_storage) {
2345 fputs("\n\n"
2346 "# C++ source & header files generated from the TTCN-3 & ASN.1 "
2347 "modules of\n"
2348 "# central project(s):\n"
2349 "BASE_GENERATED_SOURCES =", fp);
2350 if (makefile->gnu_make && makefile->BaseTTCN3ModulesRegular) {
2351 fputs(" $(BASE_TTCN3_MODULES:.ttcn=.cc)", fp);
2352 if (makefile->code_splitting_mode) {
2353 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2354 const struct module_struct *module = makefile->TTCN3Modules + i;
2355 if (module->dir_name != NULL) {
2356 print_splitted_file_names(fp, makefile, module);
2357 }
2358 }
2359 }
2360 if (makefile->preprocess) {
2361 fputs(" $(BASE_TTCN3_PP_MODULES:.ttcnpp=.cc)", fp);
2362 if (makefile->code_splitting_mode) {
2363 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2364 const struct module_struct *module = makefile->TTCN3PPModules + i;
2365 if (module->dir_name != NULL) {
2366 print_splitted_file_names(fp, makefile, module);
2367 }
2368 }
2369 }
2370 }
2371 } else {
2372 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2373 const struct module_struct *module = makefile->TTCN3Modules + i;
2374 if (module->dir_name != NULL) {
2375 print_generated_file_name(fp, module, TRUE, ".cc");
2376 if (makefile->code_splitting_mode)
2377 print_splitted_file_names(fp, makefile, module);
2378 }
2379 }
2380 if (makefile->preprocess) {
2381 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2382 const struct module_struct *module = makefile->TTCN3PPModules + i;
2383 if (module->dir_name != NULL) {
2384 print_generated_file_name(fp, module, TRUE, ".cc");
2385 if (makefile->code_splitting_mode)
2386 print_splitted_file_names(fp, makefile, module);
2387 }
2388 }
2389 }
2390 }
2391 if (makefile->gnu_make && makefile->BaseASN1ModulesRegular) {
2392 fputs(" $(BASE_ASN1_MODULES:.asn=.cc)", fp);
2393 if (makefile->code_splitting_mode) {
2394 for (i = 0; i < makefile->nASN1Modules; i++) {
2395 const struct module_struct *module = makefile->ASN1Modules + i;
2396 if (module->dir_name != NULL) {
2397 print_splitted_file_names(fp, makefile, module);
2398 }
2399 }
2400 }
2401 } else {
2402 for (i = 0; i < makefile->nASN1Modules; i++) {
2403 const struct module_struct *module = makefile->ASN1Modules + i;
2404 if (module->dir_name != NULL) {
2405 print_generated_file_name(fp, module, TRUE, ".cc");
2406 if (makefile->code_splitting_mode)
2407 print_splitted_file_names(fp, makefile, module);
2408 }
2409 }
2410 }
2411 fputs("\nBASE_GENERATED_HEADERS =", fp);
2412 if (makefile->gnu_make) {
2413 fputs(" $(BASE_GENERATED_SOURCES:.cc=.hh)", fp);
2414 } else {
2415 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2416 const struct module_struct *module = makefile->TTCN3Modules + i;
2417 if (module->dir_name != NULL)
2418 print_generated_file_name(fp, module, TRUE, ".hh");
2419 }
2420 if (makefile->preprocess) {
2421 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2422 const struct module_struct *module = makefile->TTCN3PPModules + i;
2423 if (module->dir_name != NULL)
2424 print_generated_file_name(fp, module, TRUE, ".hh");
2425 }
2426 }
2427 for (i = 0; i < makefile->nASN1Modules; i++) {
2428 const struct module_struct *module = makefile->ASN1Modules + i;
2429 if (module->dir_name != NULL)
2430 print_generated_file_name(fp, module, TRUE, ".hh");
2431 }
2432 }
2433 }
2434
2435 if (makefile->linkingStrategy) {
2436 fputs("\n\n"
2437 "# C++ source & header files generated from the TTCN-3 "
2438 " library linked modules of\n"
2439 "# central project(s):\n"
2440 "BASE2_GENERATED_SOURCES =", fp);
2441 if (makefile->gnu_make && makefile->BaseTTCN3ModulesRegular) {
2442 fputs(" $(BASE2_TTCN3_MODULES:.ttcn=.cc)", fp);
2443 fputs(" $(BASE2_ASN1_MODULES:.asn=.cc)", fp);
2444 if (makefile->preprocess)
2445 fputs(" $(BASE2_TTCN3_PP_MODULES:.ttcnpp=.cc)", fp);
2446 }
2447 else {
2448 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2449 const struct module_struct *module = makefile->TTCN3Modules + i;
2450 if (module->dir_name != NULL && isTtcn3ModuleInLibrary(module->module_name)) {
2451 print_generated_file_name(fp, module, TRUE, ".cc");
2452 }
2453 }
2454 if (makefile->preprocess) {
2455 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2456 const struct module_struct *module = makefile->TTCN3PPModules + i;
2457 if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name)) {
2458 print_generated_file_name(fp, module, TRUE, ".cc");
2459 }
2460 }
2461 }
2462 }
2463
2464 fputs("\nBASE2_GENERATED_HEADERS =", fp);
2465 if (makefile->gnu_make) {
2466 fputs(" $(BASE2_GENERATED_SOURCES:.cc=.hh)", fp);
2467 }
2468 else
2469 ERROR("the usage of 'Z' flag requires GNU make");
2470 }
2471
2472 fputs("\n\n"
2473 "# C/C++ Source & header files of Test Ports, external functions "
2474 "and\n"
2475 "# other modules:\n"
2476 "USER_SOURCES =", fp);
2477 for (i = 0; i < makefile->nUserFiles; i++) {
2478 const struct user_struct *user = makefile->UserFiles + i;
2479 if (user->dir_name == NULL || !makefile->central_storage)
2480 print_source_name(fp, user);
2481 }
2482 fprint_extra_targets(fp, makefile->target_placement_list, "USER_SOURCES");
2483 fputs("\nUSER_HEADERS =", fp);
2484 if (makefile->gnu_make && makefile->UserHeadersRegular) {
2485 fputs(" $(USER_SOURCES:.cc=.hh)", fp);
2486 } else {
2487 for (i = 0; i < makefile->nUserFiles; i++) {
2488 const struct user_struct *user = makefile->UserFiles + i;
2489 if (user->dir_name == NULL || !makefile->central_storage)
2490 print_header_name(fp, user);
2491 }
2492 }
2493 fprint_extra_targets(fp, makefile->target_placement_list, "USER_HEADERS");
2494 if (makefile->central_storage) {
2495 fputs("\n\n"
2496 "# C/C++ Source & header files of Test Ports, external functions "
2497 "and\n"
2498 "# other modules used from central project(s):\n"
2499 "BASE_USER_SOURCES =", fp);
2500 if (!makefile->linkingStrategy) {
2501 for (i = 0; i < makefile->nUserFiles; i++) {
2502 const struct user_struct *user = makefile->UserFiles + i;
2503 if (user->dir_name != NULL) {
2504 print_source_name(fp, user);
2505 }
2506 }
2507 fputs("\nBASE_USER_HEADERS =", fp);
2508 if (makefile->gnu_make && makefile->BaseUserHeadersRegular) {
2509 fputs(" $(BASE_USER_SOURCES:.cc=.hh)", fp);
2510 }
2511 else {
2512 for (i = 0; i < makefile->nUserFiles; i++) {
2513 const struct user_struct *user = makefile->UserFiles + i;
2514 if (user->dir_name != NULL)
2515 print_header_name(fp, user);
2516 }
2517 }
2518 }
2519 else {
2520 for (i = 0; i < makefile->nUserFiles; i++) {
2521 const struct user_struct *user = makefile->UserFiles + i;
2522 if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name)) {
2523 print_source_name(fp, user);
2524 }
2525 }
2526 fputs("\nBASE_USER_HEADERS =", fp);
2527 if (makefile->gnu_make && makefile->BaseUserHeadersRegular) {
2528 fputs(" $(BASE_USER_SOURCES:.cc=.hh)", fp);
2529 }
2530 else {
2531 for (i = 0; i < makefile->nUserFiles; i++) {
2532 const struct user_struct *user = makefile->UserFiles + i;
2533 if (user->dir_name != NULL && !isHeaderFileInLibrary(user->header_name))
2534 print_header_name(fp, user);
2535 }
2536 }
2537
2538 fputs("\n\n"
2539 "# C/C++ Source & header files of Test Ports, external functions "
2540 "and\n"
2541 "# other modules used from library linked central project(s):\n"
2542 "BASE2_USER_SOURCES =", fp);
2543 for (i = 0; i < makefile->nUserFiles; i++) {
2544 const struct user_struct *user = makefile->UserFiles + i;
2545 if (user->dir_name != NULL && isSourceFileInLibrary(user->source_name)) {
2546 print_source_name(fp, user);
2547 }
2548 }
2549 fputs("\nBASE2_USER_HEADERS =", fp);
2550 if (makefile->gnu_make && makefile->BaseUserHeadersRegular) {
2551 fputs(" $(BASE2_USER_SOURCES:.cc=.hh)", fp);
2552 }
2553 else {
2554 for (i = 0; i < makefile->nUserFiles; i++) {
2555 const struct user_struct *user = makefile->UserFiles + i;
2556 if (user->dir_name != NULL && isHeaderFileInLibrary(user->header_name))
2557 print_header_name(fp, user);
2558 }
2559 }
2560 }
2561 }
2562 if (makefile->dynamic) {
2563 fputs("\n\n"
2564 "# Shared object files of this project:\n"
2565 "SHARED_OBJECTS =", fp);
2566 if (makefile->gnu_make) {
2567 fputs(" $(GENERATED_SOURCES:.cc=.so)", fp);
2568 } else {
2569 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2570 const struct module_struct *module = makefile->TTCN3Modules + i;
2571 if (module->dir_name == NULL || !makefile->central_storage) {
2572 print_generated_file_name(fp, module, FALSE, ".so");
2573 if (makefile->code_splitting_mode != NULL)
2574 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2575 print_generated_file_name(fp, module, FALSE, "_seq.so");
2576 print_generated_file_name(fp, module, FALSE, "_set.so");
2577 print_generated_file_name(fp, module, FALSE, "_seqof.so");
2578 print_generated_file_name(fp, module, FALSE, "_setof.so");
2579 print_generated_file_name(fp, module, FALSE, "_union.so");
2580 }
2581 }
2582 }
2583 if (makefile->preprocess) {
2584 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2585 const struct module_struct *module = makefile->TTCN3PPModules + i;
2586 if (module->dir_name == NULL || !makefile->central_storage) {
2587 print_generated_file_name(fp, module, FALSE, ".so");
2588 if (makefile->code_splitting_mode != NULL)
2589 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2590 print_generated_file_name(fp, module, FALSE, "_seq.so");
2591 print_generated_file_name(fp, module, FALSE, "_set.so");
2592 print_generated_file_name(fp, module, FALSE, "_seqof.so");
2593 print_generated_file_name(fp, module, FALSE, "_setof.so");
2594 print_generated_file_name(fp, module, FALSE, "_union.so");
2595 }
2596 }
2597 }
2598 }
2599 for (i = 0; i < makefile->nASN1Modules; i++) {
2600 const struct module_struct *module = makefile->ASN1Modules + i;
2601 if (module->dir_name == NULL || !makefile->central_storage) {
2602 print_generated_file_name(fp, module, FALSE, ".so");
2603 if (makefile->code_splitting_mode != NULL)
2604 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2605 print_generated_file_name(fp, module, FALSE, "_seq.so");
2606 print_generated_file_name(fp, module, FALSE, "_set.so");
2607 print_generated_file_name(fp, module, FALSE, "_seqof.so");
2608 print_generated_file_name(fp, module, FALSE, "_setof.so");
2609 print_generated_file_name(fp, module, FALSE, "_union.so");
2610 }
2611 }
2612 }
2613 }
2614 if (makefile->gnu_make && makefile->UserSourcesRegular) {
2615 fputs(" $(USER_SOURCES:.cc=.so)", fp);
2616 } else {
2617 for (i = 0; i < makefile->nUserFiles; i++) {
2618 const struct user_struct *user = makefile->UserFiles + i;
2619 if (user->dir_name == NULL || !makefile->central_storage)
2620 print_shared_object_name(fp, user);
2621 }
2622 }
2623 }
2624
2625 fputs("\n\n"
2626 "# Object files of this project that are needed for the executable "
2627 "test suite:\n"
2628 "OBJECTS = $(GENERATED_OBJECTS) $(USER_OBJECTS)\n\n" /* never := */
2629 "GENERATED_OBJECTS =", fp);
2630 if (makefile->gnu_make) {
2631 fputs(" $(GENERATED_SOURCES:.cc=.o)", fp);
2632 } else {
2633 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2634 const struct module_struct *module = makefile->TTCN3Modules + i;
2635 if (module->dir_name == NULL || !makefile->central_storage) {
2636 print_generated_file_name(fp, module, FALSE, ".o");
2637 if (makefile->code_splitting_mode != NULL)
2638 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2639 print_generated_file_name(fp, module, FALSE, "_seq.o");
2640 print_generated_file_name(fp, module, FALSE, "_set.o");
2641 print_generated_file_name(fp, module, FALSE, "_seqof.o");
2642 print_generated_file_name(fp, module, FALSE, "_setof.o");
2643 print_generated_file_name(fp, module, FALSE, "_union.o");
2644 }
2645 }
2646 }
2647 if (makefile->preprocess) {
2648 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2649 const struct module_struct *module = makefile->TTCN3PPModules + i;
2650 if (module->dir_name == NULL || !makefile->central_storage) {
2651 print_generated_file_name(fp, module, FALSE, ".o");
2652 if (makefile->code_splitting_mode != NULL)
2653 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2654 print_generated_file_name(fp, module, FALSE, "_seq.o");
2655 print_generated_file_name(fp, module, FALSE, "_set.o");
2656 print_generated_file_name(fp, module, FALSE, "_seqof.o");
2657 print_generated_file_name(fp, module, FALSE, "_setof.o");
2658 print_generated_file_name(fp, module, FALSE, "_union.o");
2659 }
2660 }
2661 }
2662 }
2663 for (i = 0; i < makefile->nASN1Modules; i++) {
2664 const struct module_struct *module = makefile->ASN1Modules + i;
2665 if (module->dir_name == NULL || !makefile->central_storage) {
2666 print_generated_file_name(fp, module, FALSE, ".o");
2667 if (makefile->code_splitting_mode != NULL)
2668 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2669 print_generated_file_name(fp, module, FALSE, "_seq.o");
2670 print_generated_file_name(fp, module, FALSE, "_set.o");
2671 print_generated_file_name(fp, module, FALSE, "_seqof.o");
2672 print_generated_file_name(fp, module, FALSE, "_setof.o");
2673 print_generated_file_name(fp, module, FALSE, "_union.o");
2674 }
2675 }
2676 }
2677 }
2678
2679 fputs("\n\nUSER_OBJECTS =", fp);
2680 if (makefile->gnu_make && makefile->UserSourcesRegular) {
2681 fputs(" $(USER_SOURCES:.cc=.o)", fp);
2682 } else {
2683 for (i = 0; i < makefile->nUserFiles; i++) {
2684 const struct user_struct *user = makefile->UserFiles + i;
2685 if (user->dir_name == NULL || !makefile->central_storage)
2686 print_object_name(fp, user);
2687 }
2688 }
2689 fprint_extra_targets(fp, makefile->target_placement_list, "USER_OBJECTS");
2690
2691 if (makefile->gcc_dep) {
2692 /* GNU Make processes included makefiles in reverse order. By putting
2693 * user sources first, their .d will be generated last, after the
2694 * GENERATED_SOURCES (and GENERATED_HEADERS) have been created.
2695 * This avoid spurious errors during incremental dependency generation */
2696 fputs("\n\nDEPFILES = $(USER_OBJECTS:.o=.d) $(GENERATED_OBJECTS:.o=.d)", fp);
2697 }
2698
2699 if (makefile->central_storage) {
2700 if (makefile->dynamic) {
2701 fputs("\n\n"
2702 "# Shared object files of central project(s):\n"
2703 "BASE_SHARED_OBJECTS =", fp);
2704 if (!makefile->linkingStrategy) {
2705 if (makefile->gnu_make) {
2706 fputs(" $(BASE_GENERATED_SOURCES:.cc=.so)", fp);
2707 }
2708 else {
2709 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2710 const struct module_struct *module = makefile->TTCN3Modules + i;
2711 if (module->dir_name != NULL)
2712 print_generated_file_name(fp, module, TRUE, ".so");
2713 }
2714 if (makefile->preprocess) {
2715 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2716 const struct module_struct *module =
2717 makefile->TTCN3PPModules + i;
2718 if (module->dir_name != NULL)
2719 print_generated_file_name(fp, module, TRUE, ".so");
2720 }
2721 }
2722 for (i = 0; i < makefile->nASN1Modules; i++) {
2723 const struct module_struct *module = makefile->ASN1Modules + i;
2724 if (module->dir_name != NULL)
2725 print_generated_file_name(fp, module, TRUE, ".so");
2726 }
2727 }
2728 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
2729 fputs(" $(BASE_USER_SOURCES:.cc=.so)", fp);
2730 }
2731 else {
2732 for (i = 0; i < makefile->nUserFiles; i++) {
2733 const struct user_struct *user = makefile->UserFiles + i;
2734 if (user->dir_name != NULL)
2735 print_shared_object_name(fp, user);
2736 }
2737 }
2738 }
2739 else { // new linkingStrategy
2740 if (makefile->gnu_make) {
2741 fputs(" $(BASE_GENERATED_SOURCES:.cc=.so)", fp);
2742 }
2743 else
2744 ERROR("the usage of 'Z' flag requires GNU make");
2745
2746 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
2747 fputs(" $(BASE_USER_SOURCES:.cc=.so)", fp);
2748 }
2749 else {
2750 for (i = 0; i < makefile->nUserFiles; i++) {
2751 const struct user_struct *user = makefile->UserFiles + i;
2752 if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name))
2753 print_shared_object_name(fp, user);
2754 }
2755 }
2756 }
2757 } /* if dynamic */
2758 fputs("\n\n"
2759 "# Object files of central project(s) that are needed for the "
2760 "executable test suite:\n"
2761 "BASE_OBJECTS =", fp);
2762 if (!makefile->linkingStrategy) {
2763 if (makefile->gnu_make) {
2764 fputs(" $(BASE_GENERATED_SOURCES:.cc=.o)", fp);
2765 }
2766 else {
2767 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2768 const struct module_struct *module = makefile->TTCN3Modules + i;
2769 if (module->dir_name != NULL)
2770 print_generated_file_name(fp, module, TRUE, ".o");
2771 }
2772 if (makefile->preprocess) {
2773 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2774 const struct module_struct *module = makefile->TTCN3PPModules + i;
2775 if (module->dir_name != NULL)
2776 print_generated_file_name(fp, module, TRUE, ".o");
2777 }
2778 }
2779 for (i = 0; i < makefile->nASN1Modules; i++) {
2780 const struct module_struct *module = makefile->ASN1Modules + i;
2781 if (module->dir_name != NULL)
2782 print_generated_file_name(fp, module, TRUE, ".o");
2783 }
2784 }
2785 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
2786 fputs(" $(BASE_USER_SOURCES:.cc=.o)", fp);
2787 }
2788 else {
2789 for (i = 0; i < makefile->nUserFiles; i++) {
2790 const struct user_struct *user = makefile->UserFiles + i;
2791 if (user->dir_name != NULL)
2792 print_object_name(fp, user);
2793 }
2794 }
2795 }
2796 else { // new linkingStrategy
2797 if (makefile->gnu_make) {
2798 fputs(" $(BASE_GENERATED_SOURCES:.cc=.o)", fp);
2799 }
2800 else
2801 ERROR("the usage of 'Z' flag requires GNU make");
2802
2803 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
2804 fputs(" $(BASE_USER_SOURCES:.cc=.o)", fp);
2805 }
2806 else {
2807 for (i = 0; i < makefile->nUserFiles; i++) {
2808 const struct user_struct *user = makefile->UserFiles + i;
2809 if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name))
2810 print_object_name(fp, user);
2811 }
2812 }
2813 }
2814 }
2815 if (makefile->linkingStrategy) {
2816 fputs("\n\n"
2817 "# Object files of library linked central project(s) that are needed for the "
2818 "executable test suite:\n"
2819 "BASE2_OBJECTS =", fp);
2820 if (makefile->gnu_make) {
2821 if (makefile->dynamic)
2822 fputs(" $(BASE2_GENERATED_SOURCES:.cc=.so)", fp);
2823 else
2824 fputs(" $(BASE2_GENERATED_SOURCES:.cc=.o)", fp);
2825 }
2826 else ERROR("the usage of 'Z' flag requires GNU make");
2827
2828 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
2829 if (makefile->dynamic)
2830 fputs(" $(BASE2_USER_SOURCES:.cc=.so)", fp);
2831 else
2832 fputs(" $(BASE2_USER_SOURCES:.cc=.o)", fp);
2833 }
2834 else {
2835 for (i = 0; i < makefile->nUserFiles; i++) {
2836 const struct user_struct *user = makefile->UserFiles + i;
2837 if (user->dir_name != NULL && isSourceFileInLibrary(user->source_name)) {
2838 if (makefile->dynamic)
2839 print_shared_object_name(fp, user);
2840 else
2841 print_object_name(fp, user);
2842 }
2843 }
2844 }
2845 if (makefile->hierarchical) {
2846 fputs("\n\n"
2847 "#Libraries of referenced project(s) that are needed for the "
2848 "executable or library target:\n"
2849 "BASE2_LIBRARY =", fp);
2850 struct string2_list* head = getLinkerLibs(makefile->project_name);
2851 struct string2_list* act_elem = head;
2852 while (act_elem) {
2853 if (act_elem->str2) {
2854 fputs(" ", fp);
2855 fprintf(fp, "%s/lib%s.%s", act_elem->str1, act_elem->str2,
2856 isDynamicLibrary(act_elem->str2) ? "so" : "a");
2857 }
2858 act_elem = act_elem->next;
2859 }
2860 free_string2_list(head);
2861 }
2862 }
2863
2864 fputs("\n\n"
2865 "# Other files of the project (Makefile, configuration files, etc.)\n"
2866 "# that will be added to the archived source files:\n"
2867 "OTHER_FILES =", fp);
2868 for (i = 0; i < makefile->nOtherFiles; i++)
2869 fprintf(fp, " %s", makefile->OtherFiles[i]);
2870 fprint_extra_targets(fp, makefile->target_placement_list, "OTHER_FILES");
2871
2872 if (makefile->ets_name) {
2873 const char *ets_suffix = NULL;
2874 /* EXECUTABLE variable */
2875 fprintf(fp, "\n\n"
2876 "# The name of the executable test suite:\n"
2877 "EXECUTABLE = %s", makefile->ets_name);
2878 #ifdef WIN32
2879 {
2880 /* add the .exe suffix unless it is already present */
2881 ets_suffix = get_suffix(makefile->ets_name);
2882 if (ets_suffix == NULL || strcmp(ets_suffix, "exe"))
2883 fputs(".exe", fp);
2884 }
2885 #endif
2886 fputs("\n\n", fp);
2887 if (makefile->linkingStrategy) {
2888 #ifndef WIN32
2889 fputs("DYNAMIC_LIBRARY = lib$(EXECUTABLE).so\n", fp);
2890 fputs("STATIC_LIBRARY = lib$(EXECUTABLE).a\n", fp);
2891 #else
2892 char* name_prefix = cut_suffix(makefile->ets_name);
2893 fprintf(fp, "DYNAMIC_LIBRARY = lib%s.so\n", name_prefix);
2894 fprintf(fp, "STATIC_LIBRARY = lib%s.a\n", name_prefix);
2895 Free(name_prefix);
2896 #endif
2897 }
2898 /* LIBRARY variable */
2899 ets_suffix = get_suffix(makefile->ets_name);
2900 if (ets_suffix != NULL && !strcmp(ets_suffix, "exe")) {
2901 char* name_prefix = cut_suffix(makefile->ets_name);
2902 fprintf(fp, "\n\nLIBRARY = %s%s%s\n", "lib", name_prefix ? name_prefix : "library",
2903 makefile->dynamic ? ".so" : ".a");
2904 Free(name_prefix);
2905 }
2906 else {
2907 #ifndef WIN32
2908 fprintf(fp, "\n\nLIBRARY = lib$(EXECUTABLE)%s\n",
2909 makefile->dynamic ? ".so" : ".a");
2910 #else
2911 fprintf(fp, "\n\nLIBRARY = lib%s%s\n",
2912 makefile->ets_name, makefile->dynamic ? ".so" : ".a");
2913 #endif
2914 }
2915
2916 } else {
2917 fputs("\n\n"
2918 "# The name of the executable test suite:\n"
2919 "EXECUTABLE =\n"
2920 "LIBRARY =\n", fp);
2921 }
2922 if (!makefile->linkingStrategy || !buildObjects(makefile->project_name, add_refd_prjs)) {
2923 fprintf(fp, "\n"
2924 "TARGET = $(%s)", makefile->library ? "LIBRARY" : "EXECUTABLE");
2925 }
2926 else {
2927 if (makefile->dynamic) {
2928 fputs("\n"
2929 "TARGET = $(SHARED_OBJECTS)", fp);
2930 }
2931 else {
2932 fputs("\n"
2933 "TARGET = $(OBJECTS)", fp);
2934 }
2935 }
2936 fputs("\n\n"
2937 "#\n"
2938 "# Do not modify these unless you know what you are doing...\n"
2939 "# Platform specific additional libraries:\n"
2940 "#\n", fp);
2941
2942 fputs("SOLARIS_LIBS = -lsocket -lnsl -lxml2", fp);
2943 #ifdef USAGE_STATS
2944 fputs(" -lresolv", fp);
2945 #endif
2946 if (makefile->solspeclibraries) {
2947 struct string_list* act_elem = makefile->solspeclibraries;
2948 while (act_elem) {
2949 if (act_elem->str) {
2950 fprintf(fp, " -l%s", act_elem->str);
2951 }
2952 act_elem = act_elem->next;
2953 }
2954 }
2955 fputs("\n", fp);
2956
2957 fputs("SOLARIS8_LIBS = -lsocket -lnsl -lxml2", fp);
2958 #ifdef USAGE_STATS
2959 fputs(" -lresolv", fp);
2960 #endif
2961 if (makefile->sol8speclibraries) {
2962 struct string_list* act_elem = makefile->sol8speclibraries;
2963 while (act_elem) {
2964 if (act_elem->str) {
2965 fprintf(fp, " -l%s", act_elem->str);
2966 }
2967 act_elem = act_elem->next;
2968 }
2969 }
2970 fputs("\n", fp);
2971
2972 fputs("LINUX_LIBS = -lxml2", fp);
2973 #ifdef USAGE_STATS
2974 fputs(" -lpthread -lrt", fp);
2975 #endif
2976 if (makefile->linuxspeclibraries) {
2977 struct string_list* act_elem = makefile->linuxspeclibraries;
2978 while (act_elem) {
2979 if (act_elem->str) {
2980 fprintf(fp, " -l%s", act_elem->str);
2981 }
2982 act_elem = act_elem->next;
2983 }
2984 }
2985 fputs("\n", fp);
2986
2987 fputs("FREEBSD_LIBS = -lxml2", fp);
2988 if (makefile->freebsdspeclibraries) {
2989 struct string_list* act_elem = makefile->freebsdspeclibraries;
2990 while (act_elem) {
2991 if (act_elem->str) {
2992 fprintf(fp, " -l%s", act_elem->str);
2993 }
2994 act_elem = act_elem->next;
2995 }
2996 }
2997 fputs("\n", fp);
2998
2999 fputs("WIN32_LIBS = -lxml2", fp);
3000 if (makefile->win32speclibraries) {
3001 struct string_list* act_elem = makefile->win32speclibraries;
3002 while (act_elem) {
3003 if (act_elem->str) {
3004 fprintf(fp, " -l%s", act_elem->str);
3005 }
3006 act_elem = act_elem->next;
3007 }
3008 }
3009 fputs("\n\n", fp);
3010
3011 fputs("#\n"
3012 "# Rules for building the executable...\n"
3013 "#\n\n", fp);
3014 fprintf(fp, "all:%s $(TARGET) ;\n\n", add_refd_prjs?" referenced-all":"");
3015
3016 if (makefile->dynamic) {
3017 fprintf(fp, "shared_objects:%s $(SHARED_OBJECTS) ;\n\n", add_refd_prjs?" referenced-shared_objects":"");
3018 }
3019
3020 fprintf(fp,
3021 "executable:%s $(EXECUTABLE) ;\n\n"
3022 "library:%s $(LIBRARY) ;\n\n"
3023 "objects:%s $(OBJECTS) compile;\n\n", add_refd_prjs?" referenced-executable":"", add_refd_prjs?" referenced-library":"", add_refd_prjs?" referenced-objects":"");
3024
3025 /* target $(EXECUTABLE) */
3026 if (makefile->dynamic && makefile->library) {
3027 /* There is no need to create the .so for all the source files */
3028 fputs("$(EXECUTABLE): $(LIBRARY)\n"
3029 "\tif $(CXX) $(LDFLAGS) -o $@ $(LIBRARY)", fp);
3030 }
3031 else {
3032 fprintf(fp, "$(EXECUTABLE): %s", makefile->dynamic ? "$(SHARED_OBJECTS)" : "$(OBJECTS)");
3033 if (!makefile->linkingStrategy) { // use the old linking method
3034 if (makefile->central_storage) {
3035 if (makefile->dynamic) {
3036 fputs(" $(BASE_SHARED_OBJECTS)", fp);
3037 } else {
3038 fputs(" $(BASE_OBJECTS)", fp);
3039 }
3040 }
3041 }
3042 else {
3043 if (!makefile->library) {
3044 if (makefile->dynamic) {
3045 fputs(" $(BASE_SHARED_OBJECTS)", fp);
3046 }
3047 else {
3048 fputs(" $(BASE_OBJECTS)", fp);
3049 }
3050 if (makefile->hierarchical) {
3051 fputs(" $(BASE2_LIBRARY)", fp);
3052 }
3053 }
3054 }
3055 fprintf(fp, "\n"
3056 "\tif $(CXX) $(LDFLAGS) -o $@ %s",
3057 #if defined (SOLARIS) || defined (SOLARIS8)
3058 "");
3059 #else
3060 makefile->dynamic ? "-Wl,--no-as-needed " : ""); /* start writing the link step */
3061 #endif
3062 if (makefile->gnu_make) fputs("$^", fp);
3063 else {
3064 if (makefile->dynamic) {
3065 fputs("$(SHARED_OBJECTS)", fp);
3066 if (makefile->central_storage)
3067 fputs(" $(BASE_SHARED_OBJECTS)", fp);
3068 }
3069 else {
3070 fputs("$(OBJECTS)", fp);
3071 if (makefile->central_storage)
3072 fputs(" $(BASE_OBJECTS)", fp);
3073 }
3074 }
3075 }
3076
3077 if (makefile->additionalObjects) {
3078 struct string_list* act_elem = makefile->additionalObjects;
3079 while (act_elem) {
3080 if (act_elem->str) {
3081 fprintf(fp, " %s", act_elem->str);
3082 }
3083 act_elem = act_elem->next;
3084 }
3085 }
3086
3087 fprintf(fp, " \\\n"
3088 "\t-L$(TTCN3_DIR)/lib -l$(TTCN3_LIB)"
3089 " \\\n"
3090 "\t-L$(OPENSSL_DIR)/lib -lcrypto");
3091 if (!makefile->linkingStrategy) {
3092 if (makefile->linkerlibraries) {
3093 struct string_list* act_elem = makefile->linkerlibraries;
3094 while (act_elem) {
3095 if (act_elem->str) {
3096 fprintf(fp, " -l%s", act_elem->str);
3097 }
3098 act_elem = act_elem->next;
3099 }
3100 }
3101 if (makefile->linkerlibsearchpath) {
3102 struct string_list* act_elem = makefile->linkerlibsearchpath;
3103 while (act_elem) {
3104 if (act_elem->str) {
3105 fprintf(fp, " -L%s", act_elem->str);
3106 }
3107 act_elem = act_elem->next;
3108 }
3109 }
3110 fprintf(fp, " \\\n"
3111 "\t-L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \\\n"
3112 "\tthen : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi\n");
3113 }
3114 else { // new linking strategy
3115 fputs (" \\\n", fp);
3116 if (makefile->linkerlibraries && !makefile->library) {
3117 struct string2_list* head = getLinkerLibs(makefile->project_name);
3118 struct string2_list* act_elem = head;
3119 while (act_elem) {
3120 if (act_elem->str1 && act_elem->str2) {
3121 fprintf(fp, "\t-L%s -Wl,-rpath=%s -l%s \\\n", act_elem->str1, act_elem->str1, act_elem->str2);
3122 }
3123 act_elem = act_elem->next;
3124 }
3125 free_string2_list(head);
3126
3127 struct string_list* act_head = getExternalLibPaths(makefile->project_name);
3128 struct string_list* act_ext_elem = act_head;
3129 while (act_ext_elem) {
3130 if (act_ext_elem->str) {
3131 fprintf(fp, "\t-L%s \\\n", act_ext_elem->str);
3132 }
3133 act_ext_elem = act_ext_elem->next;
3134 }
3135 free_string_list(act_head);
3136 act_head = getExternalLibs(makefile->project_name);
3137 act_ext_elem = act_head;
3138 while (act_ext_elem) {
3139 if (act_ext_elem->str) {
3140 fprintf(fp, "\t-l%s \\\n", act_ext_elem->str);
3141 }
3142 act_ext_elem = act_ext_elem->next;
3143 }
3144 free_string_list(act_head);
3145 }
3146 fprintf(fp,
3147 "\t-L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \\\n"
3148 "\tthen : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi\n");
3149 }
3150 /* If the compiler will not be run because there are no TTCN(PP) or ASN.1
3151 * files, create the "compile" marker file which is checked by the
3152 * superior makefile if using this project as central storage */
3153 if (!run_compiler) fputs("\ttouch compile\n", fp);
3154 /* End of target $(EXECUTABLE) */
3155
3156 /* target $(LIBRARY) */
3157 if (makefile->dynamic) {
3158 fprintf(fp, "\n"
3159 "$(LIBRARY): $(OBJECTS)%s\n"
3160 "\t$(CXX) -shared -o $@ $(OBJECTS)",
3161 makefile->hierarchical ? " $(BASE2_LIBRARY)" : "");
3162 if (makefile->central_storage && !makefile->linkingStrategy) {
3163 fputs(" $(BASE_SHARED_OBJECTS) ;\n"
3164 "\tln -s $@ $(subst lib, ,$@) > /dev/null 2>&1 ;", fp);
3165 }
3166 if (makefile->linkingStrategy) {
3167 struct string2_list* head = getLinkerLibs(makefile->project_name);
3168 struct string2_list* act_elem = head;
3169 // If the project is Executable on Top Level the linker can link the *.a and *.so together
3170 while (act_elem && !isTopLevelExecutable(makefile->project_name)) {
3171 if (act_elem->str1 && act_elem->str2 && isDynamicLibrary(act_elem->str2)) {
3172 fputs(" \\\n", fp);
3173 fprintf(fp, "\t-L%s -Wl,-rpath=%s -l%s", act_elem->str1, act_elem->str1, act_elem->str2);
3174 }
3175 else {
3176 const char* mainLibName = getLibFromProject(makefile->project_name);
3177 ERROR("Library archive 'lib%s.a' cannot be linked to dynamic library 'lib%s.so' "
3178 "in project '%s' ",
3179 act_elem->str2, mainLibName ? mainLibName : "", makefile->project_name);
3180 free_string2_list(head);
3181 exit(EXIT_FAILURE);
3182 }
3183 act_elem = act_elem->next;
3184 }
3185 free_string2_list(head);
3186 struct string_list* act_head = getExternalLibPaths(makefile->project_name);
3187 struct string_list* act_ext_elem = act_head;
3188 while (act_ext_elem) {
3189 if (act_ext_elem->str) {
3190 fputs(" \\\n", fp);
3191 fprintf(fp, "\t-L%s", act_ext_elem->str);
3192 }
3193 act_ext_elem = act_ext_elem->next;
3194 }
3195 free_string_list(act_head);
3196 act_head = getExternalLibs(makefile->project_name);
3197 act_ext_elem = act_head;
3198 while (act_ext_elem) {
3199 if (act_ext_elem->str) {
3200 fputs(" \\\n", fp);
3201 fprintf(fp, "\t-l%s", act_ext_elem->str);
3202 }
3203 act_ext_elem = act_ext_elem->next;
3204 }
3205 free_string_list(act_head);
3206 }
3207 }
3208 else { // static linking
3209 fprintf(fp, "\n"
3210 "$(LIBRARY): $(OBJECTS)%s\n"
3211 "\t$(AR) -r%s $(ARFLAGS) $(LIBRARY) $(OBJECTS)",
3212 makefile->hierarchical ? " $(BASE2_LIBRARY)" : "",
3213 makefile->linkingStrategy ? "cT" : "");
3214 if (makefile->central_storage && !makefile->linkingStrategy) {
3215 fputs(" $(BASE_OBJECTS)", fp);
3216 }
3217 if (makefile->linkingStrategy) {
3218 if ( makefile->library) {
3219 struct string2_list* head = getLinkerLibs(makefile->project_name);
3220 struct string2_list* act_elem = head;
3221 while (act_elem) {
3222 if (act_elem->str2 && !isDynamicLibrary(act_elem->str2)) {
3223 fputs(" \\\n", fp);
3224 fprintf(fp, "\t%s/lib%s.a", act_elem->str1, act_elem->str2);
3225 }
3226 else {
3227 const char* mainLibName = getLibFromProject(makefile->project_name);
3228 if (act_elem->str2) {
3229 ERROR("Dynamic library 'lib%s.so' cannot be linked to static library 'lib%s.a' "
3230 "in project '%s' ",
3231 act_elem->str2, mainLibName ? mainLibName : "", makefile->project_name);
3232 exit(EXIT_FAILURE);
3233 }
3234 else {
3235 struct string_list* ext_libs = getExternalLibs(makefile->project_name);
3236 if (ext_libs && ext_libs->str) {
3237 ERROR("Third party dynamic library '%s' cannot be linked to static library 'lib%s.a' "
3238 "in project '%s' ", ext_libs->str,
3239 mainLibName ? mainLibName : "", makefile->project_name);
3240 free_string_list(ext_libs);
3241 exit(EXIT_FAILURE);
3242 }
3243 free_string_list(ext_libs);
3244 }
3245 }
3246 act_elem = act_elem->next;
3247 }
3248 free_string2_list(head);
3249
3250 struct string_list* act_head = getExternalLibs(makefile->project_name);
3251 struct string_list* act_ext_elem = act_head;
3252 while (act_ext_elem) {
3253 if (act_ext_elem->str && hasExternalLibrary(act_ext_elem->str, makefile->project_name)) {
3254 fputs(" \\\n", fp);
3255 fprintf(fp, "\tlib%s.a", act_ext_elem->str);
3256 ERROR("linking static 3d party or system library 'lib%s.a' to "
3257 "project library 'lib%s.a' is not supported ",
3258 act_ext_elem->str, makefile->ets_name);
3259 exit(EXIT_FAILURE);
3260 }
3261 act_ext_elem = act_ext_elem->next;
3262 }
3263 free_string_list(act_head);
3264 }
3265 }
3266 }
3267 fputs("\n\n.cc.o .c.o:\n"
3268 "\t$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $<\n\n", fp);
3269
3270 if (makefile->gcc_dep) {
3271 fputs(".cc.d .c.d:\n"
3272 "\t@echo Creating dependency file for '$<'; set -e; \\\n"
3273 "\t$(CXX) $(CXXDEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $< \\\n"
3274 "\t| sed 's/\\($*\\)\\.o[ :]*/\\1.o $@ : /g' > $@; \\\n"
3275 "\t[ -s $@ ] || rm -f $@\n\n", fp);
3276 /* "set -e" causes bash to exit the script if any statement
3277 * returns nonzero (failure).
3278 * The sed line transforms the first line of the dependency from
3279 * "x.o: x.cc" to "x.o x.d: x.cc", making the dependency file depend
3280 * on the source and headers.
3281 * [ -s x.d ] checks that the generated dependency is not empty;
3282 * otherwise it gets deleted.
3283 */
3284 }
3285
3286 if (makefile->dynamic) {
3287 fputs("%.so: %.o\n"
3288 "\t$(CXX) -shared -o $@ $<\n\n", fp);
3289 }
3290
3291 if (makefile->preprocess) {
3292 fputs("%.ttcn: %.ttcnpp $(TTCN3_INCLUDES)\n"
3293 "\t$(CPP) -x c -nostdinc $(CPPFLAGS_TTCN3) $< $@\n\n"
3294 "preprocess: $(PREPROCESSED_TTCN3_MODULES) ;\n\n", fp);
3295 }
3296
3297 boolean merge_profiled_file_lists = makefile->profiled_file_list
3298 && makefile->profiled_file_list->next && !makefile->central_storage;
3299 if (makefile->central_storage) {
3300 boolean is_first = TRUE;
3301 fprintf(fp, "$(GENERATED_SOURCES) $(GENERATED_HEADERS):%s compile-all compile ",
3302 makefile->hierarchical ? " update" : "");
3303
3304 if (add_refd_prjs) fputs("referenced-dep", fp);
3305 /* These extra compile dependencies for the generated .cc are here to
3306 * check if all the referenced projects are up to date.
3307 * If the referenced projects are built too then they are not needed
3308 * (and cause problems as the included .d depends on the .cc).
3309 */
3310 if (!add_refd_prjs) for (i = 0; i < makefile->nBaseDirs; i++) {
3311 const struct base_dir_struct *base_dir = makefile->BaseDirs + i;
3312 if (base_dir->has_modules) {
3313 if (is_first) {
3314 fputs(" \\\n", fp);
3315 is_first = FALSE;
3316 }
3317 else putc(' ', fp);
3318 fprintf(fp, "%s/compile", base_dir->dir_name);
3319 }
3320 }
3321 if (makefile->preprocess) {
3322 fprintf(fp, "\n"
3323 "\t@if [ ! -f $@ ]; then %s compile-all; $(MAKE) compile-all; fi\n"
3324 "\n"
3325 "check:%s $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3326 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
3327 "%s\\\n"
3328 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n"
3329 "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ",
3330 rm_command, add_refd_prjs?" referenced-check":"",
3331 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3332 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
3333 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3334 if (makefile->gnu_make) {
3335 if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul
3336 fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3337 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
3338 "%s\\\n"
3339 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n",
3340 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3341 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
3342 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3343 else
3344 fputs("$^", fp);
3345 }
3346 else {
3347 fputs("\\\n"
3348 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n"
3349 "\t$(PREPROCESSED_TTCN3_MODULES) "
3350 "$(BASE_PREPROCESSED_TTCN3_MODULES) \\\n"
3351 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)", fp);
3352 }
3353 fprintf(fp, "\n\n"
3354 "port: $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3355 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
3356 "%s\n"
3357 "\t$(TTCN3_DIR)/bin/compiler -t $(COMPILER_FLAGS) ",
3358 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3359 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"");
3360 if (makefile->gnu_make) {
3361 if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul
3362 fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3363 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
3364 "%s\n",
3365 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3366 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"");
3367 else
3368 fputs("$^", fp);
3369 }
3370 else {
3371 fputs("\\\n"
3372 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n"
3373 "\t$(PREPROCESSED_TTCN3_MODULES) "
3374 "$(BASE_PREPROCESSED_TTCN3_MODULES) \n", fp);
3375 }
3376 if (makefile->linkingStrategy && makefile->hierarchical) {
3377 fputs("\n\n"
3378 "update: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) \\\n"
3379 "\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) $(BASE2_PREPROCESSED_TTCN3_MODULES)\n"
3380 "ifneq ($(wildcard $(GENERATED_SOURCES)), ) \n"
3381 "ifeq ($(wildcard $?), ) \n"
3382 "\ttouch compile-all; \n"
3383 "\ttouch update; \n"
3384 "endif\n"
3385 "endif",fp);
3386 }
3387 if (makefile->profiled_file_list) {
3388 fputs("\n\n"
3389 "compile:: $(PROFILED_FILE_LIST)\n"
3390 "\ttouch $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) "
3391 "$(ASN1_MODULES)", fp);
3392 }
3393 fprintf(fp, "\n\n"
3394 "compile:%s $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) "
3395 "$(ASN1_MODULES)\n"
3396 "\t@echo \"compiling \"'$(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\\\n"
3400 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s - $?\n"
3401 "\ttouch $@\n\n",
3402 makefile->profiled_file_list ? ":" : "",
3403 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3404 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
3405 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES)":"");
3406 fprintf (fp,
3407 "compile-all: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
3408 "%s"
3409 "\t$(MAKE) preprocess\n"
3410 "\t@echo \"compiling all \"'$(patsubst %%.tpd, %%, $(TPD))';\n"
3411 "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
3412 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3413 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) %s"
3414 "\\\n"
3415 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
3416 "\t- $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES)\n"
3417 "\ttouch $@ compile\n\n",
3418 makefile->linkingStrategy ? "\\\n\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) "
3419 "$(BASE2_PREPROCESSED_TTCN3_MODULES) \n":"\n",
3420 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3421 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
3422 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3423 }
3424 else {
3425 fprintf(fp, "\n"
3426 "\t@if [ ! -f $@ ]; then %s compile-all; $(MAKE) compile-all; fi\n", rm_command);
3427 fprintf(fp, "\n"
3428 "check:%s $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3429 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n"
3430 "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ",
3431 add_refd_prjs?" referenced-check":"",
3432 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3433 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3434 if (makefile->gnu_make) {
3435 if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul
3436 fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3437 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n",
3438 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3439 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3440 else
3441 fputs("$^", fp);
3442 }
3443 else {
3444 fputs("\\\n"
3445 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n"
3446 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)", fp);
3447 }
3448
3449 fprintf(fp, "\n\n"
3450 "port: $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\n"
3451 "\t$(TTCN3_DIR)/bin/compiler -t $(COMPILER_FLAGS) ",
3452 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"");
3453 if (makefile->gnu_make) {
3454 if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul
3455 fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\n",
3456 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"");
3457 else
3458 fputs("$^", fp);
3459 }
3460 else {
3461 fputs("\\\n"
3462 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \n", fp);
3463 }
3464
3465 if (makefile->linkingStrategy && makefile->hierarchical) {
3466 fputs("\n\n"
3467 "update: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) \\\n"
3468 "\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) $(BASE2_PREPROCESSED_TTCN3_MODULES)\n"
3469 "ifneq ($(wildcard $(GENERATED_SOURCES)), ) \n"
3470 "ifeq ($(wildcard $?), ) \n"
3471 "\ttouch compile-all; \n"
3472 "\ttouch update; \n"
3473 "endif\n"
3474 "endif",fp);
3475 }
3476
3477 if (makefile->profiled_file_list) {
3478 fputs("\n\n"
3479 "compile:: $(PROFILED_FILE_LIST)\n"
3480 "\ttouch $(TTCN3_MODULES) $(ASN1_MODULES)", fp);
3481 }
3482 fprintf(fp, "\n\n"
3483 "compile:%s $(TTCN3_MODULES) $(ASN1_MODULES)\n"
3484 "\t@echo \"compiling \"'$(patsubst %%.tpd, %%, $(TPD))';\n"
3485 "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
3486 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3487 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
3488 "\t- $?\n"
3489 "\ttouch $@\n\n",
3490 makefile->profiled_file_list ? ":" : "",
3491 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "",
3492 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : "");
3493 fprintf(fp,
3494 "compile-all: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) %s\n",
3495 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES)" : "");
3496 fputs("\t@echo \"compiling all \"'$(patsubst %.tpd, %, $(TPD))';\n", fp);
3497 fprintf(fp,"\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
3498 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3499 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
3500 "\t- $(TTCN3_MODULES) $(ASN1_MODULES)\n"
3501 "\ttouch $@ compile\n\n",
3502 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "",
3503 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : "");
3504 }
3505 if (!makefile->hierarchical)
3506 for (i = 0; i < makefile->nBaseDirs; i++) {
3507 const struct base_dir_struct *base_dir = makefile->BaseDirs + i;
3508 if (base_dir->has_modules) {
3509 size_t j;
3510 fprintf(fp, "%s/compile:", base_dir->dir_name);
3511 for (j = 0; j < makefile->nTTCN3Modules; j++) {
3512 const struct module_struct *module = makefile->TTCN3Modules + j;
3513 if (module->dir_name != NULL &&
3514 !strcmp(base_dir->dir_name, module->dir_name))
3515 print_file_name(fp, module);
3516 }
3517 for (j = 0; j < makefile->nTTCN3PPModules; j++) {
3518 const struct module_struct *module = makefile->TTCN3PPModules + j;
3519 if (module->dir_name != NULL &&
3520 !strcmp(base_dir->dir_name, module->dir_name))
3521 print_file_name(fp, module);
3522 }
3523 for (j = 0; j < makefile->nASN1Modules; j++) {
3524 const struct module_struct *module = makefile->ASN1Modules + j;
3525 if (module->dir_name != NULL &&
3526 !strcmp(base_dir->dir_name, module->dir_name))
3527 print_file_name(fp, module);
3528 }
3529 fprintf(fp, "\n"
3530 "\t@echo 'Central directory %s is not up-to-date!'\n"
3531 "\t@exit 2\n\n", base_dir->dir_name);
3532 }
3533 }
3534 }
3535 else { /* not central storage */
3536 fprintf(fp, "$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile\n"
3537 "\t@if [ ! -f $@ ]; then %s compile; $(MAKE) compile; fi\n\n"
3538 "%s"
3539 "check:%s $(TTCN3_MODULES) ", rm_command,
3540 merge_profiled_file_lists ? "check:: $(PROFILED_FILE_LIST)\n\n" : "",
3541 merge_profiled_file_lists ? ":" : "");
3542 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3543 fputs("$(ASN1_MODULES)\n"
3544 "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ", fp);
3545 if (makefile->gnu_make) fputs("$^", fp);
3546 else {
3547 fputs("\\\n"
3548 "\t$(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES)",
3549 fp);
3550 }
3551
3552 fputs("\n\n", fp);
3553 fprintf(fp, "port: $(TTCN3_MODULES) ");
3554 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3555 fputs("\n", fp);
3556 fputs("\t$(TTCN3_DIR)/bin/compiler -t $(COMPILER_FLAGS) ", fp);
3557 if (makefile->gnu_make) fputs("$^", fp);
3558 else {
3559 fputs("\\\n"
3560 "\t$(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES)",
3561 fp);
3562 }
3563
3564 if (makefile->profiled_file_list) {
3565 fputs("\n\ncompile:: $(PROFILED_FILE_LIST)\n"
3566 "\ttouch $(TTCN3_MODULES) ", fp);
3567 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3568 fputs("$(ASN1_MODULES)", fp);
3569 }
3570 fprintf(fp, "\n\n"
3571 "compile:%s $(TTCN3_MODULES) ", makefile->profiled_file_list ? ":" : "");
3572 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3573 fputs("$(ASN1_MODULES)\n"
3574 "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) ", fp);
3575 if (makefile->gnu_make) fputs("$^", fp);
3576 else {
3577 fputs("\\\n"
3578 "\t$(TTCN3_MODULES) ", fp);
3579 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3580 fputs("$(ASN1_MODULES)", fp);
3581 }
3582 fputs(" - $?\n"
3583 "\ttouch $@\n"
3584 "\n", fp);
3585 if (merge_profiled_file_lists) {
3586 fputs("$(PROFILED_FILE_LIST): $(PROFILED_FILE_LIST_SEGMENTS)\n"
3587 "\tcat $(PROFILED_FILE_LIST_SEGMENTS) > $(PROFILED_FILE_LIST)\n\n", fp);
3588 }
3589 }
3590 // clean:
3591 if (makefile->linkingStrategy) {
3592 fprintf(fp, "clean:%s\n", (add_refd_prjs && !makefile->hierarchical) ?
3593 " referenced-clean" : "");
3594 if (makefile->dynamic && (makefile->central_storage || makefile->linkingStrategy)) {
3595 fprintf(fp,"\tfind . -type l -name \"*.so\" -exec unlink {} \\;\n");
3596 }
3597 fprintf(fp, "\t%s $(EXECUTABLE) $(DYNAMIC_LIBRARY) $(STATIC_LIBRARY) "
3598 "$(OBJECTS) $(GENERATED_HEADERS) \\\n"
3599 "\t$(GENERATED_SOURCES) ", rm_command);
3600 if (makefile->dynamic) fputs("$(SHARED_OBJECTS) ", fp);
3601 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3602 fputs("compile", fp);
3603 if (makefile->central_storage) fputs(" compile-all", fp);
3604 if (makefile->gcc_dep) fputs(" $(DEPFILES)", fp);
3605 if (merge_profiled_file_lists) {
3606 fputs(" $(PROFILED_FILE_LIST)", fp);
3607 }
3608 fprintf(fp, " \\\n"
3609 "\ttags *.log%s%s\n\n",
3610 add_refd_prjs?" referenced*":"",
3611 makefile->hierarchical ? " update":"");
3612 }
3613 else {
3614 fprintf(fp, "clean:%s\n"
3615 "\t-%s $(EXECUTABLE) $(LIBRARY) $(OBJECTS) $(GENERATED_HEADERS) \\\n"
3616 "\t$(GENERATED_SOURCES) ", add_refd_prjs?" referenced-clean":"", rm_command);
3617 if (makefile->dynamic) fputs("$(SHARED_OBJECTS) ", fp);
3618 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3619 fputs("compile", fp);
3620 if (makefile->central_storage) fputs(" compile-all", fp);
3621 if (makefile->gcc_dep) fputs(" $(DEPFILES)", fp);
3622 if (merge_profiled_file_lists) {
3623 fputs(" $(PROFILED_FILE_LIST)", fp);
3624 }
3625 fprintf(fp, " \\\n"
3626 "\ttags *.log%s",
3627 add_refd_prjs?" referenced*":"");
3628 }
3629
3630 // clean-all:
3631 if (makefile->linkingStrategy && makefile->hierarchical)
3632 fprintf(fp, "clean-all: %s clean\n", add_refd_prjs ? "referenced-clean-all":"");
3633
3634 // dep:
3635 fputs("\n\ndep: $(GENERATED_SOURCES) $(USER_SOURCES)",fp);
3636 if (add_refd_prjs) {
3637 fprintf(fp, "\n\t%s referenced-dep", rm_command);
3638 }
3639 else fputs(" ;",fp);
3640
3641 if (makefile->gcc_dep) {
3642 fprintf(fp, " \n\n"
3643 "ifeq ($(findstring n,$(MAKEFLAGS)),)\n"
3644 "ifeq ($(filter clean%s check port compile archive diag%s,$(MAKECMDGOALS)),)\n"
3645 "-include $(DEPFILES)\n"
3646 "endif\n"
3647 "endif",
3648 (makefile->linkingStrategy && makefile->hierarchical) ? " clean-all" : "",
3649 (makefile->preprocess ? " preprocess" : ""));
3650 /* Don't include .d files when cleaning etc.; make will try to build them
3651 * and this involves running the Titan compiler. Same for preprocess.
3652 * The check target would be pointless if running the compiler
3653 * without generating code was always preceded by running the compiler
3654 * _and_ generating C++ code. */
3655 }
3656 else { /* old-style dep with makedepend. Do not check compiler version. */
3657 fputs("\n\tmakedepend $(CPPFLAGS) -DMAKEDEPEND_RUN ", fp);
3658 if (makefile->gnu_make) fputs("$^", fp);
3659 else fputs("$(GENERATED_SOURCES) $(USER_SOURCES)", fp);
3660 }
3661
3662 if (makefile->linkingStrategy) {
3663 fputs("\n\n"
3664 "archive:\n"
3665 "\t@perl $(TTCN3_DIR)/bin/ttcn3_archive\n\n", fp);
3666 }
3667 else {
3668 fputs("\n\n"
3669 "archive:\n"
3670 "\tmkdir -p $(ARCHIVE_DIR)\n"
3671 "\ttar -cvhf - ", fp);
3672 if (makefile->central_storage) {
3673 fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n",
3674 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "");
3675 if (makefile->preprocess) {
3676 fprintf(fp, "\t$(TTCN3_PP_MODULES) $(BASE_TTCN3_PP_MODULES) "
3677 "%s $(TTCN3_INCLUDES) \\\n",
3678 makefile->linkingStrategy ? "$(BASE2_TTCN3_PP_MODULES)" : "");
3679 }
3680 fprintf(fp, "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
3681 "\t$(USER_HEADERS) $(BASE_USER_HEADERS) %s\\\n"
3682 "\t$(USER_SOURCES) $(BASE_USER_SOURCES) %s",
3683 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : "",
3684 makefile->linkingStrategy ? "$(BASE2_USER_HEADERS) " : "",
3685 makefile->linkingStrategy ? "$(BASE2_USER_SOURCES)" : "");
3686 }
3687 else {
3688 fputs("$(TTCN3_MODULES) ", fp);
3689 if (makefile->preprocess) {
3690 fputs("$(TTCN3_PP_MODULES) \\\n"
3691 "\t$(TTCN3_INCLUDES) ", fp);
3692 }
3693 fputs("$(ASN1_MODULES) \\\n"
3694 "\t$(USER_HEADERS) $(USER_SOURCES)", fp);
3695 }
3696 fputs(" $(OTHER_FILES) \\\n"
3697 "\t| gzip >$(ARCHIVE_DIR)/`basename $(TARGET) .exe`-"
3698 "`date '+%y%m%d-%H%M'`.tgz\n\n", fp);
3699 }
3700
3701 fprintf(fp, "diag:\n"
3702 "\t$(TTCN3_DIR)/bin/compiler -v 2>&1\n"
3703 "\t$(TTCN3_DIR)/bin/mctr_cli -v 2>&1\n"
3704 "\t$(CXX) -v 2>&1\n"
3705 "%s"
3706 "\t@echo TTCN3_DIR=$(TTCN3_DIR)\n"
3707 "\t@echo OPENSSL_DIR=$(OPENSSL_DIR)\n"
3708 "\t@echo XMLDIR=$(XMLDIR)\n"
3709 "\t@echo PLATFORM=$(PLATFORM)\n\n",
3710 makefile->dynamic ? "" : "\t$(AR) -V 2>&1\n");
3711
3712 if (add_refd_prjs) {
3713 fprintf(fp, "referenced-all referenced-shared_objects referenced-executable referenced-library \\\n"
3714 "referenced-objects referenced-check \\\n"
3715 "referenced-clean%s:\n"
3716 "\t@for dir in $(REFERENCED_PROJECT_DIRS); do \\\n"
3717 "\t $(MAKE) -C $$dir $(subst referenced-,,$@) || exit; \\\n"
3718 "\tdone; \n\n",
3719 (makefile->linkingStrategy && makefile->hierarchical) ? "-all" : "");
3720 fputs("referenced-dep:\n"
3721 "\t@for dir in $(REFERENCED_PROJECT_DIRS); do \\\n"
3722 "\t $(MAKE) -C $$dir $(subst referenced-,,$@) || exit; \\\n"
3723 "\tdone; \n"
3724 "\ttouch $@\n\n", fp);
3725 }
3726
3727 if (makefile->generatorCommandOutput) {
3728 fputs("### Project specific rules generated by user written script:\n\n", fp);
3729 fputs(makefile->generatorCommandOutput, fp);
3730 fputs("\n### End of project specific rules.\n\n", fp);
3731 }
3732
3733 fputs("#\n"
3734 "# Add your rules here if necessary...\n"
3735 "#\n\n", fp);
3736 fclose(fp);
3737 if (strcmp(makefile->output_file, "Makefile")) {
3738 NOTIFY("Makefile skeleton was written to `%s'.", makefile->output_file);
3739 } else {
3740 NOTIFY("Makefile skeleton was generated.");
3741 }
3742 }
3743 else {
3744 ERROR("Output file `%s' already exists. Use switch `%s' to force "
3745 "overwrite.",
3746 makefile->output_file,
3747 makefile->linkingStrategy ? "-F" : "-f");
3748 }
3749 }
3750
3751 #undef COMMENT_PREFIX
3752 #define COMMENT_PREFIX
3753
3754 /** run makefilegen commans for sub-projects */
3755 static void run_makefilegen_commands(struct string2_list* run_command_list)
3756 {
3757 struct string2_list* act_elem = run_command_list;
3758 while (act_elem) {
3759 struct string2_list* next_elem = act_elem->next;
3760 /* run commands if there were no ERRORs */
3761 if ((error_count == 0) && act_elem->str1 && act_elem->str2) {
3762 int rv;
3763 char* sub_proj_effective_work_dir = act_elem->str1;
3764 char* command = act_elem->str2;
3765 char* orig_dir = get_working_dir();
3766 rv = set_working_dir(sub_proj_effective_work_dir);
3767 if (rv) ERROR("Could not set working dir to `%s'", sub_proj_effective_work_dir);
3768 else {
3769 fprintf(stderr, "Executing `%s' in working directory `%s'...\n",
3770 command, sub_proj_effective_work_dir);
3771 rv = system(command);
3772 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
3773 }
3774 rv = set_working_dir(orig_dir);
3775 if (rv) ERROR("Could not restore working dir to `%s'", orig_dir);
3776 Free(orig_dir);
3777 }
3778 Free(act_elem->str1);
3779 Free(act_elem->str2);
3780 Free(act_elem);
3781 act_elem = next_elem;
3782 }
3783 }
3784
3785 /** create symlinks and delete list */
3786 static void generate_symlinks(struct string2_list* create_symlink_list)
3787 {
3788 struct string2_list* act_elem = create_symlink_list;
3789 while (act_elem) {
3790 struct string2_list* next_elem = act_elem->next;
3791 /* create symlinks if there were no ERRORs */
3792 if ((error_count == 0) && act_elem->str1 && act_elem->str2) {
3793 int fail = symlink(act_elem->str1, act_elem->str2);
3794 if (fail) perror(act_elem->str2); /* complain but do not call ERROR() */
3795 }
3796 Free(act_elem->str1);
3797 Free(act_elem->str2);
3798 Free(act_elem);
3799 act_elem = next_elem;
3800 }
3801 }
3802
3803 /** Performs all tasks of Makefile generation based on the given list of
3804 * modules/files (taken from the command line) and options that represent
3805 * command line switches. */
3806 static void generate_makefile(size_t n_arguments, char *arguments[],
3807 size_t n_other_files, const char *other_files[], const char *output_file,
3808 const char *ets_name, char *project_name, boolean gnu_make, boolean single_mode,
3809 boolean central_storage, boolean absolute_paths, boolean preprocess,
3810 boolean dump_makefile_data, boolean force_overwrite, boolean use_runtime_2,
3811 boolean dynamic, boolean makedepend, boolean coverage,
3812 const char *code_splitting_mode, const char *tcov_file_name, struct string_list* profiled_file_list,
3813 boolean Lflag, boolean Zflag, boolean Hflag, struct string_list* sub_project_dirs, struct string_list* ttcn3_prep_includes,
3814 struct string_list* ttcn3_prep_defines, struct string_list* ttcn3_prep_undefines, struct string_list* prep_includes,
3815 struct string_list* prep_defines, struct string_list* prep_undefines, boolean codesplittpd, boolean quietly, boolean disablesubtypecheck,
3816 const char* cxxcompiler, const char* optlevel, const char* optflags, boolean disableber, boolean disableraw, boolean disabletext,
3817 boolean disablexer, boolean disablejson, boolean forcexerinasn, boolean defaultasomit, boolean gccmsgformat,
3818 boolean linenumbersonlymsg, boolean includesourceinfo, boolean addsourcelineinfo, boolean suppresswarnings,
3819 boolean outparamboundness, boolean omit_in_value_list, boolean warnings_for_bad_variants, boolean disable_predef_ext_folder, struct string_list* solspeclibraries,
3820 struct string_list* sol8speclibraries, struct string_list* linuxspeclibraries, struct string_list* freebsdspeclibraries,
3821 struct string_list* win32speclibraries, const char* ttcn3preprocessor, struct string_list* linkerlibraries,
3822 struct string_list* additionalObjects, struct string_list* linkerlibsearchpath, char* generatorCommandOutput,
3823 struct string2_list* target_placement_list)
3824 {
3825 size_t i;
3826
3827 struct makefile_struct makefile;
3828 init_makefile_struct(&makefile);
3829
3830 makefile.project_name = project_name;
3831 makefile.central_storage = central_storage;
3832 makefile.gnu_make = gnu_make;
3833 makefile.preprocess = preprocess;
3834 makefile.single_mode = single_mode;
3835 makefile.force_overwrite = force_overwrite;
3836 makefile.use_runtime_2 = use_runtime_2;
3837 makefile.dynamic = dynamic;
3838 makefile.gcc_dep = gnu_make && !makedepend;
3839 makefile.coverage = coverage;
3840 makefile.library = Lflag;
3841 makefile.linkingStrategy = Zflag;
3842 makefile.hierarchical = Hflag;
3843 makefile.sub_project_dirs = sub_project_dirs;
3844 makefile.ttcn3_prep_includes = ttcn3_prep_includes;
3845 makefile.ttcn3_prep_defines = ttcn3_prep_defines;
3846 makefile.ttcn3_prep_undefines = ttcn3_prep_undefines;
3847 makefile.prep_includes = prep_includes;
3848 makefile.prep_defines = prep_defines;
3849 makefile.prep_undefines = prep_undefines;
3850 makefile.codesplittpd = codesplittpd;
3851 makefile.quietly = quietly;
3852 makefile.disablesubtypecheck = disablesubtypecheck;
3853 makefile.cxxcompiler = cxxcompiler;
3854 makefile.optlevel = optlevel;
3855 makefile.optflags = optflags;
3856 makefile.disableber = disableber;
3857 makefile.disableraw = disableraw;
3858 makefile.disabletext = disabletext;
3859 makefile.disablexer = disablexer;
3860 makefile.disablejson = disablejson;
3861 makefile.forcexerinasn = forcexerinasn;
3862 makefile.defaultasomit = defaultasomit;
3863 makefile.gccmsgformat = gccmsgformat;
3864 makefile.linenumbersonlymsg = linenumbersonlymsg;
3865 makefile.includesourceinfo = includesourceinfo;
3866 makefile.addsourcelineinfo = addsourcelineinfo;
3867 makefile.suppresswarnings = suppresswarnings;
3868 makefile.outparamboundness = outparamboundness;
3869 makefile.omit_in_value_list = omit_in_value_list;
3870 makefile.warnings_for_bad_variants = warnings_for_bad_variants;
3871 makefile.disable_predef_ext_folder = disable_predef_ext_folder;
3872 makefile.solspeclibraries = solspeclibraries;
3873 makefile.sol8speclibraries = sol8speclibraries;
3874 makefile.linuxspeclibraries = linuxspeclibraries;
3875 makefile.freebsdspeclibraries = freebsdspeclibraries;
3876 makefile.win32speclibraries = win32speclibraries;
3877 makefile.ttcn3preprocessor = ttcn3preprocessor;
3878 makefile.linkerlibraries = linkerlibraries;
3879 makefile.additionalObjects = additionalObjects;
3880 makefile.linkerlibsearchpath = linkerlibsearchpath;
3881 makefile.generatorCommandOutput = generatorCommandOutput;
3882 makefile.target_placement_list = target_placement_list;
3883
3884 for (i = 0; i < n_arguments; i++) {
3885 char *file_name = get_file_name_for_argument(arguments[i]);
3886 if (file_name != NULL) {
3887 FILE *fp = fopen(file_name, "r");
3888 if (fp != NULL) {
3889 char *module_name;
3890 if (is_ttcn3_module(file_name, fp, &module_name)) {
3891 if (is_asn1_module(file_name, fp, NULL)) {
3892 ERROR("File `%s' looks so strange that it can be both ASN.1 and "
3893 "TTCN-3 module. Add it to the Makefile manually.", file_name);
3894 Free(module_name);
3895 } else {
3896 add_ttcn3_module(&makefile, file_name, module_name);
3897 }
3898 } else if (is_asn1_module(file_name, fp, &module_name)) {
3899 if (is_valid_asn1_filename(file_name)) {
3900 add_asn1_module(&makefile, file_name, module_name);
3901 } else {
3902 ERROR("The file name (without suffix) shall be identical to the module name.\n"
3903 "If the name of the ASN.1 module contains a hyphen, the corresponding "
3904 "file name shall contain an underscore character instead.");
3905 }
3906 } else {
3907 add_user_file(&makefile, file_name);
3908 }
3909 fclose(fp);
3910 } else {
3911 ERROR("Cannot open file `%s' for reading: %s", file_name,
3912 strerror(errno));
3913 errno = 0;
3914 }
3915 Free(file_name);
3916 } else if (get_path_status(arguments[i]) == PS_DIRECTORY) {
3917 ERROR("Argument `%s' is a directory.", arguments[i]);
3918 } else {
3919 ERROR("Cannot find any source file for argument `%s'.", arguments[i]);
3920 }
3921 }
3922 for (i = 0; i < n_other_files; i++) {
3923 char *file_name = get_file_name_for_argument(other_files[i]);
3924 if (file_name != NULL) {
3925 add_path_to_list(&makefile.nOtherFiles, &makefile.OtherFiles, file_name,
3926 makefile.working_dir, TRUE);
3927 Free(file_name);
3928 } else if (get_path_status(other_files[i]) == PS_DIRECTORY) {
3929 ERROR("Argument `%s' given as other file is a directory.",
3930 other_files[i]);
3931 } else {
3932 ERROR("Cannot find any other file for argument `%s'.", other_files[i]);
3933 }
3934 }
3935
3936 if (ets_name != NULL) {
3937 char *dir_name = get_dir_name(ets_name, makefile.working_dir);
3938 char *file_name = get_file_from_path(ets_name);
3939 makefile.ets_name = compose_path_name(dir_name, file_name);
3940 Free(dir_name);
3941 Free(file_name);
3942 }
3943
3944 if (code_splitting_mode != NULL) {
3945 makefile.code_splitting_mode = mputprintf(makefile.code_splitting_mode, "-U %s", code_splitting_mode);
3946 }
3947
3948 if (tcov_file_name != NULL) {
3949 makefile.tcov_file_name = mprintf(" -K %s", tcov_file_name);
3950 }
3951
3952 if (profiled_file_list != NULL) {
3953 makefile.profiled_file_list = profiled_file_list;
3954 }
3955
3956 if (makefile.nTTCN3Modules >= 1) {
3957 if (makefile.ets_name == NULL)
3958 makefile.ets_name = mcopystr(makefile.TTCN3Modules[0].module_name);
3959 } else if (preprocess && (makefile.nTTCN3PPModules >= 1)) {
3960 if (makefile.ets_name == NULL)
3961 makefile.ets_name = mcopystr(makefile.TTCN3PPModules[0].module_name);
3962 } else if (makefile.nASN1Modules >= 1) {
3963 WARNING("No TTCN-3 module was given for the Makefile.");
3964 if (makefile.ets_name == NULL)
3965 makefile.ets_name = mcopystr(makefile.ASN1Modules[0].module_name);
3966 } else if (makefile.nUserFiles > 0) {
3967 WARNING("No TTCN-3 or ASN.1 module was given for the Makefile.");
3968 if (makefile.ets_name == NULL)
3969 makefile.ets_name = mcopystr(makefile.UserFiles[0].file_prefix);
3970 } else {
3971 WARNING("No source files were given for the Makefile");
3972 }
3973
3974 if (output_file != NULL) {
3975 if (get_path_status(output_file) == PS_DIRECTORY)
3976 makefile.output_file = mprintf("%s/Makefile", output_file);
3977 else makefile.output_file = mcopystr(output_file);
3978 } else makefile.output_file = mcopystr("Makefile");
3979 add_path_to_list(&makefile.nOtherFiles, &makefile.OtherFiles,
3980 makefile.output_file, makefile.working_dir, FALSE);
3981
3982 if (preprocess) check_preprocessed_filename_collision(&makefile);
3983 filter_out_generated_files(&makefile);
3984 complete_user_files(&makefile);
3985 if (!absolute_paths) convert_dirs_to_relative(&makefile);
3986 check_special_chars(&makefile);
3987 if (central_storage) collect_base_dirs(&makefile);
3988 check_naming_convention(&makefile);
3989
3990 if (dump_makefile_data) dump_makefile_struct(&makefile, 0);
3991
3992 if (error_count == 0) print_makefile(&makefile);
3993 free_makefile_struct(&makefile);
3994 }
3995
3996 #ifdef COVERAGE_BUILD
3997 #define C_flag "C"
3998 #else
3999 #define C_flag
4000 #endif
4001
4002
4003 static void usage(void)
4004 {
4005 fprintf(stderr, "\n"
4006 "usage: %s [-abc" C_flag "dDEfFglLmMprRstTVwWXZ] [-K file] [-z file ] [-P dir]"
4007 " [-U none|type] [-e ets_name] [-o dir|file]\n"
4008 " [-t project_descriptor.tpd [-b buildconfig]]\n"
4009 " [-O file] ... module_name ... testport_name ...\n"
4010 " or %s -v\n"
4011 "\n"
4012 "OPTIONS:\n"
4013 " -a: use absolute pathnames in the generated Makefile\n"
4014 " -c: use the pre-compiled files from central directories\n"
4015 #ifdef COVERAGE_BUILD
4016 " -C: enable coverage of generated C++ code\n"
4017 #endif
4018 " -d: dump the data used for Makefile generation\n"
4019 " -e ets_name: name of the target executable\n"
4020 " -E: display only warnings for unrecognized encoding variants\n"
4021 " -f: force overwriting of the output Makefile\n"
4022 " -g: generate Makefile for use with GNU make\n"
4023 " -I path: Add path to the search paths when using TPD files\n"
4024 " -K file: enable selective code coverage\n"
4025 " -l: use dynamic linking\n"
4026 " -L: create makefile with library archive as the default target\n"
4027 " -m: always use makedepend for dependencies\n"
4028 " -M: allow 'omit' in template value lists (legacy behavior)\n"
4029 " -o dir|file: write the Makefile to the given directory or file\n"
4030 " -O file: add the given file to the Makefile as other file\n"
4031 " -p: generate Makefile with TTCN-3 preprocessing\n"
4032 " -R: use function test runtime (TITAN_RUNTIME_2)\n"
4033 " -s: generate Makefile for single mode\n"
4034 " -U none|type: split generated code\n"
4035 " -v: show version\n"
4036 " -w: suppress warnings\n"
4037 " -Y: Enforces legacy behaviour of the \"out\" function parameters (see refguide)\n"
4038 " -z file: enable profiling and code coverage for the TTCN-3 files in the argument\n"
4039 "Options for processing the Titan Project Descriptor file(s):\n"
4040 " -t tpd: read project descriptor file\n"
4041 " -b buildconfig: use the specified build config instead of the default\n"
4042 " -D: use current directory as working directory\n"
4043 " -V: disable validation of TPD file with schema\n"
4044 " -r: generate Makefile hierarchy for TPD hierarchy (recursive)\n"
4045 " -F: force overwriting of all generated Makefiles, use with -r\n"
4046 " -T: generate only top-level Makefile of the hierarchy, use with -r\n"
4047 " -P dir: prints out a file list found in a given TPD relative to the given directory\n"
4048 " -X: generate XML file that describes the TPD hierarchy, use with -r\n"
4049 " -W: prefix working directories with project name\n"
4050 " -Z: recursive Makefile generation from TPD using object files and dynamic libraries too\n"
4051 " -H: hierachical Makefile generation from TPD use with -Z\n"
4052 , program_name, program_name);
4053 }
4054
4055 #define SET_FLAG(x) if (x##flag) {\
4056 ERROR("Flag -" #x " was specified more than once.");\
4057 error_flag = TRUE;\
4058 } else x##flag = TRUE
4059
4060 void free_string_list(struct string_list* act_elem)
4061 {
4062 while (act_elem) {
4063 struct string_list* next_elem = act_elem->next;
4064 Free(act_elem->str);
4065 Free(act_elem);
4066 act_elem = next_elem;
4067 }
4068 }
4069
4070 void free_string2_list(struct string2_list* act_elem)
4071 {
4072 while (act_elem) {
4073 struct string2_list* next_elem = act_elem->next;
4074 Free(act_elem->str1);
4075 Free(act_elem->str2);
4076 Free(act_elem);
4077 act_elem = next_elem;
4078 }
4079 }
4080
4081 int main(int argc, char *argv[])
4082 {
4083 boolean
4084 aflag = FALSE, bflag = FALSE, cflag = FALSE, Cflag = FALSE,
4085 dflag = FALSE, eflag = FALSE, fflag = FALSE, gflag = FALSE,
4086 oflag = FALSE, Kflag = FALSE, lflag = FALSE, pflag = FALSE,
4087 Pflag = FALSE, Rflag = FALSE, sflag = FALSE, tflag = FALSE,
4088 wflag = FALSE, vflag = FALSE, mflag = FALSE, Uflag = FALSE,
4089 Lflag = FALSE, rflag = FALSE, Fflag = FALSE, Xflag = FALSE,
4090 Tflag = FALSE, Yflag = FALSE, csflag = FALSE, quflag = FALSE,
4091 dsflag = FALSE, dbflag = FALSE, drflag = FALSE, dtflag = FALSE,
4092 dxflag = FALSE, fxflag = FALSE, doflag = FALSE,
4093 gfflag = FALSE, lnflag = FALSE, isflag = FALSE, asflag = FALSE,
4094 swflag = FALSE, Vflag = FALSE, Dflag = FALSE, Wflag = FALSE,
4095 djflag = FALSE, Zflag = FALSE, Hflag = FALSE, Mflag = FALSE,
4096 diflag = FALSE, zflag = FALSE, Eflag = FALSE;
4097 boolean error_flag = FALSE;
4098 char *output_file = NULL;
4099 char *ets_name = NULL;
4100 char *project_name = NULL;
4101 size_t n_other_files = 0;
4102 const char **other_files = NULL;
4103 const char *code_splitting_mode = NULL;
4104 const char *tpd_file_name = NULL;
4105 const char *tpd_build_config = NULL;
4106 const char *tcov_file_name = NULL;
4107 size_t n_search_paths = 0;
4108 const char **search_paths = NULL;
4109 struct string_list* profiled_file_list = NULL;
4110 const char *profiled_file_list_zflag = NULL;
4111 const char *file_list_path = NULL;
4112 enum tpd_result tpd_processed = FALSE;
4113 struct string_list* sub_project_dirs = NULL;
4114 struct string2_list* create_symlink_list = NULL;
4115 struct string_list* ttcn3_prep_includes = NULL;
4116 struct string_list* ttcn3_prep_defines = NULL;
4117 struct string_list* ttcn3_prep_undefines = NULL;
4118 struct string_list* prep_includes = NULL;
4119 struct string_list* prep_defines = NULL;
4120 struct string_list* prep_undefines = NULL;
4121 char *cxxcompiler = NULL;
4122 char *optlevel = NULL;
4123 char *optflags = NULL;
4124 struct string_list* solspeclibraries = NULL;
4125 struct string_list* sol8speclibraries = NULL;
4126 struct string_list* linuxspeclibraries = NULL;
4127 struct string_list* freebsdspeclibraries = NULL;
4128 struct string_list* win32speclibraries = NULL;
4129 char *ttcn3prep = NULL;
4130 struct string_list* linkerlibraries = NULL;
4131 struct string_list* additionalObjects = NULL;
4132 struct string_list* linkerlibsearchpath = NULL;
4133 char* generatorCommandOutput = NULL;
4134 struct string2_list* target_placement_list = NULL;
4135 struct string2_list* run_command_list = NULL;
4136 struct string2_list* required_configs = NULL;
4137
4138 #ifdef LICENSE
4139 license_struct lstr;
4140 int valid_license;
4141 #endif
4142
4143 program_name = argv[0];
4144
4145 if (argc == 1) {
4146 fputs("Makefile Generator for the TTCN-3 Test Executor, version "
4147 PRODUCT_NUMBER "\n", stderr);
4148 usage();
4149 return EXIT_FAILURE;
4150 }
4151
4152 for ( ; ; ) {
4153 int c = getopt(argc, argv, "O:ab:c" C_flag "dDe:EfFgI:K:o:lLmMpP:rRst:TU:vVwWXYz:ZH");
4154 if (c == -1) break;
4155 switch (c) {
4156 case 'O':
4157 n_other_files++;
4158 other_files = (const char**)
4159 Realloc(other_files, n_other_files * sizeof(*other_files));
4160 other_files[n_other_files - 1] = optarg;
4161 break;
4162 case 'I':
4163 n_search_paths++;
4164 search_paths = (const char**)
4165 Realloc(search_paths, n_search_paths * sizeof(*search_paths));
4166 search_paths[n_search_paths - 1] = optarg;
4167 break;
4168 case 'a':
4169 SET_FLAG(a);
4170 break;
4171 case 'b':
4172 SET_FLAG(b);
4173 tpd_build_config = optarg;
4174 break;
4175 case 'c':
4176 SET_FLAG(c);
4177 break;
4178 case 'K':
4179 SET_FLAG(K);
4180 tcov_file_name = optarg;
4181 break;
4182 #ifdef COVERAGE_BUILD
4183 case 'C':
4184 SET_FLAG(C);
4185 break;
4186 #endif
4187 case 'd':
4188 SET_FLAG(d);
4189 break;
4190 case 'D':
4191 SET_FLAG(D);
4192 break;
4193 case 'e':
4194 SET_FLAG(e);
4195 ets_name = optarg;
4196 break;
4197 case 'E':
4198 SET_FLAG(E);
4199 break;
4200 case 'f':
4201 SET_FLAG(f);
4202 break;
4203 case 'F':
4204 SET_FLAG(F);
4205 break;
4206 case 'g':
4207 SET_FLAG(g);
4208 break;
4209 case 'H':
4210 SET_FLAG(H);
4211 break;
4212 case 'o':
4213 SET_FLAG(o);
4214 output_file = optarg;
4215 break;
4216 case 'l':
4217 SET_FLAG(l);
4218 break;
4219 case 'L':
4220 SET_FLAG(L);
4221 break;
4222 case 'm':
4223 SET_FLAG(m);
4224 break;
4225 case 'M':
4226 SET_FLAG(M);
4227 break;
4228 case 'p':
4229 SET_FLAG(p);
4230 break;
4231 case 'P':
4232 SET_FLAG(P);
4233 /* Optional arguments with `::' are GNU specific... */
4234 if (get_path_status(optarg) == PS_DIRECTORY) {
4235 file_list_path = optarg;
4236 } else {
4237 ERROR("The -P flag requires a valid directory as its argument "
4238 "instead of `%s'", optarg);
4239 error_flag = TRUE;
4240 }
4241 break;
4242 case 'r':
4243 SET_FLAG(r);
4244 break;
4245 case 'R':
4246 SET_FLAG(R);
4247 break;
4248 case 's':
4249 SET_FLAG(s);
4250 break;
4251 case 't':
4252 SET_FLAG(t);
4253 tpd_file_name = optarg;
4254 break;
4255 case 'T':
4256 SET_FLAG(T);
4257 break;
4258 case 'Y':
4259 SET_FLAG(Y);
4260 break;
4261 case 'U':
4262 SET_FLAG(U);
4263 code_splitting_mode = optarg;
4264 if (strcmp(optarg, "none") != 0 &&
4265 strcmp(optarg, "type") != 0)
4266 ERROR("Unrecognizable argument: '%s'. Valid options for -U switch are: "
4267 "'none', 'type'", optarg);
4268 break;
4269 case 'v':
4270 SET_FLAG(v);
4271 break;
4272 case 'V':
4273 SET_FLAG(V);
4274 break;
4275 case 'w':
4276 SET_FLAG(w);
4277 suppress_warnings = TRUE;
4278 break;
4279 case 'W':
4280 SET_FLAG(W);
4281 break;
4282 case 'X':
4283 SET_FLAG(X);
4284 break;
4285 case 'z':
4286 SET_FLAG(z);
4287 profiled_file_list_zflag = optarg;
4288 break;
4289 case 'Z':
4290 SET_FLAG(Z);
4291 break;
4292 default:
4293 error_flag = TRUE;
4294 break;
4295 }
4296 }
4297
4298 /* Checking incompatible options */
4299 if (vflag) {
4300 /* -v prints the version and exits, it's pointless to specify other flags */
4301 if ( aflag || bflag || cflag || Cflag || dflag || eflag || fflag || Fflag || gflag
4302 || mflag || oflag || lflag || pflag || Pflag || rflag || Rflag || sflag
4303 || tflag || Tflag || Vflag || wflag || Xflag || Kflag || Dflag || Wflag || Yflag
4304 || Zflag || Hflag || Mflag || zflag || Eflag || n_other_files > 0 || n_search_paths > 0)
4305 error_flag = TRUE;
4306 }
4307
4308 if (Zflag) {
4309 if (!gflag) gflag = TRUE; // GNU make
4310 if (!cflag) cflag = TRUE; // central sorage
4311 }
4312
4313 if ((bflag || Dflag || Pflag || Vflag || rflag || Wflag || Zflag) && !tflag) {
4314 ERROR("Using the '-b', '-D', '-P', '-V', '-r' 'Z' or '-W' option requires the use of the -t' option.");
4315 error_flag = TRUE;
4316 }
4317
4318 if (rflag && !cflag) {
4319 ERROR("Using the '-r' option requires use of the '-c' option. Recursive makefile hierarchy uses the central directory feature.");
4320 error_flag = TRUE;
4321 }
4322
4323 if (Fflag && !rflag) {
4324 ERROR("Using the '-F' option requires use of the '-r' option.");
4325 error_flag = TRUE;
4326 }
4327
4328 if (Xflag && !rflag) {
4329 ERROR("Using the '-X' option requires use of the '-r' option.");
4330 error_flag = TRUE;
4331 }
4332
4333 if (Tflag && !rflag) {
4334 ERROR("Using the '-T' option requires use of the '-r' option.");
4335 error_flag = TRUE;
4336 }
4337
4338 if (!Zflag && Hflag) {
4339 ERROR("Using the '-H' option requires use of the '-Z' option.");
4340 error_flag = TRUE;
4341 }
4342
4343 if (Zflag && !Fflag && !fflag) {
4344 ERROR("Using the '-Z' option requires use of the '-F' option.");
4345 error_flag = TRUE;
4346 }
4347
4348 if (lflag && !strncmp(get_platform_string(), "WIN32", 5)) {
4349 ERROR("Generating Makefile with dynamic linking enabled is not supported "
4350 "on Windows platform");
4351 error_flag = TRUE;
4352 }
4353
4354 if (n_search_paths > 0 && !tflag) {
4355 ERROR("Using the '-I' option requires use of the '-t' option.");
4356 error_flag = TRUE;
4357 }
4358
4359 for (size_t i = 0; i < n_search_paths; i++) {
4360 boolean is_abs_path =
4361 #if defined WIN32 && defined MINGW
4362 /* On native Windows the absolute path name shall begin with
4363 * a drive letter, colon and backslash */
4364 (((search_paths[i][0] < 'A' || search_paths[i][0] > 'Z') &&
4365 (search_paths[i][0] < 'a' || search_paths[i][0] > 'z')) ||
4366 search_paths[i][1] != ':' || search_paths[i][2] != '\\');
4367 #else
4368 /* On UNIX-like systems the absolute path name shall begin with
4369 * a slash */
4370 search_paths[i][0] != '/';
4371 #endif
4372 if (is_abs_path) {
4373 ERROR("The path after the -I flag must be an absolute path.");
4374 error_flag = TRUE;
4375 }
4376 }
4377
4378 if (error_flag) {
4379 usage();
4380 return EXIT_FAILURE;
4381 }
4382
4383 if (vflag) {
4384 fputs("Makefile Generator for the TTCN-3 Test Executor\n"
4385 "Product number: " PRODUCT_NUMBER "\n"
4386 "Build date: " __DATE__ " " __TIME__ "\n"
4387 "Compiled with: " C_COMPILER_VERSION "\n\n"
4388 COPYRIGHT_STRING "\n\n", stderr);
4389 #ifdef LICENSE
4390 print_license_info();
4391 #endif
4392 return EXIT_SUCCESS;
4393 }
4394
4395 #ifdef LICENSE
4396 init_openssl();
4397 load_license(&lstr);
4398 valid_license = verify_license(&lstr);
4399 free_openssl();
4400 if (!valid_license) {
4401 free_license(&lstr);
4402 exit(EXIT_FAILURE);
4403 }
4404 if (!check_feature(&lstr, FEATURE_TPGEN)) {
4405 ERROR("The license key does not allow the generation of "
4406 "Makefile skeletons.");
4407 return EXIT_FAILURE;
4408 }
4409 free_license(&lstr);
4410 #endif
4411
4412 if (tflag) {
4413 char* abs_work_dir = NULL;
4414 FILE* prj_graph_fp = NULL;
4415 sub_project_dirs = (struct string_list*)Malloc(sizeof(struct string_list));
4416 sub_project_dirs->str = NULL;
4417 sub_project_dirs->next = NULL;
4418 ttcn3_prep_includes = (struct string_list*)Malloc(sizeof(struct string_list));
4419 ttcn3_prep_includes->str = NULL;
4420 ttcn3_prep_includes->next = NULL;
4421 ttcn3_prep_defines = (struct string_list*)Malloc(sizeof(struct string_list));
4422 ttcn3_prep_defines->str = NULL;
4423 ttcn3_prep_defines->next = NULL;
4424 ttcn3_prep_undefines = (struct string_list*)Malloc(sizeof(struct string_list));
4425 ttcn3_prep_undefines->str = NULL;
4426 ttcn3_prep_undefines->next = NULL;
4427 prep_includes = (struct string_list*)Malloc(sizeof(struct string_list));
4428 prep_includes->str = NULL;
4429 prep_includes->next = NULL;
4430 prep_defines = (struct string_list*)Malloc(sizeof(struct string_list));
4431 prep_defines->str = NULL;
4432 prep_defines->next = NULL;
4433 prep_undefines = (struct string_list*)Malloc(sizeof(struct string_list));
4434 prep_undefines->str = NULL;
4435 prep_undefines->next = NULL;
4436 solspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4437 solspeclibraries->str = NULL;
4438 solspeclibraries->next = NULL;
4439 sol8speclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4440 sol8speclibraries->str = NULL;
4441 sol8speclibraries->next = NULL;
4442 linuxspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4443 linuxspeclibraries->str = NULL;
4444 linuxspeclibraries->next = NULL;
4445 freebsdspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4446 freebsdspeclibraries->str = NULL;
4447 freebsdspeclibraries->next = NULL;
4448 win32speclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4449 win32speclibraries->str = NULL;
4450 win32speclibraries->next = NULL;
4451 linkerlibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4452 linkerlibraries->str = NULL;
4453 linkerlibraries->next = NULL;
4454 additionalObjects = (struct string_list*)Malloc(sizeof(struct string_list));
4455 additionalObjects->str = NULL;
4456 additionalObjects->next = NULL;
4457 linkerlibsearchpath = (struct string_list*)Malloc(sizeof(struct string_list));
4458 linkerlibsearchpath->str = NULL;
4459 linkerlibsearchpath->next = NULL;
4460
4461 if (Xflag) {
4462 const char* prj_graph_filename = "project_hierarchy_graph.xml";
4463 prj_graph_fp = fopen(prj_graph_filename, "w");
4464 if (prj_graph_fp==NULL) WARNING("Cannot open output file `%s' for writing: %s", prj_graph_filename, strerror(errno));
4465 if (prj_graph_fp) fprintf(prj_graph_fp, "<project_hierarchy_graph top_level_tpd=\"%s\">\n", tpd_file_name);
4466 }
4467 create_symlink_list = (struct string2_list*)Malloc(sizeof(struct string2_list));
4468 create_symlink_list->str1 = NULL;
4469 create_symlink_list->str2 = NULL;
4470 create_symlink_list->next = NULL;
4471 target_placement_list = (struct string2_list*)Malloc(sizeof(struct string2_list));
4472 target_placement_list->str1 = NULL;
4473 target_placement_list->str2 = NULL;
4474 target_placement_list->next = NULL;
4475 run_command_list = (struct string2_list*)Malloc(sizeof(struct string2_list));
4476 run_command_list->str1 = NULL;
4477 run_command_list->str2 = NULL;
4478 run_command_list->next = NULL;
4479 required_configs = (struct string2_list*)Malloc(sizeof(struct string2_list));
4480 required_configs->str1 = NULL;
4481 required_configs->str2 = NULL;
4482 required_configs->next = NULL;
4483
4484 tpd_processed = process_tpd(tpd_file_name, tpd_build_config, file_list_path,
4485 &argc, &argv, &optind, &ets_name, &project_name,
4486 &gflag, &sflag, &cflag, &aflag, &pflag,
4487 &Rflag, &lflag, &mflag, &Pflag, &Lflag, rflag, Fflag, Tflag, output_file, &abs_work_dir, sub_project_dirs, program_name, prj_graph_fp,
4488 create_symlink_list,ttcn3_prep_includes, ttcn3_prep_defines,ttcn3_prep_undefines, prep_includes, prep_defines, prep_undefines, &csflag,
4489 &quflag, &dsflag, &cxxcompiler, &optlevel, &optflags, &dbflag, &drflag, &dtflag, &dxflag, &djflag, &fxflag, &doflag, &gfflag, &lnflag, &isflag,
4490 &asflag, &swflag, &Yflag, &Mflag, &Eflag, &diflag, solspeclibraries, sol8speclibraries, linuxspeclibraries, freebsdspeclibraries, win32speclibraries, &ttcn3prep,
4491 linkerlibraries, additionalObjects, linkerlibsearchpath, Vflag, Dflag, &Zflag, &Hflag,
4492 &generatorCommandOutput, target_placement_list, Wflag, run_command_list, required_configs, &profiled_file_list, search_paths, n_search_paths);
4493
4494 Free(abs_work_dir);
4495 if (prj_graph_fp) {
4496 fprintf(prj_graph_fp, "</project_hierarchy_graph>\n");
4497 fclose(prj_graph_fp);
4498 }
4499 if (tpd_processed == TPD_FAILED) {
4500 ERROR("Failed to process %s", tpd_file_name);
4501 exit(EXIT_FAILURE);
4502 }
4503 if (zflag) {
4504 WARNING("Compiler option '-z' and its argument will be overwritten by "
4505 "the settings in the TPD");
4506 }
4507 }
4508 else if (zflag) {
4509 // use the argument given in the command line if there is no TPD
4510 profiled_file_list = (struct string_list*)Malloc(sizeof(struct string_list));
4511 profiled_file_list->str = mcopystr(profiled_file_list_zflag);
4512 profiled_file_list->next = NULL;
4513 }
4514
4515 if (!Pflag) {
4516 run_makefilegen_commands(run_command_list);
4517 generate_symlinks(create_symlink_list);
4518 if (Zflag) {
4519 if (Fflag)
4520 NOTIFY("Makefile generation from top-level TPD: %s", tpd_file_name);
4521 if (!Fflag && fflag)
4522 NOTIFY("Makefile generation from lower level TPD: %s", tpd_file_name);
4523 }
4524 generate_makefile(argc - optind, argv + optind, n_other_files, other_files,
4525 output_file, ets_name, project_name, gflag, sflag, cflag, aflag, pflag, dflag, fflag||Fflag,
4526 Rflag, lflag, mflag, Cflag, code_splitting_mode, tcov_file_name, profiled_file_list,
4527 Lflag, Zflag, Hflag, rflag ? sub_project_dirs : NULL, ttcn3_prep_includes,
4528 ttcn3_prep_defines, ttcn3_prep_undefines, prep_includes, prep_defines, prep_undefines, csflag, quflag, dsflag, cxxcompiler, optlevel, optflags, dbflag,
4529 drflag, dtflag, dxflag, djflag, fxflag, doflag, gfflag, lnflag, isflag, asflag, swflag, Yflag, Mflag, Eflag, diflag, solspeclibraries,
4530 sol8speclibraries, linuxspeclibraries, freebsdspeclibraries, win32speclibraries, ttcn3prep, linkerlibraries, additionalObjects,
4531 linkerlibsearchpath, generatorCommandOutput, target_placement_list);
4532 }
4533
4534 free_string_list(sub_project_dirs);
4535 free_string_list(ttcn3_prep_includes);
4536 free_string_list(ttcn3_prep_defines);
4537 free_string_list(ttcn3_prep_undefines);
4538 free_string_list(prep_includes);
4539 free_string_list(prep_defines);
4540 free_string_list(prep_undefines);
4541 free_string_list(solspeclibraries);
4542 free_string_list(sol8speclibraries);
4543 free_string_list(linuxspeclibraries);
4544 free_string_list(freebsdspeclibraries);
4545 free_string_list(win32speclibraries);
4546 free_string_list(linkerlibraries);
4547 free_string_list(additionalObjects);
4548 free_string_list(linkerlibsearchpath);
4549 free_string_list(profiled_file_list);
4550
4551 Free(search_paths);
4552
4553 Free(generatorCommandOutput);
4554 free_string2_list(target_placement_list);
4555 free_string2_list(required_configs);
4556
4557 Free(other_files);
4558 if (tpd_processed == TPD_SUCCESS) {
4559 int E;
4560 if (!(eflag && ets_name))
4561 Free(ets_name);
4562 if (cxxcompiler)
4563 Free(cxxcompiler);
4564 if (optlevel)
4565 Free(optlevel);
4566 if (optflags)
4567 Free(optflags);
4568 if (ttcn3prep)
4569 Free(ttcn3prep);
4570 /* Free(output_file); */
4571 for (E = 0; E < argc; ++E) Free(argv[E]);
4572 Free(argv);
4573 }
4574 /* check_mem_leak(program_name); not needed when linked to new.cc */
4575 return error_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
4576 }
4577
This page took 0.314365 seconds and 6 git commands to generate.