2013-06-06 75 views
1

我正在尝试构建简单的gcc插件。我是一个新手,但我想在未来实现更复杂的插件。 我阅读了很多手册,看起来我做的都对,但有些不对。 我无法构建它。每当我尝试构建我的插件时,出现错误:构建gcc插件的问题

/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/crt1.o: In function `_start': 
(.text+0x18): undefined reference to `main' 
/tmp/ccjmG33v.o: In function `plugin_init': 
plugin.c:(.text+0x9e): undefined reference to `register_callback' 
plugin.c:(.text+0xc6): undefined reference to `register_callback' 
collect2: ld returned 1 exit status 
make: *** [plugin.o] Error 1 

我不知道什么是错的。我执行了与我找到的所有手册中所述相同的步骤。

我有Ubuntu 12.04 gcc-4.6.3编译器。

我安装了gcc-4.6-plugin-dev。

我甚至试图构建一个基于gcc_4.6.4的插件,这个插件是我自己仔细下载和构建的。但结果是一样的。

我的Makefile:

PLUGINS_DIR = /usr/lib/gcc/i686-linux-gnu/4.6/plugin/include 

INCLUDES = \ 
    -I$(PLUGINS_DIR) 

DEFINES =  -Dbool=int -DTRUE=1 -DFALSE=0 

plugin.so :  plugin.o 
    gcc -shared -Wl,-export-dynamic -o plugin.so plugin.o 

%.o :   %.c 
    gcc $(DEFINES) $(INCLUDES) -fPIC -o [email protected] $^ 

clean : 
    rm *.o *.so 

插件的源代码:

#include <aspell.h> 
#include <gcc-plugin.h> 
#include <coretypes.h> 
#include <diagnostic.h> 
#include <gimple.h> 
#include <tree.h> 
#include <tree-flow.h> 
#include <tree-pass.h> 




#define is_alpha(c) (((c)>64 && (c)<91) || ((c)>96 && (c)<123)) 


int plugin_is_GPL_compatible = 1; 
static AspellSpeller *speller_g; 


/* Help info about the plugin if one were to use gcc's --version --help */ 
static struct plugin_info speller_info = 
{ 
    .version = "42", 
    .help = "Hahahaha yeaaaaa....", 
}; 


static struct plugin_gcc_version speller_ver = 
{ 
    .basever = "4.6", 
}; 


/* We don't need to run any tests before we execute our plugin pass */ 
static bool speller_gate(void) 
{ 
    return true; 
} 


static const_tree is_str_cst(const_tree node) 
{ 
/* 
    const_tree str = node; 

    // Filter out types we are ignoring 
    if (TREE_CODE(str) == VAR_DECL) 
    { 
     if (!(str = DECL_INITIAL(node))) 
      return NULL_TREE; 
     else if (TREE_OPERAND_LENGTH(str)) 
      str = TREE_OPERAND(str, 0); 
    } 
    else if (TREE_CODE(str) == ADDR_EXPR && 
      TREE_OPERAND_LENGTH(str) > 0) 
     str = TREE_OPERAND(str, 0); 

    if (TREE_CODE(str) != STRING_CST && 
     TREE_OPERAND_LENGTH(str) > 0) 
     str = TREE_OPERAND(str, 0); 

    if (TREE_CODE(str) != STRING_CST) 
     return NULL_TREE; 
    else 
     return str; 
*/ 
} 


static AspellSpeller *init_spellchecker(void) 
{ 
/* 
    AspellConfig *cfg; 
    AspellCanHaveError *err; 

    // Configure and instantiate a spell checker 
    cfg = new_aspell_config(); 
    aspell_config_replace(cfg, "lang", "en_US"); 
    err = new_aspell_speller(cfg); 
    if (aspell_error_number(err) != 0) 
    { 
     puts(aspell_error_message(err)); 
     return NULL; 
    } 

    return to_aspell_speller(err); 
*/ 
} 


static void spell_check(const_gimple stmt, const_tree str) 
{ 
/* 
    char buf[32] = {0}; 
    const char *data, *end; 

    data = TREE_STRING_POINTER(str); 
    printf("Spell checking string: \'%s\'\n", data); 

    while (*data) 
    { 
     // Skip non alphas including whitespace 
     while (!is_alpha(data[0])) 
     { 
      if (data[0] == '\0') 
       return; 
      ++data; 
     } 

     // Find the end of the word 
     end = data; 
     while (is_alpha(end[0])) 
      ++end; 

     if ((end - data) > sizeof(buf)) 
      return; 

     memcpy(buf, data, end - data); 
     buf[end-data] = '\0'; 
     if (!(aspell_speller_check(speller_g, buf, end - data))) 
      warning_at(gimple_location(stmt), 0, "%s (bad spelling)", buf); 
     data = end; 
    } 
*/ 
} 


static unsigned speller_exec(void) 
{ 
/* 
    unsigned i; 
    const_tree str, op; 
    basic_block bb; 
    gimple stmt; 
    gimple_stmt_iterator gsi; 

    FOR_EACH_BB(bb) 
     for (gsi=gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) 
     { 
      stmt = gsi_stmt(gsi); 
      for (i=0; i<gimple_num_ops(stmt); ++i) 
      if ((op = gimple_op(stmt, i)) && (str = is_str_cst(op))) 
       spell_check(stmt, str); 
     } 

    return 0; 
*/ 
} 


/* See tree-pass.h for a list and desctiptions for the fields of this struct */ 
static struct gimple_opt_pass speller_pass = 
{ 
    .pass.type = GIMPLE_PASS, 
    .pass.name = "speller",  /* For use in the dump file */ 
    .pass.gate = speller_gate, 
    .pass.execute = speller_exec, /* Pass handler/callback */ 
}; 


/* Return 0 on success or error code on failure */ 
int plugin_init(struct plugin_name_args *info, /* Argument infor */ 
       struct plugin_gcc_version *ver) /* Version of GCC */ 
{ 
    struct register_pass_info pass; 

    if (strncmp(ver->basever, speller_ver.basever, strlen("4.6"))) 
     return -1; /* Incorrect version of gcc */ 

    pass.pass = &speller_pass.pass; 
    pass.reference_pass_name = "ssa"; 
    pass.ref_pass_instance_number = 1; 
    pass.pos_op = PASS_POS_INSERT_AFTER; 

    /* Tell gcc we want to be called after the first SSA pass */ 
    register_callback("speller", PLUGIN_PASS_MANAGER_SETUP, NULL, &pass); 
    register_callback("speller", PLUGIN_INFO, NULL, &speller_info); 

    /* Initilize our spell checker */ 
    if (!(speller_g = init_spellchecker())) 
     return -1; 

    return 0; 
} 

注释的源代码包含函数调用未定义的连接了。据我所知,问题与register_callback函数相同。

有人可以帮助我解决这个问题吗?关于gcc插件写作的好的,详细的,不过时的手册也是非常有用的。 任何帮助将不胜感激。

+1

您是否考虑使用[MELT](http://gcc-melt.org/)高级域特定语言来扩展GCC?它可能会更简单... –

+1

我认为这种可能性。但它不符合我的要求。据了解,MELT有一种特殊的语言来与GCC内部进行交互。我更喜欢使用众所周知的语言C/C++,因为我对MELT语言的成熟度和稳定性有所了解。另外,添加一些库来扩展插件功能可能会有困难。 –

+0

至少在最后一点(添加一些库),您的MELT扩展可以很容易地使用任何'pkg-config'urable库。有关详细信息,请咨询[email protected]。 –

回答

2

试着改变Makefile到的最后第二条:

%.o :   %.c 
    gcc $(DEFINES) $(INCLUDES) -fPIC -o [email protected] -c $^ 

注意“-c”我已经添加它告诉它来编译,但在此阶段不链接。

+0

非常感谢!有用! :) –

0

这正是在网上找到的例子,如果没有错误的话。编译插件时,如果gcc提示找不到某些库,而不是在编译插件时使用-I来逐一指定每个库,那么我们可以使用Makefile来指定所有这些目录吗?谢谢