从单个C源代码生成库和二进制文件

时间:2018-12-24 12:56:48

标签: c compilation

我有一个C源文件,带主要功能和其他一些功能。像这样:

#include "stdlib.h"

int program(int argc, char ** argv)
{
    int a = atoi(argv[1]);
    int b = atoi(argv[2]);
    return a + b;
}

int main(int argc, char ** argv)
{
    return program(argc, argv);
}

我知道如何将其编译为二进制文件。

是否可以将其编译为省略了main符号/功能的目标文件?

我知道我可以通过将main拆分到自己的文件中来实现自己的目标,但是我不想这样做。

4 个答案:

答案 0 :(得分:3)

通常,在库中定义main()并不是问题,因为链接器仅在任何非库二进制文件中没有main()的情况下才使用它。甚至可以利用它来包含默认的main()。例如,请参见与-ll一起使用的Posix标准lex库(如果使用flex则为-lfl)。

如果确实要确保该符号不可用于解析,则可以从库中删除该符号。有一些用于处理二进制文件的工具,这些工具因系统而异。例如,看一下objcopy--strip-symbol选项。 (这不会删除已编译的代码;只会使其无法解析。)

答案 1 :(得分:1)

库只是对象模块的存档-要省略main(),它必须位于单独的对象模块中,然后从库构建中省略它,或者使用条件编译,以便在以下位置将其省略编译时间

实际上,如果main位于单独的对象模块中,则不忽略它并不重要,因为直接链接的对象模块中的任何定义都将覆盖任何静态库定义,因此仅使用库定义如果未重新定义。我不确定如果main()是在包含二进制中引用的其他符号的模块中定义的,是否行得通,但是如果您尝试除重复符号错误以外的操作,则不会发生任何不良情况。

答案 2 :(得分:1)

  

有没有一种方法可以将其编译为目标文件   符号/功能省略了吗?

因此,您不希望符号main出现在目标文件中。 这可能是一种方法。

file.c

<script>

const data=[
    {IsOpen: true, Day: "Monday", Desc: "09:00 AM-5:00 PM"},
    {IsOpen: true, Day: "Sunday", Desc: "09:00 AM-11:30 PM"},
    {IsOpen: true, Day: "Wednesday", Desc: "09:00 AM-5:00 PM"},
    {IsOpen: true, Day: "Friday", Desc: "09:00 AM-5:00 PM"},
    {IsOpen: true, Day: "Tuesday", Desc: "09:00 AM-5:00 PM"},
    {IsOpen: true, Day: "Thursday", Desc: "09:00 AM-5:00 PM"},
    {IsOpen: true, Day: "Saturday", Desc: "09:00 AM-5:00 PM"},
]
</script>

然后编译 [gcc]

  

gcc file.c -o文件-e not_main -nostartfiles

符号表:

#include "stdlib.h"

int program(int argc, char ** argv)
{
    int a = atoi(argv[1]);
    int b = atoi(argv[2]);
    return a + b;
}

int not_main(int argc, char ** argv)
{
    exit(0);
}

答案 3 :(得分:0)

  

有没有一种方法可以将其编译成目标文件,而省略主要符号/功能?

是的,通过使用preprocessor技巧和/或preprocessor options编译器。

将您的C代码(在文件mycode.c中)更改为包含以下内容:

#ifdef HAVE_MAIN
int main(int argc, char ** argv)
{
    return program(argc, argv);
}
#endif 

然后,仅获取目标文件mycode.o,编译为gcc -Wall -Wextra -g mycode.c -c -o mycode.o(如果使用GCC

要获取整个程序myprog,请将其编译为gcc -Wall -Wextra -g -DHAVE_MAIN mycode.c -o myprog

您甚至可以(避免使用任何#ifdef HAVE_MAIN的情况下,使用gcc -Wall -Wextra -g -Dmain=mymain -c mycode.c进行编译,以通过预处理将main重命名为mymain(然后失去了魔幻的作用)进入点的状态)。

但是,这样做被认为是不好的味道(不是很可读的代码)。您最好将main放在另一个translation unit中,并仅在需要整个程序时才对其进行编译。通常,library(或executable)是由几个翻译单元(每个翻译单元编译成一些object file;目标文件集会得到{ {3}})。您实际上将使用某些linked工具(例如build automationmake等)来构建它。