COBOL

COBOL

COBOL

COBOL is responsible for the efficient, reliable, secure, and unseen day-to-day operations of the world's economy.

 View Only
Expand all | Collapse all

JCL compiling, linking, running of Cobol source against custom library built on USS

  • 1.  JCL compiling, linking, running of Cobol source against custom library built on USS

    Posted Tue February 27, 2024 11:22 AM
    Edited by Piotr Synowiec Tue February 27, 2024 11:34 AM

    Whole story

    All these steps are done in USS 

    1. I have custom C library that contains over 1000 different functions.

    2. I can compile library and link to DLL by
      xlc  -O2 -Wl,DLL -qdll -qexportall -v src/*.c
      xlc -o MYLIB.o  o/*.o -Wl,DLL -qdll -qexportall -v

    3. In result I have two files MYLIB.o and MYLIB.x

    4. Now I have several Cobol source programs to test some of the functions from library

    5. I can compile them dynamic
      cob2 -v -o test1 -qdll test1.cbl MYLIB.x
      and static
      cob2 -v -o test1 test1.cbl MYLIB.o
      I can execute them both and they work fine.

    Now problem starts (JCL part)

    1. I have basic Cobol Hello world source that I can compile and run with JCL (thanks to Geoffrey Decker)

    2. I can't figure it out how I can compile my test1.cbl file and link it with my custom library

    3. Things I did so far.
      I have IBMUSER.APP.COBOL dataset with all my Cobol sources including Hello World
      I have IBMUSER.APP.LIB dataset where I copied MYLIB.o of course without extension
      I have IBMUSER.APP.OO dataset where compiled programs are sent
      I didn't find a way to copy MYLIB.x file to dataset as it is just one line file.

    Could anybody help me to sort out this issue ?
    I basically need a way to copy my custom library compiled in USS to dataset and compile test programs from IBMUSER.APP.COBOL
    against my custom library preferably static and dynamic way

    Could anybody help me with that ?



    ------------------------------
    Piotr Synowiec
    ------------------------------



  • 2.  RE: JCL compiling, linking, running of Cobol source against custom library built on USS

    Posted Thu February 29, 2024 11:19 AM
    Edited by Roy Bae Thu February 29, 2024 11:22 AM
    Hello Piotr,
     
    You can compile/link/run using a JCL but if you are not familiar with JCL and its syntax, you will spend quite time to figure things out.  Alternatively, you can use USS to compile and link, but use a JCL just to run a program. I found this approach is easier to those who have more background on Linux/Unix than MVS/JCL/z/OS. Therefore my suggestion below is a combination of USS and JCL. (I know this is not what you asked). I described the general way using simple programs below. See if this helps answer your questions. 
     
    ##########################################################
    # To help you speed up and catch up the concept of a DLL, 
    ##########################################################
     
    1) Let's say a COBOL program wants to call functions named FUNC1 and FUNC2.  
    2) FUNC1 and FUNC2 are C functions defined in MYLIB (dll moudle). You need to create MYLIB (dll) and a sidedeck MYLIB.x.
    3) sidedeck (MYLIB.x) is just texts telling where FUNC1 and FUNC2 are located. 
     
    For example, 
    > cat MYLIB.x
     IMPORT CODE,'MYLIB','FUNC1'                                                     IMPORT CODE,'MYLIB','FUNC2'
     
    The sidedeck contents just say:
    - MYLIB (DLL) contains FUNC1
    - MYLIB (DLL) contains FUNC2
    4) When a COBOL source code is compiled/linked to create a runnable program (that is, COBOL program), you need to tell where FUNC1 and FUNC2 are located. Therefore COBOL source code needs to copmiled/linked with the sidedeck as follows:
     
    > cob2 -v -o test1 -qdll test1.cbl MYLIB.x
     
    5) the STEP.4 generates a runnable COBOL program, 'test1'. When test1 is executed, sidedeck is no longer needed but 'MYLIB' should be found.
     
     
    #------------------------------------------------------------------------
    #
    # ACTUAL EXAMPLE
    #
    #------------------------------------------------------------------------
     
    ########################################
    # > cat src/c.c
    ########################################
    #include<stdio.h>
     
    int FUNC1(){
      printf("I am func1\n");
    }
     
    int FUNC2(){
      printf("I am func2\n");
    }
     
    ########################################
    # > cat test1.cbl
    ########################################
            IDENTIFICATION DIVISION.
            PROGRAM-ID. TEST1.
            ENVIRONMENT DIVISION.
            DATA DIVISION.
            WORKING-STORAGE SECTION.
            PROCEDURE DIVISION.
            BEGIN.
                display "TEST1 starts"
                call 'func1'
                call 'func2'
                display "TEST1 end"
                stop run.
            END PROGRAM TEST1.
     
    ##############################################################################
    # Current in my current dir (/home/roybae/TEMP/240228_140754), I have these
    ##############################################################################
    ./src/c.c
    ./test1.cbl
     
    ##############################################################################
    # STEP.1 - Compile a 'c.c' file to generate an object named c.o
    # Note that '-c'(compile only) is used in xlc
    ##############################################################################
    > xlc  -c -O2 -Wl,DLL -qdll -qexportall -v src/*.c
    > ls  # note c.o is generated
    c.o         src         test1.cbl
     
    #########################################################################################
    # STEP.2 - link a 'c.o' file to generate a dll named 'MYLIB' and a sidedeck named 'MYLIB.x'
    #########################################################################################
    > xlc -o MYLIB  *.o -Wl,DLL -qdll -qexportall -v
    > ls  # note MYLIB and MYLIB.x are generated
    MYLIB    MYLIB.x    c.o        src        test1.cbl
     
    #########################################################################################
    # What's the sidedeck?
    #########################################################################################
    > cat MYLIB.x
     IMPORT CODE,'MYLIB','FUNC1'                                                     IMPORT CODE,'MYLIB','FUNC2'
     
    It tells that 
    - the C function 'FUNC1' is located in a module named 'MYLIB'
    - the C function 'FUNC2' is located in a module named 'MYLIB'.
     
    When COBOL code is compiled/linked, the sidedeck is needed. Otherwise COBOL does not know where to find FUNC1 and FUNC2
     
    #########################################################################################
    # STEP.3 - Compile a COBOL code with the sidedeck. It generates a program named test1
    #########################################################################################
    > cob2 -v -o test1 -qdll test1.cbl MYLIB.x
    > ls # note test1 is generated along with .lst and .o
    MYLIB       MYLIB.x     c.o      test1       test1.cbl   test1.lst   test1.o
     
     
    #########################################################################################
    # STEP.4
    #   Let's run test1. Note that LIBPATH should point to the dir where MYLIB is located.
    #   In my case, /home/roybae/TEMP/240228_140754 is where MYLIB is created 
    #########################################################################################
    > LIBPATH=/home/roybae/TEMP/240228_140754:$LIBPATH ./test1
    TEST1 starts
    I am func1
    I am func2
    TEST1 end
     
    #########################################################################################
    # STEP.5
    #   Let's run test1 using JCL.
    #   For preparation, 
    #   1) I copy 'test1' to ROYBAE.COBOL.LOAD
    #   2) I copy 'MYLIB' to ROYBAE.APP.LIB
    #########################################################################################
    > cp test1 "//'ROYBAE.COBOL.LOAD(TEST1)'"
    > cp MYLIB "//'ROYBAE.APP.LIB(MYLIB)'"
     
    Both ROYBAE.COBOL.LOAD and ROYBAE.APP.LIB need to be pre-created. I used the following attributes for both.
     
    Data Set Name  . . . : ROYBAE.APP.LIB                                     
                                                                              
    General Data                          Current Allocation                  
     Management class . . : STANDARD       Allocated tracks  . : 3            
     Storage class  . . . : OS390          Allocated extents . : 1            
      Volume serial . . . : LW002E         Maximum dir. blocks : NOLIMIT      
      Device type . . . . : 3390                                              
     Data class . . . . . : **None**                                          
      Organization  . . . : PO            Current Utilization                 
      Record format . . . : U              Used pages  . . . . : 22           
      Record length . . . : 0              % Utilized  . . . . : 61           
      Block size  . . . . : 4096           Number of members . : 1            
      1st extent tracks . : 3                                                 
      Secondary tracks  . : 4                                                 
      Data set name type  : LIBRARY       Dates                               
      Data set version  . : 2              Creation date . . . : 2024/02/29   
                                           Referenced date . . : 2024/02/29   
                                           Expiration date . . : ***None***   
     
    #########################################################################################
    # STEP.6
    #   Let's run test1 using JCL.
    #########################################################################################
    Submit the following JCL. 
    - Change 'ROYBAEZ' to yours
    - Change 'ROYBAE.COBOL.LOAD' and 'ROYBAE.APP.LIB'.
     
    EXEC PGM=TEST1 tells which program to run. It will look up datasets in STEPLIB.
    In this case, the STEPLIB has ROYBAE.COBOL.LOAD and ROYBAE.APP.LIB.
     
     ROYBAE.COBOL.LOAD is where TEST1 is found
     ROYBAE.APP.LIB is where MYLIB is found
     
    #----------
    # JCL
    #----------
    //ROYBAEZ  JOB (641A,2327),'COBOL TEST',TIME=60,
    //  REGION=512M,CLASS=B,MSGCLASS=S,             
    //  MSGLEVEL=(1,1),NOTIFY=&SYSUID               
    /*JOBPARM  T=60,L=300                           
    //RUN1     EXEC PGM=TEST1,                      
    // PARM=''                                      
    //STEPLIB  DD DSN=ROYBAE.COBOL.LOAD,DISP=SHR    
    //         DD DSN=ROYBAE.APP.LIB,DISP=SHR       
    //SYSOUT   DD SYSOUT=*                          
    //SYSPRINT DD SYSOUT=*                          
    //CEEDUMP  DD SYSOUT=*                          
    //SYSMDUMP DD SYSOUT=*                          
    //CEEOPTS  DD *                                 
    /*                                              
     
    #-----------------------------------------------------------------------------------
    # in the joglog, at the very bottom of it, I can find the program output as follows:
    #-----------------------------------------------------------------------------------
    ...
     TEST1 starts
     TEST1 end
     I am func1
     I am func2
     
     



    ------------------------------
    Roy Bae
    ------------------------------



  • 3.  RE: JCL compiling, linking, running of Cobol source against custom library built on USS

    Posted Thu February 29, 2024 12:22 PM

    For the sake of the complete information, 

    This shows a COBOL main calls a COBOL DLL subprogram 

    https://www.ibm.com/docs/en/cobol-zos/6.4?topic=application-example-sample-jcl-procedural-dll

    I asked IBM to add this second example below which is a COBOL main calls a C DLL subprogram:

    //DLLSAMP  JOB ,                                                            
    //  TIME=(1),MSGLEVEL=(1,1),MSGCLASS=H,CLASS=A,                             
    //  NOTIFY=&SYSUID,USER=&SYSUID                                             
    // SET LEPFX='SYS1'                                                         
    //*                                                                         
    // JCLLIB ORDER=(CBC.SCCNPRC)       TO FIND EDCCL                           
    //*---------------------------------------------------------------------    
    //* Compile C subprogram, bind to form a DLL.                               
    //STEP1 EXEC EDCCL,REGION=200M,GOPGM=DEMODLL,                               
    //       PARM.COMPILE='DLL,EXPORTALL,LIST',                                 
    //       PARM.LKED='RENT,LIST,XREF,LET,MAP,DYNAM(DLL),CASE(MIXED)'          
    //COMPILE.SYSIN    DD *                                                     
     #include<stdio.h>                                                          
     void DemoDLLSubprogram(){                                                  
       printf("Hello from DemoDLLSubprogram!\n");                               
     }                                                                          
                                                                                
     void DemoDLLSub2(){                                                        
       printf("Hello from DemoDLLSub2!!\n");                                    
     }                                                                          
    /*                                                                          
    //LKED.SYSDEFSD DD DSN=&&SIDEDECK,UNIT=SYSDA,DISP=(NEW,PASS),               
    //             SPACE=(TRK,(1,1))                                            
    //LKED.SYSLMOD   DD DSN=&&GOSET(&GOPGM),DSNTYPE=LIBRARY,DISP=(MOD,PASS)     
    //LKED.SYSIN     DD DUMMY                                                   
    //*---------------------------------------------------------------------    
    //* Compile and bind COBOL main program                                     
    //*---------------------------------------------------------------------    
    //STEP2 EXEC IGYWCL,REGION=80M,GOPGM=MAINPGM,                               
    //       PARM.COBOL='RENT,PGMNAME(LM),DLL',                                 
    //       PARM.LKED='RENT,LIST,XREF,LET,MAP,DYNAM(DLL),CASE(MIXED)'          
    //COBOL.SYSIN    DD *                                                       
           Identification division.                                             
           Program-id. "MainProgram".                                           
           Procedure division.                                                  
               Call "DemoDLLSubprogram"                                         
               Call "DemoDLLSub2"                                               
               Stop Run.                                                        
           End program "MainProgram".                                           
    /*                                                                          
    //LKED.SYSIN    DD DSN=&&SIDEDECK,DISP=(OLD,DELETE)                         
    //*---------------------------------------------------------------------    
    //* Execute the main program, calling the subprogram DLL.                   
    //*---------------------------------------------------------------------    
    //STEP3 EXEC PGM=MAINPGM,REGION=80M                                         
    //STEPLIB DD DSN=&&GOSET,DISP=(OLD,DELETE)                                  
    //        DD DSN=&LEPFX..SCEERUN,DISP=SHR                                   
    //        DD DSN=&LEPFX..SCEERUN2,DISP=SHR                                  
    //SYSOUT  DD SYSOUT=*                                                       
    //SYSPRINT DD SYSOUT=*                                                      
    //CEEDUMP DD SYSOUT=*                                                       




    ------------------------------
    Roy Bae
    ------------------------------



  • 4.  RE: JCL compiling, linking, running of Cobol source against custom library built on USS

    Posted Mon March 04, 2024 09:21 AM

    Hi Roy,

    Thank you for so comprehensive response.
    steps 1 to 5 I had already working.

    Step 6 implemented and work great.

    The problem I face is that final user of the library I compiled doesn't know USS and they do everything through TN3270 with JCL.
    That's why I'm looking for the way to compile Cobol source code against my custom library in dataset.
    I already have DLL library created and USS compiled objects runs through JCL with library specified on dataset.

    Could you please provide mean example how to compile and link Cobol source code againts my library ?
    source code IBMUSER.APP.COBOL(TEST1)
    library IBMUSER.APP.LIB(MYLIB)

    Regards,
    Piotr



    ------------------------------
    Piotr Synowiec
    ------------------------------



  • 5.  RE: JCL compiling, linking, running of Cobol source against custom library built on USS

    Posted Mon March 04, 2024 11:24 AM
    Hello Piotr,
     
    I am not too sure how far you can make it without understanding JCL syntax and usage. Anyway the JCL you are asking is in my previous posting which can be found from 
    https://www.ibm.com/docs/en/cobol-zos/6.4?topic=application-example-sample-jcl-procedural-dll
     
     
    If I may try to provide the customization, it is below.  
     
    ############################################################################
    # STEP.1 Pre-allocate a DS for a sidedeck using the following attribute:
    ############################################################################
     
    Data Set Name . . . . : IBMUSER.COBOL.SIDEDECK                            
                                                                             
    General Data                           Current Allocation                
     Management class . . : STANDARD        Allocated cylinders : 1          
     Storage class  . . . : OS390           Allocated extents . : 1          
      Volume serial . . . : LABW80                                           
      Device type . . . . : 3390                                             
     Data class . . . . . : **None**                                         
      Organization  . . . : PO             Current Utilization               
      Record format . . . : FB              Used cylinders  . . : 1          
      Record length . . . : 80              Used extents  . . . : 1          
      Block size  . . . . : 3200                                             
      1st extent cylinders: 1                                                
      Secondary cylinders : 1              Dates                             
      Data set name type  : PDS             Creation date . . . : 2024/03/04 
                                            Referenced date . . : 2024/03/04 
                                            Expiration date . . : ***None*** 
     
    ############################################################################
    # STEP.2
    ############################################################################
    Open your sidedeck in USS and edit it in such a way that each line starts with a space and is 80 columns long.
    For example, before editing:
     
    > cat MYLIB.x
     IMPORT CODE,'MYLIB','DemoDLLSubprogram'                                         IMPORT CODE,'MYLIB','DemoDLLSub2'
     
    After editing:
    > cat MYLIB.x
     IMPORT CODE,'MYLIB','DemoDLLSubprogram'
     IMPORT CODE,'MYLIB','DemoDLLSub2'
     
     
    ############################################################################
    # STEP.3 copy the edited MYLIB.x to IBMUSER.COBOL.SIDEDECK in USS
    ############################################################################
    > cp MYLIB.x "//'IBMUSER.COBOL.SIDEDECK(MYLIB)'"
     
     
    ############################################################################
    # STEP.4 run the following JCL 
    # Note: you might need to customize this JCL for your environment
    ############################################################################
    //IBMUSER1  JOB ,                                                              
    //  TIME=(1),MSGLEVEL=(1,1),MSGCLASS=S,CLASS=A,                               
    //  NOTIFY=&SYSUID,USER=IBMUSER
    //*---------------------------------------------------------------------      
    //* Compile and bind COBOL main program                                       
    //*---------------------------------------------------------------------      
    //STEP2 EXEC IGYWCL,REGION=800M,GOPGM=MAINPGM,                                
    //       PARM.COBOL='RENT,PGMNAME(LM),DLL',                                   
    //       PARM.LKED='RENT,LIST,XREF,LET,MAP,DYNAM(DLL),CASE(MIXED)'            
    //COBOL.SYSIN   DD DSN=IBMUSER.APP.COBOL(TEST1),DISP=SHR       *SOURCE               
    //LKED.SYSIN    DD DSN=IBMUSER.COBOL.SIDEDECK(MYLIB),DISP=SHR  *SIDEDECK       
    //*---------------------------------------------------------------------      
    //* Execute the main program, calling the subprogram DLL.                     
    //*---------------------------------------------------------------------      
    //STEP3 EXEC PGM=MAINPGM,REGION=80M                                           
    //STEPLIB DD DSN=&&GOSET,DISP=(OLD,DELETE)                                    
    //        DD DSN=IBMUSER.APP.LIB,DISP=SHR                      *DLL            
    //SYSOUT  DD SYSOUT=*                                                         
    //SYSPRINT DD SYSOUT=*                                                        
    //CEEDUMP DD SYSOUT=*                                                         
     
    #---------------------------
    # Note
    #---------------------------
    Where IBMUSER.APP.COBOL(TEST1) is a COBOL soure code that contains
           Identification division.
           Program-id. "MainProgram".
           Procedure division.
               Call "DemoDLLSubprogram"
               Call "DemoDLLSub2"
               Stop Run.
           End program "MainProgram".
     
    Where IBMUSER.COBOL.SIDEDECK(MYLIB) is a sidedeck
    Where IBMUSER.APP.LIB(MYLIB) is a DLL   
    (I happened to use the same name, MYLIB, for both sidedeck and DLL)
     
     


    ------------------------------
    Roy Bae
    ------------------------------



  • 6.  RE: JCL compiling, linking, running of Cobol source against custom library built on USS

    Posted Mon March 04, 2024 12:53 PM

    Big Thanks Roy
    This was exactly what I was looking for.
    Works like charm,

    Regards,
    Piotr



    ------------------------------
    Piotr Synowiec
    ------------------------------



  • 7.  RE: JCL compiling, linking, running of Cobol source against custom library built on USS

    Posted Mon March 04, 2024 01:48 PM
    Edited by Frank Swarbrick Mon March 04, 2024 01:48 PM

    If you want to use the .x Unix file directly, replace this:

    //LKED.SYSIN    DD DSN=IBMUSER.COBOL.SIDEDECK(MYLIB),DISP=SHR  *SIDEDECK   

    with this:

    //LKED.SYSIN  DD  *
     INCLUDE /your/Unix/library/MYLIB.x



    ------------------------------
    Frank Swarbrick
    ------------------------------



  • 8.  RE: JCL compiling, linking, running of Cobol source against custom library built on USS

    Posted Mon March 04, 2024 01:51 PM

    Edited.  Forgot 'DD'.



    ------------------------------
    Frank Swarbrick
    ------------------------------



  • 9.  RE: JCL compiling, linking, running of Cobol source against custom library built on USS

    Posted Thu February 29, 2024 12:21 PM
    Edited by Frank Swarbrick Thu February 29, 2024 12:24 PM

    I guess you didn't see my response in another thread, but the program binder can include .x files from the Unix file system.

    In your bind (link-edit) step, have this in your SYSLIB concatenation:

     INCLUDE /your/Unix/library/MYLIB.x

    By the way, I recommend not calling your dll MYLIB.o.  Use MYLIB.dll or MYLIB.so, so it doesn't look like a static object.



    ------------------------------
    Frank Swarbrick
    ------------------------------



  • 10.  RE: JCL compiling, linking, running of Cobol source against custom library built on USS

    Posted Mon March 04, 2024 09:10 AM

    Hi Frank,
    I could not figure it out 

    Regards,
    Piotr



    ------------------------------
    Piotr Synowiec
    ------------------------------