makefile $* $^....

本文详细解析了使用GCC编译器时Makefile的编写方法,通过具体示例展示了目标文件与依赖文件的关系,以及如何利用Makefile进行自动化编译。

$* 不包含扩展名的目标文件名称
$+ 所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件
$< 第一个依赖文件的名称
$@ 目标文件的完整名称
$^ 所有不重复的依赖文件,以空格分开
$% 如果目标是归档成员,则该变量表示目标的归档成员名称


hello:hello.o
Gcc hello.o -o hello
hello.o:hello.c hello.h 
Gcc -c hello.c -o hello.o

OBJS :=hello.o
CC :=Gcc
hello:$(OBJS)
$(CC) $^ -o $@

OBJS1 :=hello.o
OBJS2 :=hello.c hello.h
CC :=Gcc
hello:$(OBJS1)
$(CC) $^ -o $@
$(OBJS1):$(OBJS2)
$(CC) -c $< -o $@
<think>我们正在讨论Makefile中Pro*C的编译规则。用户提供的规则片段是: $(proc) INAME=$*.pc ONAME=$*.c $(PCFLAGS) 根据引用内容,我们可以构建一个完整的Pro*C编译规则。在Makefile中,通常我们会定义如何将.pc文件(Pro*C源文件)转换为.c文件,然后再将.c文件编译成.o文件。 参考引用[1]中的例子,我们可以看到: 1. 他们使用了环境提供的env_precomp.mk文件,其中可能定义了PROC(Pro*C预编译器)等变量。 2. 在规则中,他们使用$(PROC)命令来编译.pc文件,生成.c文件。 用户提供的规则片段中使用了ONAME=$*.c来指定输出文件名,这与引用[1]中的例子略有不同(引用[1]中使用的是iname=$*.pc,没有显式指定输出文件名)。但是,根据Pro*C的文档,我们可以使用ONAME选项来指定输出文件名。 因此,我们可以这样写规则: ```makefile # 定义Pro*C预编译器,如果env_precomp.mk中已经定义,则可以直接使用 include $(ORACLE_HOME)/precomp/lib/env_precomp.mk # 其他自定义变量 # 例如:PCFLAGS 可以包含Pro*C的编译选项 # 将.pc文件转换为.c文件的规则 %.c: %.pc $(PROC) $(PCFLAGS) iname=$< oname=$@ # 或者使用模式规则(suffix rule)的方式,但注意后缀规则已经过时,推荐使用模式规则 # 或者使用如下方式(与用户提供的片段类似): # .pc.c: # $(PROC) $(PCFLAGS) iname=$*.pc oname=$*.c # 注意:在引用[1]的例子中,他们使用了两个步骤:先由.pc生成.c,再编译.c为.o # 因此,我们还需要一个从.c到.o的规则 %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ ``` 但是,在引用[1]的例子中,他们在一个规则中同时做了两步(由.pc直接生成.o),但这样其实不太符合Makefile的最佳实践(因为这样会隐藏中间文件.c)。不过,用户提供的规则片段只做了第一步:从.pc到.c。 另外,根据引用[2]和[3],我们需要注意: 1. 环境变量和路径设置,特别是头文件路径和库路径。 2. 在链接时,需要链接Oracle的客户端库(如-lclntsh)。 因此,一个完整的Makefile可能如下: ```makefile include $(ORACLE_HOME)/precomp/lib/env_precomp.mk # 自定义变量 TARGET = test OBJS = test.o PCFLAGS = code=ansi_c sqlcheck=semantics # 根据引用[1]中的例子 CC = gcc CFLAGS = -g -I$(ORACLE_HOME)/precomp/public LDFLAGS = -L$(ORACLE_HOME)/lib -lclntsh # 默认目标 all: $(TARGET) # 链接目标程序 $(TARGET): $(OBJS) $(CC) -o $@ $(OBJS) $(LDFLAGS) # 模式规则:从.pc到.c %.c: %.pc $(PROC) $(PCFLAGS) iname=$< oname=$@ # 模式规则:从.c到.o %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ # 或者,如果我们想一步从.pc生成.o(跳过显式的.c文件),我们可以这样写: # %.o: %.pc # $(PROC) $(PCFLAGS) iname=$< oname=$*.c # $(CC) $(CFLAGS) -c $*.c -o $@ # rm -f $*.c # 如果不需要保留中间文件.c,可以删除 clean: rm -f $(TARGET) $(OBJS) *.c ``` 注意: 1. 在规则中,`$<`表示第一个依赖项,`$@`表示目标。 2. 在Pro*C编译步骤中,我们使用`iname=$<`指定输入文件,`oname=$@`指定输出文件(即.c文件)。 3. 在引用[1]的例子中,他们使用了`$(PROC) $(ORADEF) $(PROCFLAGS) iname=$*.pc`,这里我们简化了,但如果有额外的定义(如ORADEF)和标志(PROCFLAGS),应该加上。 另外,根据引用[4],我们可能需要在Pro*C源文件中使用Whenever语句来处理错误,但这与Makefile规则无关。 最后,关于用户提供的规则片段:`$(proc) INAME=$*.pc ONAME=$*.c $(PCFLAGS)`,我们需要注意: 1. 变量名`proc`应该与预编译器变量一致,通常是大写的`PROC`(在env_precomp.mk中定义)。 2. `$*.pc`和`$*.c`是自动变量,表示与目标文件同名的基名(不带后缀)加上指定的后缀。在模式规则中,我们更常用`$<`和`$@`。 因此,在模式规则中,我们更推荐使用: ```makefile %.c: %.pc $(PROC) $(PCFLAGS) iname=$< oname=$@ ``` 这样更清晰。 如果用户希望在一个规则中直接从.pc生成.o(不保留.c文件),则可以使用: ```makefile %.o: %.pc $(PROC) $(PCFLAGS) iname=$< oname=$*.c $(CC) $(CFLAGS) -c $*.c -o $@ rm -f $*.c ``` 但这样会删除中间文件.c,如果编译过程中需要调试,可能不方便。 综上所述,根据用户提供的规则片段,我们将其整合到Makefile的模式规则中,并给出完整的示例。 相关问题: 1. Pro*C预编译器选项ONAME和INAME有什么区别? 2.Makefile中,如何正确处理Pro*C编译的依赖关系(例如头文件)? 3. 如何设置Pro*C的代码生成选项(如ANSI C)?</think>### Makefile中Pro*C编译规则解析 根据您提供的规则片段和引用内容,以下是完整的Pro*C编译规则实现及说明: ```makefile # Pro*C编译规则(从.pc到.c) %.c: %.pc $(PROC) $(PCFLAGS) iname=$*.pc oname=$*.c # 核心编译指令 # C文件编译规则(从.c到.o) %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ ``` #### 关键元素说明: 1. **`$(PROC)`** Pro*C预编译器可执行文件(通常在`$ORACLE_HOME/bin/proc`) 2. **`INAME=$*.pc`** - `$*` 是Makefile自动变量,表示目标文件的主文件名(不含扩展名) - 指定输入文件为`<filename>.pc`[^1][^3] 3. **`ONAME=$*.c`** - 显式指定输出C文件名为`<filename>.c`[^1][^3] - 若不指定,默认生成`<filename>.c` 4. **`$(PCFLAGS)`** 预编译选项,建议包含: ```makefile PCFLAGS = code=ansi_c parse=full sqlcheck=semantics lines=yes ``` #### 完整Makefile示例: ```makefile include $(ORACLE_HOME)/precomp/lib/env_precomp.mk # 包含Oracle预定义规则[^1] # 工具配置 PROC = $(ORACLE_HOME)/bin/proc CC = gcc # 目录配置 ORAINC = $(ORACLE_HOME)/precomp/public ORALIB = $(ORACLE_HOME)/lib # 编译选项 PCFLAGS = code=ansi_c parse=full sqlcheck=semantics lines=yes CFLAGS = -I$(ORAINC) -g -O0 LDFLAGS = -L$(ORALIB) -lclntsh # 目标设置 TARGET = app OBJS = module1.o module2.o # 编译规则 $(TARGET): $(OBJS) $(CC) -o $@ $^ $(LDFLAGS) %.c: %.pc $(PROC) $(PCFLAGS) iname=$*.pc oname=$*.c %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ clean: rm -f $(TARGET) *.o *.c *.lis ``` #### 注意事项: 1. **ANSI C模式** 必须指定`code=ansi_c`,因Oracle默认非ANSI模式[^1] 2. **路径验证** 检查`env_precomp.mk`和`pcscfg.cfg`中的包含路径是否匹配当前环境[^2] 3. **头文件依赖**.pc文件包含自定义头文件,需添加依赖: ```makefile module1.c: module1.pc custom_header.h ``` 4. **SQL验证** 推荐`sqlcheck=semantics`进行深度SQL验证[^1][^4] 5. **Whenever语句** 程序首条嵌入式SQL前需放置`EXEC SQL WHENEVER`错误处理语句[^4]
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值