Après 1 semaine de questions, lecture de doc, expérimentations diverses...
Voici comment compiler du C sur z/OS en mode batch (JCL), avec CCNDRVR (XL C/C++) et IEWL, selon un débutant sur le C/zOS :
1) Créer les PDS contenant les sources (.c), les headers (.h), les objets (.o), les load modules (le binaire final/exécutable) :
- METAL.MALIB.C : RECFM=FB, LRECL=240
- METAL.MALIB.H : RECFM=FB, LRECL=80 (peut aussi être du VB 255...)
- METAL.MALIB.OBJ : RECFM=FB, LRECL=80
- METAL.MALIB.OUT : RECFM=U, LRECL=80
2) Taper le code et ses headers en code page 1047 - US (à régler dans son terminal 3270)...
Mon exemple ne nécessite pas tous les headers, mais je les ai mis pour indiquer quelques précisions après.
METAL.MALIB.C(HELLOC)
METAL.MALIB.H(MYINCL)Code:
1
2
3
4
5
6
7
8
9
10
11 #include "myincl.h" int main(void) { int i = 42; char *str = "Hello World!"; printf("i : %d, str : %s\n", i, str); return (0); }
3) JCL de compilation (avec XL C/C++, CCNDRVR) + binding/linking (avec IEWL) :Code:
1
2
3
4
5
6
7
8
9
10
11
12 #ifndef MYINCL_H_ # define MYINCL_H_ # define _POSIX_SOURCE # include <unistd.h> # include <fcntl.h> # undef _POSIX_SOURCE # include <stdlib.h> # include <stdio.h> #endif /* !MYINCL_H_ */
On peut mettre plusieurs cartes DD au niveau du USERLIB pour plusieurs headers.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 //COMPILNK JOB CLASS=A,MSGLEVEL=(1,1),MSGCLASS=X,REGION=0M, // NOTIFY=&SYSUID,TIME=30 // SET FICHIER=HELLOC //* //***************************************************************** //** COMPILE CCNDRVR '/SEARCH(''CEE.SCEEH.+'') NOOPT SO OBJ LIST' * //***************************************************************** //* //COMPILE EXEC PGM=CCNDRVR, // PARM='/SEARCH(''CEE.SCEEH.+'') NOOPT SO OBJ LIST' //USERLIB DD DSNAME=METAL.MALIB.H,DISP=SHR //STEPLIB DD DSNAME=CEE.SCEERUN,DISP=SHR // DD DSNAME=CEE.SCEERUN2,DISP=SHR // DD DSNAME=CBC.SCCNCMP,DISP=SHR //SYSPRINT DD SYSOUT=* //SYSCPRTT DD SYSOUT=* //*SYSLIB DD DSN=METAL.MALIB.C,DISP=SHR //* DD DISP=SHR,DSN=TCPIP.SEZACMAC //* DD DISP=SHR,DSN=CEE.SCEEH.H //SYSIN DD DSN=METAL.MALIB.C(&FICHIER),DISP=SHR //SYSLIN DD DSN=METAL.MALIB.OBJ(&FICHIER),DISP=SHR //* //************************************************** //** BIND1 IEWL 'OPTIONS=OPTS' * //************************************************** //* //BIND1 EXEC PGM=IEWL,PARM='OPTIONS=OPTS' //OPTS DD * AMODE=31,MAP NORENT,DYNAM=DLL CASE=MIXED /* //SYSLIB DD DISP=SHR,DSN=CEE.SCEELKEX // DD DISP=SHR,DSN=TCPIP.SEZACMTX // DD DISP=SHR,DSN=CEE.SCEELKED // DD DISP=SHR,DSN=CEE.SCEECPP // DD DISP=SHR,DSN=SYS1.CSSLIB //SYSLIN DD DISP=SHR,DSN=METAL.MALIB.OBJ(&FICHIER) //* DD DISP=SHR,DSN=SYS1.MDALBIN.PROG.OBJ(EDSATT) //* DD DISP=SHR,DSN=SYS1.MDALBIN.PROG.OBJ(WAIT) //* DD DISP=SHR,DSN=SYS1.MDALBIN.PROG.OBJ(STOP0C1) // DD DISP=SHR,DSN=CBC.SCLBSID(IOSTREAM) //SYSLMOD DD DISP=SHR,DSN=METAL.MALIB.OUT(&FICHIER) //SYSPRINT DD SYSOUT=* //*
Ou on peut remplacer la carte DD USERLIB par un paramètre plus complet :
On retrouve les erreurs de compilation dans SDSF, log "st"...Code:
1
2
3 // PARM=('/SEARCH(''CEE.SCEEH.+'',''METAL.MALIB.+''),', // ' NOOPT,SO,OBJ,LIST')
Ou dans le PDS créé à côté du PDS contenant les sources (il se créer automatiquement et se nomme dans mon cas : META.MALIB.C.LIST)
Je n'ai pas encore essayé de compiler plusieurs fichiers, mais de ce que j'ai pu lire, une des méthodes "possible" est de compiler chaque membre contenant des sources (1 step par source à compiler), puis de binder tous les objets générés en les indiquant dans plusieurs cartes DD associées à SYSLIN.
4) JCL d'exécution du load module/binaire final :
PARM sert à indiquer les paramètres donnés au programme.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 //MYRUN JOB CLASS=A,MSGLEVEL=(1,1),MSGCLASS=A,REGION=0M, // NOTIFY=&SYSUID,TIME=30 // SET FICHIER=HELLOC //RUNPRM EXEC PGM=&FICHIER, // PARM='METAL.TEST', // REGION=0M //STEPLIB DD DSN=METAL.MALIB.OUT,DISP=SHR //* CONFIG DD DSN=METAL.TEST,DISP=SHR //SYSPRINT DD SYSOUT=* //SYSUDUMP DD SYSOUT=* //SYSABEND DD SYSOUT=* //SYSCPRTT DD SYSOUT=*
La sortie standard se retrouve dans la log "st", pour plus de détails, on peut taper "?" devant le job du programme, puis "s" sur la SYSPRINT pour voir uniquement la sortie des printf.
Je ne sais pas encore comment ouvrir un DSN donné en DD, j'ai essayé plusieurs méthodes : open(CONFIG, O_RDONLY) mais cela renvoi -1...
D'ailleurs ! Pour que les defines O_RDONLY, STDOUT_FILENO, STDERR_FILENO, etc... fonctionnent, IL FAUT indiquer le define _POSIX_SOURCE !
Pour essayer d'utiliser le préprocesseur, j'ai trouvé ce lien : préprocesseur
On peut voir que le premier step met en paramètre :
Code:
1
2
3 //COMP1 EXEC PGM=CCNDRVR,REGION=0M, // PARM=('PP(COMMENTS,NOLINES)')
Un grand merci à tous !