host-i686-pc-cygwin/fixincludes/Makefile分析

快乐虾

http://blog.youkuaiyun.com/lights_joy/

lights@hb165.com

   

 

本文适用于

gcc- 4.3.1

configure –target=bfin-uclinux-gnu

Blackfin系列DSP

Cygwin gcc 3.4.4

   

 

欢迎转载,但请保留作者信息

 

 

cygwin gcc 3.4.4 环境下构建交叉编译器bfin-uclinux-gcc时,首先执行的是configure –target=bfin-uclinux-gnu命令,然后执行make操作,它将创建host-i686-pc-cygwin/ fixincludes子目录,并调用fixincludes /configure脚本生成Makefile,然后在主控Makefile中调用make生成目标,此时传递进来的目标为all

本文就是分析这个动态生成的host-i686-pc-cygwin/ fixincludes /Makefile

all目标的依赖关系为:

all : oneprocess fixinc.sh mkheaders

 

1.1    oneprocess

这个依赖关系定义为:

oneprocess : full-stamp

full-stamp : $(ALLOBJ) $(LIBIBERTY)

       $(CC) $(CFLAGS) $(LDFLAGS) -o $(FI) $(ALLOBJ) $(LIBIBERTY)

       $(STAMP) $@

在这里LIBIBERTY的定义为:

LIBIBERTY=../libiberty/libiberty.a

因为libiberty.a已经先于此目标生成,这个依赖关系可略过。

ALLOBJ变量的值则为:

ALLOBJ = fixincl.o fixtests.o fixfixes.o server.o procopen.o /

      fixlib.o fixopts.o

在此Makefile中,并没有为这些文件定义显式的规则,只是定义了一个通用的规则:

.c.o:

       $(CC) -c $(CFLAGS) $(WARN_CFLAGS) $(CPPFLAGS) $(FIXINC_CFLAGS) $<

在这个规则中,需要注意FIXINC_CFLAGS的定义:

INCLUDES = - I. -I$(srcdir) -I../include -I$(srcdir)/../include

FIXINC_CFLAGS = -DHAVE_CONFIG_H $(INCLUDES)

在生成所需要的.O文件后,oneprocess这段脚本将它们链接成fixincl.exe。然后生成一个full-stamp的内容为空的文件。

FI的定义为:

FI  = fixincl.exe

当然,这个目标在vs2005中是无法生成的。

1.2    fixinc.sh

这个目标定义为:

fixinc.sh : fixinc.in mkfixinc.sh Makefile

       srcdir="$(srcdir)" $(SHELL) $(srcdir)/mkfixinc.sh $(target)

在这里fixinc.inmkfixinc.sh都是gcc- 4.3.1 /fixincludes目录下的文件。

这个目标的脚本将在host-i686-pc-cygwin/fixincludes目录下生成一个fixinc.sh的脚本。

 

1.3    mkheaders

这个目标定义为:

mkheaders: mkheaders.almost $(srcdir)/../gcc/BASE-VER

       sed -e 's/@gcc_version@/$(gcc_version)/' < $< > $@T

       mv -f $@T $@

mkheaders.almost: $(srcdir)/mkheaders.in config.status

       CONFIG_FILES=mkheaders.almost:mkheaders.in /

       CONFIG_HEADERS= ./config.status

这个目标的脚本将在host-i686-pc-cygwin/fixincludes目录下生成一个mkheaders的脚本。

 

 

 

参考资料

host-i686-pc-cygwin/libiberty/Makefile解析( 2008-8-19 )

 

 

 

/usr/lib/gcc/x86_64-pc-cygwin/12/../../../../x86_64-pc-cygwin/bin/ld: output_executable.exe: in function `mainCRTStartup': /usr/src/debug/cygwin-3.6.1-1/winsup/cygwin/crt0.c:16: multiple definition of `mainCRTStartup'; /usr/lib/gcc/x86_64-pc-cygwin/12/../../../../lib/crt0.o:/usr/src/debug/cygwin-3.6.1-1/winsup/cygwin/crt0.c:16: first defined here /usr/lib/gcc/x86_64-pc-cygwin/12/../../../../x86_64-pc-cygwin/bin/ld: output_executable.exe: in function `mainCRTStartup': /usr/src/debug/cygwin-3.6.1-1/winsup/cygwin/crt0.c:16: multiple definition of `WinMainCRTStartup'; /usr/lib/gcc/x86_64-pc-cygwin/12/../../../../lib/crt0.o:/usr/src/debug/cygwin-3.6.1-1/winsup/cygwin/crt0.c:16: first defined here /usr/lib/gcc/x86_64-pc-cygwin/12/../../../../x86_64-pc-cygwin/bin/ld: output_executable.exe:cygming-crtbeg:(.text+0x50): multiple definition of `__gcc_register_frame'; /usr/lib/gcc/x86_64-pc-cygwin/12/crtbegin.o:cygming-crtbeg:(.text+0x0): first defined here /usr/lib/gcc/x86_64-pc-cygwin/12/../../../../x86_64-pc-cygwin/bin/ld: output_executable.exe:cygming-crtbeg:(.text+0x70): multiple definition of `__gcc_deregister_frame'; /usr/lib/gcc/x86_64-pc-cygwin/12/crtbegin.o:cygming-crtbeg:(.text+0x20): first defined here /usr/lib/gcc/x86_64-pc-cygwin/12/../../../../x86_64-pc-cygwin/bin/ld: output_executable.exe:cygming-crtbeg:(.data+0x0): multiple definition of `__dso_handle'; /usr/lib/gcc/x86_64-pc-cygwin/12/crtbegin.o:cygming-crtbeg:(.data+0x0): first defined here collect2: 错误:ld 返回 1
最新发布
06-09
<think>我们正在解决Cygwin环境下链接器报错的问题,错误涉及多个定义(multipledefinition)和crt0.c文件冲突。具体错误信息包括`mainCRTStartup`,`WinMainCRTStartup`,`__gcc_register_frame`等符号的多重定义,以及`collect2:ldreturned1exitstatus`。根据引用[1]中的经验,当使用`gcca.o-oa.exe`时出现多重定义错误,而添加`-nostartfiles`选项可以解决。这是因为Cygwin环境下的GCC默认会链接系统的启动函数(如`mainCRTStartup`),这些启动函数已经在C运行时库(如`crt0.o`)中定义。如果我们编译的源文件(例如`a.c`)中包含了相同的启动函数定义,就会导致冲突。###🔍问题分析1.**多重定义错误来源**:CygwinGCC在链接时自动链接了标准启动文件(如`crt0.o`或`crt1.o`),这些文件包含程序入口点(如`mainCRTStartup`)。如果用户程序中也定义了这些符号(例如,用户试图自己实现启动函数),则会出现多重定义。2.**`-nostartfiles`的作用**:该选项告诉链接器不要使用标准系统启动文件,从而避免与用户定义的启动函数冲突。###⚙️解决方案####1.避免在用户代码中定义系统启动函数除非你有特殊需求(如编写操作系统内核或裸机程序),否则不要定义`mainCRTStartup`、`WinMainCRTStartup`等函数。标准的C程序应该从`main`函数开始。####2.使用正确的编译命令-**编译源文件直接生成可执行文件**(推荐):```bashgcca.c-oa.exe```这种方式不会出现多重定义问题,因为编译器会自动处理启动代码。-**先编译成目标文件,再链接**:如果必须分步编译,在链接步骤使用`-nostartfiles`:```bashgcc-ca.c-oa.o#编译成目标文件gcca.o-oa.exe-nostartfiles```注意:使用`-nostartfiles`意味着你需要自己提供程序入口点(例如,定义`_start`函数)。通常,标准C程序不需要这样做,除非是特殊环境。####3.检查代码中的入口点定义确保你的代码中没有定义以下函数(这些是系统启动函数):-`mainCRTStartup`-`WinMainCRTStartup`-`_start`标准C程序应该只有一个`main`函数。####4.确保没有链接多个启动文件在Cygwin环境中,检查是否错误地链接了多个启动文件(如同时链接了`crt0.o`和`crt1.o`)。这通常发生在复杂的构建脚本中。使用以下命令查看链接的库和对象文件:```bashgcc-va.c-oa.exe```输出中会显示详细的链接过程,注意是否链接了多个启动文件。###💡错误示例分析根据引用[1]中的示例:```bashgcca.oa.o-oa.exe#错误:同一个目标文件链接两次```这会引发多重定义错误,因为同一个目标文件(`a.o`)被链接了两次,导致其中定义的每个符号都被重复定义。确保每个目标文件只链接一次。###⚠️注意事项使用`-nostartfiles`可能会导致程序运行时环境初始化不完整(例如,标准输入输出未初始化)。如果你只是编写普通用户程序,避免使用此选项,而是让链接器自动处理启动文件。###🔧调试技巧1.**查看符号定义**:使用`nm`工具检查目标文件和可执行文件中的符号:```bashnma.o#查看a.o中的符号nm/usr/lib/crt0.o#查看系统启动文件中的符号```如果你在`a.o`中看到`mainCRTStartup`等符号,说明你的代码中定义了这些符号,需要移除。2.**详细链接过程**:添加`-Wl,--verbose`选项查看链接器详细输出:```bashgcca.o-oa.exe-Wl,--verbose```###示例:标准C程序结构```c#include<stdio.h>intmain(){printf("Hello,Cygwin!\n");return0;}```编译命令:```bashgcchello.c-ohello.exe```§§相关问题§§1.Cygwin环境中如何自定义程序入口点?2.`-nostartfiles`和`-nostdlib`选项有何区别?3.如何为Cygwin编写裸机程序(不依赖标准库)?4.如何解决链接时出现的`__gcc_register_frame`多重定义错误?[^1]</think> 我将针对Cygwin环境下链接器报错问题提供结构化解决方案。此问题涉及多个符号(mainCRTStartup, WinMainCRTStartup等)的多重定义冲突,以及crt0启动文件相关错误。 ### 🔍 问题核心分析Cygwin环境下遇到的链接错误主要原因是**多重符号定义冲突**和**启动文件选择错误**: 1. **mainCRTStartup/WinMainCRTStartup冲突**: - CygwinGCC默认链接标准C启动文件(crt0.o或crt1.o),其中已定义程序入口点 - 用户代码中若包含同名的启动函数定义会导致多重定义错误 - 冲突函数包括:`mainCRTStartup`(控制台程序), `WinMainCRTStartup`(GUI程序)[^1] 2. **__gcc_register_frame冲突**: - 与异常处理框架相关,通常由重复链接libgcc导致 - 常见于混用不同编译器生成的目标文件时 3. **crt0.c相关错误**: - Cygwin环境使用特殊启动文件适配Windows环境 - 错误使用-nostartfiles/-nostdlib选项可能导致启动流程不完整 ### ⚙️ 分步解决方案 #### 方案1:使用标准编译流程(推荐) ```bash # 控制台应用程序(使用标准入口点) gcc main.c -o app.exe # GUI应用程序(使用WinMain入口) gcc main.c -o app.exe -mwindows ``` 此方案让链接器自动选择正确的启动文件,避免手动干预。 #### 方案2:正确使用入口点选项 当需要自定义入口点时: ```bash # 1. 首先正常编译目标文件(不加-nostartfiles) gcc -c main.c -o main.o # 2. 显式指定入口点链接(避免多重定义) gcc main.o -o app.exe -e my_entry_point -nostartfiles ``` 要点: - `-e`指定自定义入口点函数名 - `-nostartfiles`需与`-e`配合使用 - 在自定义入口点中需手动初始化CRT[^1] #### 方案3:解决__gcc_register_frame冲突 ```bash # 添加链接器选项解决异常处理冲突 gcc main.o -o app.exe -Wl,--disable-dynamicbase ``` #### 方案4:检查库链接顺序 调整库链接顺序可解决多数符号冲突: ```bash gcc main.o -o app.exe -lgcc -lcygwin -luser32 -lkernel32 ``` 遵循顺序:目标文件 → 语言支持库(libgcc) → 系统库 ### 💻 正确项目结构示例 ```makefile # Makefile示例 (Cygwin环境) TARGET = app.exe SRC = main.c $(TARGET): $(SRC) # 控制台程序使用标准编译 gcc $^ -o $@ # 若必须自定义入口点: # gcc -c $^ -o main.o # gcc main.o -o $@ -e my_entry -nostartfiles clean: rm -f *.o $(TARGET) ``` ### ⚠️ 关键注意事项 1. 避免在用户代码中定义`mainCRTStartup`等标准入口点 2. `-nostartfiles`会禁用所有标准启动代码,需手动完成: ```c // 自定义入口点示例 void _start() { // 1. 初始化堆栈 // 2. 初始化CRT extern void __main(void); __main(); // 初始化全局对象 // 3. 调用主函数 int ret = main(); // 4. 清理并退出 exit(ret); } ``` 3. Cygwin环境中`crt0.o`的特殊作用: - 处理Windows↔Unix环境转换 - 初始化cygwin运行时环境 - 设置异常处理框架 ### 🔧 高级调试技巧 1. 查看链接过程细节: ```bash gcc -v main.c -o app.exe ``` 2. 分析目标文件符号: ```bash nm main.o | grep 'mainCRTStartup\|WinMainCRTStartup' ``` 3. 检查默认链接脚本: ```bash ld --verbose | less ``` 4. 查看系统启动文件: ```bash ls /usr/lib/crt*.o ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌云阁主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值