[英]Compile C code without it's main function
所以我有一些我正在研究的大学项目的文件; 每个文件都有几个函数和一个用于测试目的的main
函数。 但是,有些文件需要使用其他文件中的函数,这会给链接器提供关于预期的多个main
声明的投诉。 我想知道是否有办法将这些文件编译到目标文件而不编译main
功能,基本上剥离main
只留下可用的功能。
一个例子(不是我的实际文件中的一个非常大),对于每个我假设存在一个包含foo
和bar
声明的头文件:
//File foo.c
#include <stdio.h>
#include <stdlib.h>
#include "foo.h"
int foo(int x, int y)
{
return x + y;
}
//Assumes the user gives 2 integer inputs
int main(int argc, char **argv)
{
int x, y;
sscanf(argv[1], "%d", &x);
sscanf(argv[2], "%d", &y);
printf("foo(%d, %d) = %d\n", x, y, foo(x,y));
}
//File bar.c
#include <stdio.h>
#include <stdlib.h>
#include "foo.h"
#include "bar.h"
int bar(int x, int y, int z);
{
return foo(x, y) * z;
}
//Assums the user gives 3 integer inputs
int main(int argc, char **argv)
{
int x, y, z;
sscanf(argv[1], "%d", &x);
sscanf(argv[2], "%d", &y);
sscanf(argv[3], "%d", &z);
printf("bar(%d, %d, %d) = %d\n", x, y, z, bar(x, y, z));
}
是否可以将foo.c
编译为目标文件,以便我可以调用gcc bar.c foo.o
并获取bar.c
的可执行文件?
只有在编译文件以生成“测试可执行文件”时才可以对您定义的符号执行#ifdef
,而不是在将文件与其他文件一起使用时; 我已经看到这用于小型库的快速功能测试。
#include "foo.h"
int foo(int x, int y)
{
return x + y;
}
#ifdef COMPILE_MAIN
//Assumes the user gives 2 integer inputs
int main(int argc, char **argv)
{
int x, y;
sscanf(argv[1], "%d", &x);
sscanf(argv[2], "%d", &y);
printf("foo(%d, %d) = %d\n", x, y, foo(x,y));
}
#endif
现在你可以做到
gcc -DCOMPILE_MAIN foo.c -o foo.x
制作一个可以直接调用foo
的可执行文件foo.x
,你可以这样做
gcc foo.c bar.c main.c -o yourapp.x
使用其他文件(包括具有“真实”应用程序main
文件的文件)生成可执行文件,而不会抱怨多重定义的符号。
如果您使用gcc或clang编译代码,则可以将测试main
s声明为弱符号:
extern void main(int argc, char ** argv) __attribute__((weak));
void main(int argc, char ** argv) { ... }
弱main
将仅在没有强main
情况下使用。
对于Visual Studio(来自此答案 ):
// in foo.cpp
extern "C" void main(int argc, char ** argv;
extern "C" void defaultMainFoo(int argc, char ** argv)
// different name for each file
{ ... }
#pragma comment(linker, "/alternatename:_main=_defaultMainFoo");
/alternatename
表示如果main
未在其他位置提供,则链接器将使用defaultMain
作为main
。
虽然把#ifdef
放在你的main
功能上,但IMO并不是正确的做法,特别是因为...
[..]我的实际文件非常大[..]
合理的做法是将您的代码分成逻辑的,可重用的部分,并将这些(小)部分放入单独的文件中。
一个小例子:假设你有一个你正在为你的大学做的项目foo
,其中一部分是实现一个链表。 合理的做法是创建(至少)两个源文件foo.c
和list.c
,并将项目特定部分(即使只是一些测试)放入foo.c
以及有关实现的所有代码你的链表到list.c
然后将链接列表的接口(即可能是一些struct ...
声明,以及创建和修改列表的函数)放入头文件list.h
,该文件包含来自任何需要链表的文件,例如未来项目bar
:
list.c
struct list * create_list(void) {
// awesome code
}
// and more awesome code
list.h
struct list {
// an awesome list
};
struct list * create_list(void); // <- only a declaration
// more awesome declarations
foo.c的
#include "foo.h"
int main() {
// awesome use of the list
return 0;
}
bar.c
#include "foo.h"
int main() {
// also awesome
return 0;
}
然后你可以:
a)分别编译每个源文件,并将生成的目标文件链接在一起:
gcc -c list.c
gcc -c foo.c
gcc -o foo foo.o list.o
这种方式也可以用make完美表达,事实上至少在GNU中,甚至还有一个隐含的规则来将C文件编译为目标文件( %.o: %.c
)。
如果没有链接时间优化,您可能会失去一些使用此方法的优化。 如果您的项目需要不同的编译器标志,那么这不是一个好方法。
b)使用所需的源文件组装命令行并执行单个计算:
gcc -o foo foo.c list.c
您也可以使用make来执行此操作,例如使用变量FOO_DEPENDENCIES := list.c
请注意,使用此方法编译时间会更长。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.