代码的编译与执行
编译,执行C程序
准备源代码
如果在Windows或Linux上编辑代码,通过FTP上传至主机中,需要在ftp转码
quote site sbdataconn=(IBM-935,ISO8859-1)
quote type b 9
备注:本文中用于编译的CLIST由于有分隔符,ftp上传的话不能转码
编译
设源代码为数据集IBMUSER.DEVP.SRC(HELLOW), 输出的可执行程序到IBMUSER.RUN.LOAD(HELLOW) JCL编译脚本
//CBND JOB CLASS=A,MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=&SYSUID
//CPROC JCLLIB ORDER=CBC.SCCNPRC
//STEP1 EXEC EDCCB,REGION=75M,CPARM='LOCALE("ZH_CN.IBM-1388")'
//COMPILE.SYSIN DD DSN=IBMUSER.DEVP.SRC(HELLOW),DISP=SHR
//BIND.SYSLMOD DD DSN=IBMUSER.RUN.LOAD(HELLOW),DISP=OLD
注: 试验的时候发现:如果不加EXEC的REGION参数 REGION报错
CEE3536S Not enough storage was available for the WSA.
From entry point get_dll_symbol at statement 89 at compile unit offset +000000B4
at entry offset +000000B4at address 1E14A774.
或
CCN0634(U) Unable to load CCNETBY
上面的JCL中//COMPILE.SYSIN
和//BIND.SYSLMOD
等是为编目过程EDCCB的DD定义。
//COMPILE.SYSIN
是为EDCCB的过程步COMPILE的SYSIN定义(C源代码所在的数据集)//BIND.SYSLMOD
是为BIND过程步定义SYSLMOD(输出)。
需要说明的是编译工具对相关数据集的类型有要求。关于数据集IBMUSER.PROJ.LOAD的类型参见项目数据集属性。
运行程序
可以通过TSO的CALL命令调用程序
TSO CALL 'IBMUSER.RUN.LOAD(HELLOW)'
或者使用JCL脚本
//RUNA JOB CLASS=A,MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=&SYSUID
//STEP1 EXEC PGM=HELLOW,PARM='THE TEST prog'
//STEPLIB DD DSN=IBMUSER.RUN.LOAD,DISP=SHR
// DD DSN=CEE.SCEERUN,DISP=SHR
//SYSIN DD DATA,DLM=@@
TEST INPUT STRINg
@@
//
提交后在其作业的输出中会有相关的输出。
EDCCBG
编目过程EDCCBG对C程序进行编译,绑定,运行。ADCD1.10中EDCCBG等过程在CBC.SCCNPRC中。 EDCCBG中定义了名为COMPILE, BIND, GO的过程步。
//CLRCX JOB CLASS=A,MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=&SYSUID
//DOCLG EXEC PROC=EDCCBG,INFILE='IBMUSER.DEVP.SRC(HELLOW)',
// OUTFILE='IBMUSER.RUN.LOAD(HELLOW),DISP=SHR',
// REGION=75M
//GO.SYSIN DD DATA,DLM=@@
19
@@
//
另外,在编译JCL中嵌入C源代码的时候应注意,由于C中可能有注释(/*),流内数据定义最好使用
//SYSIN DD DATA,DLM=@@
而不是
//SYSIN DD *
(类似于上图中的例子)
CCNDRVR
上面的例子中使用编目过程进行编译、绑定、运行程序。
实际上EDCCB、EDCCBG等编目过程都是调用CCNDRVR对C源代码进行编译。
为了了解C程序的编译过程,需要了解直接在JCL调用CCNDRVR指定参数的方式:参数与输入、输出数据集。
具体可以参考参考资料2。这里介绍一下比较重要的一些。
在JCL中调用CCNDRVR
SYSIN
的DD定义指定要编译的C程序所在的数据集- PARM中指定编译参数。
可以参考EDCCB、EDCCBG中调用的方式。
CCNDRVR 的位置CBC.SCCNCMP [使用m查CBC开头的数据集]
头文件搜索路径
头文件的位置通过编译参数SEARCH(系统头文件)或LSEARCH(用户定义头文件)指定。需要注意的是如果在EDCCBG等编目规程中指定C编译参数的方法:例如 CPARM=’LSEARCH(’’’’IBMUSER.PROJ.H.+’’’’)’ SEARCH的默认值为CEE.SCEEH.+ 关于SEARCH和LSEARCH的详细描述参见[参考资料2] 更常见的做法是在编译脚本中指定 CCNDRVR作业的USERLIB定义(当然也可以加载SYSLIB定义中) 如
//USERLIB DD DSNAME=IBMUSER.DEVP.H,DISP=SHR
编译器参数
编译器有很多的参数。 具体参数值的意义以及如何修改编译器的默认参数等内容参见 [参考资料2]Appendix F, “Customizing default options for z/OS XL C/C++ compiler”. 在编译程序的时候,指定编译参数SOURCE能够查看默认的参数。
以下9.5和9.6节参考sg245992. C/C++ Applications on z/OS and OS/390 UNIX chapt 2.3
USS中使用c89编译C程序
备注:在 ISPF 6 Command中输入omvs可以进入USS;也可在IBM Products Panel中选择10 OMVS MVS OpenEdition。
- 编译
下面的命令分别编译unix文件types.c和PDS数据集成员SAMPLE.SOURCE.C(TYPES)
# c89 -c types.c # c89 -c "//'SAMPLE.SOURCE.C(TYPES)'"
- 编译并绑定
下面的命令分别编译unix文件和PDS数据集成员;分别输出到unix文件和PDS成员
上面的例子中,数据集SAMPLE.LIB.OUT的ReCFmt必须为U 以上示例中,如果设置环境变量# c89 -o types types.c # c89 -o "//'SAMPLE.LIB.OUT(TYPES)'" types.c # c89 -o types "//'SAMPLE.SOURCE.C(TYPES)'" # c89 -o "//'SAMPLE.LIB.OUT(TYPES)'" "//'SAMPLE.SOURCE.C(TYPES)'"
_C89_CCMODE=1
,那么命令选项和操作符的位置可以互换,例如:
也可以写成c89 -o types types.c
c89 types.c -o types
JCL编译C程序
z/OS提供传统的JCL过程(PROC)用于编译和打包它支持的编程语言:
- EDCC过程支持C语言的编译
- EDCCB过程支持C语言的编译绑定
- CBCC过程支持C++语言的编译
CBCCB过程支持C++语言的编译绑定
编译示例 下面是两个调用EDCC过程的JCL作业。 以下作业编译输入自文件types.c的源代码,输出的目标代码写入types.o文件中:
//STEP1 EXEC EDCC //COMPILE.SYSIN DD PATH='/u/test/types.c' //COMPILE.SYSLIN DD PATH='/u/test/types.o', // PATHMODE=(SIRWXU),PATHOPTS=(ORDWR,OCREAT,OTRUNC)
以下作业编译输入自数据集成员SAMPLE.SOURCE.C(TYPES)的源代码,输出的目标代码写入types.o文件中:
//STEP1 EXEC EDCC //COMPILE.SYSIN DD DSN=SAMPLE.SOURCE.C(TYPES),DISP=SHR //COMPILE.SYSLIN DD PATH='/u/test/types.o', //PATHMODE=(SIRWXU),PATHOPTS=(ORDWR,OCREAT,OTRUNC)
编译绑定示例 z/OS中提供的JCL PROC和c89工具一样可以灵活地将输入和输出指向文件或数据集成员,因此该方法也有与c89工具对应的使用方式。 下面的作业示例调用EDCCB过程完成编译并打包的操作。
- 1) 以下作业编译输入自文件types.c的源代码,并将打包输出的可执行代码存放到已存在的types文件中:
//STEP1 EXEC EDCCB //COMPILE.SYSIN DD PATH='/u/test/types.c' //BIND.SYSLMOD DD PATH='/u/test/types',PATHMODE=(SIRWXU), //PATHOPTS=(ORDWR,OCREAT,OTRUNC)
- 2) 以下作业编译输入自文件types.c的源代码,并将打包输出的可执行代码存放到已存在的数据集成员SAMPLE.LIB.OUT(TYPES)中:
//STEP1 EXEC EDCCB //COMPILE.SYSIN DD PATH='/u/test/types.c' //BIND.SYSLMOD DD DSN=SAMPLE.LIB.OUT(TYPES),DISP=OLD
- 3) 以下命令编译输入自数据集成员SAMPLE.SOURCE.C(TYPES)的源代码,并将打包输出的可执行代码存放到已存在的types文件中:
//STEP1 EXEC EDCCB //COMPILE.SYSIN DD DSN=SAMPLE.SOURCE.C(TYPES),DISP=SHR //BIND.SYSLMOD DD PATH='/u/test/types',PATHMODE=(SIRWXU), // PATHOPTS=(ORDWR,OCREAT,OTRUNC)
- 4) 以下命令编译输入自数据集成员SAMPLE.SOURCE.C(TYPES)的源代码,并将打包输出的可执行代码存放到已存在的数据集成员SAMPLE.LIB.OUT(TYPES)中:
//STEP1 EXEC EDCCB //COMPILE.SYSIN DD DSN=SAMPLE.SOURCE.C(TYPES),DISP=SHR //BIND.SYSLMOD DD DSN=SAMPLE.LIB.OUT(TYPES),DISP=OLD