使用small3dlib单头文件C库遇链接错误,如何重构项目修复?
多文件项目中使用单头文件库small3dlib的链接错误解决方法?
项目背景与结构
我正在用small3dlib结合SDL开发一款简单3D游戏,将这个单头文件库放入项目源码目录后,创建了gfx.c和gfx.h作为图形控制模块,当前项目结构如下:
tsa-3d/ | bin/ | build/ | src/ |-- gfx.c |-- main.c |-- include/ |---- gfx.h |---- logger.h |---- loggerconf.h |---- models.h |---- small3dlib.h |---- tgc.h |-- lib/ |---- logger.c |---- loggerconf.c |---- tgc.c |-- models/ |---- carModel.c |---- cityModel.c |---- cityTexture.c
当前头文件引入方式
main.c、gfx.c/.h、models.h及所有模型文件均间接包含small3dlib.h。由于该库要求在包含前定义特定宏,我通过gfx.h统一引入它:
#ifndef GFX_H #define GFX_H #define S3L_FLAT 0 #define S3L_NEAR_CROSS_STRATEGY 3 #define S3L_PERSPECTIVE_CORRECTION 2 #define S3L_SORT 0 #define S3L_STENCIL_BUFFER 0 #define S3L_Z_BUFFER 2 #define S3L_PIXEL_FUNCTION draw_pixel #define S3L_RESOLUTION_X 640 #define S3L_RESOLUTION_Y 480 #define TEXTURE_W 256 #define TEXTURE_H 256 #define WINDOW_TITLE "hello, world" #include <SDL2/SDL.h> #include <stdint.h> #include "small3dlib.h" #include "models.h" ... #endif
链接错误问题
这种布局导致small3dlib.h中的每个函数和全局变量都出现多重定义链接错误,错误信息如下:
/usr/bin/ld: src/main.o:(.bss+0x0): multiple definition of `S3L_zBuffer'; src/gfx.o:(.bss+0x0): first defined here /usr/bin/ld: src/main.o: in function `S3L_zBufferRead': main.c:(.text+0x7d): multiple definition of `S3L_zBufferRead'; src/gfx.o:gfx.c:(.text+0x7d): first defined here /usr/bin/ld: src/main.o: in function `S3L_zBufferWrite': main.c:(.text+0xb9): multiple definition of `S3L_zBufferWrite'; src/gfx.o:gfx.c:(.text+0xb9): first defined here /usr/bin/ld: src/main.o: in function `S3L_mat4Copy': ...
此前模型文件也因头文件包含定义出现同类问题,拆分后已解决,但small3dlib库本身是单头文件结构,示例仅在单个.c文件中包含它,不知道如何处理多文件场景。
最小复现示例
为了复现问题,我做了一个最小项目,结构如下:
project/ | Makefile | src/ |-- main.c |-- foo.c |-- include/ |---- something.h |---- lib.h
Makefile
# Global SRC := $(wildcard src/*.c) \ $(wildcard src/**/*.c) \ $(wildcard src/**/**/*.c) \ $(wildcard src/**/**/**/*.c) OUT := program # Default Build EXE := ./build/${OUT} CFLAGS := -I./src/include LIBFLAGS := -lSDL2 -ldl OBJ := ${SRC:.c=.o} build: clean-obj dir ${OBJ} gcc ${OBJ} -o ${EXE} ${CFLAGS} ${LIBFLAGS} ${call clean-obj} %.o: %.c gcc -c $< -o $@ ${CFLAGS} run: build ./bin/${OUT} # Utility dir: mkdir -p ./bin ./build/ clean-obj: rm -f ${OBJ} ./bin/* clean: clean-obj rm -f ${EXE}
lib.h(模拟small3dlib.h)
#ifndef LIB_H #define LIB_H #include <stdint.h> #include <stdio.h> #ifndef SOME_MACRO #error SOME_MACRO NOT DEFINED! #endif #define ARRAY_LENGTH 3 const uint8_t array[ARRAY_LENGTH] = { 1, 2, 3 }; void hello(uint8_t x) { for (uint8_t i = 0; i < x; i++) printf("%d", i); } #endif
something.h
#ifndef SOMETHING_H #define SOMETHING_H #define SOME_MACRO 3 #include "lib.h" void bar(); #endif
main.c
#include "include/something.h" int main(int argc, char* argv[]) { hello(array[2]); bar(); }
foo.c
#include "include/something.h" void bar() { hello(8); }
运行后出现的错误信息:
... /usr/bin/ld: src/main.o:(.rodata+0x0): multiple definition of `array'; src/foo.o:(.rodata+0x0): first defined here /usr/bin/ld: src/main.o: in function `hello': main.c:(.text+0x0): multiple definition of `hello'; src/foo.o:foo.c:(.text+0x0): first defined here collect2: error: ld returned 1 exit status make: *** [Makefile:18: build] Error 1
问题
单头文件库small3dlib在多文件项目中如何正确使用?我曾尝试拆分库为头文件和源文件,但因库文件过大(2800行)难以完成,有没有不用拆分库文件的方法修复链接错误?
内容的提问来源于stack exchange,提问作者nickel
相关产品推荐
相关产品推荐

