代码的编译与执行

编译,执行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。

  1. 编译 下面的命令分别编译unix文件types.c和PDS数据集成员SAMPLE.SOURCE.C(TYPES)
    # c89 -c types.c
    # c89 -c "//'SAMPLE.SOURCE.C(TYPES)'"
    
  2. 编译并绑定 下面的命令分别编译unix文件和PDS数据集成员;分别输出到unix文件和PDS成员
    # 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)'"
    
    上面的例子中,数据集SAMPLE.LIB.OUT的ReCFmt必须为U 以上示例中,如果设置环境变量_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
    

results matching ""

    No results matching ""