;+ ; NAME: ; f2idl_mkmake ; PURPOSE: (one line) ; write Makefile for Fortran to IDL (f2idl) calls ; DESCRIPTION: ; write Makefile for Fortran to IDL (f2idl) calls ; CATEGORY: ; fileio ; CALLING SEQUENCE: ; f2idl_mkmake, sofile, forfiles=forfiles ; INPUTS: ; OPTIONAL INPUT PARAMETERS: ; sofile - name of the shared object (so) that the Makefile will create ; ; KEYWORD INPUT PARAMETERS: ; forfiles = fortran files with f2idl documentation ; default : *.f in current directory ; ccbin - binary for c compiler (default cc) ; ; KEYWORD OUTPUT PARAMETERS: ; OUTPUTS: ; COMMON BLOCKS: ; SIDE EFFECTS: ; Writes Makefile ; RESTRICTIONS: ; Filenames cannot be *_b.f or *_f.f ; Filenames ending *_d.f are assumed to contain only documentation ; PROCEDURE: ; ; MODIFICATION HISTORY: ; Written 2007 Feb 7, LAY ; 2007 Aug 20 LAY. ; - expanded documentation ; - changed outer loop index from idim to idiml to avoid ; name conflict in the dimension and rank loop ; - change how we split variables in the fortran dimension ; statements to deal with mutli-dimensioned arrays (with ; commas inside the parantheses) ; - in idl output, use array_equal rather than eq to check proper ; dimensions of 2-d arrays ; 2007 Aug 28 LAY. ; - correct return types for functions ; 2007 Aug 31 LAY ; - change integer type from 2 (integer) to 3 (longword integer) ;- pro f2idl_mkmake, sofile, forfiles = forfiles, progfiles=progfiles, version = version, $ ccbin=ccbin, cflags=cflags, f2cbin=f2cbin, f2cflags=f2cflags, c_ld_flags=c_ld_flags version = '1 (2007 Oct 16)' defsysv, '!textout', exists = i if i ne 1 then astrolib delvarx, i cd, current = cwd if not keyword_set(ccbin) then ccbin = 'cc' if not keyword_set(cflags) then begin cflags = ['-I/sw/include -I/usr/local/rsi/idl/external/include', $ '-fPIC -no-cpp-precomp -dynamic -fno-common', $ '-ansi -Wall -Wundef -Wpointer-arith -Wcast-align -Wsign-compare', $ '-c -D_REENTRANT' ] endif if not keyword_set(c_ld_flags) then begin c_ld_flags = '-bundle -flat_namespace -undefined suppress -L/sw/lib -lm -lf2c' endif if not keyword_set(f2cbin) then f2cbin = 'f2c' if not keyword_set(f2cflags) then begin f2cflags = '-C' endif ; ------------------------------------ ; Create sofn, the fileneame for the shared object ; ------------------------------------ if n_elements(sofile) eq 0 then begin sofile = file_basename(cwd) endif if strmatch(sofile, '*.so') then sofn = sofile else sofn = sofile+'.so' ; ------------------------------------ ; Open the Makefile ; ------------------------------------ makefn = 'Makefile' openw, makefp, makefn, /get_lun, width = 132 ; ------------------------------------ ; get the list of filenames ; ------------------------------------ if not keyword_set(forfiles) then begin forfnarr = file_search('*.f') endif else begin forfnarr = forfiles endelse nforfn = n_elements(forfnarr) ; ------------------------------------ ; Begin the Makefile ; ------------------------------------ hashline = '###############################################' printf, makefp, hashline printf, makefp, '# Make file created by f2idl_mkmake, version ', version printf, makefp, '# File created on ', systime(/utc) + ' UTC' printf, makefp, '# Current working directory is ', cwd printf, makefp, '# Makefile name is ', makefn printf, makefp, '# Shared object name is ', sofn printf, makefp, '# Fortran files are ' for iforfn = 0, nforfn-1 do begin printf, makefp, '# ', forfnarr[iforfn] endfor printf, makefp, hashline ; ------------------------------------ ; Set the shell, the SUFFIXES declaration, and the compilation flags ; ------------------------------------ printf, makefp, 'SHELL = /bin/sh' printf, makefp, '.SUFFIXES: .c .o .f .batch' printf, makefp, '.SECONDARY:' printf, makefp, '' printf, makefp, 'CC=',ccbin printf, makefp, 'CFLAGS= ',cflags[0] for i=1, n_elements(cflags)-1 do begin printf, makefp, 'CFLAGS+= ',cflags[i] endfor printf, makefp, 'C_LD_FLAGS= ',c_ld_flags[0] for i=1, n_elements(c_ld_flags)-1 do begin printf, makefp, 'C_LD_FLAGS+= ',c_ld_flags[i] endfor printf, makefp, 'F2C=',f2cbin printf, makefp, 'F2CFLAGS= ',f2cflags[0] for i=1, n_elements(f2cflags)-1 do begin printf, makefp, 'F2CFLAGS+= ',f2cflags[i] endfor ; ------------------------------------ ; f2c of input fortran array ; forfntypearr - list of 'doc' 'obj' or 'prog' ; ------------------------------------ forfntypearr = strarr(nforfn) for iforfn = 0, nforfn-1 do begin forfn = forfnarr[iforfn] ; only translate this if it contains code if strmatch(forfn, '*_d.f') then begin type = 'doc' endif else begin type = 'obj' if keyword_set(progfiles) then begin if total( forfn eq progfiles) gt 0 then type = 'prog' endif else begin spawn, 'grep PROGRAM ' + forfn, result if size(result, /n_dim) gt 0 then begin ; it's a program if one or more lines ; does NOT start 'C' if total(strmatch(result, 'C*') eq 0) gt 0 then begin type = 'prog' endif endif endelse endelse forfntypearr[iforfn] = type endfor delvarx, iforfn, forfn, type ; ------------------------------------ ; Identify functions and routines with documentation ; ------------------------------------ ; make sure we start clean delvarx, funcarr, funcforindxarr nfunc = 0 for iforfn = 0, nforfn-1 do begin forfn = forfnarr[iforfn] spawn, 'grep STARTDOC ' + forfn, result if size(result, /n_dim) gt 0 then begin for ires = 0, n_elements(result)-1 do begin tok = strsplit(result[ires], ' ', /extract) if n_elements(tok) eq 3 then begin if nfunc eq 0 then begin funcarr = [strlowcase(tok[2])] funcforindxarr = [iforfn] endif else begin funcarr = [funcarr, strlowcase(tok[2])] funcforindxarr = [funcforindxarr, iforfn] endelse nfunc = nfunc + 1 endif endfor endif endfor ;------------------------------------ ; Define PRO - the output pro files ;------------------------------------ printf, makefp, '' printf, makefp, $ '# PRO - .pro, one per idl function defined with STARTDOC ... ENDDOC lines' printf, makefp, '' str = 'PRO= ' for i = 0, nfunc-1 do begin func = funcarr[i] if strlen(str) gt 70 then begin printf, makefp, str str = 'PRO+= ' endif str = str + func + '.pro ' endfor printf, makefp, str delvarx, i, func, str ;------------------------------------ ; Define PRO - the output pro files ;------------------------------------ printf, makefp, '' printf, makefp, $ '# PRO_B - _b.pro, one per idl function defined with STARTDOC ... ENDDOC lines' printf, makefp, '# temporary files used to make _b.c and _b.o files' printf, makefp, '' str = 'PRO_B= ' for i = 0, nfunc-1 do begin func = funcarr[i] if strlen(str) gt 70 then begin printf, makefp, str str = 'PRO_B+= ' endif str = str + func + '_b.pro ' endfor printf, makefp, str delvarx, i, func, str ;------------------------------------ ; Define OBJS_B - objects created by f2idl_b ;------------------------------------ printf, makefp, '' printf, makefp, $ '# OBJS_B - _b.o, one per idl function defined with STARTDOC ... ENDDOC lines' printf, makefp, '' str = 'OBJS_B= ' for i = 0, nfunc-1 do begin func = funcarr[i] if strlen(str) gt 70 then begin printf, makefp, str str = 'OBJS_B+= ' endif str = str + func + '_b.o ' endfor printf, makefp, str delvarx, i, func, str ;------------------------------------ ; Define OBJS_F - objects created from the fortran ;------------------------------------ if2c = where(forfntypearr ne 'doc', nf2c) printf, makefp, '' printf, makefp, '# OBJS_F - *_f.o, one per fortran file (excluding *_d.f, doc files)' printf, makefp, '' str = 'OBJS_F= ' for i = 0, nf2c-1 do begin forfn = forfnarr[if2c[i]] root = file_basename(forfn,'.f') if strlen(str) gt 70 then begin printf, makefp, str str = 'OBJS_F+= ' endif str = str + root + '_f.o ' endfor printf, makefp, str delvarx, if2c, nf2c, i, forfn, root, str ;------------------------------------ ; make all, the shared object file, and clean ;------------------------------------ printf, makefp, '' printf, makefp, hashline printf, makefp, hashline printf, makefp, '' printf, makefp, 'all: '+sofn+' $(PRO) Makefile' printf, makefp, '' printf, makefp, sofn+': $(OBJS_B) $(OBJS_F) Makefile' printf, makefp, ' $(CC) $(C_LD_FLAGS) -o '+sofn+' $(OBJS_B) $(OBJS_F)' printf, makefp, '' printf, makefp, '' printf, makefp, 'clean:' printf, makefp, ' $(RM) *.c *.o *~ *.bk core $(PRO_B)' printf, makefp, '' printf, makefp, 'cleanall:' printf, makefp, ' $(RM) *.c *.o *~ *.bk core $(PRO_B) $(PRO)' printf, makefp, '' printf, makefp, hashline printf, makefp, hashline printf, makefp, '' ;------------------------------------ ; Create .pro and _b.pro ;------------------------------------ printf, makefp, '' printf, makefp, $ '# Crate .pro and _b.pro, ' printf, makefp, $ '# one per idl function defined with STARTDOC ... ENDDOC lines' printf, makefp, '' q = "'" ; single quote for i = 0, nfunc-1 do begin func = funcarr[i] iforfn = funcforindxarr[i] forfn = forfnarr[iforfn] type = forfntypearr[iforfn] if type eq 'doc' then begin ;blacm.pro:plutot.f plutot_d.f ; echo f2idl,"'blacm', fileroot='plutot'" | idl -IDL_STARTUP ' ' -quiet ;blacm_b.pro:plutot.f plutot_d.f ; echo f2idl_b,"'blacm', fileroot='plutot'" | idl -IDL_STARTUP ' ' -quiet root = file_basename(forfn, '_d.f') printf, makefp, func+'.pro:'+root+'.f ' + forfn printf, makefp, ' echo f2idl,"'+q+func+q+', fileroot='+q+root+q+'" '+$ '| idl -IDL_STARTUP '+q+' '+q+' -quiet' printf, makefp, func+'_b.pro:'+root+'.f ' + forfn printf, makefp, ' echo f2idl_b,"'+q+func+q+', fileroot='+q+root+q+'" '+$ '| idl -IDL_STARTUP '+q+' '+q+' -quiet' endif else begin printf, makefp, func+'.pro:'+forfn printf, makefp, ' echo f2idl,"'+q+func+q+'" | idl -IDL_STARTUP '+q+' '+q+' -quiet' printf, makefp, func+'_b.pro:'+forfn printf, makefp, ' echo f2idl_b,"'+q+func+q+'" | idl -IDL_STARTUP '+q+' '+q+' -quiet' endelse printf, makefp, '' endfor delvarx, i, func ;------------------------------------ ; Creation of the *_b.c files ;------------------------------------ printf, makefp, '' printf, makefp, '# MAKE THE C WRAPPERS FROM THE IDL BATCH FILE' printf, makefp, '' printf, makefp, '%_b.c : %_b.pro' printf, makefp, ' idl -IDL_STARTUP '+q+' '+q+' -quiet < $*_b.pro' printf, makefp, '' ;------------------------------------ ; Creation of the *_f.c files ;------------------------------------ printf, makefp, '' printf, makefp, hashline printf, makefp, hashline printf, makefp, '' printf, makefp, '# MAKE THE C FILES FROM THE FORTRAN FILES' printf, makefp, '' printf, makefp, "# treat program files differently, since these doesn't have -E" printf, makefp, '' iprog = where(forfntypearr eq 'prog', nprog) for i = 0, nprog-1 do begin forfn = forfnarr[iprog[i]] root = file_basename(forfn,'.f') printf, makefp, root + '_f.c : ' + forfn printf, makefp, ' $(F2C) $(F2CFLAGS) '+forfn printf, makefp, ' mv ' + root + '.c ' + root + '_f.c' endfor delvarx, iprog, nprog, i, forfn, root printf, makefp, '' printf, makefp, '%_f.c : %.f' printf, makefp, ' $(F2C) $(F2CFLAGS) -E $*.f' printf, makefp, ' mv $*.c $*_f.c' printf, makefp, '' ;------------------------------------ ; C file compilation ;------------------------------------ printf, makefp, '' printf, makefp, '# COMPILE C WRAPPERS AND F2C PRODUCTS' printf, makefp, '' printf, makefp, '.c.o :' printf, makefp, ' $(CC) $(CFLAGS) $*.c' ; ------------------------------------ ; Close the Makefile ; ------------------------------------ close, makefp & free_lun, makefp end