-
Botond Baranyi authored
Signed-off-by:
Botond Baranyi <botond.baranyi@ericsson.com>
Botond Baranyi authoredSigned-off-by:
Botond Baranyi <botond.baranyi@ericsson.com>
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
makefile.c 176.98 KiB
/******************************************************************************
* Copyright (c) 2000-2016 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*
* >
* Baji, Laszlo
* Balasko, Jeno
* Baranyi, Botond
* Beres, Szabolcs
* Delic, Adam
* Forstner, Matyas
* Koppany, Csaba
* Kovacs, Ferenc
* Kremer, Peter
* Lovassy, Arpad
* Pandi, Krisztian
* Raduly, Csaba
* Szabados, Kristof
* Szabo, Bence Janos
* Szabo, Janos Zoltan – initial implementation
* Szalay, Akos
* Zalanyi, Balazs Andor
* Pandi, Krisztian
*
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#if defined SOLARIS || defined SOLARIS8
#include <sys/utsname.h>
#endif
#include "../common/memory.h"
#include "../common/path.h"
#include "../common/version_internal.h"
#include "../common/userinfo.h"
#include "ttcn3/ttcn3_preparser.h"
#include "asn1/asn1_preparser.h"
#ifdef LICENSE
#include "../common/license.h"
#endif
#include "xpather.h"
static const char *program_name = NULL;
static unsigned int error_count = 0;
static boolean suppress_warnings = FALSE;
void free_string2_list(struct string2_list* act_elem);
void free_string_list(struct string_list* act_elem);
void ERROR(const char *fmt, ...)
{
va_list parameters;
fprintf(stderr, "%s: error: ", program_name);
va_start(parameters, fmt);
vfprintf(stderr, fmt, parameters);
va_end(parameters);
fprintf(stderr, "\n");
fflush(stderr);
error_count++;
}
void WARNING(const char *fmt, ...)
{
va_list parameters;
if (suppress_warnings) return;
fprintf(stderr, "%s: warning: ", program_name);
va_start(parameters, fmt);
vfprintf(stderr, fmt, parameters);
va_end(parameters);
putc('\n', stderr);
fflush(stderr);
}
void NOTIFY(const char *fmt, ...)
{
va_list parameters;
va_start(parameters, fmt);
vfprintf(stderr, fmt, parameters);
va_end(parameters);
putc('\n', stderr);
fflush(stderr);
}
void DEBUG(unsigned level, const char *fmt, ...)
{
va_list parameters;
fprintf(stderr, "%*s", 2 * level, "");
va_start(parameters, fmt);
vfprintf(stderr, fmt, parameters);
va_end(parameters);
putc('\n', stderr);
fflush(stderr);
}
void path_error(const char *fmt, ...)
{
va_list ap;
char *err_msg;
va_start(ap, fmt);
err_msg = mprintf_va_list(fmt, ap);
va_end(ap);
ERROR("%s", err_msg);
Free(err_msg);
}
#if defined SOLARIS || defined SOLARIS8
/** Automatic detection of Solaris version based on uname() system call.
* Distinguishing is needed because some socket functions use socklen_t
* (which is an alias for unsigned int) as length arguments on Solaris 8.
* On Solaris 2.6 the argument type is simply int and no socklen_t or other
* alias exists.
* Note: It was discovered later that Solaris 7 (which is used rarely within
* Ericsson) already uses socklen_t thus the SOLARIS8 platform identifier is a
* bit misleading. */
static const char *get_platform_string(void)
{
struct utsname name;
int major, minor;
if (uname(&name) < 0) {
WARNING("System call uname() failed: %s", strerror(errno));
errno = 0;
return "SOLARIS";
}
if (sscanf(name.release, "%d.%d", &major, &minor) == 2 && major == 5) {
if (minor <= 6) return "SOLARIS";
else return "SOLARIS8";
} else {
ERROR("Invalid OS release: %s", name.release);
return "SOLARIS";
}
}
#elif defined LINUX
#define get_platform_string() "LINUX"
#elif defined FREEBSD
#define get_platform_string() "FREEBSD"
#elif defined WIN32
#define get_platform_string() "WIN32"
#elif defined INTERIX
#define get_platform_string() "INTERIX"
#else
#error Platform was not set.
#endif
/** structure for describing TTCN-3 and ASN.1 modules */
struct module_struct {
char *dir_name; /* directory of the TTCN-3 or ASN.1 file, it is NULL if the
file is in the current working directory */
char *file_name; /* name of the TTCN-3 or ASN.1 file */
char *module_name; /* name of the TTCN-3 or ASN.1 module */
boolean is_regular; /* indicates whether the name of the source file follows
the default naming convention */
};
/** structure for describing test ports and other C/C++ modules */
struct user_struct {
char *dir_name; /* directory of the C/C++ source files, it is NULL if the
files are in the current working directory */
char *file_prefix; /* the common prefix of the header and source file */
char *header_name; /* name of the C/C++ header file, which has .hh or .h or .hpp
suffix, it is NULL if there is no header file */
char *source_name; /* name of the C/C++ source file, which has .cc or .c or .cpp
suffix, it is NULL if there is no source file */
boolean has_hh_suffix; /* indicates whether the header file is present and
has .hh or .hpp suffix */
boolean has_cc_suffix; /* indicates whether the source file is present and
has .cc or .cpp suffix */
};
/** structure for directories that pre-compiled files are taken from */
struct base_dir_struct {
const char *dir_name; /* name of the directory */
boolean has_modules; /* indicates whether there are TTCN-3/ASN.1 modules in
the directory (it is set to FALSE if dir_name
contains user C/C++ files only */
};
/** data structure that describes the information needed for the Makefile */
struct makefile_struct {
char *project_name;
size_t nTTCN3Modules;
struct module_struct *TTCN3Modules;
boolean preprocess;
size_t nTTCN3PPModules;
struct module_struct *TTCN3PPModules;
boolean TTCN3ModulesRegular;
boolean BaseTTCN3ModulesRegular;
size_t nTTCN3IncludeFiles;
char **TTCN3IncludeFiles;
size_t nASN1Modules;
struct module_struct *ASN1Modules;
boolean ASN1ModulesRegular;
boolean BaseASN1ModulesRegular;
size_t nUserFiles;
struct user_struct *UserFiles;
boolean UserHeadersRegular;
boolean UserSourcesRegular;
boolean BaseUserHeadersRegular;
boolean BaseUserSourcesRegular;
size_t nOtherFiles;
char **OtherFiles;
boolean central_storage;
size_t nBaseDirs;
struct base_dir_struct *BaseDirs;
char *working_dir;
boolean gnu_make;
boolean single_mode;
char *output_file;
char *ets_name;
boolean force_overwrite;
boolean use_runtime_2;
boolean dynamic;
boolean gcc_dep;
char *code_splitting_mode;
boolean coverage;
char *tcov_file_name;
struct string_list* profiled_file_list; /* not owned */
boolean library;
boolean linkingStrategy;
boolean hierarchical;
struct string_list* sub_project_dirs; /* not owned */
struct string_list* ttcn3_prep_includes; /* not owned */
struct string_list* ttcn3_prep_defines; /* not owned */
struct string_list* ttcn3_prep_undefines; /* not owned */
struct string_list* prep_includes; /* not owned */
struct string_list* prep_defines; /* not owned */
struct string_list* prep_undefines; /* not owned */
boolean codesplittpd;
boolean quietly;
boolean disablesubtypecheck;
const char *cxxcompiler;
const char *optlevel;
const char *optflags;
boolean disableber;
boolean disableraw;
boolean disabletext;
boolean disablexer;
boolean disablejson;
boolean forcexerinasn;
boolean defaultasomit;
boolean gccmsgformat;
boolean linenumbersonlymsg;
boolean includesourceinfo;
boolean addsourcelineinfo;
boolean suppresswarnings;
boolean outparamboundness;
boolean omit_in_value_list;
boolean warnings_for_bad_variants;
boolean activate_debugger;
boolean disable_predef_ext_folder;
struct string_list* solspeclibraries; /* not owned */
struct string_list* sol8speclibraries; /* not owned */
struct string_list* linuxspeclibraries; /* not owned */
struct string_list* freebsdspeclibraries; /* not owned */
struct string_list* win32speclibraries; /* not owned */
const char *ttcn3preprocessor;
struct string_list* linkerlibraries; /* not owned */
struct string_list* additionalObjects; /* not owned */
struct string_list* linkerlibsearchpath; /* not owned */
char* generatorCommandOutput; /* not owned */
struct string2_list* target_placement_list; /* not owned */
};
/** Initializes structure \a makefile with empty lists and default settings. */
static void init_makefile_struct(struct makefile_struct *makefile)
{
makefile->project_name = NULL;
makefile->nTTCN3Modules = 0;
makefile->TTCN3Modules = NULL;
makefile->preprocess = FALSE;
makefile->nTTCN3PPModules = 0;
makefile->TTCN3PPModules = NULL;
makefile->TTCN3ModulesRegular = TRUE;
makefile->BaseTTCN3ModulesRegular = TRUE;
makefile->nTTCN3IncludeFiles = 0;
makefile->TTCN3IncludeFiles = NULL;
makefile->nASN1Modules = 0;
makefile->ASN1Modules = NULL;
makefile->ASN1ModulesRegular = TRUE;
makefile->BaseASN1ModulesRegular = TRUE;
makefile->nUserFiles = 0;
makefile->UserFiles = NULL;
makefile->UserHeadersRegular = TRUE;
makefile->UserSourcesRegular = TRUE;
makefile->BaseUserHeadersRegular = TRUE;
makefile->BaseUserSourcesRegular = TRUE;
makefile->nOtherFiles = 0;
makefile->OtherFiles = NULL;
makefile->central_storage = FALSE;
makefile->nBaseDirs = 0;
makefile->BaseDirs = NULL;
makefile->working_dir = get_working_dir();
makefile->gnu_make = FALSE;
makefile->single_mode = FALSE;
makefile->ets_name = NULL;
makefile->output_file = NULL;
makefile->force_overwrite = FALSE;
makefile->use_runtime_2 = FALSE;
makefile->dynamic = FALSE;
makefile->gcc_dep = FALSE;
makefile->code_splitting_mode = NULL;
makefile->coverage = FALSE;
makefile->tcov_file_name = NULL;
makefile->profiled_file_list = NULL;
makefile->library = FALSE;
makefile->linkingStrategy = FALSE;
makefile->hierarchical = FALSE;
makefile->sub_project_dirs = NULL;
makefile->ttcn3_prep_includes = NULL;
makefile->prep_includes = NULL;
makefile->prep_defines = NULL;
makefile->outparamboundness = FALSE;
makefile->omit_in_value_list = FALSE;
makefile->warnings_for_bad_variants = FALSE;
makefile->activate_debugger = FALSE;
makefile->solspeclibraries = NULL;
makefile->sol8speclibraries = NULL;
makefile->linuxspeclibraries = NULL;
makefile->freebsdspeclibraries = NULL;
makefile->win32speclibraries = NULL;
makefile->linkerlibraries = NULL;
makefile->additionalObjects = NULL;
makefile->linkerlibsearchpath = NULL;
makefile->generatorCommandOutput = NULL;
makefile->target_placement_list = NULL;
}
/** Deallocates all memory associated with structure \a makefile. */
static void free_makefile_struct(const struct makefile_struct *makefile)
{
Free(makefile->project_name);
size_t i;
for (i = 0; i < makefile->nTTCN3Modules; i++) {
Free(makefile->TTCN3Modules[i].dir_name);
Free(makefile->TTCN3Modules[i].file_name);
Free(makefile->TTCN3Modules[i].module_name);
}
Free(makefile->TTCN3Modules);
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
Free(makefile->TTCN3PPModules[i].dir_name);
Free(makefile->TTCN3PPModules[i].file_name);
Free(makefile->TTCN3PPModules[i].module_name);
}
Free(makefile->TTCN3PPModules);
for (i = 0; i < makefile->nTTCN3IncludeFiles; i++)
Free(makefile->TTCN3IncludeFiles[i]);
Free(makefile->TTCN3IncludeFiles);
for (i = 0; i < makefile->nASN1Modules; i++) {
Free(makefile->ASN1Modules[i].dir_name);
Free(makefile->ASN1Modules[i].file_name);
Free(makefile->ASN1Modules[i].module_name);
}
Free(makefile->ASN1Modules);
for (i = 0; i < makefile->nUserFiles; i++) {
Free(makefile->UserFiles[i].dir_name);
Free(makefile->UserFiles[i].file_prefix);
Free(makefile->UserFiles[i].header_name);
Free(makefile->UserFiles[i].source_name);
}
Free(makefile->UserFiles);
for (i = 0; i < makefile->nOtherFiles; i++) Free(makefile->OtherFiles[i]);
Free(makefile->OtherFiles);
Free(makefile->BaseDirs);
Free(makefile->working_dir);
Free(makefile->ets_name);
Free(makefile->output_file);
Free(makefile->code_splitting_mode);
Free(makefile->tcov_file_name);
}
/** Displays the contents of structure \a makefile as debug messages. */
static void dump_makefile_struct(const struct makefile_struct *makefile,
unsigned level)
{
size_t i;
DEBUG(level, "Data used for Makefile generation:");
DEBUG(level + 1, "TTCN-3 project name: %s", makefile->project_name);
DEBUG(level + 1, "TTCN-3 modules: (%u pcs.)", makefile->nTTCN3Modules);
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
DEBUG(level + 2, "Module name: %s", module->module_name);
if (module->dir_name != NULL)
DEBUG(level + 3, "Directory: %s", module->dir_name);
DEBUG(level + 3, "File name: %s", module->file_name);
DEBUG(level + 3, "Follows the naming convention: %s",
module->is_regular ? "yes" : "no");
}
DEBUG(level + 1, "TTCN-3 preprocessing: %s",
makefile->preprocess ? "yes" : "no");
if (makefile->preprocess) {
DEBUG(level + 1, "TTCN-3 modules to be preprocessed: (%u pcs.)",
makefile->nTTCN3PPModules);
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
DEBUG(level + 2, "Module name: %s", module->module_name);
if (module->dir_name != NULL)
DEBUG(level + 3, "Directory: %s", module->dir_name);
DEBUG(level + 3, "File name: %s", module->file_name);
DEBUG(level + 3, "Follows the naming convention: %s",
module->is_regular ? "yes" : "no");
}
DEBUG(level + 1, "TTCN-3 include files: (%u pcs.)",
makefile->nTTCN3IncludeFiles);
for (i = 0; i < makefile->nTTCN3IncludeFiles; i++)
DEBUG(level + 2, "File name: %s", makefile->TTCN3IncludeFiles[i]);
}
DEBUG(level + 1, "All local TTCN-3 modules follow the naming convention: %s",
makefile->TTCN3ModulesRegular ? "yes" : "no");
if (makefile->central_storage) DEBUG(level + 1, "All TTCN-3 modules from other "
"directories follow the naming convention: %s",
makefile->BaseTTCN3ModulesRegular ? "yes" : "no");
DEBUG(level + 1, "ASN.1 modules: (%u pcs.)", makefile->nASN1Modules);
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
DEBUG(level + 2, "Module name: %s", module->module_name);
if (module->dir_name != NULL)
DEBUG(level + 3, "Directory: %s", module->dir_name);
DEBUG(level + 3, "File name: %s", module->file_name);
DEBUG(level + 3, "Follows the naming convention: %s",
module->is_regular ? "yes" : "no");
}
DEBUG(level + 1, "All local ASN.1 modules follow the naming convention: %s",
makefile->ASN1ModulesRegular ? "yes" : "no");
if (makefile->central_storage) DEBUG(level + 1, "All ASN.1 modules from other "
"directories follow the naming convention: %s",
makefile->BaseASN1ModulesRegular ? "yes" : "no");
DEBUG(level + 1, "User C/C++ modules: (%u pcs.)", makefile->nUserFiles);
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
DEBUG(level + 2, "File prefix: %s", user->file_prefix);
if (user->dir_name != NULL)
DEBUG(level + 3, "Directory: %s", user->dir_name);
if (user->header_name != NULL) {
DEBUG(level + 3, "Header file: %s", user->header_name);
DEBUG(level + 3, "Header file has .hh or .hpp suffix: %s",
user->has_hh_suffix ? "yes" : "no");
}
if (user->source_name != NULL) {
DEBUG(level + 3, "Source file: %s", user->source_name);
DEBUG(level + 3, "Source file has .cc or .cpp suffix: %s",
user->has_cc_suffix ? "yes" : "no");
DEBUG(level + 3, "Object file: %s.o", user->file_prefix);
}
}
DEBUG(level + 1, "All local C/C++ header files follow the naming "
"convention: %s", makefile->UserHeadersRegular ? "yes" : "no");
DEBUG(level + 1, "All local C/C++ source files follow the naming "
"convention: %s", makefile->UserSourcesRegular ? "yes" : "no");
if (makefile->central_storage) {
DEBUG(level + 1, "All C/C++ header files from other directories follow the "
"naming convention: %s", makefile->BaseUserHeadersRegular ? "yes" : "no");
DEBUG(level + 1, "All C/C++ source files from other directories follow the "
"naming convention: %s", makefile->BaseUserSourcesRegular ? "yes" : "no");
}
DEBUG(level + 1, "Other files: (%u pcs.)", makefile->nOtherFiles);
for (i = 0; i < makefile->nOtherFiles; i++)
DEBUG(level + 2, "File name: %s", makefile->OtherFiles[i]);
DEBUG(level + 1, "Use pre-compiled files from central storage: %s",
makefile->central_storage ? "yes" : "no");
if (makefile->central_storage) {
DEBUG(level + 1, "Directories of pre-compiled files: (%u pcs.)",
makefile->nBaseDirs);
for (i = 0; i < makefile->nBaseDirs; i++) {
const struct base_dir_struct *base_dir = makefile->BaseDirs + i;
DEBUG(level + 2, "Directory: %s", base_dir->dir_name);
DEBUG(level + 3, "Has TTCN-3/ASN.1 modules: %s",
base_dir->has_modules ? "yes" : "no");
}
}
DEBUG(level + 1, "Working directory: %s",
makefile->working_dir != NULL ? makefile->working_dir : "<unknown>");
DEBUG(level + 1, "GNU make: %s", makefile->gnu_make ? "yes" : "no");
DEBUG(level + 1, "Execution mode: %s",
makefile->single_mode ? "single" : "parallel");
DEBUG(level + 1, "Name of executable: %s",
makefile->ets_name != NULL ? makefile->ets_name : "<unknown>");
DEBUG(level + 1, "Output file: %s",
makefile->output_file != NULL ? makefile->output_file : "<unknown>");
DEBUG(level + 1, "Force overwrite: %s",
makefile->force_overwrite ? "yes" : "no");
DEBUG(level + 1, "Use function test runtime: %s",
makefile->use_runtime_2 ? "yes" : "no");
DEBUG(level + 1, "Use dynamic linking: %s",
makefile->dynamic ? "yes" : "no");
DEBUG(level + 1, "Code splitting mode: %s",
makefile->code_splitting_mode != NULL ?
makefile->code_splitting_mode : "<unknown>");
DEBUG(level + 1, "Code coverage file: %s",
makefile->tcov_file_name != NULL ?
makefile->tcov_file_name : "<unknown>");
if (makefile->profiled_file_list) {
char* lists = mcopystr(makefile->profiled_file_list->str);
struct string_list* iter = makefile->profiled_file_list->next;
while(iter != NULL) {
lists = mputprintf(lists, " %s", iter->str);
iter = iter->next;
}
DEBUG(level + 1, "Profiled file list(s): %s", lists);
Free(lists);
}
#ifdef COVERAGE_BUILD
DEBUG(level + 1, "Enable coverage: %s", makefile->coverage ? "yes" : "no");
#endif
}
/** Returns the name of an existing file that is related to command line
* argument \a argument. Tries the given list of suffixes. NULL pointer is
* returned if no file was found. The returned string shall be deallocated
* by the caller. */
static char *get_file_name_for_argument(const char *argument)
{
static const char * const suffix_list[] = {
"", ".ttcnpp", ".ttcnin", ".ttcn", ".ttcn3", ".3mp", ".asn", ".asn1",
".cc", ".c", ".cpp", ".hh", ".h",".hpp", ".cfg", ".prj", NULL
};
const char * const *suffix_ptr;
for (suffix_ptr = suffix_list; *suffix_ptr != NULL; suffix_ptr++) {
char *file_name = mputstr(mcopystr(argument), *suffix_ptr);
if (get_path_status(file_name) == PS_FILE) return file_name;
Free(file_name);
}
return NULL;
}
/** Converts \a path_name to an absolute directory using \a working_dir.
* NULL pointer is returned if \a path_name does not contain a directory or
* the resulting absolute directory is identical to \a working_dir.
* The returned string shall be deallocated by the caller. */
static char *get_dir_name(const char *path_name, const char *working_dir)
{
char *dir_name = get_dir_from_path(path_name);
if (dir_name != NULL) {
char *absolute_dir = get_absolute_dir(dir_name, working_dir, TRUE);
Free(dir_name);
if (absolute_dir == NULL || working_dir == NULL) {
/* an error occurred */
return NULL;
} else if (!strcmp(absolute_dir, working_dir)) {
/* the directory is identical to the working dir */
Free(absolute_dir);
return NULL;
} else return absolute_dir;
} else return NULL;
}
/** Returns whether \a dirname1 and \a dirname2 contain the same (canonized
* absolute) directories. NULL pointer is handled in a special way: it is
* identical only to itself. */
static boolean is_same_directory(const char *dirname1, const char *dirname2)
{
if (dirname1 == NULL) {
if (dirname2 == NULL) return TRUE;
else return FALSE;
} else {
if (dirname2 == NULL) return FALSE;
else if (strcmp(dirname1, dirname2)) return FALSE;
else return TRUE;
}
}
/** Returns whether the file \a filename1 in directory \a dirname1 is identical
* to file \a filename2 in directory \a dirname2. Only the directory names can
* be NULL. */
static boolean is_same_file(const char *dirname1, const char *filename1,
const char *dirname2, const char *filename2)
{
/* first examine the file names for efficiency reasons */
if (strcmp(filename1, filename2)) return FALSE;
else return is_same_directory(dirname1, dirname2);
}
/** Determines whether the TTCN-3 or ASN.1 module identifiers \a module1 and
* \a module2 are the same. Characters '-' and '_' in module names are not
* distinguished. */
static boolean is_same_module(const char *module1, const char *module2)
{
size_t i;
for (i = 0; ; i++) {
switch (module1[i]) {
case '\0':
if (module2[i] == '\0') return TRUE;
else return FALSE;
case '-':
case '_':
if (module2[i] != '-' && module2[i] != '_') return FALSE;
break;
default:
if (module1[i] != module2[i]) return FALSE;
break;
}
}
return FALSE; /* to avoid warnings */
}
/** Determines the suffix (i.e. the character sequence following the last dot)
* of file or path name \a file_name. NULL pointer is returned if \a file_name
* does not contain any dot character or the last character of it is a dot.
* The suffix is not copied, the returned pointer points to the tail of
* \a file_name. */
static const char *get_suffix(const char *file_name)
{
size_t last_dot = (size_t)-1;
size_t i;
for (i = 0; file_name[i] != '\0'; i++)
if (file_name[i] == '.') last_dot = i;
if (last_dot == (size_t)-1 || file_name[last_dot + 1] == '\0') return NULL;
else return file_name + last_dot + 1;
}
/** Truncates the suffix (i.e. the last dot and the characters following it)
* from \a file_name and returns a copy of the prefix of \a file_name.
* If \a file_name does not have a suffix an exact copy of it is returned.
* The returned string shall be deallocated by the caller. */
static char *cut_suffix(const char *file_name)
{
char *ret_val;
size_t last_dot = (size_t)-1;
size_t i;
for (i = 0; file_name[i] != '\0'; i++)
if (file_name[i] == '.') last_dot = i;
ret_val = mcopystr(file_name);
if (last_dot != (size_t)-1) ret_val = mtruncstr(ret_val, last_dot);
return ret_val;
}
/** Determines the name of the preprocessed file from \a file_name.
* It is assumed that \a file_name has ttcnpp suffix.
* The returned string shall be deallocated by the caller. */
static char *get_preprocessed_file_name(const char *file_name)
{
char *ret_val = cut_suffix(file_name);
ret_val = mputstr(ret_val, ".ttcn");
return ret_val;
}
/** Check if any of the preprocessed ttcn file names with the preprocessed
* (TTCN-3) suffix is equal to any other file given in the \a makefile */
static void check_preprocessed_filename_collision(
struct makefile_struct *makefile)
{
size_t i;
if (makefile->nTTCN3PPModules == 0) {
WARNING("TTCN-3 preprocessing (option `-p') is enabled, but no TTCN-3 "
"files to be preprocessed were given for the Makefile.");
}
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *pp_module = makefile->TTCN3PPModules + i;
/* name of the intermediate preprocessed file */
char *preprocessed_name = get_preprocessed_file_name(pp_module->file_name);
size_t j;
for (j = 0; j < makefile->nTTCN3Modules; j++) {
struct module_struct *module = makefile->TTCN3Modules + j;
if (is_same_file(pp_module->dir_name, preprocessed_name,
module->dir_name, module->file_name)) {
if (is_same_module(pp_module->module_name, module->module_name)) {
/* same file with the same module */
char *pp_pathname = compose_path_name(pp_module->dir_name,
pp_module->file_name);
char *m_pathname = compose_path_name(module->dir_name,
module->file_name);
WARNING("File `%s' containing TTCN-3 module `%s' is generated by "
"the preprocessor from `%s'. Removing the file from the list of "
"normal TTCN-3 modules.", m_pathname, module->module_name,
pp_pathname);
Free(pp_pathname);
Free(m_pathname);
Free(module->dir_name);
Free(module->file_name);
Free(module->module_name);
makefile->nTTCN3Modules--;
memmove(module, module + 1, (makefile->nTTCN3Modules - j) *
sizeof(*makefile->TTCN3Modules));
makefile->TTCN3Modules =
(struct module_struct*)Realloc(makefile->TTCN3Modules,
makefile->nTTCN3Modules * sizeof(*makefile->TTCN3Modules));
} else {
/* same file with different module */
char *pp_pathname = compose_path_name(pp_module->dir_name,
pp_module->file_name);
char *m_pathname = compose_path_name(module->dir_name,
module->file_name);
ERROR("Preprocessed intermediate file of `%s' (module `%s') clashes "
"with file `%s' containing TTCN-3 module `%s'.", pp_pathname,
pp_module->module_name, m_pathname, module->module_name);
Free(pp_pathname);
Free(m_pathname);
}
} else if (is_same_module(pp_module->module_name, module->module_name)) {
/* different file with the same module */
char *pp_pathname = compose_path_name(pp_module->dir_name,
pp_module->file_name);
char *m_pathname = compose_path_name(module->dir_name,
module->file_name);
ERROR("Both files `%s' and `%s' contain TTCN-3 module `%s'.",
pp_pathname, m_pathname, pp_module->module_name);
Free(pp_pathname);
Free(m_pathname);
}
}
for (j = 0; j < makefile->nASN1Modules; j++) {
struct module_struct *module = makefile->ASN1Modules + j;
if (is_same_file(pp_module->dir_name, preprocessed_name,
module->dir_name, module->file_name)) {
char *pp_pathname = compose_path_name(pp_module->dir_name,
pp_module->file_name);
char *m_pathname = compose_path_name(module->dir_name,
module->file_name);
ERROR("Preprocessed intermediate file of `%s' (module `%s') clashes "
"with file `%s' containing ASN.1 module `%s'.", pp_pathname,
pp_module->module_name, m_pathname, module->module_name);
Free(pp_pathname);
Free(m_pathname);
}
}
for (j = 0; j < makefile->nOtherFiles; j++) {
char *dir_name = get_dir_name(makefile->OtherFiles[j],
makefile->working_dir);
char *file_name = get_file_from_path(makefile->OtherFiles[j]);
if (is_same_file(pp_module->dir_name, preprocessed_name, dir_name,
file_name)) {
char *pp_pathname = compose_path_name(pp_module->dir_name,
pp_module->file_name);
ERROR("Preprocessed intermediate file of `%s' (module `%s') clashes "
"with other file `%s'.", pp_pathname, pp_module->module_name,
makefile->OtherFiles[j]);
Free(pp_pathname);
}
Free(dir_name);
Free(file_name);
}
Free(preprocessed_name);
}
}
/** Checks the name clash between existing module \a module and newly added
* module with parameters \a path_name, \a dir_name, \a file_name,
* \a module_name. Both the existing and the new module shall be of the same
* kind, parameter \a kind shall contain the respective string (either "ASN.1"
* or "TTCN-3"). If a clash is found the parameters of the new module except
* \a path_name are deallocated and TRUE is returned. Otherwise FALSE is
* returned. */
static boolean check_module_clash_same(const struct module_struct *module,
const char *kind, const char *path_name, char *dir_name, char *file_name,
char *module_name)
{
if (is_same_module(module_name, module->module_name)) {
if (is_same_file(dir_name, file_name,
module->dir_name, module->file_name)) {
/* the same file was given twice: just issue a warning */
WARNING("File `%s' was given more than once for the Makefile.",
path_name);
} else {
/* two different files contain the same module: this cannot be
* resolved as the generated C++ files will clash */
char *path_name1 = compose_path_name(module->dir_name,
module->file_name);
char *path_name2 = compose_path_name(dir_name, file_name);
ERROR("Both files `%s' and `%s' contain %s module `%s'.",
path_name1, path_name2, kind, module_name);
Free(path_name1);
Free(path_name2);
}
Free(file_name);
Free(dir_name);
Free(module_name);
return TRUE;
} else return FALSE;
}
/** Checks the name clash between existing module \a module and newly added
* module with parameters \a dir_name, \a file_name, \a module_name. The two
* modules shall be of different kinds (one is ASN.1, the other is TTCN-3).
* Parameters \a kind1 and \a kind2 shall contain the respective strings. If a
* clash is found the parameters of the new module are deallocated and TRUE is
* returned. Otherwise FALSE is returned. */
static boolean check_module_clash_different(const struct module_struct *module,
const char *kind1, char *dir_name, char *file_name, char *module_name,
const char *kind2)
{
if (is_same_module(module_name, module->module_name)) {
/* two different files contain the same module: this cannot be resolved
* as the generated C++ files will clash */
char *path_name1 = compose_path_name(module->dir_name, module->file_name);
char *path_name2 = compose_path_name(dir_name, file_name);
ERROR("File `%s' containing %s module `%s' and file `%s' containing "
"%s module `%s' cannot be used together in the same Makefile.",
path_name1, kind1, module->module_name, path_name2, kind2, module_name);
Free(path_name1);
Free(path_name2);
Free(file_name);
Free(dir_name);
Free(module_name);
return TRUE;
} else return FALSE;
}
/** Adds a TTCN-3 module to Makefile descriptor structure \a makefile.
* The name of the TTCN-3 source file is \a path_name, the module identifier
* is \a module_name. It is checked whether a file or module with the same name
* already exists in \a makefile and an appropriate warning or error is
* reported. */
static void add_ttcn3_module(struct makefile_struct *makefile,
const char *path_name, char *module_name)
{
struct module_struct *module;
char *dir_name = get_dir_name(path_name, makefile->working_dir);
char *file_name = get_file_from_path(path_name);
const char *suffix = get_suffix(file_name);
size_t i;
boolean is_preprocessed = FALSE;
if (suffix != NULL) {
if (!strcmp(suffix, "ttcnpp")) {
if (makefile->preprocess) is_preprocessed = TRUE;
else WARNING("The suffix of TTCN-3 file `%s' indicates that it should be "
"preprocessed, but TTCN-3 preprocessing is not enabled. The file "
"will be added to the list of normal TTCN-3 modules in the Makefile.",
path_name);
} else if (!strcmp(suffix, "ttcnin")) {
WARNING("The suffix of file `%s' indicates that it should be a "
"preprocessor include file, but it contains a TTCN-3 module named `%s'. "
"The file will be added to the list of normal TTCN-3 modules in the "
"Makefile.", path_name, module_name);
}
}
for (i = 0; i < makefile->nASN1Modules; i++) {
if (check_module_clash_different(makefile->ASN1Modules + i, "ASN.1",
dir_name, file_name, module_name, "TTCN-3")) return;
}
/* never entered if suffix is NULL */
if (is_preprocessed) {
char *file_prefix;
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
if (check_module_clash_same(makefile->TTCN3PPModules + i, "TTCN-3",
path_name, dir_name, file_name, module_name)) return;
}
/* clashes with normal TTCN-3 modules will be checked (and maybe resolved)
* in \a check_preprocessed_filename_collision() */
/* add it to the list of TTCN-3 modules to be preprocessed */
makefile->TTCN3PPModules = (struct module_struct*)
Realloc(makefile->TTCN3PPModules,
(makefile->nTTCN3PPModules + 1) * sizeof(*makefile->TTCN3PPModules));
module = makefile->TTCN3PPModules + makefile->nTTCN3PPModules;
makefile->nTTCN3PPModules++;
module->dir_name = dir_name;
module->file_name = file_name;
module->module_name = module_name;
file_prefix = cut_suffix(file_name);
if (!strcmp(file_prefix, module_name)) module->is_regular = TRUE;
else module->is_regular = FALSE;
Free(file_prefix);
} else {
/* the file is not preprocessed */
for (i = 0; i < makefile->nTTCN3Modules; i++) {
if (check_module_clash_same(makefile->TTCN3Modules + i, "TTCN-3",
path_name, dir_name, file_name, module_name)) return;
}
/* clashes with preprocessed TTCN-3 modules will be checked (and maybe
* resolved) in \a check_preprocessed_filename_collision() */
/* add it to the list of normal TTCN-3 modules */
makefile->TTCN3Modules = (struct module_struct*)
Realloc(makefile->TTCN3Modules,
(makefile->nTTCN3Modules + 1) * sizeof(*makefile->TTCN3Modules));
module = makefile->TTCN3Modules + makefile->nTTCN3Modules;
makefile->nTTCN3Modules++;
module->dir_name = dir_name;
module->file_name = file_name;
module->module_name = module_name;
if (suffix != NULL && !strcmp(suffix, "ttcn")) {
char *file_prefix = cut_suffix(file_name);
if (!strcmp(file_prefix, module_name)) module->is_regular = TRUE;
else module->is_regular = FALSE;
Free(file_prefix);
} else {
module->is_regular = FALSE;
}
}
}
/** ASN.1 filename shall contain no hyphen */
static boolean is_valid_asn1_filename(const char* file_name)
{
if (0 == strchr(file_name, '-')) {
return TRUE;
}
return FALSE;
}
/** Adds an ASN.1 module to Makefile descriptor structure \a makefile.
* The name of the ASN.1 source file is \a path_name, the module identifier
* is \a module_name. It is checked whether a file or module with the same name
* already exists in \a makefile and an appropriate warning or error is
* reported. */
static void add_asn1_module(struct makefile_struct *makefile,
const char *path_name, char *module_name)
{
struct module_struct *module;
char *dir_name = get_dir_name(path_name, makefile->working_dir);
char *file_name = get_file_from_path(path_name);
const char *suffix = get_suffix(file_name);
size_t i;
for (i = 0; i < makefile->nASN1Modules; i++) {
if (check_module_clash_same(makefile->ASN1Modules + i, "ASN.1", path_name,
dir_name, file_name, module_name)) return;
}
for (i = 0; i < makefile->nTTCN3Modules; i++) {
if (check_module_clash_different(makefile->TTCN3Modules + i, "TTCN-3",
dir_name, file_name, module_name, "ASN.1")) return;
}
if (makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
if (check_module_clash_different(makefile->TTCN3PPModules + i, "TTCN-3",
dir_name, file_name, module_name, "ASN.1")) return;
}
}
makefile->ASN1Modules = (struct module_struct*)
Realloc(makefile->ASN1Modules,
(makefile->nASN1Modules + 1) * sizeof(*makefile->ASN1Modules));
module = makefile->ASN1Modules + makefile->nASN1Modules;
makefile->nASN1Modules++;
module->dir_name = dir_name;
module->file_name = file_name;
module->module_name = module_name;
if (suffix != NULL && !strcmp(suffix, "asn")) {
char *file_prefix = cut_suffix(file_name);
/* replace all '_' with '-' in file name prefix */
for (i = 0; file_prefix[i] != '\0'; i++)
if (file_prefix[i] == '_') file_prefix[i] = '-';
if (!strcmp(file_prefix, module_name)) module->is_regular = TRUE;
else module->is_regular = FALSE;
Free(file_prefix);
} else {
module->is_regular = FALSE;
}
}
/** Adds the file named \a path_name to the list of files pointed by \a list_ptr
* and \a list_size. The suffix or contents of \a path_name are not examined,
* only duplicate entries are checked. In case of duplicate entries warning is
* reported only if argument \a report_warning is set to TRUE. */
static void add_path_to_list(size_t *list_size, char ***list_ptr,
const char *path_name, const char *working_dir, boolean report_warning)
{
size_t i;
char *dir_name = get_dir_name(path_name, working_dir);
char *file_name = get_file_from_path(path_name);
char *canonized_path_name = compose_path_name(dir_name, file_name);
Free(dir_name);
Free(file_name);
for (i = 0; i < *list_size; i++) {
if (!strcmp(canonized_path_name, (*list_ptr)[i])) {
if (report_warning) WARNING("File `%s' was given more than once for the "
"Makefile.", path_name);
Free(canonized_path_name);
return;
}
}
*list_ptr = (char**)Realloc(*list_ptr, (*list_size + 1) * sizeof(**list_ptr));
(*list_ptr)[*list_size] = canonized_path_name;
(*list_size)++;
}
/** Adds a C/C++ header or source file or an other file named \a path_name to
* Makefile descriptor structure \a makefile. The file is classified based on
* its suffix and not by content. If the file clashes with existing files or
* modules the appropriate warning or error is generated. */
static void add_user_file(struct makefile_struct *makefile,
const char *path_name)
{
const char *suffix = get_suffix(path_name);
if (suffix != NULL) {
if (!strcmp(suffix, "ttcn") || !strcmp(suffix, "ttcn3") ||
!strcmp(suffix, "3mp") || !strcmp(suffix, "ttcnpp")) {
/* The file content was already checked. Since it doesn't look like
* a valid TTCN-3 file, these suffixes are suspect */
WARNING("File `%s' does not contain a valid TTCN-3 module. "
"It will be added to the Makefile as other file.", path_name);
}
else if (!strcmp(suffix, "ttcnin")) {
/* this is a TTCN-3 include file */
if (makefile->preprocess) {
add_path_to_list(&makefile->nTTCN3IncludeFiles,
&makefile->TTCN3IncludeFiles, path_name, makefile->working_dir, TRUE);
return;
}
else {
WARNING("The suffix of file `%s' indicates that it is a TTCN-3 "
"include file, but TTCN-3 preprocessing is not enabled. The file "
"will be added to the Makefile as other file.", path_name);
}
}
else if (!strcmp(suffix, "asn") || !strcmp(suffix, "asn1")) {
/* The file content was already checked. Since it doesn't look like
* a valid ASN.1 file, these suffixes are suspect */
WARNING("File `%s' does not contain a valid ASN.1 module. "
"It will be added to the Makefile as other file.", path_name);
}
else if (!strcmp(suffix, "cc") || !strcmp(suffix, "c") || !strcmp(suffix, "cpp")) {
/* this is a source file */
char *dir_name = get_dir_name(path_name, makefile->working_dir);
char *file_name = get_file_from_path(path_name);
char *file_prefix = cut_suffix(file_name);
struct user_struct *user;
size_t i;
for (i = 0; i < makefile->nUserFiles; i++) {
user = makefile->UserFiles + i;
if (!strcmp(file_prefix, user->file_prefix)) {
if (user->source_name != NULL) {
/* the source file is already present */
if (is_same_file(dir_name, file_name,
user->dir_name, user->source_name)) {
WARNING("File `%s' was given more than once for the Makefile.", path_name);
}
else {
char *path_name1 = compose_path_name(user->dir_name, user->source_name);
char *path_name2 = compose_path_name(dir_name, file_name);
ERROR("C/C++ source files `%s' and `%s' cannot be used together "
"in the same Makefile.", path_name1, path_name2);
Free(path_name1);
Free(path_name2);
}
}
else {
/* a header file with the same prefix is already present */
if (is_same_directory(dir_name, user->dir_name)) {
user->source_name = file_name;
file_name = NULL;
if (!strcmp(suffix, "cc") || !strcmp(suffix, "cpp"))
user->has_cc_suffix = TRUE;
}
else {
char *path_name1 = compose_path_name(dir_name, file_name);
char *path_name2 = compose_path_name(user->dir_name, user->header_name);
ERROR("C/C++ source file `%s' cannot be used together with "
"header file `%s' in the same Makefile.", path_name1,
path_name2);
Free(path_name1);
Free(path_name2);
}
}
Free(dir_name);
Free(file_name);
Free(file_prefix);
return;
}
}
makefile->UserFiles = (struct user_struct*)Realloc(makefile->UserFiles,
(makefile->nUserFiles + 1) * sizeof(*makefile->UserFiles));
user = makefile->UserFiles + makefile->nUserFiles;
makefile->nUserFiles++;
user->dir_name = dir_name;
user->file_prefix = file_prefix;
user->header_name = NULL;
user->source_name = file_name;
user->has_hh_suffix = FALSE;
if (!strcmp(suffix, "cc") || !strcmp(suffix, "cpp")) user->has_cc_suffix = TRUE;
else user->has_cc_suffix = FALSE;
return;
}
else if (!strcmp(suffix, "hh") || !strcmp(suffix, "h")) {
/* this is a header file */
char *dir_name = get_dir_name(path_name, makefile->working_dir);
char *file_name = get_file_from_path(path_name);
char *file_prefix = cut_suffix(file_name);
struct user_struct *user;
size_t i;
for (i = 0; i < makefile->nUserFiles; i++) {
user = makefile->UserFiles + i;
if (!strcmp(file_prefix, user->file_prefix)) {
if (user->header_name != NULL) {
/* the header file is already present */
if (is_same_file(dir_name, file_name, user->dir_name, user->header_name)) {
WARNING("File `%s' was given more than once for the Makefile.", path_name);
}
else {
char *path_name1 = compose_path_name(user->dir_name, user->header_name);
char *path_name2 = compose_path_name(dir_name, file_name);
ERROR("C/C++ header files `%s' and `%s' cannot be used together "
"in the same Makefile.", path_name1, path_name2);
Free(path_name1);
Free(path_name2);
}
}
else {
/* a source file with the same prefix is already present */
if (is_same_directory(dir_name, user->dir_name)) {
user->header_name = file_name;
file_name = NULL;
if (!strcmp(suffix, "hh") || !strcmp(suffix, "hpp"))
user->has_hh_suffix = TRUE;
}
else {
char *path_name1 = compose_path_name(dir_name, file_name);
char *path_name2 = compose_path_name(user->dir_name, user->source_name);
ERROR("C/C++ header file `%s' cannot be used together with "
"source file `%s' in the same Makefile.", path_name1, path_name2);
Free(path_name1);
Free(path_name2);
}
}
Free(dir_name);
Free(file_name);
Free(file_prefix);
return;
}
}
makefile->UserFiles = (struct user_struct*)Realloc(makefile->UserFiles,
(makefile->nUserFiles + 1) * sizeof(*makefile->UserFiles));
user = makefile->UserFiles + makefile->nUserFiles;
makefile->nUserFiles++;
user->dir_name = dir_name;
user->file_prefix = file_prefix;
user->header_name = file_name;
user->source_name = NULL;
if (!strcmp(suffix, "hh") || !strcmp(suffix, "hpp")) user->has_hh_suffix = TRUE;
else user->has_hh_suffix = FALSE;
user->has_cc_suffix = FALSE;
return;
}
} /* end if (suffix != NULL) */
/* treat the file as other file if it was not handled yet */
add_path_to_list(&makefile->nOtherFiles, &makefile->OtherFiles, path_name,
makefile->working_dir, TRUE);
}
/** Removes the generated C++ header and/or source files of module \a module
* from Makefile descriptor structure \a makefile. A warning is displayed if
* such file is found. */
static void drop_generated_files(struct makefile_struct *makefile,
const struct module_struct *module)
{
char *module_name = mcopystr(module->module_name);
size_t i;
/* transform all '-' characters in ASN.1 module name to '_' */
for (i = 0; module_name[i] != '\0'; i++)
if (module_name[i] == '-') module_name[i] = '_';
for (i = 0; i < makefile->nUserFiles; i++) {
struct user_struct *user = makefile->UserFiles + i;
if (!strcmp(module_name, user->file_prefix)) {
char *m_pathname = compose_path_name(module->dir_name, module->file_name);
/** Note: if central storage is used the generated C++ files are placed
* into the same directory as the TTCN-3/ASN.1 modules, otherwise the
* files are generated into the working directory. */
boolean is_same_dir = is_same_directory(user->dir_name,
makefile->central_storage ? module->dir_name : NULL);
if (user->header_name != NULL) {
char *u_pathname = compose_path_name(user->dir_name,
user->header_name);
if (is_same_dir && user->has_hh_suffix) {
WARNING("Header file `%s' is generated from module `%s' (file `%s'). "
"Removing it from the list of user files.", u_pathname,
module->module_name, m_pathname);
} else {
ERROR("Header file `%s' cannot be used together with module `%s' "
"(file `%s') in the same Makefile.", u_pathname,
module->module_name, m_pathname);
}
Free(u_pathname);
}
if (user->source_name != NULL) {
char *u_pathname = compose_path_name(user->dir_name,
user->source_name);
if (is_same_dir && user->has_cc_suffix) {
WARNING("Source file `%s' is generated from module `%s' (file "
"`%s'). Removing it from the list of user files.", u_pathname,
module->module_name, m_pathname);
} else {
ERROR("Source file `%s' cannot be used together with module "
"`%s' (file `%s') in the same Makefile.", u_pathname,
module->module_name, m_pathname);
}
Free(u_pathname);
}
Free(m_pathname);
Free(user->dir_name);
Free(user->file_prefix);
Free(user->header_name);
Free(user->source_name);
makefile->nUserFiles--;
memmove(user, user + 1, (makefile->nUserFiles - i) *
sizeof(*makefile->UserFiles));
makefile->UserFiles = (struct user_struct*)Realloc(makefile->UserFiles,
makefile->nUserFiles * sizeof(*makefile->UserFiles));
break;
}
}
Free(module_name);
}
/** Drops all C++ header and source files of the Makefile descriptor structure
* \a makefile that are generated from its TTCN-3 or ASN.1 modules. */
static void filter_out_generated_files(struct makefile_struct *makefile)
{
size_t i;
for (i = 0; i < makefile->nTTCN3Modules; i++) {
drop_generated_files(makefile, makefile->TTCN3Modules + i);
}
if (makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
drop_generated_files(makefile, makefile->TTCN3PPModules + i);
}
}
for (i = 0; i < makefile->nASN1Modules; i++) {
drop_generated_files(makefile, makefile->ASN1Modules + i);
}
}
/** Completes the list of user C/C++ header and source files in \a makefile.
* If only the source file was given the function looks for the corresponding
* header file or vice versa. */
static void complete_user_files(const struct makefile_struct *makefile)
{
size_t i;
for (i = 0; i < makefile->nUserFiles; i++) {
struct user_struct *user = makefile->UserFiles + i;
if (user->header_name == NULL) {
static const char * const suffix_list[] = { "hh", "h", "hpp", NULL };
const char * const *suffix_ptr;
for (suffix_ptr = suffix_list; *suffix_ptr != NULL; suffix_ptr++) {
char *file_name = mprintf("%s.%s", user->file_prefix, *suffix_ptr);
char *path_name = compose_path_name(user->dir_name, file_name);
if (get_path_status(path_name) == PS_FILE) {
Free(path_name);
user->header_name = file_name;
if (!strcmp(*suffix_ptr, "hh") || !strcmp(*suffix_ptr, "hpp"))
user->has_hh_suffix = TRUE;
break;
}
Free(file_name);
Free(path_name);
}
}
else if (user->source_name == NULL) {
static const char * const suffix_list[] = { "cc", "c", "cpp", NULL };
const char * const *suffix_ptr;
for (suffix_ptr = suffix_list; *suffix_ptr != NULL; suffix_ptr++) {
char *file_name = mprintf("%s.%s", user->file_prefix, *suffix_ptr);
char *path_name = compose_path_name(user->dir_name, file_name);
if (get_path_status(path_name) == PS_FILE) {
Free(path_name);
user->source_name = file_name;
if (!strcmp(*suffix_ptr, "cc") || !strcmp(*suffix_ptr, "cpp"))
user->has_cc_suffix = TRUE;
break;
}
Free(file_name);
Free(path_name);
}
}
}
}
/** Converts the directory name pointed by \a dir_ptr to a relative pathname
* based on \a working_dir. The original directory name is deallocated and
* replaced with a new string. Nothing happens if \a dir_ptr points to NULL. */
static void replace_dir_with_relative(char **dir_ptr, const char *working_dir)
{
if (*dir_ptr != NULL) {
char *rel_dir = get_relative_dir(*dir_ptr, working_dir);
Free(*dir_ptr);
*dir_ptr = rel_dir;
}
}
/** Converts the directory part of path name pointed by \a path_ptr to a relative
* pathname based on \a working_dir. The original path name is deallocated and
* replaced with a new string. */
static void convert_path_to_relative(char **path_ptr, const char *working_dir)
{
char *dir_name = get_dir_name(*path_ptr, working_dir);
if (dir_name != NULL) {
char *file_name = get_file_from_path(*path_ptr);
replace_dir_with_relative(&dir_name, working_dir);
Free(*path_ptr);
*path_ptr = compose_path_name(dir_name, file_name);
Free(file_name);
Free(dir_name);
}
}
/** Converts all directories used by the Makefile descriptor structure
* \a makefile to relative pathnames based on the working directory stored in
* \a makefile. */
static void convert_dirs_to_relative(struct makefile_struct *makefile)
{
size_t i;
for (i = 0; i < makefile->nTTCN3Modules; i++) {
replace_dir_with_relative(&makefile->TTCN3Modules[i].dir_name,
makefile->working_dir);
}
if (makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
replace_dir_with_relative(&makefile->TTCN3PPModules[i].dir_name,
makefile->working_dir);
}
for (i = 0; i < makefile->nTTCN3IncludeFiles; i++) {
convert_path_to_relative(makefile->TTCN3IncludeFiles + i,
makefile->working_dir);
}
}
for (i = 0; i < makefile->nASN1Modules; i++) {
replace_dir_with_relative(&makefile->ASN1Modules[i].dir_name,
makefile->working_dir);
}
for (i = 0; i < makefile->nUserFiles; i++) {
replace_dir_with_relative(&makefile->UserFiles[i].dir_name,
makefile->working_dir);
}
for (i = 0; i < makefile->nOtherFiles; i++) {
convert_path_to_relative(makefile->OtherFiles + i, makefile->working_dir);
}
if (makefile->ets_name != NULL)
convert_path_to_relative(&makefile->ets_name, makefile->working_dir);
}
/* Returns whether the string \a file_name contains special characters. */
static boolean has_special_chars(const char *file_name)
{
if (file_name != NULL) {
size_t i;
for (i = 0; ; i++) {
int c = (unsigned char)file_name[i];
switch (c) {
case '\0':
return FALSE;
case ' ':
case '*':
case '?':
case '[':
case ']':
case '<':
case '=':
case '>':
case '|':
case '&':
case '$':
case '%':
case '{':
case '}':
case ';':
case ':':
case '(':
case ')':
case '#':
case '!':
case '\'':
case '"':
case '`':
case '\\':
return TRUE;
default:
if (!isascii(c) || !isprint(c)) return TRUE;
break;
}
}
}
return FALSE;
}
/** Checks whether the path name composed of \a dir_name and \a file_name
* contains special characters that are not allowed in the Makefile. Parameter
* \a what contains the description of the corresponding file. */
static void check_special_chars_in_path(const char *dir_name,
const char *file_name, const char *what)
{
if (has_special_chars(dir_name) || has_special_chars(file_name)) {
char *path_name = compose_path_name(dir_name, file_name);
ERROR("The name of %s `%s' contains special characters that cannot be "
"handled properly by the `make' utility and/or the shell.", what,
path_name);
Free(path_name);
}
}
/** Checks whether the directory names or file names that will be used in the
* generated Makefile contain special characters that cannot be handled by the
* "make" utility. */
static void check_special_chars(const struct makefile_struct *makefile)
{
size_t i;
for (i = 0; i < makefile->nTTCN3Modules; i++) {
check_special_chars_in_path(makefile->TTCN3Modules[i].dir_name,
makefile->TTCN3Modules[i].file_name, "TTCN-3 file");
}
if (makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
check_special_chars_in_path(makefile->TTCN3PPModules[i].dir_name,
makefile->TTCN3PPModules[i].file_name,
"TTCN-3 file to be preprocessed");
}
}
for (i = 0; i < makefile->nASN1Modules; i++) {
check_special_chars_in_path(makefile->ASN1Modules[i].dir_name,
makefile->ASN1Modules[i].file_name, "ASN.1 file");
}
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->source_name != NULL)
check_special_chars_in_path(user->dir_name, user->source_name,
"C/C++ source file");
else check_special_chars_in_path(user->dir_name, user->header_name,
"C/C++ header file");
}
for (i = 0; i < makefile->nOtherFiles; i++) {
check_special_chars_in_path(NULL, makefile->OtherFiles[i], "other file");
}
}
/** Adds base directory \a dir_name to Makefile descriptor structure
* \a makefile. Flag \a has_modules indicates whether \a dir_name contains
* TTCN-3 and/or ASN.1 modules. The new directory is ignored if it is already
* added to \a makefile. */
static void add_base_dir(struct makefile_struct *makefile,
const char *dir_name, boolean has_modules)
{
struct base_dir_struct *base_dir;
if (dir_name != NULL) {
size_t i;
for (i = 0; i < makefile->nBaseDirs; i++) {
base_dir = makefile->BaseDirs + i;
if (!strcmp(dir_name, base_dir->dir_name)) {
if (has_modules) base_dir->has_modules = TRUE;
return;
}
}
makefile->BaseDirs = (struct base_dir_struct*)Realloc(makefile->BaseDirs,
(makefile->nBaseDirs + 1) * sizeof(*makefile->BaseDirs));
base_dir = makefile->BaseDirs + makefile->nBaseDirs;
makefile->nBaseDirs++;
base_dir->dir_name = dir_name;
base_dir->has_modules = has_modules;
}
}
/** Collects all directories that are used in the Makefile descriptor structure
* \a makefile in order to use pre-compiled files from them. */
static void collect_base_dirs(struct makefile_struct *makefile)
{
size_t i;
for (i = 0; i < makefile->nTTCN3Modules; i++) {
add_base_dir(makefile, makefile->TTCN3Modules[i].dir_name, TRUE);
}
if (makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
add_base_dir(makefile, makefile->TTCN3PPModules[i].dir_name, TRUE);
}
}
for (i = 0; i < makefile->nASN1Modules; i++) {
add_base_dir(makefile, makefile->ASN1Modules[i].dir_name, TRUE);
}
for (i = 0; i < makefile->nUserFiles; i++) {
add_base_dir(makefile, makefile->UserFiles[i].dir_name, FALSE);
}
if (makefile->nBaseDirs == 0) {
WARNING("Usage of pre-compiled files from central storage (option `-c') "
"is enabled, but all given files are located in the current working "
"directory.");
}
}
/** Checks whether the TTCN-3, ASN.1 and C++ files follow the default naming
* convention and sets the appropriate flags accordingly. */
static void check_naming_convention(struct makefile_struct *makefile)
{
/* initially set all flags to true */
makefile->TTCN3ModulesRegular = TRUE;
makefile->BaseTTCN3ModulesRegular = TRUE;
makefile->ASN1ModulesRegular = TRUE;
makefile->BaseASN1ModulesRegular = TRUE;
makefile->UserHeadersRegular = TRUE;
makefile->UserSourcesRegular = TRUE;
makefile->BaseUserHeadersRegular = TRUE;
makefile->BaseUserSourcesRegular = TRUE;
if (makefile->central_storage) {
/* this project (Makefile) will use pre-compiled files from other
directories */
size_t i;
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
if (module->dir_name != NULL) {
if (!module->is_regular) makefile->BaseTTCN3ModulesRegular = FALSE;
}
else {
if (!module->is_regular) makefile->TTCN3ModulesRegular = FALSE;
}
if (!makefile->TTCN3ModulesRegular && !makefile->BaseTTCN3ModulesRegular)
break;
}
/* ttcnpp files are ttcn files */
if ((makefile->TTCN3ModulesRegular || makefile->BaseTTCN3ModulesRegular) &&
makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name != NULL) {
if (!module->is_regular) makefile->BaseTTCN3ModulesRegular = FALSE;
} else {
if (!module->is_regular) makefile->TTCN3ModulesRegular = FALSE;
}
if (!makefile->TTCN3ModulesRegular && !makefile->BaseTTCN3ModulesRegular)
break;
}
}
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name != NULL) {
if (!module->is_regular) makefile->BaseASN1ModulesRegular = FALSE;
}
else {
if (!module->is_regular) makefile->ASN1ModulesRegular = FALSE;
}
if (!makefile->ASN1ModulesRegular && !makefile->BaseASN1ModulesRegular)
break;
}
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name != NULL) {
if (!user->has_cc_suffix)
makefile->BaseUserSourcesRegular = FALSE;
if (!user->has_cc_suffix || !user->has_hh_suffix)
makefile->BaseUserHeadersRegular = FALSE;
}
else {
if (!user->has_cc_suffix)
makefile->UserSourcesRegular = FALSE;
if (!user->has_cc_suffix || !user->has_hh_suffix)
makefile->UserHeadersRegular = FALSE;
}
if (!makefile->UserHeadersRegular && !makefile->UserSourcesRegular &&
!makefile->BaseUserHeadersRegular &&
!makefile->BaseUserSourcesRegular) break;
}
} else {
/* this project (Makefile) will-be stand-alone */
size_t i;
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
if (!module->is_regular || module->dir_name != NULL) {
makefile->TTCN3ModulesRegular = FALSE;
break;
}
}
if (makefile->TTCN3ModulesRegular && makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (!module->is_regular || module->dir_name != NULL) {
makefile->TTCN3ModulesRegular = FALSE;
break;
}
}
}
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (!module->is_regular || module->dir_name != NULL) {
makefile->ASN1ModulesRegular = FALSE;
break;
}
}
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (!user->has_cc_suffix)
makefile->UserSourcesRegular = FALSE;
if (!user->has_cc_suffix || !user->has_hh_suffix)
makefile->UserHeadersRegular = FALSE;
if (!makefile->UserHeadersRegular && !makefile->UserSourcesRegular)
break;
}
}
}
/** Prints the name of the TTCN-3 or ASN.1 source file that belongs to module
* \a module to file \a fp. */
static void print_file_name(FILE *fp, const struct module_struct *module)
{
char *path_name = compose_path_name(module->dir_name, module->file_name);
fprintf(fp, " %s", path_name);
Free(path_name);
}
/** Prints the name of the preprocessed TTCN-3 source file that belongs to
* module \a module to file \a fp. */
static void print_preprocessed_file_name(FILE *fp,
const struct module_struct *module)
{
char *preprocessed_name = get_preprocessed_file_name(module->file_name);
char *path_name = compose_path_name(module->dir_name, preprocessed_name);
fprintf(fp, " %s", path_name);
Free(path_name);
Free(preprocessed_name);
}
/** Prints the name of the generated header, source or object file of module
* \a module to file \a fp. The name of the directory is added only if
* \a add_directory is TRUE. Parameter \a suffix shall be "hh", "cc", "hpp", "cpp" or "o". */
static void print_generated_file_name(FILE *fp,
const struct module_struct *module, boolean add_directory, const char *suffix)
{
char *file_name = mcopystr(module->module_name);
/* replace '-' with '_' */
size_t i;
for (i = 0; file_name[i] != '\0'; i++)
if (file_name[i] == '-') file_name[i] = '_';
/* append the suffix */
file_name = mputprintf(file_name, "%s", suffix);
/* add the directory name if necessary */
if (add_directory) {
char *path_name = compose_path_name(module->dir_name, file_name);
Free(file_name);
file_name = path_name;
}
fprintf(fp, " %s", file_name);
Free(file_name);
}
/** Prints the name of the user C/C++ header file of user module \a user if the
* above file exists. */
static void print_header_name(FILE *fp, const struct user_struct *user)
{
if (user->header_name != NULL) {
char *path_name = compose_path_name(user->dir_name, user->header_name);
fprintf(fp, " %s", path_name);
Free(path_name);
}
}
/** Prints the name of the user C/C++ source file of user module \a user if the
* above file exists. */
static void print_source_name(FILE *fp, const struct user_struct *user)
{
if (user->source_name != NULL) {
char *path_name = compose_path_name(user->dir_name, user->source_name);
fprintf(fp, " %s", path_name);
Free(path_name);
}
}
/** Prints the name of the user C/C++ object file of user module \a user if the
* above file exists (i.e. the respective source file is present). */
static void print_object_name(FILE *fp, const struct user_struct *user)
{
if (user->source_name != NULL) {
char *file_name = mprintf("%s.o", user->file_prefix);
char *path_name = compose_path_name(user->dir_name, file_name);
Free(file_name);
fprintf(fp, " %s", path_name);
Free(path_name);
}
}
static void print_shared_object_name(FILE *fp, const struct user_struct *user)
{
if (user->source_name != NULL) {
char *file_name = mprintf("%s.so", user->file_prefix);
char *path_name = compose_path_name(user->dir_name, file_name);
Free(file_name);
fprintf(fp, " %s", path_name);
Free(path_name);
}
}
/** Prints the splitted files' names for a given module. */
static void print_splitted_file_names(FILE *fp,
const struct makefile_struct *makefile, const struct module_struct *module)
{
if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
print_generated_file_name(fp, module, FALSE, "_seq.cc");
print_generated_file_name(fp, module, FALSE, "_set.cc");
print_generated_file_name(fp, module, FALSE, "_seqof.cc");
print_generated_file_name(fp, module, FALSE, "_setof.cc");
print_generated_file_name(fp, module, FALSE, "_union.cc");
}
}
static void fprint_extra_targets(FILE* fp, struct string2_list* target_placement_list, const char* placement)
{
struct string2_list* act_elem = target_placement_list;
while (act_elem) {
if (act_elem->str1 && act_elem->str2 && (strcmp(act_elem->str2,placement)==0)) {
fprintf(fp, " %s", act_elem->str1);
}
act_elem = act_elem->next;
}
}
#undef COMMENT_PREFIX
#define COMMENT_PREFIX "# "
/** Prints the Makefile based on structure \a makefile. */
static void print_makefile(struct makefile_struct *makefile)
{
boolean add_refd_prjs = FALSE;
if (makefile->linkingStrategy && makefile->hierarchical) {
add_refd_prjs = hasSubProject(makefile->project_name);
}
else {
add_refd_prjs = makefile->sub_project_dirs && makefile->sub_project_dirs->str;
}
NOTIFY("Generating Makefile skeleton...");
if (makefile->force_overwrite ||
get_path_status(makefile->output_file) == PS_NONEXISTENT) {
size_t i;
char *user_info;
const char* cxx;
const char* cpp;
const char *rm_command = makefile->gnu_make ? "$(RM)" : "rm -f";
FILE *fp;
boolean run_compiler = (makefile->nASN1Modules > 0)
|| (makefile->nTTCN3Modules) || (makefile->nTTCN3PPModules > 0);
expstring_t titan_dir = 0;
const char * last_slash = strrchr(program_name, '/');
if (last_slash != NULL) {
size_t path_len = last_slash - program_name;
titan_dir = mcopystr(program_name);
/* Chop off the program name, and the /bin before it (if any) */
if (path_len >= 4
&& memcmp(titan_dir + path_len - 4, "/bin", 4) == 0) {
titan_dir = mtruncstr(titan_dir, path_len - 4);
}
else {
titan_dir = mtruncstr(titan_dir, path_len);
}
}
fp = fopen(makefile->output_file, "w");
if (fp == NULL){
ERROR("Cannot open output file `%s' for writing: %s",
makefile->output_file, strerror(errno));
return;
}
user_info = get_user_info();
fprintf(fp, "# This Makefile was generated by the Makefile Generator\n"
"# of the TTCN-3 Test Executor version " PRODUCT_NUMBER "\n"
"# for %s\n"
COPYRIGHT_STRING "\n\n"
"# The following make commands are available:\n"
"# - make, make all Builds the %s.\n"
"# - make archive Archives all source files.\n"
"# - make check Checks the semantics of TTCN-3 and ASN.1"
"modules.\n"
"# - make port Generates port skeletons.\n"
"%s" // clean:
"%s" //clean-all
"# - make compile Translates TTCN-3 and ASN.1 modules to C++.\n"
"# - make dep Creates/updates dependency list.\n"
"# - make executable Builds the executable test suite.\n"
"# - make library Builds the library archive.\n"
"# - make objects Builds the object files without linking the "
"executable.\n", user_info,
makefile->library ? "library archive." : "executable test suite",
(makefile->linkingStrategy && makefile->hierarchical) ?
"# - make clean Removes generated files from project.\n" :
"# - make clean Removes all generated files.\n",
(makefile->linkingStrategy && makefile->hierarchical) ?
"# - make clean-all Removes all generated files from the project hierarchy.\n" : "");
Free(user_info);
if (makefile->dynamic)
fprintf(fp, "# - make shared_objects Builds the shared object files "
"without linking the executable.\n");
if (makefile->preprocess)
fputs("# - make preprocess Preprocess TTCN-3 files.\n", fp);
if (makefile->central_storage) {
fputs("# WARNING! This Makefile uses pre-compiled files from the "
"following directories:\n", fp);
for (i = 0; i < makefile->nBaseDirs; i++)
fprintf(fp, "# %s\n", makefile->BaseDirs[i].dir_name);
fputs("# The executable tests will be consistent only if all directories "
"use\n"
"# the same platform and the same version of TTCN-3 Test Executor "
"and\n"
"# C++ compiler with the same command line switches.\n\n", fp);
}
if (makefile->gnu_make) {
fputs("# WARNING! This Makefile can be used with GNU make only.\n"
"# Other versions of make may report syntax errors in it.\n\n"
"#\n"
"# Do NOT touch this line...\n"
"#\n"
".PHONY: all shared_objects executable library objects check port clean dep archive", fp);
if (makefile->preprocess) fputs(" preprocess", fp);
if (add_refd_prjs) {
fprintf(fp, "\\\n referenced-all referenced-shared_objects referenced-executable referenced-library referenced-objects referenced-check"
"\\\n referenced-clean%s",
(makefile->linkingStrategy && makefile->hierarchical) ?
"-all" : "");
}
fprint_extra_targets(fp, makefile->target_placement_list, "PHONY");
if (makefile->gcc_dep) {
fputs("\n\n.SUFFIXES: .d", fp);
}
fputs("\n\n", fp);
}
if (makefile->linkingStrategy) {
const char* tpd_name = getTPDFileName(makefile->project_name);
if (tpd_name) {
fputs("# Titan Project Descriptor file what this Makefile is generated from.\n", fp);
fprintf(fp, "TPD = %s\n\n", tpd_name);
}
const char* root_dir = getPathToRootDir(makefile->project_name);
if (root_dir) {
fputs("# Relative path to top directory at OS level.\n", fp);
fprintf(fp, "ROOT_DIR = %s\n\n", root_dir);
}
}
if (add_refd_prjs) {
struct string_list* act_elem = NULL;
struct string_list* head = NULL;
if (makefile->linkingStrategy && makefile->hierarchical) {// pair with free_string_list
head = act_elem = getRefWorkingDirs(makefile->project_name);
}
else {
act_elem = makefile->sub_project_dirs;
}
if (!makefile->linkingStrategy)
fputs("# This is the top level makefile of a Makefile hierarchy generated from\n", fp);
fputs("# Titan Project Descriptor hierarchy. List of referenced project\n"
"# working directories (ordered by dependencies):\n", fp);
while (act_elem) {
if (act_elem->str) {
fprintf(fp, "# %s\n", act_elem->str);
}
act_elem = act_elem->next;
}
if (makefile->linkingStrategy && makefile->hierarchical) { // pair with getRefWorkingDirs
free_string_list(head);
}
fputs("REFERENCED_PROJECT_DIRS = ", fp);
if (makefile->linkingStrategy && makefile->hierarchical) {
head = act_elem = getRefWorkingDirs(makefile->project_name); // pair with free_string_list
}
else {
act_elem = makefile->sub_project_dirs;
}
while (act_elem) {
if (act_elem->str) {
fprintf(fp, "%s ", act_elem->str);
}
act_elem = act_elem->next;
}
fputs("\n\n", fp);
if (makefile->linkingStrategy && makefile->hierarchical) {// pair with getRefWorkingDirs
free_string_list(head);
}
}
fprintf(fp, "#\n"
"# Set these variables...\n"
"#\n\n"
"# The path of your TTCN-3 Test Executor installation:\n"
"# Uncomment this line to override the environment variable.\n"
"%s"
"# TTCN3_DIR = %s\n"
, titan_dir ?
"# The value below points to the location of the TITAN version\n"
"# that generated this makefile.\n" : ""
, titan_dir ? titan_dir : "");
if (titan_dir) Free(titan_dir);
boolean cxx_free = FALSE;
if (makefile->cxxcompiler) {
cxx = makefile->cxxcompiler;
} else {
#ifdef __clang__
unsigned int
compiler_major = __clang_major__,
compiler_minor = __clang_minor__;
cxx = mprintf("clang++-%u.%u", compiler_major, compiler_minor);
cxx_free = TRUE;
#else
cxx = "g++";
#endif
}
fprintf(fp, "\n# Your platform: (SOLARIS, SOLARIS8, LINUX, FREEBSD or "
"WIN32)\n"
"PLATFORM = %s\n\n"
"# Your C++ compiler:\n"
"# (if you change the platform, you may need to change the compiler)\n"
"CXX = %s \n\n", get_platform_string(), cxx);
if (makefile->preprocess || makefile->ttcn3preprocessor) {
if (makefile->ttcn3preprocessor) {
cpp = makefile->ttcn3preprocessor;
} else {
cpp = "cpp";
}
fprintf(fp,"# C preprocessor used for TTCN-3 files:\n"
"CPP = %s\n\n", cpp);
}
fputs("# Flags for the C++ preprocessor (and makedepend as well):\n"
"CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)/include", fp);
if (makefile->use_runtime_2) fputs(" -DTITAN_RUNTIME_2", fp);
for (i = 0; i < makefile->nBaseDirs; i++) {
fprintf(fp, " -I%s", makefile->BaseDirs[i].dir_name);
}
if (makefile->prep_includes) {
struct string_list* act_elem = makefile->prep_includes;
while (act_elem) {
if (act_elem->str) {
fprintf(fp, " -I%s", act_elem->str);
}
act_elem = act_elem->next;
}
}
if (makefile->prep_defines) {
struct string_list* act_elem = makefile->prep_defines;
while (act_elem) {
if (act_elem->str) {
fprintf(fp, " -D%s", act_elem->str);
}
act_elem = act_elem->next;
}
}
if (makefile->prep_undefines) {
struct string_list* act_elem = makefile->prep_undefines;
while (act_elem) {
if (act_elem->str) {
fprintf(fp, " -U%s", act_elem->str);
}
act_elem = act_elem->next;
}
}
fputs("\n\n", fp);
if (makefile->gcc_dep) {
fprintf(fp, "# Flags for dependency generation\n"
"CXXDEPFLAGS = -%s\n\n", strstr(cxx, "g++") ? "MM" : "xM1");
}
if (cxx_free) {
Free((char*)cxx);
cxx = NULL;
}
if (makefile->preprocess || makefile->ttcn3_prep_includes || makefile->ttcn3_prep_defines) {
fputs("# Flags for preprocessing TTCN-3 files:\n"
"CPPFLAGS_TTCN3 =", fp);
if (makefile->preprocess) {
for (i = 0; i < makefile->nBaseDirs; i++) {
fprintf(fp, " -I%s", makefile->BaseDirs[i].dir_name);
}
}
if (makefile->ttcn3_prep_includes) {
struct string_list* act_elem = makefile->ttcn3_prep_includes;
while (act_elem) {
if (act_elem->str) {
fprintf(fp, " -I%s", act_elem->str);
}
act_elem = act_elem->next;
}
}
if (makefile->ttcn3_prep_defines) {
struct string_list* act_elem = makefile->ttcn3_prep_defines;
while (act_elem) {
if (act_elem->str) {
fprintf(fp, " -D%s", act_elem->str);
}
act_elem = act_elem->next;
}
}
if (makefile->ttcn3_prep_undefines) {
struct string_list* act_elem = makefile->ttcn3_prep_undefines;
while (act_elem) {
if (act_elem->str) {
fprintf(fp, " -U%s", act_elem->str);
}
act_elem = act_elem->next;
}
}
fputs("\n\n", fp);
}
/* code splitting: command line argument wins */
if (makefile->code_splitting_mode == NULL) {
if (makefile->codesplittpd) {
makefile->code_splitting_mode = mcopystr("-U type");
}
}
fprintf(fp, "# Flags for the C++ compiler:\n"
"CXXFLAGS = %s%s %s %s\n\n"
"# Flags for the linker:\n"
"LDFLAGS = %s%s\n\n"
"ifeq ($(PLATFORM), WIN32)\n"
"# Silence linker warnings.\n"
"LDFLAGS += -Wl,--enable-auto-import,--enable-runtime-pseudo-reloc\n"
"endif\n\n"
"# Utility to create library files\n"
"AR = ar\n"
"ARFLAGS = \n\n"
"# Flags for the TTCN-3 and ASN.1 compiler:\n"
"COMPILER_FLAGS =%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n\n"
"# Execution mode: (either ttcn3 or ttcn3-parallel)\n"
"TTCN3_LIB = ttcn3%s%s%s\n\n"
#ifdef LICENSE
"# The path of your OpenSSL installation:\n"
"# If you do not have your own one, leave it unchanged.\n"
"%sOPENSSL_DIR = $(TTCN3_DIR)\n\n"
#endif
"# The path of your libxml2 installation:\n"
"# If you do not have your own one, leave it unchanged.\n"
"XMLDIR = $(TTCN3_DIR)\n\n"
"# Directory to store the archived source files:\n",
makefile->dynamic ? "-Wall -fPIC" : "-Wall", /* CXXFLAGS */
makefile->coverage ? " -fprofile-arcs -ftest-coverage -g" : "", /* CXXFLAGS COVERAGE */
makefile->optlevel ? makefile->optlevel : "", /* CXXFLAGS optimization level */
makefile->optflags ? makefile->optflags : "", /* CXXFLAGS optimization level */
makefile->dynamic ? "-fPIC" : "", /* LDFLAGS */
makefile->coverage ? " -fprofile-arcs -ftest-coverage -g -lgcov" : "", /* LDFLAGS COVERAGE */
/* COMPILER_FLAGS */
makefile->use_runtime_2 ? " -L -R " : " -L ",
(makefile->code_splitting_mode ? makefile->code_splitting_mode : ""),
(makefile->quietly ? " -q" : ""),
(makefile->disablesubtypecheck ? " -y" : ""),
(makefile->disableber ? " -b" : ""),
(makefile->disableraw ? " -r" : ""),
(makefile->disabletext ? " -x" : ""),
(makefile->disablexer ? " -X" : ""),
(makefile->disablejson ? " -j" : ""),
(makefile->forcexerinasn ? " -a" : ""),
(makefile->defaultasomit ? " -d" : ""),
(makefile->gccmsgformat ? " -g" : ""),
(makefile->linenumbersonlymsg ? " -i" : ""),
(makefile->includesourceinfo ? " -l" : ""),
/*(makefile->addsourcelineinfo ? " -L" : ""),*/
(makefile->suppresswarnings ? " -w" : ""),
(makefile->outparamboundness ? " -Y" : ""),
(makefile->omit_in_value_list ? " -M" : ""),
(makefile->warnings_for_bad_variants ? " -E" : ""),
(makefile->activate_debugger ? " -n" : ""),
(makefile->tcov_file_name ? makefile->tcov_file_name : ""),
(makefile->profiled_file_list ? " -z $(PROFILED_FILE_LIST)" : ""),
/* end of COMPILER FLAGS */
(makefile->use_runtime_2 ? "-rt2" : ""), /* TTCN3_LIB */
(makefile->single_mode ? "" : "-parallel"),
(makefile->dynamic ? "-dynamic": "")
#ifdef LICENSE
,(makefile->disable_predef_ext_folder ? "# " : "")
#endif
);
if (!makefile->gnu_make) {
fputs("# Note: you can set any directory except ./archive\n", fp);
}
fputs("ARCHIVE_DIR = backup\n\n"
"#\n"
"# You may change these variables. Add your files if necessary...\n"
"#\n\n"
"# TTCN-3 modules of this project:\n"
"TTCN3_MODULES =", fp);
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
if (module->dir_name == NULL || !makefile->central_storage)
/* If the file is in the current directory or
* is not in the current directory but central directory is not used,
* it goes into TTCN3_MODULES */
print_file_name(fp, module);
}
fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_MODULES");
if (makefile->preprocess) {
fputs("\n\n"
"# TTCN-3 modules to preprocess:\n"
"TTCN3_PP_MODULES =", fp);
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name == NULL || !makefile->central_storage)
print_file_name(fp, module);
}
fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_PP_MODULES");
}
if (makefile->central_storage) {
fputs("\n\n"
"# TTCN-3 modules used from central project(s):\n"
"BASE_TTCN3_MODULES =", fp);
if (!makefile->linkingStrategy) {
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
/* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */
if (module->dir_name != NULL) print_file_name(fp, module);
}
if (makefile->preprocess) {
fputs("\n\n"
"# TTCN-3 modules to preprocess used from central project(s):\n"
"BASE_TTCN3_PP_MODULES =", fp);
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name))
print_file_name(fp, module);
}
}
}
else { // new linking strategy
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
/* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */
if (module->dir_name != NULL && !isTtcn3ModuleInLibrary(module->module_name))
print_file_name(fp, module);
}
fputs("\n\n"
"# TTCN-3 library linked modules used from central project(s):\n"
"BASE2_TTCN3_MODULES =", fp);
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
/* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */
if (module->dir_name != NULL && isTtcn3ModuleInLibrary(module->module_name))
print_file_name(fp, module);
}
if (makefile->preprocess) {
fputs("\n\n"
"# TTCN-3 modules to preprocess used from central project(s):\n"
"BASE_TTCN3_PP_MODULES =", fp);
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name))
print_file_name(fp, module);
}
fputs("\n\n"
"# TTCN-3 library linked modules to preprocess used from central project(s):\n"
"BASE2_TTCN3_PP_MODULES =", fp);
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name))
print_file_name(fp, module);
}
}
}
}
if (makefile->preprocess) {
fputs("\n\n"
"# Files to include in TTCN-3 preprocessed modules:\n"
"TTCN3_INCLUDES =", fp);
for (i = 0; i < makefile->nTTCN3IncludeFiles; i++)
fprintf(fp, " %s", makefile->TTCN3IncludeFiles[i]);
fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_INCLUDES");
}
fputs("\n\n"
"# ASN.1 modules of this project:\n"
"ASN1_MODULES =", fp);
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name == NULL || !makefile->central_storage)
print_file_name(fp, module);
}
fprint_extra_targets(fp, makefile->target_placement_list, "ASN1_MODULES");
if (makefile->central_storage) {
fputs("\n\n"
"# ASN.1 modules used from central project(s):\n"
"BASE_ASN1_MODULES =", fp);
if (!makefile->linkingStrategy) {
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name != NULL) print_file_name(fp, module);
}
}
else {
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name != NULL && !isAsn1ModuleInLibrary(module->module_name))
print_file_name(fp, module);
}
fputs("\n\n"
"# ASN.1 library linked modules used from central project(s):\n"
"BASE2_ASN1_MODULES =", fp);
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name != NULL && isAsn1ModuleInLibrary(module->module_name))
print_file_name(fp, module);
}
}
}
if (makefile->preprocess) {
fputs("\n\n"
"# TTCN-3 source files generated by the C preprocessor:\n"
"PREPROCESSED_TTCN3_MODULES =", fp);
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name == NULL || !makefile->central_storage)
print_preprocessed_file_name(fp, module);
}
if (makefile->central_storage) {
fputs("\n\n"
"# TTCN-3 files generated by the CPP used from central project(s):\n"
"BASE_PREPROCESSED_TTCN3_MODULES =", fp);
if (!makefile->linkingStrategy) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name != NULL)
print_preprocessed_file_name(fp, module);
}
}
else { // new linking strategy
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name))
print_preprocessed_file_name(fp, module);
}
fputs("\n\n"
"# TTCN-3 library linked files generated by the CPP used from central project(s):\n"
"BASE2_PREPROCESSED_TTCN3_MODULES =", fp);
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name))
print_preprocessed_file_name(fp, module);
}
}
}
}
if (makefile->profiled_file_list) {
if (makefile->profiled_file_list->next && !makefile->central_storage) {
// merge all profiled file lists into one list
fprintf(fp, "\n\n"
"# Text file containing the list of profiled TTCN-3 files of "
"this project:\n"
"PROFILED_FILE_LIST = %s.merged\n"
"PROFILED_FILE_LIST_SEGMENTS =",
makefile->profiled_file_list->str);
struct string_list* iter = makefile->profiled_file_list;
while(iter != NULL) {
fprintf(fp, " %s", iter->str);
iter = iter->next;
}
}
else {
// only one profiled file list is needed
fprintf(fp, "\n\n"
"# Text file containing the list of profiled TTCN-3 files of "
"this project:\n"
"PROFILED_FILE_LIST = %s", makefile->profiled_file_list->str);
}
}
fputs("\n\n"
"# C++ source & header files generated from the TTCN-3 & ASN.1 "
"modules of\n"
"# this project:\n"
"GENERATED_SOURCES =", fp);
if (makefile->gnu_make && makefile->TTCN3ModulesRegular) {
fputs(" $(TTCN3_MODULES:.ttcn=.cc)", fp);
if (makefile->code_splitting_mode) {
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
if (module->dir_name == NULL || !makefile->central_storage)
print_splitted_file_names(fp, makefile, module);
}
}
if (makefile->preprocess) {
fputs(" $(TTCN3_PP_MODULES:.ttcnpp=.cc)", fp);
if (makefile->code_splitting_mode) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name == NULL || !makefile->central_storage)
print_splitted_file_names(fp, makefile, module);
}
}
}
} else {
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
if (module->dir_name == NULL || !makefile->central_storage) {
print_generated_file_name(fp, module, FALSE, ".cc");
if (makefile->code_splitting_mode)
print_splitted_file_names(fp, makefile, module);
}
}
if (makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name == NULL || !makefile->central_storage) {
print_generated_file_name(fp, module, FALSE, ".cc");
if (makefile->code_splitting_mode)
print_splitted_file_names(fp, makefile, module);
}
}
}
}
if (makefile->gnu_make && makefile->ASN1ModulesRegular) {
fputs(" $(ASN1_MODULES:.asn=.cc)", fp);
if (makefile->code_splitting_mode) {
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name == NULL || !makefile->central_storage) {
print_splitted_file_names(fp, makefile, module);
}
}
}
} else {
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name == NULL || !makefile->central_storage) {
print_generated_file_name(fp, module, FALSE, ".cc");
if (makefile->code_splitting_mode)
print_splitted_file_names(fp, makefile, module);
}
}
}
fputs("\nGENERATED_HEADERS =", fp);
if (makefile->gnu_make) {
fputs(" $(GENERATED_SOURCES:.cc=.hh)", fp);
}
else {
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
if (module->dir_name == NULL || !makefile->central_storage)
print_generated_file_name(fp, module, FALSE, ".hh");
}
if (makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name == NULL || !makefile->central_storage)
print_generated_file_name(fp, module, FALSE, ".hh");
}
}
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name == NULL || !makefile->central_storage)
print_generated_file_name(fp, module, FALSE, ".hh");
}
}
if (makefile->central_storage) {
fputs("\n\n"
"# C++ source & header files generated from the TTCN-3 & ASN.1 "
"modules of\n"
"# central project(s):\n"
"BASE_GENERATED_SOURCES =", fp);
if (makefile->gnu_make && makefile->BaseTTCN3ModulesRegular) {
fputs(" $(BASE_TTCN3_MODULES:.ttcn=.cc)", fp);
if (makefile->code_splitting_mode) {
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
if (module->dir_name != NULL) {
print_splitted_file_names(fp, makefile, module);
}
}
}
if (makefile->preprocess) {
fputs(" $(BASE_TTCN3_PP_MODULES:.ttcnpp=.cc)", fp);
if (makefile->code_splitting_mode) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name != NULL) {
print_splitted_file_names(fp, makefile, module);
}
}
}
}
} else {
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
if (module->dir_name != NULL) {
print_generated_file_name(fp, module, TRUE, ".cc");
if (makefile->code_splitting_mode)
print_splitted_file_names(fp, makefile, module);
}
}
if (makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name != NULL) {
print_generated_file_name(fp, module, TRUE, ".cc");
if (makefile->code_splitting_mode)
print_splitted_file_names(fp, makefile, module);
}
}
}
}
if (makefile->gnu_make && makefile->BaseASN1ModulesRegular) {
fputs(" $(BASE_ASN1_MODULES:.asn=.cc)", fp);
if (makefile->code_splitting_mode) {
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name != NULL) {
print_splitted_file_names(fp, makefile, module);
}
}
}
} else {
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name != NULL) {
print_generated_file_name(fp, module, TRUE, ".cc");
if (makefile->code_splitting_mode)
print_splitted_file_names(fp, makefile, module);
}
}
}
fputs("\nBASE_GENERATED_HEADERS =", fp);
if (makefile->gnu_make) {
fputs(" $(BASE_GENERATED_SOURCES:.cc=.hh)", fp);
} else {
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
if (module->dir_name != NULL)
print_generated_file_name(fp, module, TRUE, ".hh");
}
if (makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name != NULL)
print_generated_file_name(fp, module, TRUE, ".hh");
}
}
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name != NULL)
print_generated_file_name(fp, module, TRUE, ".hh");
}
}
}
if (makefile->linkingStrategy) {
fputs("\n\n"
"# C++ source & header files generated from the TTCN-3 "
" library linked modules of\n"
"# central project(s):\n"
"BASE2_GENERATED_SOURCES =", fp);
if (makefile->gnu_make && makefile->BaseTTCN3ModulesRegular) {
fputs(" $(BASE2_TTCN3_MODULES:.ttcn=.cc)", fp);
fputs(" $(BASE2_ASN1_MODULES:.asn=.cc)", fp);
if (makefile->preprocess)
fputs(" $(BASE2_TTCN3_PP_MODULES:.ttcnpp=.cc)", fp);
}
else {
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
if (module->dir_name != NULL && isTtcn3ModuleInLibrary(module->module_name)) {
print_generated_file_name(fp, module, TRUE, ".cc");
}
}
if (makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name)) {
print_generated_file_name(fp, module, TRUE, ".cc");
}
}
}
}
fputs("\nBASE2_GENERATED_HEADERS =", fp);
if (makefile->gnu_make) {
fputs(" $(BASE2_GENERATED_SOURCES:.cc=.hh)", fp);
}
else
ERROR("the usage of 'Z' flag requires GNU make");
}
fputs("\n\n"
"# C/C++ Source & header files of Test Ports, external functions "
"and\n"
"# other modules:\n"
"USER_SOURCES =", fp);
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name == NULL || !makefile->central_storage)
print_source_name(fp, user);
}
fprint_extra_targets(fp, makefile->target_placement_list, "USER_SOURCES");
fputs("\nUSER_HEADERS =", fp);
if (makefile->gnu_make && makefile->UserHeadersRegular) {
fputs(" $(USER_SOURCES:.cc=.hh)", fp);
} else {
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name == NULL || !makefile->central_storage)
print_header_name(fp, user);
}
}
fprint_extra_targets(fp, makefile->target_placement_list, "USER_HEADERS");
if (makefile->central_storage) {
fputs("\n\n"
"# C/C++ Source & header files of Test Ports, external functions "
"and\n"
"# other modules used from central project(s):\n"
"BASE_USER_SOURCES =", fp);
if (!makefile->linkingStrategy) {
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name != NULL) {
print_source_name(fp, user);
}
}
fputs("\nBASE_USER_HEADERS =", fp);
if (makefile->gnu_make && makefile->BaseUserHeadersRegular) {
fputs(" $(BASE_USER_SOURCES:.cc=.hh)", fp);
}
else {
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name != NULL)
print_header_name(fp, user);
}
}
}
else {
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name)) {
print_source_name(fp, user);
}
}
fputs("\nBASE_USER_HEADERS =", fp);
if (makefile->gnu_make && makefile->BaseUserHeadersRegular) {
fputs(" $(BASE_USER_SOURCES:.cc=.hh)", fp);
}
else {
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name != NULL && !isHeaderFileInLibrary(user->header_name))
print_header_name(fp, user);
}
}
fputs("\n\n"
"# C/C++ Source & header files of Test Ports, external functions "
"and\n"
"# other modules used from library linked central project(s):\n"
"BASE2_USER_SOURCES =", fp);
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name != NULL && isSourceFileInLibrary(user->source_name)) {
print_source_name(fp, user);
}
}
fputs("\nBASE2_USER_HEADERS =", fp);
if (makefile->gnu_make && makefile->BaseUserHeadersRegular) {
fputs(" $(BASE2_USER_SOURCES:.cc=.hh)", fp);
}
else {
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name != NULL && isHeaderFileInLibrary(user->header_name))
print_header_name(fp, user);
}
}
}
}
if (makefile->dynamic) {
fputs("\n\n"
"# Shared object files of this project:\n"
"SHARED_OBJECTS =", fp);
if (makefile->gnu_make) {
fputs(" $(GENERATED_SOURCES:.cc=.so)", fp);
} else {
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
if (module->dir_name == NULL || !makefile->central_storage) {
print_generated_file_name(fp, module, FALSE, ".so");
if (makefile->code_splitting_mode != NULL)
if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
print_generated_file_name(fp, module, FALSE, "_seq.so");
print_generated_file_name(fp, module, FALSE, "_set.so");
print_generated_file_name(fp, module, FALSE, "_seqof.so");
print_generated_file_name(fp, module, FALSE, "_setof.so");
print_generated_file_name(fp, module, FALSE, "_union.so");
}
}
}
if (makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name == NULL || !makefile->central_storage) {
print_generated_file_name(fp, module, FALSE, ".so");
if (makefile->code_splitting_mode != NULL)
if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
print_generated_file_name(fp, module, FALSE, "_seq.so");
print_generated_file_name(fp, module, FALSE, "_set.so");
print_generated_file_name(fp, module, FALSE, "_seqof.so");
print_generated_file_name(fp, module, FALSE, "_setof.so");
print_generated_file_name(fp, module, FALSE, "_union.so");
}
}
}
}
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name == NULL || !makefile->central_storage) {
print_generated_file_name(fp, module, FALSE, ".so");
if (makefile->code_splitting_mode != NULL)
if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
print_generated_file_name(fp, module, FALSE, "_seq.so");
print_generated_file_name(fp, module, FALSE, "_set.so");
print_generated_file_name(fp, module, FALSE, "_seqof.so");
print_generated_file_name(fp, module, FALSE, "_setof.so");
print_generated_file_name(fp, module, FALSE, "_union.so");
}
}
}
}
if (makefile->gnu_make && makefile->UserSourcesRegular) {
fputs(" $(USER_SOURCES:.cc=.so)", fp);
} else {
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name == NULL || !makefile->central_storage)
print_shared_object_name(fp, user);
}
}
}
fputs("\n\n"
"# Object files of this project that are needed for the executable "
"test suite:\n"
"OBJECTS = $(GENERATED_OBJECTS) $(USER_OBJECTS)\n\n" /* never := */
"GENERATED_OBJECTS =", fp);
if (makefile->gnu_make) {
fputs(" $(GENERATED_SOURCES:.cc=.o)", fp);
} else {
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
if (module->dir_name == NULL || !makefile->central_storage) {
print_generated_file_name(fp, module, FALSE, ".o");
if (makefile->code_splitting_mode != NULL)
if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
print_generated_file_name(fp, module, FALSE, "_seq.o");
print_generated_file_name(fp, module, FALSE, "_set.o");
print_generated_file_name(fp, module, FALSE, "_seqof.o");
print_generated_file_name(fp, module, FALSE, "_setof.o");
print_generated_file_name(fp, module, FALSE, "_union.o");
}
}
}
if (makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name == NULL || !makefile->central_storage) {
print_generated_file_name(fp, module, FALSE, ".o");
if (makefile->code_splitting_mode != NULL)
if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
print_generated_file_name(fp, module, FALSE, "_seq.o");
print_generated_file_name(fp, module, FALSE, "_set.o");
print_generated_file_name(fp, module, FALSE, "_seqof.o");
print_generated_file_name(fp, module, FALSE, "_setof.o");
print_generated_file_name(fp, module, FALSE, "_union.o");
}
}
}
}
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name == NULL || !makefile->central_storage) {
print_generated_file_name(fp, module, FALSE, ".o");
if (makefile->code_splitting_mode != NULL)
if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
print_generated_file_name(fp, module, FALSE, "_seq.o");
print_generated_file_name(fp, module, FALSE, "_set.o");
print_generated_file_name(fp, module, FALSE, "_seqof.o");
print_generated_file_name(fp, module, FALSE, "_setof.o");
print_generated_file_name(fp, module, FALSE, "_union.o");
}
}
}
}
fputs("\n\nUSER_OBJECTS =", fp);
if (makefile->gnu_make && makefile->UserSourcesRegular) {
fputs(" $(USER_SOURCES:.cc=.o)", fp);
} else {
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name == NULL || !makefile->central_storage)
print_object_name(fp, user);
}
}
fprint_extra_targets(fp, makefile->target_placement_list, "USER_OBJECTS");
if (makefile->gcc_dep) {
/* GNU Make processes included makefiles in reverse order. By putting
* user sources first, their .d will be generated last, after the
* GENERATED_SOURCES (and GENERATED_HEADERS) have been created.
* This avoid spurious errors during incremental dependency generation */
fputs("\n\nDEPFILES = $(USER_OBJECTS:.o=.d) $(GENERATED_OBJECTS:.o=.d)", fp);
}
if (makefile->central_storage) {
if (makefile->dynamic) {
fputs("\n\n"
"# Shared object files of central project(s):\n"
"BASE_SHARED_OBJECTS =", fp);
if (!makefile->linkingStrategy) {
if (makefile->gnu_make) {
fputs(" $(BASE_GENERATED_SOURCES:.cc=.so)", fp);
}
else {
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
if (module->dir_name != NULL)
print_generated_file_name(fp, module, TRUE, ".so");
}
if (makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module =
makefile->TTCN3PPModules + i;
if (module->dir_name != NULL)
print_generated_file_name(fp, module, TRUE, ".so");
}
}
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name != NULL)
print_generated_file_name(fp, module, TRUE, ".so");
}
}
if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
fputs(" $(BASE_USER_SOURCES:.cc=.so)", fp);
}
else {
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name != NULL)
print_shared_object_name(fp, user);
}
}
}
else { // new linkingStrategy
if (makefile->gnu_make) {
fputs(" $(BASE_GENERATED_SOURCES:.cc=.so)", fp);
}
else
ERROR("the usage of 'Z' flag requires GNU make");
if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
fputs(" $(BASE_USER_SOURCES:.cc=.so)", fp);
}
else {
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name))
print_shared_object_name(fp, user);
}
}
}
} /* if dynamic */
fputs("\n\n"
"# Object files of central project(s) that are needed for the "
"executable test suite:\n"
"BASE_OBJECTS =", fp);
if (!makefile->linkingStrategy) {
if (makefile->gnu_make) {
fputs(" $(BASE_GENERATED_SOURCES:.cc=.o)", fp);
}
else {
for (i = 0; i < makefile->nTTCN3Modules; i++) {
const struct module_struct *module = makefile->TTCN3Modules + i;
if (module->dir_name != NULL)
print_generated_file_name(fp, module, TRUE, ".o");
}
if (makefile->preprocess) {
for (i = 0; i < makefile->nTTCN3PPModules; i++) {
const struct module_struct *module = makefile->TTCN3PPModules + i;
if (module->dir_name != NULL)
print_generated_file_name(fp, module, TRUE, ".o");
}
}
for (i = 0; i < makefile->nASN1Modules; i++) {
const struct module_struct *module = makefile->ASN1Modules + i;
if (module->dir_name != NULL)
print_generated_file_name(fp, module, TRUE, ".o");
}
}
if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
fputs(" $(BASE_USER_SOURCES:.cc=.o)", fp);
}
else {
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name != NULL)
print_object_name(fp, user);
}
}
}
else { // new linkingStrategy
if (makefile->gnu_make) {
fputs(" $(BASE_GENERATED_SOURCES:.cc=.o)", fp);
}
else
ERROR("the usage of 'Z' flag requires GNU make");
if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
fputs(" $(BASE_USER_SOURCES:.cc=.o)", fp);
}
else {
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name))
print_object_name(fp, user);
}
}
}
}
if (makefile->linkingStrategy) {
fputs("\n\n"
"# Object files of library linked central project(s) that are needed for the "
"executable test suite:\n"
"BASE2_OBJECTS =", fp);
if (makefile->gnu_make) {
if (makefile->dynamic)
fputs(" $(BASE2_GENERATED_SOURCES:.cc=.so)", fp);
else
fputs(" $(BASE2_GENERATED_SOURCES:.cc=.o)", fp);
}
else ERROR("the usage of 'Z' flag requires GNU make");
if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
if (makefile->dynamic)
fputs(" $(BASE2_USER_SOURCES:.cc=.so)", fp);
else
fputs(" $(BASE2_USER_SOURCES:.cc=.o)", fp);
}
else {
for (i = 0; i < makefile->nUserFiles; i++) {
const struct user_struct *user = makefile->UserFiles + i;
if (user->dir_name != NULL && isSourceFileInLibrary(user->source_name)) {
if (makefile->dynamic)
print_shared_object_name(fp, user);
else
print_object_name(fp, user);
}
}
}
if (makefile->hierarchical) {
fputs("\n\n"
"#Libraries of referenced project(s) that are needed for the "
"executable or library target:\n"
"BASE2_LIBRARY =", fp);
struct string2_list* head = getLinkerLibs(makefile->project_name);
struct string2_list* act_elem = head;
while (act_elem) {
if (act_elem->str2) {
fputs(" ", fp);
fprintf(fp, "%s/lib%s.%s", act_elem->str1, act_elem->str2,
isDynamicLibrary(act_elem->str2) ? "so" : "a");
}
act_elem = act_elem->next;
}
free_string2_list(head);
}
}
fputs("\n\n"
"# Other files of the project (Makefile, configuration files, etc.)\n"
"# that will be added to the archived source files:\n"
"OTHER_FILES =", fp);
for (i = 0; i < makefile->nOtherFiles; i++)
fprintf(fp, " %s", makefile->OtherFiles[i]);
fprint_extra_targets(fp, makefile->target_placement_list, "OTHER_FILES");
if (makefile->ets_name) {
const char *ets_suffix = NULL;
/* EXECUTABLE variable */
fprintf(fp, "\n\n"
"# The name of the executable test suite:\n"
"EXECUTABLE = %s", makefile->ets_name);
#ifdef WIN32
{
/* add the .exe suffix unless it is already present */
ets_suffix = get_suffix(makefile->ets_name);
if (ets_suffix == NULL || strcmp(ets_suffix, "exe"))
fputs(".exe", fp);
}
#endif
fputs("\n\n", fp);
if (makefile->linkingStrategy) {
#ifndef WIN32
fputs("DYNAMIC_LIBRARY = lib$(EXECUTABLE).so\n", fp);
fputs("STATIC_LIBRARY = lib$(EXECUTABLE).a\n", fp);
#else
char* name_prefix = cut_suffix(makefile->ets_name);
fprintf(fp, "DYNAMIC_LIBRARY = lib%s.so\n", name_prefix);
fprintf(fp, "STATIC_LIBRARY = lib%s.a\n", name_prefix);
Free(name_prefix);
#endif
}
/* LIBRARY variable */
ets_suffix = get_suffix(makefile->ets_name);
if (ets_suffix != NULL && !strcmp(ets_suffix, "exe")) {
char* name_prefix = cut_suffix(makefile->ets_name);
fprintf(fp, "\n\nLIBRARY = %s%s%s\n", "lib", name_prefix ? name_prefix : "library",
makefile->dynamic ? ".so" : ".a");
Free(name_prefix);
}
else {
#ifndef WIN32
fprintf(fp, "\n\nLIBRARY = lib$(EXECUTABLE)%s\n",
makefile->dynamic ? ".so" : ".a");
#else
fprintf(fp, "\n\nLIBRARY = lib%s%s\n",
makefile->ets_name, makefile->dynamic ? ".so" : ".a");
#endif
}
} else {
fputs("\n\n"
"# The name of the executable test suite:\n"
"EXECUTABLE =\n"
"LIBRARY =\n", fp);
}
if (!makefile->linkingStrategy || !buildObjects(makefile->project_name, add_refd_prjs)) {
fprintf(fp, "\n"
"TARGET = $(%s)", makefile->library ? "LIBRARY" : "EXECUTABLE");
}
else {
if (makefile->dynamic) {
fputs("\n"
"TARGET = $(SHARED_OBJECTS)", fp);
}
else {
fputs("\n"
"TARGET = $(OBJECTS)", fp);
}
}
fputs("\n\n"
"#\n"
"# Do not modify these unless you know what you are doing...\n"
"# Platform specific additional libraries:\n"
"#\n", fp);
fputs("SOLARIS_LIBS = -lsocket -lnsl -lxml2", fp);
#ifdef USAGE_STATS
fputs(" -lresolv", fp);
#endif
#ifdef ADVANCED_DEBUGGER_UI
fputs(" -lcurses", fp);
#endif
if (makefile->solspeclibraries) {
struct string_list* act_elem = makefile->solspeclibraries;
while (act_elem) {
if (act_elem->str) {
fprintf(fp, " -l%s", act_elem->str);
}
act_elem = act_elem->next;
}
}
fputs("\n", fp);
fputs("SOLARIS8_LIBS = -lsocket -lnsl -lxml2", fp);
#ifdef USAGE_STATS
fputs(" -lresolv", fp);
#endif
#ifdef ADVANCED_DEBUGGER_UI
fputs(" -lcurses", fp);
#endif
if (makefile->sol8speclibraries) {
struct string_list* act_elem = makefile->sol8speclibraries;
while (act_elem) {
if (act_elem->str) {
fprintf(fp, " -l%s", act_elem->str);
}
act_elem = act_elem->next;
}
}
fputs("\n", fp);
fputs("LINUX_LIBS = -lxml2", fp);
#ifdef USAGE_STATS
fputs(" -lpthread -lrt", fp);
#endif
#ifdef ADVANCED_DEBUGGER_UI
fputs(" -lncurses", fp);
#endif
if (makefile->linuxspeclibraries) {
struct string_list* act_elem = makefile->linuxspeclibraries;
while (act_elem) {
if (act_elem->str) {
fprintf(fp, " -l%s", act_elem->str);
}
act_elem = act_elem->next;
}
}
fputs("\n", fp);
fputs("FREEBSD_LIBS = -lxml2", fp);
#ifdef ADVANCED_DEBUGGER_UI
fputs(" -lncurses", fp);
#endif
if (makefile->freebsdspeclibraries) {
struct string_list* act_elem = makefile->freebsdspeclibraries;
while (act_elem) {
if (act_elem->str) {
fprintf(fp, " -l%s", act_elem->str);
}
act_elem = act_elem->next;
}
}
fputs("\n", fp);
fputs("WIN32_LIBS = -lxml2", fp);
#ifdef ADVANCED_DEBUGGER_UI
fputs(" -lncurses", fp);
#endif
if (makefile->win32speclibraries) {
struct string_list* act_elem = makefile->win32speclibraries;
while (act_elem) {
if (act_elem->str) {
fprintf(fp, " -l%s", act_elem->str);
}
act_elem = act_elem->next;
}
}
fputs("\n\n", fp);
fputs("#\n"
"# Rules for building the executable...\n"
"#\n\n", fp);
fprintf(fp, "all:%s $(TARGET) ;\n\n", add_refd_prjs?" referenced-all":"");
if (makefile->dynamic) {
fprintf(fp, "shared_objects:%s $(SHARED_OBJECTS) ;\n\n", add_refd_prjs?" referenced-shared_objects":"");
}
fprintf(fp,
"executable:%s $(EXECUTABLE) ;\n\n"
"library:%s $(LIBRARY) ;\n\n"
"objects:%s $(OBJECTS) compile;\n\n", add_refd_prjs?" referenced-executable":"", add_refd_prjs?" referenced-library":"", add_refd_prjs?" referenced-objects":"");
/* target $(EXECUTABLE) */
if (makefile->dynamic && makefile->library) {
/* There is no need to create the .so for all the source files */
fputs("$(EXECUTABLE): $(LIBRARY)\n"
"\tif $(CXX) $(LDFLAGS) -o $@ $(LIBRARY)", fp);
}
else {
fprintf(fp, "$(EXECUTABLE): %s", makefile->dynamic ? "$(SHARED_OBJECTS)" : "$(OBJECTS)");
if (!makefile->linkingStrategy) { // use the old linking method
if (makefile->central_storage) {
if (makefile->dynamic) {
fputs(" $(BASE_SHARED_OBJECTS)", fp);
} else {
fputs(" $(BASE_OBJECTS)", fp);
}
}
}
else {
if (!makefile->library) {
if (makefile->dynamic) {
fputs(" $(BASE_SHARED_OBJECTS)", fp);
}
else {
fputs(" $(BASE_OBJECTS)", fp);
}
if (makefile->hierarchical) {
fputs(" $(BASE2_LIBRARY)", fp);
}
}
}
fprintf(fp, "\n"
"\tif $(CXX) $(LDFLAGS) -o $@ %s",
#if defined (SOLARIS) || defined (SOLARIS8)
"");
#else
makefile->dynamic ? "-Wl,--no-as-needed " : ""); /* start writing the link step */
#endif
if (makefile->gnu_make) fputs("$^", fp);
else {
if (makefile->dynamic) {
fputs("$(SHARED_OBJECTS)", fp);
if (makefile->central_storage)
fputs(" $(BASE_SHARED_OBJECTS)", fp);
}
else {
fputs("$(OBJECTS)", fp);
if (makefile->central_storage)
fputs(" $(BASE_OBJECTS)", fp);
}
}
}
if (makefile->additionalObjects) {
struct string_list* act_elem = makefile->additionalObjects;
while (act_elem) {
if (act_elem->str) {
fprintf(fp, " %s", act_elem->str);
}
act_elem = act_elem->next;
}
}
fprintf(fp, " \\\n"
"\t-L$(TTCN3_DIR)/lib -l$(TTCN3_LIB)"
" \\\n"
"\t-L$(OPENSSL_DIR)/lib -lcrypto");
if (!makefile->linkingStrategy) {
if (makefile->linkerlibraries) {
struct string_list* act_elem = makefile->linkerlibraries;
while (act_elem) {
if (act_elem->str) {
fprintf(fp, " -l%s", act_elem->str);
}
act_elem = act_elem->next;
}
}
if (makefile->linkerlibsearchpath) {
struct string_list* act_elem = makefile->linkerlibsearchpath;
while (act_elem) {
if (act_elem->str) {
fprintf(fp, " -L%s", act_elem->str);
}
act_elem = act_elem->next;
}
}
fprintf(fp, " \\\n"
"\t-L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \\\n"
"\tthen : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi\n");
}
else { // new linking strategy
fputs (" \\\n", fp);
if (makefile->linkerlibraries && !makefile->library) {
struct string2_list* head = getLinkerLibs(makefile->project_name);
struct string2_list* act_elem = head;
while (act_elem) {
if (act_elem->str1 && act_elem->str2) {
fprintf(fp, "\t-L%s -Wl,-rpath=%s -l%s \\\n", act_elem->str1, act_elem->str1, act_elem->str2);
}
act_elem = act_elem->next;
}
free_string2_list(head);
struct string_list* act_head = getExternalLibPaths(makefile->project_name);
struct string_list* act_ext_elem = act_head;
while (act_ext_elem) {
if (act_ext_elem->str) {
fprintf(fp, "\t-L%s \\\n", act_ext_elem->str);
}
act_ext_elem = act_ext_elem->next;
}
free_string_list(act_head);
act_head = getExternalLibs(makefile->project_name);
act_ext_elem = act_head;
while (act_ext_elem) {
if (act_ext_elem->str) {
fprintf(fp, "\t-l%s \\\n", act_ext_elem->str);
}
act_ext_elem = act_ext_elem->next;
}
free_string_list(act_head);
}
fprintf(fp,
"\t-L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \\\n"
"\tthen : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi\n");
}
/* If the compiler will not be run because there are no TTCN(PP) or ASN.1
* files, create the "compile" marker file which is checked by the
* superior makefile if using this project as central storage */
if (!run_compiler) fputs("\ttouch compile\n", fp);
/* End of target $(EXECUTABLE) */
/* target $(LIBRARY) */
if (makefile->dynamic) {
fprintf(fp, "\n"
"$(LIBRARY): $(OBJECTS)%s\n"
"\t$(CXX) -shared -o $@ $(OBJECTS)",
makefile->hierarchical ? " $(BASE2_LIBRARY)" : "");
if (makefile->central_storage && !makefile->linkingStrategy) {
fputs(" $(BASE_SHARED_OBJECTS) ;\n"
"\tln -s $@ $(subst lib, ,$@) > /dev/null 2>&1 ;", fp);
}
if (makefile->linkingStrategy) {
struct string2_list* head = getLinkerLibs(makefile->project_name);
struct string2_list* act_elem = head;
// If the project is Executable on Top Level the linker can link the *.a and *.so together
while (act_elem && !isTopLevelExecutable(makefile->project_name)) {
if (act_elem->str1 && act_elem->str2 && isDynamicLibrary(act_elem->str2)) {
fputs(" \\\n", fp);
fprintf(fp, "\t-L%s -Wl,-rpath=%s -l%s", act_elem->str1, act_elem->str1, act_elem->str2);
}
else {
const char* mainLibName = getLibFromProject(makefile->project_name);
ERROR("Library archive 'lib%s.a' cannot be linked to dynamic library 'lib%s.so' "
"in project '%s' ",
act_elem->str2, mainLibName ? mainLibName : "", makefile->project_name);
free_string2_list(head);
exit(EXIT_FAILURE);
}
act_elem = act_elem->next;
}
free_string2_list(head);
struct string_list* act_head = getExternalLibPaths(makefile->project_name);
struct string_list* act_ext_elem = act_head;
while (act_ext_elem) {
if (act_ext_elem->str) {
fputs(" \\\n", fp);
fprintf(fp, "\t-L%s", act_ext_elem->str);
}
act_ext_elem = act_ext_elem->next;
}
free_string_list(act_head);
act_head = getExternalLibs(makefile->project_name);
act_ext_elem = act_head;
while (act_ext_elem) {
if (act_ext_elem->str) {
fputs(" \\\n", fp);
fprintf(fp, "\t-l%s", act_ext_elem->str);
}
act_ext_elem = act_ext_elem->next;
}
free_string_list(act_head);
}
}
else { // static linking
fprintf(fp, "\n"
"$(LIBRARY): $(OBJECTS)%s\n"
"\t$(AR) -r%s $(ARFLAGS) $(LIBRARY) $(OBJECTS)",
makefile->hierarchical ? " $(BASE2_LIBRARY)" : "",
makefile->linkingStrategy ? "cT" : "");
if (makefile->central_storage && !makefile->linkingStrategy) {
fputs(" $(BASE_OBJECTS)", fp);
}
if (makefile->linkingStrategy) {
if ( makefile->library) {
struct string2_list* head = getLinkerLibs(makefile->project_name);
struct string2_list* act_elem = head;
while (act_elem) {
if (act_elem->str2 && !isDynamicLibrary(act_elem->str2)) {
fputs(" \\\n", fp);
fprintf(fp, "\t%s/lib%s.a", act_elem->str1, act_elem->str2);
}
else {
const char* mainLibName = getLibFromProject(makefile->project_name);
if (act_elem->str2) {
ERROR("Dynamic library 'lib%s.so' cannot be linked to static library 'lib%s.a' "
"in project '%s' ",
act_elem->str2, mainLibName ? mainLibName : "", makefile->project_name);
exit(EXIT_FAILURE);
}
else {
struct string_list* ext_libs = getExternalLibs(makefile->project_name);
if (ext_libs && ext_libs->str) {
ERROR("Third party dynamic library '%s' cannot be linked to static library 'lib%s.a' "
"in project '%s' ", ext_libs->str,
mainLibName ? mainLibName : "", makefile->project_name);
free_string_list(ext_libs);
exit(EXIT_FAILURE);
}
free_string_list(ext_libs);
}
}
act_elem = act_elem->next;
}
free_string2_list(head);
struct string_list* act_head = getExternalLibs(makefile->project_name);
struct string_list* act_ext_elem = act_head;
while (act_ext_elem) {
if (act_ext_elem->str && hasExternalLibrary(act_ext_elem->str, makefile->project_name)) {
fputs(" \\\n", fp);
fprintf(fp, "\tlib%s.a", act_ext_elem->str);
ERROR("linking static 3d party or system library 'lib%s.a' to "
"project library 'lib%s.a' is not supported ",
act_ext_elem->str, makefile->ets_name);
exit(EXIT_FAILURE);
}
act_ext_elem = act_ext_elem->next;
}
free_string_list(act_head);
}
}
}
fputs("\n\n.cc.o .c.o:\n"
"\t$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $<\n\n", fp);
if (makefile->gcc_dep) {
fputs(".cc.d .c.d:\n"
"\t@echo Creating dependency file for '$<'; set -e; \\\n"
"\t$(CXX) $(CXXDEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $< \\\n"
"\t| sed 's/\\($*\\)\\.o[ :]*/\\1.o $@ : /g' > $@; \\\n"
"\t[ -s $@ ] || rm -f $@\n\n", fp);
/* "set -e" causes bash to exit the script if any statement
* returns nonzero (failure).
* The sed line transforms the first line of the dependency from
* "x.o: x.cc" to "x.o x.d: x.cc", making the dependency file depend
* on the source and headers.
* [ -s x.d ] checks that the generated dependency is not empty;
* otherwise it gets deleted.
*/
}
if (makefile->dynamic) {
fputs("%.so: %.o\n"
"\t$(CXX) -shared -o $@ $<\n\n", fp);
}
if (makefile->preprocess) {
fputs("%.ttcn: %.ttcnpp $(TTCN3_INCLUDES)\n"
"\t$(CPP) -x c -nostdinc $(CPPFLAGS_TTCN3) $< $@\n\n"
"preprocess: $(PREPROCESSED_TTCN3_MODULES) ;\n\n", fp);
}
boolean merge_profiled_file_lists = makefile->profiled_file_list
&& makefile->profiled_file_list->next && !makefile->central_storage;
if (makefile->central_storage) {
boolean is_first = TRUE;
fprintf(fp, "$(GENERATED_SOURCES) $(GENERATED_HEADERS):%s compile-all compile ",
makefile->hierarchical ? " update" : "");
if (add_refd_prjs) fputs("referenced-dep", fp);
/* These extra compile dependencies for the generated .cc are here to
* check if all the referenced projects are up to date.
* If the referenced projects are built too then they are not needed
* (and cause problems as the included .d depends on the .cc).
*/
if (!add_refd_prjs) for (i = 0; i < makefile->nBaseDirs; i++) {
const struct base_dir_struct *base_dir = makefile->BaseDirs + i;
if (base_dir->has_modules) {
if (is_first) {
fputs(" \\\n", fp);
is_first = FALSE;
}
else putc(' ', fp);
fprintf(fp, "%s/compile", base_dir->dir_name);
}
}
if (makefile->preprocess) {
fprintf(fp, "\n"
"\t@if [ ! -f $@ ]; then %s compile-all; $(MAKE) compile-all; fi\n"
"\n"
"check:%s $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
"\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
"%s\\\n"
"\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n"
"\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ",
rm_command, add_refd_prjs?" referenced-check":"",
makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
if (makefile->gnu_make) {
if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul
fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
"\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
"%s\\\n"
"\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n",
makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
else
fputs("$^", fp);
}
else {
fputs("\\\n"
"\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n"
"\t$(PREPROCESSED_TTCN3_MODULES) "
"$(BASE_PREPROCESSED_TTCN3_MODULES) \\\n"
"\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)", fp);
}
fprintf(fp, "\n\n"
"port: $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
"\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
"%s\n"
"\t$(TTCN3_DIR)/bin/compiler -t $(COMPILER_FLAGS) ",
makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"");
if (makefile->gnu_make) {
if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul
fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
"\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
"%s\n",
makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"");
else
fputs("$^", fp);
}
else {
fputs("\\\n"
"\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n"
"\t$(PREPROCESSED_TTCN3_MODULES) "
"$(BASE_PREPROCESSED_TTCN3_MODULES) \n", fp);
}
if (makefile->linkingStrategy && makefile->hierarchical) {
fputs("\n\n"
"update: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) \\\n"
"\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) $(BASE2_PREPROCESSED_TTCN3_MODULES)\n"
"ifneq ($(wildcard $(GENERATED_SOURCES)), ) \n"
"ifeq ($(wildcard $?), ) \n"
"\ttouch compile-all; \n"
"\ttouch update; \n"
"endif\n"
"endif",fp);
}
if (makefile->profiled_file_list) {
fputs("\n\n"
"compile:: $(PROFILED_FILE_LIST)\n"
"\ttouch $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) "
"$(ASN1_MODULES)", fp);
}
fprintf(fp, "\n\n"
"compile:%s $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) "
"$(ASN1_MODULES)\n"
"\t@echo \"compiling \"'$(patsubst %%.tpd, %%, $(TPD))';\n"
"\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
"\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
"\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) %s\\\n"
"\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s - $?\n"
"\ttouch $@\n\n",
makefile->profiled_file_list ? ":" : "",
makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES)":"");
fprintf (fp,
"compile-all: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
"%s"
"\t$(MAKE) preprocess\n"
"\t@echo \"compiling all \"'$(patsubst %%.tpd, %%, $(TPD))';\n"
"\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
"\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
"\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) %s"
"\\\n"
"\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
"\t- $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES)\n"
"\ttouch $@ compile\n\n",
makefile->linkingStrategy ? "\\\n\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) "
"$(BASE2_PREPROCESSED_TTCN3_MODULES) \n":"\n",
makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
}
else {
fprintf(fp, "\n"
"\t@if [ ! -f $@ ]; then %s compile-all; $(MAKE) compile-all; fi\n", rm_command);
fprintf(fp, "\n"
"check:%s $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
"\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n"
"\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ",
add_refd_prjs?" referenced-check":"",
makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
if (makefile->gnu_make) {
if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul
fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
"\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n",
makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
else
fputs("$^", fp);
}
else {
fputs("\\\n"
"\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n"
"\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)", fp);
}
fprintf(fp, "\n\n"
"port: $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\n"
"\t$(TTCN3_DIR)/bin/compiler -t $(COMPILER_FLAGS) ",
makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"");
if (makefile->gnu_make) {
if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul
fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\n",
makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"");
else
fputs("$^", fp);
}
else {
fputs("\\\n"
"\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \n", fp);
}
if (makefile->linkingStrategy && makefile->hierarchical) {
fputs("\n\n"
"update: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) \\\n"
"\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) $(BASE2_PREPROCESSED_TTCN3_MODULES)\n"
"ifneq ($(wildcard $(GENERATED_SOURCES)), ) \n"
"ifeq ($(wildcard $?), ) \n"
"\ttouch compile-all; \n"
"\ttouch update; \n"
"endif\n"
"endif",fp);
}
if (makefile->profiled_file_list) {
fputs("\n\n"
"compile:: $(PROFILED_FILE_LIST)\n"
"\ttouch $(TTCN3_MODULES) $(ASN1_MODULES)", fp);
}
fprintf(fp, "\n\n"
"compile:%s $(TTCN3_MODULES) $(ASN1_MODULES)\n"
"\t@echo \"compiling \"'$(patsubst %%.tpd, %%, $(TPD))';\n"
"\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
"\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
"\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
"\t- $?\n"
"\ttouch $@\n\n",
makefile->profiled_file_list ? ":" : "",
makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "",
makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : "");
fprintf(fp,
"compile-all: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) %s\n",
makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES)" : "");
fputs("\t@echo \"compiling all \"'$(patsubst %.tpd, %, $(TPD))';\n", fp);
fprintf(fp,"\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
"\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
"\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
"\t- $(TTCN3_MODULES) $(ASN1_MODULES)\n"
"\ttouch $@ compile\n\n",
makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "",
makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : "");
}
if (!makefile->hierarchical)
for (i = 0; i < makefile->nBaseDirs; i++) {
const struct base_dir_struct *base_dir = makefile->BaseDirs + i;
if (base_dir->has_modules) {
size_t j;
fprintf(fp, "%s/compile:", base_dir->dir_name);
for (j = 0; j < makefile->nTTCN3Modules; j++) {
const struct module_struct *module = makefile->TTCN3Modules + j;
if (module->dir_name != NULL &&
!strcmp(base_dir->dir_name, module->dir_name))
print_file_name(fp, module);
}
for (j = 0; j < makefile->nTTCN3PPModules; j++) {
const struct module_struct *module = makefile->TTCN3PPModules + j;
if (module->dir_name != NULL &&
!strcmp(base_dir->dir_name, module->dir_name))
print_file_name(fp, module);
}
for (j = 0; j < makefile->nASN1Modules; j++) {
const struct module_struct *module = makefile->ASN1Modules + j;
if (module->dir_name != NULL &&
!strcmp(base_dir->dir_name, module->dir_name))
print_file_name(fp, module);
}
fprintf(fp, "\n"
"\t@echo 'Central directory %s is not up-to-date!'\n"
"\t@exit 2\n\n", base_dir->dir_name);
}
}
}
else { /* not central storage */
fprintf(fp, "$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile\n"
"\t@if [ ! -f $@ ]; then %s compile; $(MAKE) compile; fi\n\n"
"%s"
"check:%s $(TTCN3_MODULES) ", rm_command,
merge_profiled_file_lists ? "check:: $(PROFILED_FILE_LIST)\n\n" : "",
merge_profiled_file_lists ? ":" : "");
if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
fputs("$(ASN1_MODULES)\n"
"\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ", fp);
if (makefile->gnu_make) fputs("$^", fp);
else {
fputs("\\\n"
"\t$(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES)",
fp);
}
fputs("\n\n", fp);
fprintf(fp, "port: $(TTCN3_MODULES) ");
if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
fputs("\n", fp);
fputs("\t$(TTCN3_DIR)/bin/compiler -t $(COMPILER_FLAGS) ", fp);
if (makefile->gnu_make) fputs("$^", fp);
else {
fputs("\\\n"
"\t$(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES)",
fp);
}
if (makefile->profiled_file_list) {
fputs("\n\ncompile:: $(PROFILED_FILE_LIST)\n"
"\ttouch $(TTCN3_MODULES) ", fp);
if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
fputs("$(ASN1_MODULES)", fp);
}
fprintf(fp, "\n\n"
"compile:%s $(TTCN3_MODULES) ", makefile->profiled_file_list ? ":" : "");
if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
fputs("$(ASN1_MODULES)\n"
"\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) ", fp);
if (makefile->gnu_make) fputs("$^", fp);
else {
fputs("\\\n"
"\t$(TTCN3_MODULES) ", fp);
if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
fputs("$(ASN1_MODULES)", fp);
}
fputs(" - $?\n"
"\ttouch $@\n"
"\n", fp);
if (merge_profiled_file_lists) {
fputs("$(PROFILED_FILE_LIST): $(PROFILED_FILE_LIST_SEGMENTS)\n"
"\tcat $(PROFILED_FILE_LIST_SEGMENTS) > $(PROFILED_FILE_LIST)\n\n", fp);
}
}
// clean:
if (makefile->linkingStrategy) {
fprintf(fp, "clean:%s\n", (add_refd_prjs && !makefile->hierarchical) ?
" referenced-clean" : "");
if (makefile->dynamic && (makefile->central_storage || makefile->linkingStrategy)) {
fprintf(fp,"\tfind . -type l -name \"*.so\" -exec unlink {} \\;\n");
}
fprintf(fp, "\t%s $(EXECUTABLE) $(DYNAMIC_LIBRARY) $(STATIC_LIBRARY) "
"$(OBJECTS) $(GENERATED_HEADERS) \\\n"
"\t$(GENERATED_SOURCES) ", rm_command);
if (makefile->dynamic) fputs("$(SHARED_OBJECTS) ", fp);
if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
fputs("compile", fp);
if (makefile->central_storage) fputs(" compile-all", fp);
if (makefile->gcc_dep) fputs(" $(DEPFILES)", fp);
if (merge_profiled_file_lists) {
fputs(" $(PROFILED_FILE_LIST)", fp);
}
fprintf(fp, " \\\n"
"\ttags *.log%s%s\n\n",
add_refd_prjs?" referenced*":"",
makefile->hierarchical ? " update":"");
}
else {
fprintf(fp, "clean:%s\n"
"\t-%s $(EXECUTABLE) $(LIBRARY) $(OBJECTS) $(GENERATED_HEADERS) \\\n"
"\t$(GENERATED_SOURCES) ", add_refd_prjs?" referenced-clean":"", rm_command);
if (makefile->dynamic) fputs("$(SHARED_OBJECTS) ", fp);
if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
fputs("compile", fp);
if (makefile->central_storage) fputs(" compile-all", fp);
if (makefile->gcc_dep) fputs(" $(DEPFILES)", fp);
if (merge_profiled_file_lists) {
fputs(" $(PROFILED_FILE_LIST)", fp);
}
fprintf(fp, " \\\n"
"\ttags *.log%s",
add_refd_prjs?" referenced*":"");
}
// clean-all:
if (makefile->linkingStrategy && makefile->hierarchical)
fprintf(fp, "clean-all: %s clean\n", add_refd_prjs ? "referenced-clean-all":"");
// dep:
fputs("\n\ndep: $(GENERATED_SOURCES) $(USER_SOURCES)",fp);
if (add_refd_prjs) {
fprintf(fp, "\n\t%s referenced-dep", rm_command);
}
else fputs(" ;",fp);
if (makefile->gcc_dep) {
fprintf(fp, " \n\n"
"ifeq ($(findstring n,$(MAKEFLAGS)),)\n"
"ifeq ($(filter clean%s check port compile archive diag%s,$(MAKECMDGOALS)),)\n"
"-include $(DEPFILES)\n"
"endif\n"
"endif",
(makefile->linkingStrategy && makefile->hierarchical) ? " clean-all" : "",
(makefile->preprocess ? " preprocess" : ""));
/* Don't include .d files when cleaning etc.; make will try to build them
* and this involves running the Titan compiler. Same for preprocess.
* The check target would be pointless if running the compiler
* without generating code was always preceded by running the compiler
* _and_ generating C++ code. */
}
else { /* old-style dep with makedepend. Do not check compiler version. */
fputs("\n\tmakedepend $(CPPFLAGS) -DMAKEDEPEND_RUN ", fp);
if (makefile->gnu_make) fputs("$^", fp);
else fputs("$(GENERATED_SOURCES) $(USER_SOURCES)", fp);
}
if (makefile->linkingStrategy) {
fputs("\n\n"
"archive:\n"
"\t@perl $(TTCN3_DIR)/bin/ttcn3_archive\n\n", fp);
}
else {
fputs("\n\n"
"archive:\n"
"\tmkdir -p $(ARCHIVE_DIR)\n"
"\ttar -cvhf - ", fp);
if (makefile->central_storage) {
fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n",
makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "");
if (makefile->preprocess) {
fprintf(fp, "\t$(TTCN3_PP_MODULES) $(BASE_TTCN3_PP_MODULES) "
"%s $(TTCN3_INCLUDES) \\\n",
makefile->linkingStrategy ? "$(BASE2_TTCN3_PP_MODULES)" : "");
}
fprintf(fp, "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
"\t$(USER_HEADERS) $(BASE_USER_HEADERS) %s\\\n"
"\t$(USER_SOURCES) $(BASE_USER_SOURCES) %s",
makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : "",
makefile->linkingStrategy ? "$(BASE2_USER_HEADERS) " : "",
makefile->linkingStrategy ? "$(BASE2_USER_SOURCES)" : "");
}
else {
fputs("$(TTCN3_MODULES) ", fp);
if (makefile->preprocess) {
fputs("$(TTCN3_PP_MODULES) \\\n"
"\t$(TTCN3_INCLUDES) ", fp);
}
fputs("$(ASN1_MODULES) \\\n"
"\t$(USER_HEADERS) $(USER_SOURCES)", fp);
}
fputs(" $(OTHER_FILES) \\\n"
"\t| gzip >$(ARCHIVE_DIR)/`basename $(TARGET) .exe`-"
"`date '+%y%m%d-%H%M'`.tgz\n\n", fp);
}
fprintf(fp, "diag:\n"
"\t$(TTCN3_DIR)/bin/compiler -v 2>&1\n"
"\t$(TTCN3_DIR)/bin/mctr_cli -v 2>&1\n"
"\t$(CXX) -v 2>&1\n"
"%s"
"\t@echo TTCN3_DIR=$(TTCN3_DIR)\n"
"\t@echo OPENSSL_DIR=$(OPENSSL_DIR)\n"
"\t@echo XMLDIR=$(XMLDIR)\n"
"\t@echo PLATFORM=$(PLATFORM)\n\n",
makefile->dynamic ? "" : "\t$(AR) -V 2>&1\n");
if (add_refd_prjs) {
fprintf(fp, "referenced-all referenced-shared_objects referenced-executable referenced-library \\\n"
"referenced-objects referenced-check \\\n"
"referenced-clean%s:\n"
"\t@for dir in $(REFERENCED_PROJECT_DIRS); do \\\n"
"\t $(MAKE) -C $$dir $(subst referenced-,,$@) || exit; \\\n"
"\tdone; \n\n",
(makefile->linkingStrategy && makefile->hierarchical) ? "-all" : "");
fputs("referenced-dep:\n"
"\t@for dir in $(REFERENCED_PROJECT_DIRS); do \\\n"
"\t $(MAKE) -C $$dir $(subst referenced-,,$@) || exit; \\\n"
"\tdone; \n"
"\ttouch $@\n\n", fp);
}
if (makefile->generatorCommandOutput) {
fputs("### Project specific rules generated by user written script:\n\n", fp);
fputs(makefile->generatorCommandOutput, fp);
fputs("\n### End of project specific rules.\n\n", fp);
}
fputs("#\n"
"# Add your rules here if necessary...\n"
"#\n\n", fp);
fclose(fp);
if (strcmp(makefile->output_file, "Makefile")) {
NOTIFY("Makefile skeleton was written to `%s'.", makefile->output_file);
} else {
NOTIFY("Makefile skeleton was generated.");
}
}
else {
ERROR("Output file `%s' already exists. Use switch `%s' to force "
"overwrite.",
makefile->output_file,
makefile->linkingStrategy ? "-F" : "-f");
}
}
#undef COMMENT_PREFIX
#define COMMENT_PREFIX
/** run makefilegen commans for sub-projects */
static void run_makefilegen_commands(struct string2_list* run_command_list)
{
struct string2_list* act_elem = run_command_list;
while (act_elem) {
struct string2_list* next_elem = act_elem->next;
/* run commands if there were no ERRORs */
if ((error_count == 0) && act_elem->str1 && act_elem->str2) {
int rv;
char* sub_proj_effective_work_dir = act_elem->str1;
char* command = act_elem->str2;
char* orig_dir = get_working_dir();
rv = set_working_dir(sub_proj_effective_work_dir);
if (rv) ERROR("Could not set working dir to `%s'", sub_proj_effective_work_dir);
else {
fprintf(stderr, "Executing `%s' in working directory `%s'...\n",
command, sub_proj_effective_work_dir);
rv = system(command);
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
}
rv = set_working_dir(orig_dir);
if (rv) ERROR("Could not restore working dir to `%s'", orig_dir);
Free(orig_dir);
}
Free(act_elem->str1);
Free(act_elem->str2);
Free(act_elem);
act_elem = next_elem;
}
}
/** create symlinks and delete list */
static void generate_symlinks(struct string2_list* create_symlink_list)
{
struct string2_list* act_elem = create_symlink_list;
while (act_elem) {
struct string2_list* next_elem = act_elem->next;
/* create symlinks if there were no ERRORs */
if ((error_count == 0) && act_elem->str1 && act_elem->str2) {
int fail = symlink(act_elem->str1, act_elem->str2);
if (fail) perror(act_elem->str2); /* complain but do not call ERROR() */
}
Free(act_elem->str1);
Free(act_elem->str2);
Free(act_elem);
act_elem = next_elem;
}
}
/** Performs all tasks of Makefile generation based on the given list of
* modules/files (taken from the command line) and options that represent
* command line switches. */
static void generate_makefile(size_t n_arguments, char *arguments[],
size_t n_other_files, const char *other_files[], const char *output_file,
const char *ets_name, char *project_name, boolean gnu_make, boolean single_mode,
boolean central_storage, boolean absolute_paths, boolean preprocess,
boolean dump_makefile_data, boolean force_overwrite, boolean use_runtime_2,
boolean dynamic, boolean makedepend, boolean coverage,
const char *code_splitting_mode, const char *tcov_file_name, struct string_list* profiled_file_list,
boolean Lflag, boolean Zflag, boolean Hflag, struct string_list* sub_project_dirs, struct string_list* ttcn3_prep_includes,
struct string_list* ttcn3_prep_defines, struct string_list* ttcn3_prep_undefines, struct string_list* prep_includes,
struct string_list* prep_defines, struct string_list* prep_undefines, boolean codesplittpd, boolean quietly, boolean disablesubtypecheck,
const char* cxxcompiler, const char* optlevel, const char* optflags, boolean disableber, boolean disableraw, boolean disabletext,
boolean disablexer, boolean disablejson, boolean forcexerinasn, boolean defaultasomit, boolean gccmsgformat,
boolean linenumbersonlymsg, boolean includesourceinfo, boolean addsourcelineinfo, boolean suppresswarnings,
boolean outparamboundness, boolean omit_in_value_list, boolean warnings_for_bad_variants, boolean activate_debugger,
boolean disable_predef_ext_folder, struct string_list* solspeclibraries,
struct string_list* sol8speclibraries, struct string_list* linuxspeclibraries, struct string_list* freebsdspeclibraries,
struct string_list* win32speclibraries, const char* ttcn3preprocessor, struct string_list* linkerlibraries,
struct string_list* additionalObjects, struct string_list* linkerlibsearchpath, char* generatorCommandOutput,
struct string2_list* target_placement_list)
{
size_t i;
struct makefile_struct makefile;
init_makefile_struct(&makefile);
makefile.project_name = project_name;
makefile.central_storage = central_storage;
makefile.gnu_make = gnu_make;
makefile.preprocess = preprocess;
makefile.single_mode = single_mode;
makefile.force_overwrite = force_overwrite;
makefile.use_runtime_2 = use_runtime_2;
makefile.dynamic = dynamic;
makefile.gcc_dep = gnu_make && !makedepend;
makefile.coverage = coverage;
makefile.library = Lflag;
makefile.linkingStrategy = Zflag;
makefile.hierarchical = Hflag;
makefile.sub_project_dirs = sub_project_dirs;
makefile.ttcn3_prep_includes = ttcn3_prep_includes;
makefile.ttcn3_prep_defines = ttcn3_prep_defines;
makefile.ttcn3_prep_undefines = ttcn3_prep_undefines;
makefile.prep_includes = prep_includes;
makefile.prep_defines = prep_defines;
makefile.prep_undefines = prep_undefines;
makefile.codesplittpd = codesplittpd;
makefile.quietly = quietly;
makefile.disablesubtypecheck = disablesubtypecheck;
makefile.cxxcompiler = cxxcompiler;
makefile.optlevel = optlevel;
makefile.optflags = optflags;
makefile.disableber = disableber;
makefile.disableraw = disableraw;
makefile.disabletext = disabletext;
makefile.disablexer = disablexer;
makefile.disablejson = disablejson;
makefile.forcexerinasn = forcexerinasn;
makefile.defaultasomit = defaultasomit;
makefile.gccmsgformat = gccmsgformat;
makefile.linenumbersonlymsg = linenumbersonlymsg;
makefile.includesourceinfo = includesourceinfo;
makefile.addsourcelineinfo = addsourcelineinfo;
makefile.suppresswarnings = suppresswarnings;
makefile.outparamboundness = outparamboundness;
makefile.omit_in_value_list = omit_in_value_list;
makefile.warnings_for_bad_variants = warnings_for_bad_variants;
makefile.activate_debugger = activate_debugger;
makefile.disable_predef_ext_folder = disable_predef_ext_folder;
makefile.solspeclibraries = solspeclibraries;
makefile.sol8speclibraries = sol8speclibraries;
makefile.linuxspeclibraries = linuxspeclibraries;
makefile.freebsdspeclibraries = freebsdspeclibraries;
makefile.win32speclibraries = win32speclibraries;
makefile.ttcn3preprocessor = ttcn3preprocessor;
makefile.linkerlibraries = linkerlibraries;
makefile.additionalObjects = additionalObjects;
makefile.linkerlibsearchpath = linkerlibsearchpath;
makefile.generatorCommandOutput = generatorCommandOutput;
makefile.target_placement_list = target_placement_list;
for (i = 0; i < n_arguments; i++) {
char *file_name = get_file_name_for_argument(arguments[i]);
if (file_name != NULL) {
FILE *fp = fopen(file_name, "r");
if (fp != NULL) {
char *module_name;
if (is_ttcn3_module(file_name, fp, &module_name)) {
if (is_asn1_module(file_name, fp, NULL)) {
ERROR("File `%s' looks so strange that it can be both ASN.1 and "
"TTCN-3 module. Add it to the Makefile manually.", file_name);
Free(module_name);
} else {
add_ttcn3_module(&makefile, file_name, module_name);
}
} else if (is_asn1_module(file_name, fp, &module_name)) {
if (is_valid_asn1_filename(file_name)) {
add_asn1_module(&makefile, file_name, module_name);
} else {
ERROR("The file name (without suffix) shall be identical to the module name.\n"
"If the name of the ASN.1 module contains a hyphen, the corresponding "
"file name shall contain an underscore character instead.");
}
} else {
add_user_file(&makefile, file_name);
}
fclose(fp);
} else {
ERROR("Cannot open file `%s' for reading: %s", file_name,
strerror(errno));
errno = 0;
}
Free(file_name);
} else if (get_path_status(arguments[i]) == PS_DIRECTORY) {
ERROR("Argument `%s' is a directory.", arguments[i]);
} else {
ERROR("Cannot find any source file for argument `%s'.", arguments[i]);
}
}
for (i = 0; i < n_other_files; i++) {
char *file_name = get_file_name_for_argument(other_files[i]);
if (file_name != NULL) {
add_path_to_list(&makefile.nOtherFiles, &makefile.OtherFiles, file_name,
makefile.working_dir, TRUE);
Free(file_name);
} else if (get_path_status(other_files[i]) == PS_DIRECTORY) {
ERROR("Argument `%s' given as other file is a directory.",
other_files[i]);
} else {
ERROR("Cannot find any other file for argument `%s'.", other_files[i]);
}
}
if (ets_name != NULL) {
char *dir_name = get_dir_name(ets_name, makefile.working_dir);
char *file_name = get_file_from_path(ets_name);
makefile.ets_name = compose_path_name(dir_name, file_name);
Free(dir_name);
Free(file_name);
}
if (code_splitting_mode != NULL) {
makefile.code_splitting_mode = mputprintf(makefile.code_splitting_mode, "-U %s", code_splitting_mode);
}
if (tcov_file_name != NULL) {
makefile.tcov_file_name = mprintf(" -K %s", tcov_file_name);
}
if (profiled_file_list != NULL) {
makefile.profiled_file_list = profiled_file_list;
}
if (makefile.nTTCN3Modules >= 1) {
if (makefile.ets_name == NULL)
makefile.ets_name = mcopystr(makefile.TTCN3Modules[0].module_name);
} else if (preprocess && (makefile.nTTCN3PPModules >= 1)) {
if (makefile.ets_name == NULL)
makefile.ets_name = mcopystr(makefile.TTCN3PPModules[0].module_name);
} else if (makefile.nASN1Modules >= 1) {
WARNING("No TTCN-3 module was given for the Makefile.");
if (makefile.ets_name == NULL)
makefile.ets_name = mcopystr(makefile.ASN1Modules[0].module_name);
} else if (makefile.nUserFiles > 0) {
WARNING("No TTCN-3 or ASN.1 module was given for the Makefile.");
if (makefile.ets_name == NULL)
makefile.ets_name = mcopystr(makefile.UserFiles[0].file_prefix);
} else {
WARNING("No source files were given for the Makefile");
}
if (output_file != NULL) {
if (get_path_status(output_file) == PS_DIRECTORY)
makefile.output_file = mprintf("%s/Makefile", output_file);
else makefile.output_file = mcopystr(output_file);
} else makefile.output_file = mcopystr("Makefile");
add_path_to_list(&makefile.nOtherFiles, &makefile.OtherFiles,
makefile.output_file, makefile.working_dir, FALSE);
if (preprocess) check_preprocessed_filename_collision(&makefile);
filter_out_generated_files(&makefile);
complete_user_files(&makefile);
if (!absolute_paths) convert_dirs_to_relative(&makefile);
check_special_chars(&makefile);
if (central_storage) collect_base_dirs(&makefile);
check_naming_convention(&makefile);
if (dump_makefile_data) dump_makefile_struct(&makefile, 0);
if (error_count == 0) print_makefile(&makefile);
free_makefile_struct(&makefile);
}
#ifdef COVERAGE_BUILD
#define C_flag "C"
#else
#define C_flag
#endif
static void usage(void)
{
fprintf(stderr, "\n"
"usage: %s [-abc" C_flag "dDEfFglLmMnprRstTVwWXZ] [-K file] [-z file ] [-P dir]"
" [-U none|type] [-e ets_name] [-o dir|file]\n"
" [-t project_descriptor.tpd [-b buildconfig]]\n"
" [-O file] ... module_name ... testport_name ...\n"
" or %s -v\n"
"\n"
"OPTIONS:\n"
" -a: use absolute pathnames in the generated Makefile\n"
" -c: use the pre-compiled files from central directories\n"
#ifdef COVERAGE_BUILD
" -C: enable coverage of generated C++ code\n"
#endif
" -d: dump the data used for Makefile generation\n"
" -e ets_name: name of the target executable\n"
" -E: display only warnings for unrecognized encoding variants\n"
" -f: force overwriting of the output Makefile\n"
" -g: generate Makefile for use with GNU make\n"
" -I path: Add path to the search paths when using TPD files\n"
" -K file: enable selective code coverage\n"
" -l: use dynamic linking\n"
" -L: create makefile with library archive as the default target\n"
" -m: always use makedepend for dependencies\n"
" -M: allow 'omit' in template value lists (legacy behavior)\n"
" -n: activate debugger (generates extra code for debugging)\n"
" -o dir|file: write the Makefile to the given directory or file\n"
" -O file: add the given file to the Makefile as other file\n"
" -p: generate Makefile with TTCN-3 preprocessing\n"
" -R: use function test runtime (TITAN_RUNTIME_2)\n"
" -s: generate Makefile for single mode\n"
" -U none|type: split generated code\n"
" -v: show version\n"
" -w: suppress warnings\n"
" -Y: Enforces legacy behaviour of the \"out\" function parameters (see refguide)\n"
" -z file: enable profiling and code coverage for the TTCN-3 files in the argument\n"
"Options for processing the Titan Project Descriptor file(s):\n"
" -t tpd: read project descriptor file\n"
" -b buildconfig: use the specified build config instead of the default\n"
" -D: use current directory as working directory\n"
" -V: disable validation of TPD file with schema\n"
" -r: generate Makefile hierarchy for TPD hierarchy (recursive)\n"
" -F: force overwriting of all generated Makefiles, use with -r\n"
" -T: generate only top-level Makefile of the hierarchy, use with -r\n"
" -P dir: prints out a file list found in a given TPD relative to the given directory\n"
" -X: generate XML file that describes the TPD hierarchy, use with -r\n"
" -W: prefix working directories with project name\n"
" -Z: recursive Makefile generation from TPD using object files and dynamic libraries too\n"
" -H: hierachical Makefile generation from TPD use with -Z\n"
, program_name, program_name);
}
#define SET_FLAG(x) if (x##flag) {\
ERROR("Flag -" #x " was specified more than once.");\
error_flag = TRUE;\
} else x##flag = TRUE
void free_string_list(struct string_list* act_elem)
{
while (act_elem) {
struct string_list* next_elem = act_elem->next;
Free(act_elem->str);
Free(act_elem);
act_elem = next_elem;
}
}
void free_string2_list(struct string2_list* act_elem)
{
while (act_elem) {
struct string2_list* next_elem = act_elem->next;
Free(act_elem->str1);
Free(act_elem->str2);
Free(act_elem);
act_elem = next_elem;
}
}
int main(int argc, char *argv[])
{
boolean
aflag = FALSE, bflag = FALSE, cflag = FALSE, Cflag = FALSE,
dflag = FALSE, eflag = FALSE, fflag = FALSE, gflag = FALSE,
oflag = FALSE, Kflag = FALSE, lflag = FALSE, pflag = FALSE,
Pflag = FALSE, Rflag = FALSE, sflag = FALSE, tflag = FALSE,
wflag = FALSE, vflag = FALSE, mflag = FALSE, Uflag = FALSE,
Lflag = FALSE, rflag = FALSE, Fflag = FALSE, Xflag = FALSE,
Tflag = FALSE, Yflag = FALSE, csflag = FALSE, quflag = FALSE,
dsflag = FALSE, dbflag = FALSE, drflag = FALSE, dtflag = FALSE,
dxflag = FALSE, fxflag = FALSE, doflag = FALSE,
gfflag = FALSE, lnflag = FALSE, isflag = FALSE, asflag = FALSE,
swflag = FALSE, Vflag = FALSE, Dflag = FALSE, Wflag = FALSE,
djflag = FALSE, Zflag = FALSE, Hflag = FALSE, Mflag = FALSE,
diflag = FALSE, zflag = FALSE, Eflag = FALSE, nflag = FALSE;
boolean error_flag = FALSE;
char *output_file = NULL;
char *ets_name = NULL;
char *project_name = NULL;
size_t n_other_files = 0;
const char **other_files = NULL;
const char *code_splitting_mode = NULL;
const char *tpd_file_name = NULL;
const char *tpd_build_config = NULL;
const char *tcov_file_name = NULL;
size_t n_search_paths = 0;
const char **search_paths = NULL;
struct string_list* profiled_file_list = NULL;
const char *profiled_file_list_zflag = NULL;
const char *file_list_path = NULL;
enum tpd_result tpd_processed = FALSE;
struct string_list* sub_project_dirs = NULL;
struct string2_list* create_symlink_list = NULL;
struct string_list* ttcn3_prep_includes = NULL;
struct string_list* ttcn3_prep_defines = NULL;
struct string_list* ttcn3_prep_undefines = NULL;
struct string_list* prep_includes = NULL;
struct string_list* prep_defines = NULL;
struct string_list* prep_undefines = NULL;
char *cxxcompiler = NULL;
char *optlevel = NULL;
char *optflags = NULL;
struct string_list* solspeclibraries = NULL;
struct string_list* sol8speclibraries = NULL;
struct string_list* linuxspeclibraries = NULL;
struct string_list* freebsdspeclibraries = NULL;
struct string_list* win32speclibraries = NULL;
char *ttcn3prep = NULL;
struct string_list* linkerlibraries = NULL;
struct string_list* additionalObjects = NULL;
struct string_list* linkerlibsearchpath = NULL;
char* generatorCommandOutput = NULL;
struct string2_list* target_placement_list = NULL;
struct string2_list* run_command_list = NULL;
struct string2_list* required_configs = NULL;
#ifdef LICENSE
license_struct lstr;
int valid_license;
#endif
program_name = argv[0];
if (argc == 1) {
fputs("Makefile Generator for the TTCN-3 Test Executor, version "
PRODUCT_NUMBER "\n", stderr);
usage();
return EXIT_FAILURE;
}
for ( ; ; ) {
int c = getopt(argc, argv, "O:ab:c" C_flag "dDe:EfFgI:K:o:lLmMnpP:rRst:TU:vVwWXYz:ZH");
if (c == -1) break;
switch (c) {
case 'O':
n_other_files++;
other_files = (const char**)
Realloc(other_files, n_other_files * sizeof(*other_files));
other_files[n_other_files - 1] = optarg;
break;
case 'I':
n_search_paths++;
search_paths = (const char**)
Realloc(search_paths, n_search_paths * sizeof(*search_paths));
search_paths[n_search_paths - 1] = optarg;
break;
case 'a':
SET_FLAG(a);
break;
case 'b':
SET_FLAG(b);
tpd_build_config = optarg;
break;
case 'c':
SET_FLAG(c);
break;
case 'K':
SET_FLAG(K);
tcov_file_name = optarg;
break;
#ifdef COVERAGE_BUILD
case 'C':
SET_FLAG(C);
break;
#endif
case 'd':
SET_FLAG(d);
break;
case 'D':
SET_FLAG(D);
break;
case 'e':
SET_FLAG(e);
ets_name = optarg;
break;
case 'E':
SET_FLAG(E);
break;
case 'f':
SET_FLAG(f);
break;
case 'F':
SET_FLAG(F);
break;
case 'g':
SET_FLAG(g);
break;
case 'H':
SET_FLAG(H);
break;
case 'o':
SET_FLAG(o);
output_file = optarg;
break;
case 'l':
SET_FLAG(l);
break;
case 'L':
SET_FLAG(L);
break;
case 'm':
SET_FLAG(m);
break;
case 'M':
SET_FLAG(M);
break;
case 'n':
SET_FLAG(n);
break;
case 'p':
SET_FLAG(p);
break;
case 'P':
SET_FLAG(P);
/* Optional arguments with `::' are GNU specific... */
if (get_path_status(optarg) == PS_DIRECTORY) {
file_list_path = optarg;
} else {
ERROR("The -P flag requires a valid directory as its argument "
"instead of `%s'", optarg);
error_flag = TRUE;
}
break;
case 'r':
SET_FLAG(r);
break;
case 'R':
SET_FLAG(R);
break;
case 's':
SET_FLAG(s);
break;
case 't':
SET_FLAG(t);
tpd_file_name = optarg;
break;
case 'T':
SET_FLAG(T);
break;
case 'Y':
SET_FLAG(Y);
break;
case 'U':
SET_FLAG(U);
code_splitting_mode = optarg;
if (strcmp(optarg, "none") != 0 &&
strcmp(optarg, "type") != 0)
ERROR("Unrecognizable argument: '%s'. Valid options for -U switch are: "
"'none', 'type'", optarg);
break;
case 'v':
SET_FLAG(v);
break;
case 'V':
SET_FLAG(V);
break;
case 'w':
SET_FLAG(w);
suppress_warnings = TRUE;
break;
case 'W':
SET_FLAG(W);
break;
case 'X':
SET_FLAG(X);
break;
case 'z':
SET_FLAG(z);
profiled_file_list_zflag = optarg;
break;
case 'Z':
SET_FLAG(Z);
break;
default:
error_flag = TRUE;
break;
}
}
/* Checking incompatible options */
if (vflag) {
/* -v prints the version and exits, it's pointless to specify other flags */
if ( aflag || bflag || cflag || Cflag || dflag || eflag || fflag || Fflag || gflag
|| mflag || oflag || lflag || pflag || Pflag || rflag || Rflag || sflag
|| tflag || Tflag || Vflag || wflag || Xflag || Kflag || Dflag || Wflag || Yflag
|| Zflag || Hflag || Mflag || zflag || Eflag || nflag || n_other_files > 0 || n_search_paths > 0)
error_flag = TRUE;
}
if (Zflag) {
if (!gflag) gflag = TRUE; // GNU make
if (!cflag) cflag = TRUE; // central sorage
}
if ((bflag || Dflag || Pflag || Vflag || rflag || Wflag || Zflag) && !tflag) {
ERROR("Using the '-b', '-D', '-P', '-V', '-r' 'Z' or '-W' option requires the use of the -t' option.");
error_flag = TRUE;
}
if (rflag && !cflag) {
ERROR("Using the '-r' option requires use of the '-c' option. Recursive makefile hierarchy uses the central directory feature.");
error_flag = TRUE;
}
if (Fflag && !rflag) {
ERROR("Using the '-F' option requires use of the '-r' option.");
error_flag = TRUE;
}
if (Xflag && !rflag) {
ERROR("Using the '-X' option requires use of the '-r' option.");
error_flag = TRUE;
}
if (Tflag && !rflag) {
ERROR("Using the '-T' option requires use of the '-r' option.");
error_flag = TRUE;
}
if (!Zflag && Hflag) {
ERROR("Using the '-H' option requires use of the '-Z' option.");
error_flag = TRUE;
}
if (Zflag && !Fflag && !fflag) {
ERROR("Using the '-Z' option requires use of the '-F' option.");
error_flag = TRUE;
}
if (lflag && !strncmp(get_platform_string(), "WIN32", 5)) {
ERROR("Generating Makefile with dynamic linking enabled is not supported "
"on Windows platform");
error_flag = TRUE;
}
if (n_search_paths > 0 && !tflag) {
ERROR("Using the '-I' option requires use of the '-t' option.");
error_flag = TRUE;
}
for (size_t i = 0; i < n_search_paths; i++) {
boolean is_abs_path =
#if defined WIN32 && defined MINGW
/* On native Windows the absolute path name shall begin with
* a drive letter, colon and backslash */
(((search_paths[i][0] < 'A' || search_paths[i][0] > 'Z') &&
(search_paths[i][0] < 'a' || search_paths[i][0] > 'z')) ||
search_paths[i][1] != ':' || search_paths[i][2] != '\\');
#else
/* On UNIX-like systems the absolute path name shall begin with
* a slash */
search_paths[i][0] != '/';
#endif
if (is_abs_path) {
ERROR("The path after the -I flag must be an absolute path.");
error_flag = TRUE;
}
}
if (error_flag) {
usage();
return EXIT_FAILURE;
}
if (vflag) {
fputs("Makefile Generator for the TTCN-3 Test Executor\n"
"Product number: " PRODUCT_NUMBER "\n"
"Build date: " __DATE__ " " __TIME__ "\n"
"Compiled with: " C_COMPILER_VERSION "\n\n"
COPYRIGHT_STRING "\n\n", stderr);
#ifdef LICENSE
print_license_info();
#endif
return EXIT_SUCCESS;
}
#ifdef LICENSE
init_openssl();
load_license(&lstr);
valid_license = verify_license(&lstr);
free_openssl();
if (!valid_license) {
free_license(&lstr);
exit(EXIT_FAILURE);
}
if (!check_feature(&lstr, FEATURE_TPGEN)) {
ERROR("The license key does not allow the generation of "
"Makefile skeletons.");
return EXIT_FAILURE;
}
free_license(&lstr);
#endif
if (tflag) {
char* abs_work_dir = NULL;
FILE* prj_graph_fp = NULL;
sub_project_dirs = (struct string_list*)Malloc(sizeof(struct string_list));
sub_project_dirs->str = NULL;
sub_project_dirs->next = NULL;
ttcn3_prep_includes = (struct string_list*)Malloc(sizeof(struct string_list));
ttcn3_prep_includes->str = NULL;
ttcn3_prep_includes->next = NULL;
ttcn3_prep_defines = (struct string_list*)Malloc(sizeof(struct string_list));
ttcn3_prep_defines->str = NULL;
ttcn3_prep_defines->next = NULL;
ttcn3_prep_undefines = (struct string_list*)Malloc(sizeof(struct string_list));
ttcn3_prep_undefines->str = NULL;
ttcn3_prep_undefines->next = NULL;
prep_includes = (struct string_list*)Malloc(sizeof(struct string_list));
prep_includes->str = NULL;
prep_includes->next = NULL;
prep_defines = (struct string_list*)Malloc(sizeof(struct string_list));
prep_defines->str = NULL;
prep_defines->next = NULL;
prep_undefines = (struct string_list*)Malloc(sizeof(struct string_list));
prep_undefines->str = NULL;
prep_undefines->next = NULL;
solspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
solspeclibraries->str = NULL;
solspeclibraries->next = NULL;
sol8speclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
sol8speclibraries->str = NULL;
sol8speclibraries->next = NULL;
linuxspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
linuxspeclibraries->str = NULL;
linuxspeclibraries->next = NULL;
freebsdspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
freebsdspeclibraries->str = NULL;
freebsdspeclibraries->next = NULL;
win32speclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
win32speclibraries->str = NULL;
win32speclibraries->next = NULL;
linkerlibraries = (struct string_list*)Malloc(sizeof(struct string_list));
linkerlibraries->str = NULL;
linkerlibraries->next = NULL;
additionalObjects = (struct string_list*)Malloc(sizeof(struct string_list));
additionalObjects->str = NULL;
additionalObjects->next = NULL;
linkerlibsearchpath = (struct string_list*)Malloc(sizeof(struct string_list));
linkerlibsearchpath->str = NULL;
linkerlibsearchpath->next = NULL;
if (Xflag) {
const char* prj_graph_filename = "project_hierarchy_graph.xml";
prj_graph_fp = fopen(prj_graph_filename, "w");
if (prj_graph_fp==NULL) WARNING("Cannot open output file `%s' for writing: %s", prj_graph_filename, strerror(errno));
if (prj_graph_fp) fprintf(prj_graph_fp, "<project_hierarchy_graph top_level_tpd=\"%s\">\n", tpd_file_name);
}
create_symlink_list = (struct string2_list*)Malloc(sizeof(struct string2_list));
create_symlink_list->str1 = NULL;
create_symlink_list->str2 = NULL;
create_symlink_list->next = NULL;
target_placement_list = (struct string2_list*)Malloc(sizeof(struct string2_list));
target_placement_list->str1 = NULL;
target_placement_list->str2 = NULL;
target_placement_list->next = NULL;
run_command_list = (struct string2_list*)Malloc(sizeof(struct string2_list));
run_command_list->str1 = NULL;
run_command_list->str2 = NULL;
run_command_list->next = NULL;
required_configs = (struct string2_list*)Malloc(sizeof(struct string2_list));
required_configs->str1 = NULL;
required_configs->str2 = NULL;
required_configs->next = NULL;
tpd_processed = process_tpd(tpd_file_name, tpd_build_config, file_list_path,
&argc, &argv, &optind, &ets_name, &project_name,
&gflag, &sflag, &cflag, &aflag, &pflag,
&Rflag, &lflag, &mflag, &Pflag, &Lflag, rflag, Fflag, Tflag, output_file, &abs_work_dir, sub_project_dirs, program_name, prj_graph_fp,
create_symlink_list,ttcn3_prep_includes, ttcn3_prep_defines,ttcn3_prep_undefines, prep_includes, prep_defines, prep_undefines, &csflag,
&quflag, &dsflag, &cxxcompiler, &optlevel, &optflags, &dbflag, &drflag, &dtflag, &dxflag, &djflag, &fxflag, &doflag, &gfflag, &lnflag, &isflag,
&asflag, &swflag, &Yflag, &Mflag, &Eflag, &nflag, &diflag, solspeclibraries, sol8speclibraries, linuxspeclibraries, freebsdspeclibraries, win32speclibraries, &ttcn3prep,
linkerlibraries, additionalObjects, linkerlibsearchpath, Vflag, Dflag, &Zflag, &Hflag,
&generatorCommandOutput, target_placement_list, Wflag, run_command_list, required_configs, &profiled_file_list, search_paths, n_search_paths);
Free(abs_work_dir);
if (prj_graph_fp) {
fprintf(prj_graph_fp, "</project_hierarchy_graph>\n");
fclose(prj_graph_fp);
}
if (tpd_processed == TPD_FAILED) {
ERROR("Failed to process %s", tpd_file_name);
exit(EXIT_FAILURE);
}
if (zflag) {
WARNING("Compiler option '-z' and its argument will be overwritten by "
"the settings in the TPD");
}
}
else if (zflag) {
// use the argument given in the command line if there is no TPD
profiled_file_list = (struct string_list*)Malloc(sizeof(struct string_list));
profiled_file_list->str = mcopystr(profiled_file_list_zflag);
profiled_file_list->next = NULL;
}
if (!Pflag) {
run_makefilegen_commands(run_command_list);
generate_symlinks(create_symlink_list);
if (Zflag) {
if (Fflag)
NOTIFY("Makefile generation from top-level TPD: %s", tpd_file_name);
if (!Fflag && fflag)
NOTIFY("Makefile generation from lower level TPD: %s", tpd_file_name);
}
generate_makefile(argc - optind, argv + optind, n_other_files, other_files,
output_file, ets_name, project_name, gflag, sflag, cflag, aflag, pflag, dflag, fflag||Fflag,
Rflag, lflag, mflag, Cflag, code_splitting_mode, tcov_file_name, profiled_file_list,
Lflag, Zflag, Hflag, rflag ? sub_project_dirs : NULL, ttcn3_prep_includes,
ttcn3_prep_defines, ttcn3_prep_undefines, prep_includes, prep_defines, prep_undefines, csflag, quflag, dsflag, cxxcompiler, optlevel, optflags, dbflag,
drflag, dtflag, dxflag, djflag, fxflag, doflag, gfflag, lnflag, isflag, asflag, swflag, Yflag, Mflag, Eflag, nflag, diflag, solspeclibraries,
sol8speclibraries, linuxspeclibraries, freebsdspeclibraries, win32speclibraries, ttcn3prep, linkerlibraries, additionalObjects,
linkerlibsearchpath, generatorCommandOutput, target_placement_list);
}
free_string_list(sub_project_dirs);
free_string_list(ttcn3_prep_includes);
free_string_list(ttcn3_prep_defines);
free_string_list(ttcn3_prep_undefines);
free_string_list(prep_includes);
free_string_list(prep_defines);
free_string_list(prep_undefines);
free_string_list(solspeclibraries);
free_string_list(sol8speclibraries);
free_string_list(linuxspeclibraries);
free_string_list(freebsdspeclibraries);
free_string_list(win32speclibraries);
free_string_list(linkerlibraries);
free_string_list(additionalObjects);
free_string_list(linkerlibsearchpath);
free_string_list(profiled_file_list);
Free(search_paths);
Free(generatorCommandOutput);
free_string2_list(target_placement_list);
free_string2_list(required_configs);
Free(other_files);
if (tpd_processed == TPD_SUCCESS) {
int E;
if (!(eflag && ets_name))
Free(ets_name);
if (cxxcompiler)
Free(cxxcompiler);
if (optlevel)
Free(optlevel);
if (optflags)
Free(optflags);
if (ttcn3prep)
Free(ttcn3prep);
/* Free(output_file); */
for (E = 0; E < argc; ++E) Free(argv[E]);
Free(argv);
}
/* check_mem_leak(program_name); not needed when linked to new.cc */
return error_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}