It depends on the system. On a DOS/VS system on an old IBM mainframe (or on Hercules) you'd code a JCL/JECL script like this:
* $$ JOB JNM=CMPLNKGO,DISP=D,PRI=3,CLASS=0,USER='PROGRAMMER' <== if you are running with POWER/VS, code JECL such as this.
* $$ LST LST=00E,DISP=D,PRI=3,CLASS=Z,FNO=W001,JSEP=1<== if you are running with POWER/VS, code JECL such as this.
// JOB CMPLNKGO
// ASSGN SYSLNK,X'537' <== or wherever your SYSLNK file resides in your standard labels
// ASSGN SYS001,X'537'
// ASSGN SYS002,X'537'
// ASSGN SYS003,X'537'
// ASSGN SYS004,X'537' <== SYS001 - SYS004 are for compiler work files the locations of which must also be defined in your standard labels
// OPTION LINK
// EXEC FCOBOL <== produces a relocatable module input to the linkage editor (LNKEDT)
[Your COBOL source code goes here]
// EXEC LNKEDT <== produces a temporary phase for execution
[if your program uses any files, the // ASSGN, // DLBL and // EXTENT statements for them must be coded here and MUST
match up with the system-names in your COBOL source code]
[any data for a card file goes here]
* $$ EOJ <== if you are running with POWER/VS, code JECL such as this.
z/VSE JCL might be similar to this, but I am 40+ years out of style!