C项目头文件全局变量重定义及Makefile免硬编码优化问题
多重定义链接报错修复方案
头文件的#ifndef守卫仅能避免单个编译单元(单个.c文件)内重复引入头文件,无法解决跨编译单元的全局符号重复问题。
你在公共头文件test.h中直接定义了两个全局变量:
int SET_MAIN=0; int ads_today=0;
所有包含test.h的源文件(test.c、test_func.c)编译时都会各自生成这两个变量的全局符号,链接时就会报重复定义错误。
修复步骤:
- 第一步:修改
test.h中的变量为声明,使用extern关键字,不要赋值:
// 替换原来的变量定义 extern int SET_MAIN; extern int ads_today;
- 第二步:任选一个源文件(推荐用带main函数的test.c)中添加这两个变量的定义:
// 加到test.c的全局位置即可 int SET_MAIN = 0; int ads_today = 0;
修改后重新编译即可解决链接错误。
通用自动编译Makefile优化方案
你原来的Makefile本身存在两个小问题:一是变量名拼写错误(定义的是HEADER_FROM_FUNCS_DIR,用的时候写成了HEADERS_FROM_FUNCS_DIR);二是test_func目标名错误,应该为funcs/test_func.o,所以之前编译时make调用了默认隐式规则生成目标文件。
优化后的Makefile无需硬编码任何源文件、头文件名,新增文件无需修改Makefile,自动识别编译,同时支持头文件修改自动重编对应源文件:
# 基础编译配置 CC = gcc # CFLAGS配置:开启警告、指定全局头文件搜索路径,所有源文件直接#include "xxx.h"即可找headers下的头文件 CFLAGS = -Wall -I./headers LDFLAGS = # 自动扫描所有源文件:根目录所有.c、funcs目录所有.c SRC_ROOT = $(wildcard *.c) SRC_FUNCS = $(wildcard funcs/*.c) # 自动生成所有.o目标文件列表 OBJS = $(patsubst %.c, %.o, $(SRC_ROOT) $(SRC_FUNCS)) # 自动生成依赖文件列表,用于记录头文件依赖 DEPS = $(patsubst %.c, %.d, $(SRC_ROOT) $(SRC_FUNCS)) # 最终生成的可执行文件名 TARGET = lh # 主目标规则 $(TARGET): $(OBJS) $(CC) $(OBJS) -o $@ $(LDFLAGS) # 引入所有自动生成的头文件依赖 -include $(DEPS) # 通用编译规则:.c生成.o,同时生成.d依赖文件记录头文件关联 %.o: %.c $(CC) $(CFLAGS) -MMD -c $< -o $@ # 清理规则:自动删除所有生成的文件 clean: rm -f $(TARGET) $(OBJS) $(DEPS)
优化后特性:
- 无需硬编码任何源文件、头文件名称,新增.c文件放到根目录或funcs目录、新增头文件放到headers目录后直接执行
make即可自动编译 - 自动处理头文件依赖,修改头文件后仅会重编依赖该头文件的源文件,无需手动全量清理
- 自动优先编译funcs目录的功能源文件,链接顺序符合要求
内容的提问来源于stack exchange,提问作者user786
相关产品推荐
相关产品推荐

