lccrt/tools/lcbe/src/lcbe_driver.cpp

1235 lines
31 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Part of the Lccrt Project, under the Apache License v2.0
* See http://www.apache.org/licenses/LICENSE-2.0.txt for license information.
* SPDX-License-Identifier: Apache-2.0
*
* lcbe - библиотека динамической компиляции.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <dlfcn.h>
#include <ctype.h>
#include <libgen.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include "lcbe_real.h"
#define lcbe_str_eq( a, b) (strcmp( a, b) == 0)
#define lcbe_assign( a, b) ((a) ? (*(a) = (b)) : 0)
#define lcbe_max( a, b) ((a) > (b) ? (a) : (b))
extern "C" int LCCRT_ASM_FUNC_COMPILE( lccrt_module_ptr m, lccrt_asm_compile_config_t *cnf);
extern "C" const char *LCCRT_ASM_FUNC_GETTOOL( const char *targ, const char *type, const char *name);
const char *LCCRT_PLUGIN_LCCRT_VERSION = LCCRT_VERSION;
const char *LCCRT_PLUGIN_LIBRARY_NAME = "lcbe";
const char *LCCRT_PLUGIN_TARGETS[] = {"e2k64", "x86_64", 0};
static void lcbe_init( void) __attribute__((constructor));
static void lcbe_done( void) __attribute__((destructor));
/**
* Внешние утилиты.
*/
typedef struct
{
char *gcc_path; /* путь установки программы gcc */
char *gcc; /* компилятор */
char *include_path; /* путь до стандартной директории include */
char *include_cpp_stl_path; /* путь до стандартной директории include/c++/stl */
char *ld_path; /* путь до программы линковщик */
char *ld; /* линковщик */
char *as_path; /* путь до программы ассемблер */
char *as; /* ассемблер */
char *lib32_path; /* путь до 32-битных библиотек компилятора */
char *lib64_path; /* путь до 32-битных библиотек компилятора */
char *gcc_base_path; /* путь до системных файлов компилятора */
char *gcc_lib32_path; /* путь до 32-битных системных библиотек компилятора */
char *gcc_lib64_path; /* путь до 64-битных системных библиотек компилятора */
char *bd; /* путь до директории с утилитами (binutils) */
char *fs; /* путь до системной директории */
} lcbe_tools_t;
/**
* Настройки оптимизирующего бекэнда.
*/
typedef struct
{
int verbose; /* флаг информационного режима */
const char *save_temps; /* флаг сохранения временных файлов */
char *cc_flags; /* дополнительные флаги компиляции */
int8_t is_dbg; /* флаг создания отладочных dwarf-структур */
char *lcbe_cc_config; /* внешняя программа вычисления конфигурации */
char *lcbe_home; /* home-директория библиотеки */
char *lcbe_conf; /* конфигурационный файл библиотеки */
} lcbe_config_t;
/**
* Глобальные данные библиотеки.
*/
typedef struct
{
lcbe_tools_t tools; /* внешние утилиты */
lcbe_config_t conf; /* настройки оптимизирующего бекэнда */
} lcbe_info_t;
/**
* Данные потока компиляции.
*/
typedef struct
{
lcbe_info_t *info; /* ссылка на глобальные данные библиотеки */
lccrt_asm_compile_config_t *aci;
lccrt_module_ptr m;
char *tmp_dir; /* директория для размещения временных файлов */
char *out_name; /* название выходного файла */
char *src_name; /* название файла с Си-кодом */
int8_t is_obj;
int8_t save_temps; /* флаг сохранения временных файлов */
int ofd; /* дескриптор выходного файла */
} lcbe_compile_t;
/**
* Глобальные данные потока компиляции.
*/
static __thread lcbe_compile_t lcbe_comp = {0};
/**
* Глобальные данные библиотеки.
*/
static lcbe_info_t lcbe_info = {{0}};
/**
* Проверка на установку опции.
*/
static int
lcbe_is_option( const char *opt,
int default_value)
{
int result = default_value;
const char *v = getenv( opt);
if ( v )
{
if ( (strcmp( v, "yes") == 0)
|| (strcmp( v, "YES") == 0)
|| (strcmp( v, "on") == 0)
|| (strcmp( v, "ON") == 0)
|| (strcmp( v, "enable") == 0)
|| (strcmp( v, "ENABLE") == 0)
|| (strcmp( v, "1") == 0) )
{
result = 1;
} else
{
result = 0;
}
}
return (result);
} /* lcbe_is_option */
/**
* Чтение опции.
*/
static char *
lcbe_get_option( const char *opt,
const char *default_value)
{
char *result = (char *)default_value;
char *v = getenv( opt);
if ( v )
{
result = v;
}
if ( result )
{
result = strdup( result);
}
return (result);
} /* lcbe_get_option */
/**
* Ожидание завершения дочернего процесса с возвратом кода завершения.
*/
static int
lcbe_waitpid( pid_t pid)
{
int r = -1;
int state = -1;
if ( (pid > 0) )
{
pid_t wpid = waitpid( pid, &state, 0);
if ( (wpid != pid)
|| !WIFEXITED( state)
|| (WEXITSTATUS( state) != 0) )
{
r = WEXITSTATUS( state) ? WEXITSTATUS( state) : -1;
} else
{
r = 0;
}
}
return (r);
} /* lcbe_waitpid */
/**
* Подготовка аргументов для компиляции модуля.
*/
static int
lcbe_compile_module_args_init( lcbe_compile_t *l, char *argv[50])
{
char b[4096];
int k = 0;
lcbe_config_t *c = &(l->info->conf);
//argv[k] = strdup( "lccrt"); k++;
argv[k] = strdup( l->src_name); k++;
argv[k] = strdup( "-O1"); k++;
argv[k] = strdup( "-fexceptions"); k++;
//argv[k] = strdup( "--mcpu-internal=elbrus-v2"); k++;
if ( (l->aci->is_pic == 0) )
{
if ( (l->aci->pie_level == 0) )
{
argv[k] = strdup( "-fPIC"); k++;
} else if ( (l->aci->pie_level == 1) )
{
argv[k] = strdup( "-fpie"); k++;
} else if ( (l->aci->pie_level == 2) )
{
argv[k] = strdup( "-fPIE"); k++;
} else
{
assert( 0);
}
} else
{
assert( l->aci->pie_level == 0);
}
if ( l->aci->function_sections )
{
argv[k] = strdup( "-ffunction-sections"); k++;
}
if ( l->aci->data_sections )
{
argv[k] = strdup( "-fdata-sections"); k++;
}
if ( 1 || (l->aci->dbg_level > 0) )
{
argv[k] = strdup( "-g"); k++;
c->is_dbg = 1;
}
argv[k] = strdup( l->is_obj ? "-c" : "-S"); k++;
argv[k] = strdup( "-o"); k++;
argv[k] = strdup( l->out_name); k++;
if ( c->cc_flags )
{
int j = 0;
char *p = c->cc_flags + 0;
while ( p[j]
&& (k < 50) )
{
while ( p[j]
&& (p[j] == ' ') )
{
j++;
}
if ( p[j] )
{
int h = 0;
while ( p[j+h]
&& (p[j+h] != ' ') )
{
h++;
}
argv[k] = strndup( p + j, h); k++;
j += h;
}
}
}
argv[k] = 0;
assert( k < 50);
return (k);
} /* lcbe_compile_module_args_init */
/**
* Компиляция модуля до ассемблерного файла.
*/
static int
lcbe_compile_module( lcbe_compile_t *l)
{
char data[4096];
int i;
int r = 0;
int k = 0;
int read_count = 0;
int write_count = 0;
int argc = 0;
FILE *f = 0;
char *argv[50] = {0};
/* Преобразуем представление модуля в Си-код. */
lcbe_emit_c( l->m, l->src_name);
/* Подготовка задачи компиляции. */
argc = lcbe_compile_module_args_init( l, argv);
k += snprintf( data + k, lcbe_max( 0, 4096 - k), "gcc");
for ( i = 0; i < argc; ++i )
{
k += snprintf( data + k, lcbe_max( 0, 4096 - k), " %s", argv[i]);
free( argv[i]);
}
if ( (k >= 4096) )
{
return (-1);
}
/* Выполнение задачи компиляции. */
if ( l->info->conf.verbose )
{
printf( "COMPILE: %s\n", data);
}
if ( (system( data) != 0) )
{
return (-1);
}
/* Передача результирующего файла в выходной файловой поток. */
f = fopen( l->out_name, "r");
if ( !f )
{
return (-1);
}
while ( !feof( f) )
{
int n = fread( data, 1, 4096, f);
if ( (n < 0) )
{
fclose( f);
return (-1);
} else if ( (n > 0) )
{
l->aci->write( l->aci->write_info, data, n);
}
}
fclose( f);
return (r);
} /* lcbe_compile_module */
/**
* Подготовка к работе.
*/
static int
lcbe_compile_module_init( lcbe_compile_t *l, lccrt_module_ptr m, lccrt_asm_compile_config_t *cnf)
{
char s[1024];
int r = 0;
int sl = 0;
int sfd = -1;
unsigned mode = 0;
memset( l, 0, sizeof( l[0]));
l->info = &lcbe_info;
l->m = m;
l->aci = cnf;
l->ofd = -1;
l->out_name = 0;
l->src_name = 0;
if ( getenv( "LCBE_TMP") )
{
l->tmp_dir = strdup( getenv( "LCBE_TMP"));
} else
{
l->tmp_dir = strdup( "/tmp/lcbe");
}
if ( getenv( "LCBE_SAVE") )
{
l->save_temps = atoi( getenv( "LCBE_SAVE"));
}
if ( lcbe_str_eq( cnf->out_type, "asm") )
{
l->is_obj = 0;
} else if ( lcbe_str_eq( cnf->out_type, "obj") )
{
l->is_obj = 1;
} else
{
return (-1);
}
sl = snprintf( s, 1024, "mkdir -p -m a+rwx %s", l->tmp_dir);
if ( (sl >= 1024)
|| (system( s) != 0) )
{
return (-1);
}
mode |= S_IRWXU;
mode |= S_IRWXG;
mode |= S_IRWXO;
sl = snprintf( s, 1024, "%s/%d.XXXXXX.%s", l->tmp_dir, getpid(), l->is_obj ? "o" : "s");
if ( (sl >= 1024) )
{
return (-1);
}
l->out_name = strdup( s);
l->ofd = mkostemps( l->out_name, 2, mode);
if ( (l->ofd < 0) )
{
return (-1);
}
l->src_name = strdup( l->out_name);
l->src_name[sl - 1] = 'c';
#if 0
sfd = mkostemps( l->src_name, 2, mode);
if ( (sfd < 0) )
{
return (-1);
} else
{
close( sfd);
}
#endif
return (0);
} /* lcbe_compile_module_init */
/**
* Завершение работы.
*/
static int
lcbe_compile_module_done( lcbe_compile_t *l)
{
int r = 0;
if ( (l->ofd >= 0) )
{
close( l->ofd);
if ( !l->save_temps )
{
unlink( l->out_name);
}
}
if ( l->out_name )
{
free( l->out_name);
}
if ( l->src_name )
{
if ( !l->save_temps )
{
unlink( l->src_name);
}
free( l->src_name);
}
if ( l->tmp_dir )
{
free( l->tmp_dir);
}
memset( l, 0, sizeof( l[0]));
l->ofd = -1;
return (r);
} /* lcbe_compile_module_done */
/**
* Компиляция модуля до ассемблерного файла.
*/
int
LCCRT_ASM_FUNC_COMPILE( lccrt_module_ptr m,
lccrt_asm_compile_config_t *cnf)
{
int r = -1;
lcbe_compile_t *l = &lcbe_comp;
if ( (lcbe_compile_module_init( l, m, cnf) == 0)
&& (lcbe_compile_module( l) == 0) )
{
r = 0;
}
if ( (lcbe_compile_module_done( l) != 0) )
{
r = -1;
}
return (r);
} /* LCCRT_ASM_FUNC_COMPILE */
/**
* Старт внешней программы с перенаправлением стандартного потока вывода
* на канальный файловый дескриптор. При успешном запуске возвращается
* файловый дескриптор, доступный на чтение, с выводом внешней программы
* и номер процесса с внешней программой (wpid) для проверки успешного
* выполнения внешней программы (см. lcbe_waitpid).
*/
static int
lcbe_exec_open( pid_t *wpid,
const char *path, /* первый аргумент execv */
char *argv[]) /* второй аргумент execv */
{
pid_t pid;
int fd[2] = {-1, -1};
int r = -1;
lcbe_assign( wpid, -1);
if ( (pipe( fd) != 0) )
{
/* Не удалось создать канал. */
return (r);
}
pid = fork();
if ( (pid < 0) )
{
/* Не удалось создать процесс. */
return (r);
}
if ( (pid == 0) )
{
/* Запускаем внешнюю программу. */
close( fd[0]);
dup2( fd[1], STDOUT_FILENO);
dup2( fd[1], STDERR_FILENO);
close( fd[1]);
execvp( path, argv);
} else
{
/* Возвращаем файловый дескриптор с выводом внешней программы. */
close( fd[1]);
r = fd[0];
if ( wpid )
{
(*wpid) = pid;
}
}
return (r);
} /* lcbe_exec_open */
/**
* Удаление старого значения и возврат копии нового значения, либо сохранение
* старого значения, если новое значение равно 0.
*/
static char *
lcbe_reinit_str( char *old_value,
const char *new_value)
{
char *r = old_value;
if ( new_value )
{
r = strdup( new_value);
if ( old_value )
{
free( old_value);
}
}
return (r);
} /* lcbe_reinit_str */
/**
* Возврат конкатенация строк a и b с удалением строки a.
*/
static char *
lcbe_concat_str_by( char *a,
const char *b)
{
char *r = 0;
if ( !a )
{
r = strdup( b);
} else
{
int la = strlen( a);
int lb = strlen( b);
r = (char *)malloc( la + lb + 1);
strcpy( r, a);
strcpy( r + la, b);
free( a);
}
return (r);
} /* lcbe_concat_str_by */
/**
* Возврат количества пробельных символов с начала строки (без учета перевода строки).
*/
static int
lcbe_skip_space( const char *s)
{
int k = 0;
while ( s[k]
&& isspace( s[k])
&& (s[k] != '\n') )
{
k++;
}
return (k);
} /* lcbe_skip_space */
/**
* Возврат количества непробельных символов в начале строки.
*/
static int
lcbe_skip_str( const char *s)
{
int k = 0;
while ( s[k]
&& !isspace( s[k])
&& (s[k] != '\n') )
{
k++;
}
return (k);
} /* lcbe_skip_str */
/**
* Чтение из файлового потока значений переменных.
*/
static int
lcbe_read_block( int fd,
char *block,
int size)
{
int n;
int is_work = 1;
n = 0;
while ( is_work )
{
int l = read( fd, block + n, size - n);
is_work = (l > 0);
n += l;
}
return (n);
} /* lcbe_read_block */
/**
* Исполнение внешней команды с записью выходного потока.
*/
static int
lcbe_get_exec_result( const char *cmd, char **argv, int max_len, char res[])
{
int n = 0;
int fd = -1;
pid_t pid = -1;
if ( res )
{
res[0] = 0;
}
fd = lcbe_exec_open( &pid, cmd, argv);
if ( (fd < 0) )
{
assert( 0);
return (0);
}
if ( res )
{
n = lcbe_read_block( fd, res, max_len);
res[n] = 0;
if ( (n > 0)
&& (res[n-1] == '\n') )
{
res[n-1] = 0;
}
}
if ( (lcbe_waitpid( pid) != 0) )
{
int k = 0;
fprintf( stderr, "Can't execute programm [%s] with arguments:", cmd);
while ( argv[k] )
{
fprintf( stderr, " [%s]", argv[k]);
k++;
}
fprintf( stderr, "\n");
close( fd);
abort();
return (0);
}
close( fd);
return (n);
} /* lcbe_get_exec_result */
/**
* Получить путь до библиотек.
*/
static const char *
lcbe_get_include_path( const char *name,
int ptr_bit_size)
{
const char *r = 0;
if ( (strcmp( name, "c") == 0) )
{
r = lcbe_info.tools.include_path;
} else if ( (strcmp( name, "c++-stl") == 0) )
{
r = lcbe_info.tools.include_cpp_stl_path;
}
return (r);
} /* lcbe_get_include_path */
/**
* Получить путь до библиотек.
*/
static const char *
lcbe_get_lib_path( const char *name,
int ptr_bit_size)
{
const char *r = 0;
if ( (strcmp( name, "mvec") == 0) )
{
if ( (ptr_bit_size == 32) )
{
r = lcbe_info.tools.gcc_lib32_path;
} else
{
r = lcbe_info.tools.gcc_lib64_path;
}
} else if ( (strcmp( name, "c") == 0) )
{
if ( (ptr_bit_size == 32) )
{
r = lcbe_info.tools.lib32_path;
} else
{
r = lcbe_info.tools.lib64_path;
}
}
return (r);
} /* lcbe_get_lib_path */
/**
* Получить для программы полный путь размещения программы.
*/
static const char *
lcbe_get_toolchain_path( const char *tool,
int ptr_bit_size)
{
const char *r = 0;
if ( (strcmp( tool, "ld") == 0) )
{
r = lcbe_info.tools.ld_path;
} else if ( (strcmp( tool, "as") == 0) )
{
r = lcbe_info.tools.as_path;
} else if ( (strcmp( tool, "gcc") == 0) )
{
r = lcbe_info.tools.gcc_path;
} else if ( (strcmp( tool, "fs") == 0) )
{
r = lcbe_info.tools.fs;
}
return (r);
} /* lcbe_get_toolchain_path */
/**
* Получить название программы вместе с полным путем.
*/
static const char *
lcbe_get_toolchain( const char *tool,
int ptr_bit_size)
{
const char *r = 0;
if ( (strcmp( tool, "ld") == 0) )
{
r = lcbe_info.tools.ld;
} else if ( (strcmp( tool, "as") == 0) )
{
r = lcbe_info.tools.as;
}
return (r);
} /* lcbe_get_toolchain */
/**
* Получить название или местоположение утилиты.
*/
const char *
LCCRT_ASM_FUNC_GETTOOL( const char *targ, const char *type, const char *name)
{
const char *r = 0;
if ( (strcmp( targ, "e2k32") == 0)
|| (strcmp( targ, "e2k64") == 0) )
{
int ptr_bits = (strcmp( targ, "e2k32") == 0) ? 32 : 64;
if ( (strcmp( type, "tool") == 0) )
{
r = lcbe_get_toolchain( name, ptr_bits);
} else if ( (strcmp( type, "tool_path") == 0) )
{
r = lcbe_get_toolchain_path( name, ptr_bits);
} else if ( (strcmp( type, "lib_path") == 0) )
{
r = lcbe_get_lib_path( name, ptr_bits);
} else if ( (strcmp( type, "include_path") == 0) )
{
r = lcbe_get_include_path( name, ptr_bits);
}
}
r = r ? r : "";
return (r);
} /* LCCRT_ASM_FUNC_GETTOOL */
/**
* Разбор строки из конфигурационного файла в формате "name : value".
* (В строку s вставляются символы '0' и возвращаются указатели по подстроки.)
*/
static int
lcbe_parse_config_line( char *s, char **name, char **value)
{
int r = 0;
int i = 0;
i += lcbe_skip_space( s + i);
if ( (s[i] == 0)
|| (s[i] == '#') )
{
/* Встретили комментарий. */
} else
{
int n0 = 0;
int n1 = 0;
int v0 = 0;
int v1 = 0;
n0 = i;
i += lcbe_skip_str( s + i);
i = (s[i] == ':') ? (i - 1) : i;
n1 = i;
i += lcbe_skip_space( s + i);
if ( !((n0 < n1)
&& (s[i] == ':')) )
{
r = -1;
} else
{
r = 1;
i++;
i += lcbe_skip_space( s + i);
v0 = i;
while ( s[i] && (s[i] != '#') ) i++;
v1 = i;
(*name) = s + n0;
(*value) = s + v0;
s[n1] = 0;
v1--;
while ( (v1 >= v0)
&& isspace( (int)s[v1]) )
{
v1--;
}
s[v1+1] = 0;
}
}
return (r);
} /* lcbe_parse_config_line */
/**
* Чтение настроек из файла конфигурации.
*/
static void
lcbe_parse_config_file( lcbe_config_t *cnf, lcbe_tools_t *tls)
{
FILE *f = 0;
f = fopen( cnf->lcbe_conf, "r");
if ( !f )
{
fprintf( stderr, "Can't open file with lcbe-configuration [%s]\n", cnf->lcbe_conf);
abort();
} else
{
int n = 0;
char *ld = 0;
size_t ld_len = 0;
while ( !feof( f) )
{
int v = 0;
char *name = 0;
char *value = 0;
if ( (getline( &ld, &ld_len, f) > 0)
&& ((v = lcbe_parse_config_line( ld, &name, &value)) > 0) )
{
if ( lcbe_str_eq( name, "cc-config") )
{
cnf->lcbe_cc_config = lcbe_reinit_str( cnf->lcbe_cc_config, value);
} else if ( lcbe_str_eq( name, "ld") )
{
tls->ld = lcbe_reinit_str( tls->ld, value);
} else if ( lcbe_str_eq( name, "as") )
{
tls->as = lcbe_reinit_str( tls->as, value);
} else if ( lcbe_str_eq( name, "fs") )
{
tls->fs = lcbe_reinit_str( tls->fs, value);
} else if ( lcbe_str_eq( name, "include") )
{
tls->include_path = lcbe_reinit_str( tls->include_path, value);
} else if ( lcbe_str_eq( name, "lib32") )
{
tls->lib32_path = lcbe_reinit_str( tls->lib32_path, value);
} else if ( lcbe_str_eq( name, "lib64") )
{
tls->lib64_path = lcbe_reinit_str( tls->lib64_path, value);
} else if ( lcbe_str_eq( name, "cc-base") )
{
tls->gcc_base_path = lcbe_reinit_str( tls->gcc_base_path, value);
} else if ( lcbe_str_eq( name, "cc-lib32") )
{
tls->gcc_lib32_path = lcbe_reinit_str( tls->gcc_lib32_path, value);
} else if ( lcbe_str_eq( name, "cc-lib64") )
{
tls->gcc_lib64_path = lcbe_reinit_str( tls->gcc_lib64_path, value);
} else
{
fprintf( stderr, "Wrong parameter's name in file with cc-configuration [%s]\n", name);
v = -1;
}
} else if ( (v == -1) )
{
fprintf( stderr, "Wrong format in file with cc-configuration!\n");
}
if ( (v == -1) )
{
fprintf( stderr, " line number : %d\n", n);
fprintf( stderr, " line : [%s]\n", ld);
abort();
}
n++;
}
if ( ld )
{
free( ld);
}
}
fclose( f);
return;
} /* lcbe_parse_config_file */
/**
* Вычисление утилит на базе параметров конфигурации.
*/
static void
lcbe_init_library_tools( lcbe_config_t *cnf, lcbe_tools_t *tls)
{
char buf[4096];
char *ld_args[] = {"cc-config", "-print-prog-name=ld", 0};
char *as_args[] = {"cc-config", "-print-prog-name=as", 0};
char *fs_args[] = {"cc-config", "-print-config=fs-dir", 0};
char *in_args[] = {"cc-config", "-print-internal-dir=include", 0};
char *in_cpp_stl_args[] = {"cc-config", "-print-internal-dir=include-c++-stl", 0};
char *gcc_base_args[] = {"cc-config", "-print-internal-dir=base", 0};
tls->ld = lcbe_reinit_str( tls->ld, getenv( "LCBE_LD"));
tls->as = lcbe_reinit_str( tls->as, getenv( "LCBE_AS"));
tls->include_path = lcbe_reinit_str( tls->include_path, getenv( "LCBE_INCLUDE"));
tls->lib32_path = lcbe_reinit_str( tls->lib32_path, getenv( "LCBE_LIB32"));
tls->lib64_path = lcbe_reinit_str( tls->lib64_path, getenv( "LCBE_LIB64"));
tls->gcc_base_path = lcbe_reinit_str( tls->gcc_base_path, getenv( "LCBE_CC_BASE"));
tls->gcc_lib32_path = lcbe_reinit_str( tls->gcc_base_path, getenv( "LCBE_CC_LIB32"));
tls->gcc_lib64_path = lcbe_reinit_str( tls->gcc_base_path, getenv( "LCBE_CC_LIB64"));
tls->fs = lcbe_reinit_str( tls->fs, getenv( "LCBE_FS"));
if ( !cnf->lcbe_cc_config )
{
if ( !tls->ld
|| !tls->as
|| !tls->fs
|| !tls->gcc_base_path )
{
fprintf( stderr, "One of variables [ld], [as], [lcc-base] or [fs] doesn't set, "
"but [lcc-config] utility is unknown!\n");
abort();
}
}
if ( 0 )
{
if ( !tls->ld )
{
lcbe_get_exec_result( cnf->lcbe_cc_config, ld_args, 4095, buf);
tls->ld = lcbe_reinit_str( 0, buf);
}
if ( !tls->as )
{
lcbe_get_exec_result( cnf->lcbe_cc_config, as_args, 4095, buf);
tls->as = lcbe_reinit_str( 0, buf);
}
if ( !tls->fs )
{
lcbe_get_exec_result( cnf->lcbe_cc_config, fs_args, 4095, buf);
tls->fs = lcbe_reinit_str( 0, buf);
}
if ( !tls->gcc_base_path )
{
lcbe_get_exec_result( cnf->lcbe_cc_config, gcc_base_args, 4095, buf);
tls->gcc_base_path = lcbe_reinit_str( 0, buf);
}
tls->ld_path = dirname( strdup( tls->ld));
tls->as_path = dirname( strdup( tls->ld));
if ( !tls->gcc_lib32_path )
{
snprintf( buf, 4096, "ls -l %s/lib/ptr32 >& /dev/null", tls->gcc_base_path);
snprintf( buf, 4096, "%s/lib%s", tls->gcc_base_path, (system( buf) == 0) ? "/ptr32" : "32");
tls->gcc_lib32_path = lcbe_reinit_str( 0, buf);
}
if ( !tls->gcc_lib64_path )
{
snprintf( buf, 4096, "ls -l %s/lib/ptr64 >& /dev/null", tls->gcc_base_path);
snprintf( buf, 4096, "%s/lib%s", tls->gcc_base_path, (system( buf) == 0) ? "/ptr64" : "64");
tls->gcc_lib64_path = lcbe_reinit_str( 0, buf);
}
if ( !tls->include_path )
{
lcbe_get_exec_result( cnf->lcbe_cc_config, in_args, 4095, buf);
tls->include_path = lcbe_reinit_str( 0, buf);
}
if ( !tls->include_cpp_stl_path )
{
lcbe_get_exec_result( cnf->lcbe_cc_config, in_cpp_stl_args, 4095, buf);
tls->include_cpp_stl_path = lcbe_reinit_str( 0, buf);
}
if ( !tls->lib32_path )
{
snprintf( buf, 4096, "%s/usr/lib32", tls->fs);
tls->lib32_path = lcbe_reinit_str( 0, buf);
}
if ( !tls->lib64_path )
{
snprintf( buf, 4096, "%s/usr/lib64", tls->fs);
tls->lib64_path = lcbe_reinit_str( 0, buf);
}
}
return;
} /* lcbe_init_library_tools */
/**
* Вычисление базовых параметров конфигурации библиотеки.
*/
static void
lcbe_init_config( lcbe_config_t *cnf, lcbe_tools_t *tls)
{
Dl_info dli;
char *s = 0;
char *t = 0;
memset( cnf, 0, sizeof( cnf[0]));
memset( tls, 0, sizeof( tls[0]));
cnf->verbose = lcbe_is_option( "LCBE_VERBOSE", 0) ? ~0 : 0;
dladdr( (void *)&lcbe_init_config, &dli);
s = strdup( dli.dli_fname);
cnf->lcbe_conf = lcbe_concat_str_by( strdup( basename( s)), ".conf");
free( s);
s = getenv( "LCBE_HOME");
if ( s )
{
s = strdup( s);
} else
{
t = realpath( dli.dli_fname, 0);
if ( !t )
{
fprintf( stderr, "Can't resolve real path of lcbe-library's location [%s]\n", dli.dli_fname);
abort();
}
s = dirname( t);
if ( !s )
{
fprintf( stderr, "Can't resolve directory of lcbe-library's location [%s]\n", t);
abort();
}
s = strdup( s);
free( t);
}
t = cnf->lcbe_conf;
cnf->lcbe_home = s;
cnf->lcbe_conf = lcbe_concat_str_by( lcbe_concat_str_by( strdup( s), "/"), t);
free( t);
cnf->lcbe_conf = lcbe_reinit_str( cnf->lcbe_conf, getenv( "LCBE_CONF"));
if ( cnf->verbose )
{
fprintf( stderr, "\nLCBE (LCCRT-plugin) library config:\n\n");
fprintf( stderr, " LCBE_VERBOSE : %s\n", getenv( "LCBE_VERBOSE"));
fprintf( stderr, " LCBE_HOME : %s\n", cnf->lcbe_home);
fprintf( stderr, " LCBE_CONF : %s\n", cnf->lcbe_conf);
}
lcbe_parse_config_file( cnf, tls);
cnf->lcbe_cc_config = lcbe_reinit_str( cnf->lcbe_cc_config, getenv( "LCBE_CC_CONFIG"));
if ( cnf->verbose )
{
fprintf( stderr, " LCBE_CC_CONFIG : %s\n", cnf->lcbe_cc_config);
}
lcbe_init_library_tools( cnf, tls);
if ( cnf->verbose )
{
fprintf( stderr, " LCBE_LD : %s\n", tls->ld);
fprintf( stderr, " LCBE_AS : %s\n", tls->as);
fprintf( stderr, " LCBE_FS : %s\n", tls->fs);
fprintf( stderr, " LCBE_INCLUDE : %s\n", tls->include_path);
fprintf( stderr, " LCBE_INCLUDE_CPP_STL : %s\n", tls->include_cpp_stl_path);
fprintf( stderr, " LCBE_LIB32 : %s\n", tls->lib32_path);
fprintf( stderr, " LCBE_LIB64 : %s\n", tls->lib64_path);
fprintf( stderr, " LCBE_CC_BASE : %s\n", tls->gcc_base_path);
fprintf( stderr, " LCBE_CC_LIB32 : %s\n", tls->gcc_lib32_path);
fprintf( stderr, " LCBE_CC_LIB64 : %s\n", tls->gcc_lib64_path);
}
return;
} /* lcbe_init_config */
/**
* Инициализация библиотеки.
*/
static void
lcbe_init( void)
{
lcbe_tools_t *t = &(lcbe_info.tools);
lcbe_config_t *c = &(lcbe_info.conf);
lcbe_init_config( c, t);
c->cc_flags = lcbe_get_option( "LCBE_CFLAGS", 0);
c->save_temps = lcbe_get_option( "LCBE_SAVE", 0);
if ( c->verbose )
{
fprintf( stderr, " LCBE_CFLAGS : %s\n", c->cc_flags);
fprintf( stderr, " LCBE_SAVE : %s\n", c->save_temps);
fprintf( stderr, "\n");
}
return;
} /* lcbe_init */
/**
* Завершение работы библиотеки.
*/
static void
lcbe_done( void)
{
return;
} /* lcbe_done */