3 # A script to download and build pythia6.
5 # Build both a static library for use with fortran and a shared object
6 # library for use with ROOT. Strips out the dummy routines that would
7 # hide the real ones found in pdflib. Currently does *not* extract include
8 # files from the downloaded source, but uses definitions embedded in this
9 # script. Should work on both Linux and Mac OS X.
11 # Usage: ./build_pythia6 [version] [--dummies=bestry|remove|keep] \
12 # [--refetch] [gfortran|g77|g95] [-m32]
14 # where [version] takes a form like "6.4.28", "6428" or "6_428" w/ or
15 # without an optional leading "v". It will created a subdirectory named
16 # "v6_428" so it is probably wise to run this in a directory named "pythia6"
17 # or some such. The --dummies=XYZZY controls whether the dummy PDFSET,
18 # STRUCTM and STRUCTP routines are removed. The -m32 forces a 32-bit
21 # Creates directory structure:
23 # pythia6/ - start in this directory
24 # v6_428/ - created subdirectory
25 # download/ - code downloaded from remote locations
26 # inc/ - include files for selected common blocks
27 # (hardcoded! not from downloaded source)
28 # lib/ - liblund.a pydata.o libPythia6.so
29 # src/ - fsplit source (and intermediate .o files)
30 # tpythia6_build/ - files for building ROOT interface
32 # Questions? Suggestions? Improvements? Offers of insane amounts of cash?
33 # Write me at: Robert Hatcher <rhatcher@fnal.gov>
36 # 2006-10-20: original version created by <rhatcher@fnal.gov>
37 # 2007-06-28: strict bash needs -gt to compare an int value, not ">"
38 # bail out if fetching source fails
39 # 2007-08-07: version 6.4.11 and beyond are at www.hepforge.org and use
40 # a different naming convention; support 6409 and earlier
41 # from old location (6.4.10 is in tar form... punt for now)
42 # more alternatives for version specification, this is
43 # needed for different file naming schemes old vs. new
44 # use wget if possible, curl if not, bail if neither avail
45 # 2007-10-16: add flags
46 # --keep-dummies : force the keeping of pdflib dummies
47 # --refetch : force refetch of source code
48 # look around for CERNLIB pdflib[804], mathlib, kernlib
49 # libraries with which to link against in order
50 # to satisfy removed dummies
51 # 2007-10-17: change to --dummmies=[besttry|remove|keep]
52 # besttry (default) means try to link to CERNLIB
53 # if any of the libraries can't be found then
54 # don't remove dummmies
55 # remove always removes dummy routine and tries to link
56 # to what ever libraries that it can find
57 # keep always keeps dummy routine
58 # 2008-01-05: fix "keep" option to actually keep dummy stubs.
59 # 2009-04-09: choose fortran compiler, if cmd line specified use that
60 # otherwise first of gfortran or g77 found
61 # 2010-12-29: addition of -m32 option; default v6_422
62 # 2011-01-13: default v6_424; clean up comments
63 # 2014-07-14: default v6_428; http->https for hepforge
64 # 2016-05-19: new location for root download
66 ############################################################################
74 while [ $# -gt 0 ] ; do
83 dummyaction="remove" ;;
85 dummyaction="besttry" ;;
87 echo "failed to parse $1" ;;
94 whichftn="gfortran" ;;
105 ############################################################################
106 export ESCCHAR="\x1B" # or \033 # Mac OS X bash doesn't support \e as esc?
107 export OUTBLACK="${ESCCHAR}[0;30m"
108 export OUTBLUE="${ESCCHAR}[0;34m"
109 export OUTGREEN="${ESCCHAR}[0;32m"
110 export OUTCYAN="${ESCCHAR}[0;36m"
111 export OUTRED="${ESCCHAR}[0;31m"
112 export OUTPURPLE="${ESCCHAR}[0;35m"
113 export OUTORANGE="${ESCCHAR}[0;33m" # orange, more brownish?
114 export OUTLTGRAY="${ESCCHAR}[0;37m"
115 export OUTDKGRAY="${ESCCHAR}[1;30m"
116 # labelled "light but appear in some cases to show as "bold"
117 export OUTLTBLUE="${ESCCHAR}[1;34m"
118 export OUTLTGREEN="${ESCCHAR}[1;32m"
119 export OUTLTCYAN="${ESCCHAR}[1;36m"
120 export OUTLTRED="${ESCCHAR}[1;31m"
121 export OUTLTPURPLE="${ESCCHAR}[1;35m"
122 export OUTYELLOW="${ESCCHAR}[1;33m"
123 export OUTWHITE="${ESCCHAR}[1;37m"
124 export OUTNOCOL="${ESCCHAR}[0m" # No Color
125 # use as: echo -e "${OUTRED} this is red ${OUTNOCOL}"
126 ##############################################################################
129 ############################################################################
131 # decompose version string which could take any of the forms:
132 # [v]{Major}.{minor}.{tiny}, [v]{Major}_{minor}{tiny} or
133 # [v]{Major}{minor}{tiny}, with the assumption that {Major} is always "6"
134 # and {tiny} is two digits.
136 # remove any "v" in version number
137 version0=${version#v*}
139 major=${version0%%.*}
140 if [ "${major}" = "6" ] ; then
146 major=${version0%%_*}
147 if [ "${major}" = "6" ] ; then
148 # in M_mtt format, convert to Mmtt
149 version0=${version0/_/}
151 # assume Mmtt format, could it also be Mmmtt? anticipate it could be.
152 # ${parmeter:offset:length} doesn't work for negative offsets as advertized
153 major=${version0:0:1}
154 foo=`echo $version0 | cut -c2-`
155 if [ ${foo} -lt 1000 ] ; then
156 minor=`echo $foo | cut -c1`
157 tiny=`echo $foo | cut -c2-3`
159 minor=`echo $foo | cut -c1-2`
160 tiny=`echo $foo | cut -c3-4`
164 ############################################################################
166 # script only works for pythia6
168 if [ "${major}" != "6" ] ; then
169 echo -e "${OUTRED}sorry this script only works for pythia6, not ${major}${OUTNOCOL}"
173 ############################################################################
175 # use the naming conventions v{Major}_{minos}{tiny} for the subdir
176 # to match that used by UPS at FNAL.
178 topdir=v${major}_${minor}${tiny}
179 toppath=`pwd`/${topdir}
181 echo -e ${OUTCYAN}version $version major $major minor $minor tiny $tiny ${OUTNOCOL}
182 echo -e ${OUTGREEN}full path: $toppath ${OUTNOCOL}
184 if [ ! -d ${topdir} ] ; then
188 for subdir in inc lib download src tpythia6_build ; do
189 if [ ! -d ${subdir} ] ; then
194 ############################################################################
196 # pick a fortran: g77 vs. gfortran vs. g95
198 if [ "$whichftn" == "unknown" ] ; then
199 # for now not g95 option ...
200 # whichg95=`which g95 | grep -v "no g95 in"`
201 if [ ! -z "${whichg95}" ] ; then
205 whichgfortran=`which gfortran | grep -v "no gfortran in"`
206 if [ ! -z "${whichgfortran}" ] ; then
210 whichg77=`which g77 | grep -v "no g77 in"`
211 if [ ! -z "${whichg77}" ] ; then
214 echo "could not find a fortran compiler (g95, gfortran, g77)"
219 export FORT=$whichftn
220 echo -e "${OUTGREEN}using $FORT as fortran compiler${OUTNOCOL}"
222 ############################################################################
225 # (various scripts disagree about where the include files should live)
228 if [ ! -f inc ] ; then
229 echo make symlink src/../inc src/inc
232 echo src/inc symlink exists
237 ############################################################################
241 # routine for building up linkage "-Lpath -llibrary" in variable
242 # given by varname (arg 1) for library (arg 2) in potential locations
243 # (args 3+). Don't repeat location in string. Look for various extensions
250 while [ $# -gt 0 ] ; do
253 for ext in .a .so .dylib ; do
254 fullname=${loc}/lib${libname}${ext}
255 #echo look for ${fullname}
256 if [ -f ${fullname} ] ; then
257 #echo hit it at -L${loc} -l${libname}
259 echo ${!varname} | grep ${loc} 2>&1 > /dev/null
260 if [ $? -ne 0 ] ; then
261 export $varname="${!varname} -L${loc} -l${libname}"
263 export $varname="${!varname} -l${libname}"
268 if [ ${foundlib} -ne 0 ] ; then break ; fi
272 ############################################################################
274 # look for the CERNLIB libraries: pdflib[804], mathlib, kernlib
275 # these are needed in order to satisfy the removed dummy routines
276 # if they can't be found then don't remove the dummies
278 CERNLINK="" # -L${CERNLIBS} -lpdflib804 -lmathlib -lkernlib"
279 if [ "$dummyaction" = "keep" ] ; then
280 echo requested to keep dummy PDFSET, STRUCTM and STRUCTP
283 add2link CERNLINK pdflib $CERNLIB $CERNLIBS $CERN_DIR/lib $CERN_ROOT/lib
284 if [ ${foundlib} -eq 0 ] ; then
285 add2link CERNLINK pdflib804 $CERNLIB $CERNLIBS $CERN_DIR/lib $CERN_ROOT/lib
286 if [ ${foundlib} -eq 0 ] ; then
287 missinglib="$missinglib pdflib[804]"
290 add2link CERNLINK mathlib $CERNLIB $CERNLIBS $CERN_DIR/lib $CERN_ROOT/lib
291 if [ ${foundlib} -eq 0 ] ; then
292 missinglib="$missinglib mathlib"
294 add2link CERNLINK kernlib $CERNLIB $CERNLIBS $CERN_DIR/lib $CERN_ROOT/lib
295 if [ ${foundlib} -eq 0 ] ; then
296 missinglib="$missinglib kernlib"
298 # didn't find something?
299 if [ -n "$missinglib" ] ; then
300 echo "### unable to locate library: ${missinglib} "
301 if [ "$dummyaction" = "besttry" ] ; then
302 echo "### revert to keeping dummy PDFSET, STRUCTM and STRUCTP "
309 if [ -n "$CERNLINK" ] ; then
310 echo will attempt to resolve removed dummies with CERNLINK =
313 fi # user didn't initially request "keep"
315 ############################################################################
317 if [ ${doclean} -ne 0 ] ; then
318 echo clean out old code
321 ############################################################################
323 # decide on how to fetch the source files
325 cd ${toppath}/download
327 # wget or curl for retreiving remote files?
328 # (OS X doesn't generally have wget on it, so fall back on curl in that case)
330 whichfetchit=`which wget | grep -v "no wget in"`
331 if [ ! -z "${whichfetchit}" ] ; then
332 echo use \"wget\" for fetching files
333 fetchit='wget --no-check-certificate '
335 whichfetchit=`which curl | grep -v "no curl in"`
336 if [ ! -z "${whichfetchit}" ] ; then
337 # -f = fail without creating dummy, -O output local named like remoteza
338 echo use \"curl -f -O\" for fetching files
339 fetchit='curl -f -O '
341 echo "Neither wget nor curl available -- can't download files"
346 ############################################################################
348 # retrieve the pythia6 fortran soruce file
349 # naming and location depends on version
352 if [ $mt -lt 410 ] ; then
353 # old location, unzip .f file
354 basef=pythia${major}${minor}${tiny}.f
355 #location=http://www.thep.lu.se/~torbjorn/pythia
356 #location=http://home.thep.lu.se/~torbjorn/pythia
358 elif [ $mt -eq 410 ] ; then
359 # not a case we can handle
360 # there is a .tar.gz file at the new location .. but that's too much work
361 echo "source files for minor version $minor can't be handled by this script"
364 # new location, .f file is gzipped
365 basef=pythia${major}${minor}${tiny}.f
366 #location=hhttp://home.thep.lu.se/~torbjorn/pythia6
367 #location=http://home.thep.lu.se/~torbjorn/pythia6
368 location=https://pythia.org/download/pythia6
371 # if we don't already have it, fetch the .f file
372 if [ ! -f ${basef}_with_dummies -o ${refetch} -ne 0 ] ; then
373 echo -e "${OUTCYAN}${fetchit} ${location}/${basef}${gzipped} ${OUTNOCOL}"
374 $fetchit ${location}/${basef}${gzipped}
375 if [ ! ${basef}${gzipped} ] ; then
376 echo -e "${OUTRED}Sorry could not fetch ${basef}${gzipped} from ${location}${OUTNOCOL}"
379 if [ -n "${gzipped}" ] ; then
381 gzip -d ${basef}${gzipped}
383 mv ${basef} ${basef}_with_dummies
386 ############################################################################
388 # fetch the ROOT interface code
390 if [ ! -f pythia6.tar.gz -o ${refetch} -ne 0 ] ; then
391 # rooti="ftp://root.cern.ch/root/pythia6.tar.gz"
392 rooti=https://root.cern.ch/download/pythia6.tar.gz
393 echo -e "${OUTCYAN}${fetchit} ${rooti}${OUTNOCOL}"
397 ############################################################################
399 # need to remove PDFSET/STRUCTM/STRUCTP routines from pythia6 code
400 # if we're using PDFLIB to supply the PDFSET, STRUCTM, STRUCTP routines
402 if [ "$dummyaction" = "keep" ] ; then
403 cp ${basef}_with_dummies ${basef}
404 echo not removing dummy routines
406 cat > rm_dummy.awk <<EOF
407 BEGIN { writeout=1; isend=0; }
408 /SUBROUTINE PDFSET/ { writeout=0; }
409 /SUBROUTINE STRUCTM/ { writeout=0; }
410 /SUBROUTINE STRUCTP/ { writeout=0; }
411 / END\$/ { if ( writeout == 1 ) print \$0; writeout=1; isend=1; }
412 // { if ( writeout == 1 && isend != 1 ) print \$0; isend=0; }
414 awk -f rm_dummy.awk ${basef}_with_dummies > ${basef}
417 # extract block data routine
418 #cat > extract_pydata.awk <<EOF
419 #BEGIN { writeout=0; }
420 #/C...PYDATA/ { writeout=1; }
421 #/ END\$/ { if ( writeout == 1 ) print \$0; writeout=0; }
422 #// { if ( writeout == 1 ) print \$0; }
424 #awk -f extract_pydata.awk ${basef} > pydata.f
426 ############################################################################
428 # create a Makefile for the pythia6 source code
433 # simple pythia6 makefile
435 UNAME = \$(shell uname)
436 ifeq "\$(UNAME)" "Linux"
439 FFLAG= -O -fno-second-underscore -fPIC $m32flag
443 ifeq "\$(UNAME)" "Darwin"
446 FFLAG= -O -fno-second-underscore -fPIC $m32flag
451 CPPFLGS = \$(CPPFLG) -D\$(UNAME)
453 FOBJSALL = \$(patsubst %.f,%.o,\$(wildcard *.f)) \
454 \$(patsubst %.F,%.o,\$(wildcard *.F))
456 # remove the "pdfdum.o" as we don't want that going into the .a library
457 FOBJS = \$(filter-out pdfdum.o,\$(FOBJSALL))
459 #------------------------------------------
461 all: \$(LIB)/liblund.a \$(LIB)/pydata.o
463 \$(LIB)/liblund.a: \$(FOBJS)
464 \$(AR) -urs \$(LIB)/liblund.a \$(FOBJS)
466 \$(LIB)/pydata.o: pydata.o
467 cp -p pydata.o \$(LIB)/pydata.o
469 \$(LIB)/pdfdum.o: pdfdum.o
470 cp -p pdfdum.o \$(LIB)/pdfdum.o
476 rm -f \$(LIB)/liblund.a \$(LIB)/pydata.o \$(LIB)/pdfdum.o
479 #------------------------------------------
484 \$(F77) \$(FFLAG) -c \$<
487 \$(F77) \$(FFLAG) -c \$<
491 ############################################################################
493 # split the pythia6 source code, build the library
495 whichfsplit=`which fsplit | grep -v "no fsplit in"`
496 echo initial ${whichfsplit}
497 if [ -z "${whichfsplit}" ] ; then
498 echo "No 'fsplit' -- can't build library without it"
499 echo "try to build fsplit"
500 # echo -e "${OUTCYAN}$fetchit -O http://home.fnal.gov/~rhatcher/fsplit.c ${OUTNOCOL}"
501 # $fetchit http://home.fnal.gov/~rhatcher/fsplit.c
502 echo -e "${OUTCYAN}$fetchit https://scisoft.fnal.gov/scisoft/packages/fsplit/fsplit.c ${OUTNOCOL}"
503 $fetchit https://scisoft.fnal.gov/scisoft/packages/fsplit/fsplit.c
505 gcc -o fsplit fsplit.c
507 whichfsplit=`which fsplit`
508 echo "built ${whichfsplit}"
511 if [ ! -z "${whichfsplit}" ] ; then
512 echo "build static lund library"
513 if [ ${doclean} -gt 0 ] ; then rm -f *.f ; fi
514 if [ ! -f pydata.f ] ; then
515 fsplit ${toppath}/download/${basef}
516 # hack for illegal computation in DATA statement in some versions
517 # apparently works for g77 but not gfortran
518 mv pyalps.f pyalps.f_original
519 sed -e 's+(2D0\*107D0/2025D0)+0.10567901234568D0+g' \
520 -e 's+(2D0\*963D0/14375D0)+0.13398260869565D0+g' \
521 -e 's+(2D0\*321D0/3703D0)+0.17337294085876D0+g' \
522 -e 's+(-2D0\*107D0/1875D0)+-0.11413333333333D0+g' \
523 -e 's+(-2D0\*963D0/13225D0)+-0.14563327032136D0+g' \
524 -e 's+(-2D0\*321D0/3381D0)+-0.18988464951198D0+g' \
525 pyalps.f_original > pyalps.f
528 if [ "$dummyaction" != "keep" ] ; then
529 for junk in pdfset.f structm.f structp.f ; do
530 if [ -f ${junk} ] ; then
531 echo "${junk} in split output, should have been removed"
539 ############################################################################
541 # build the ROOT interface library libPythia6.so
543 echo "build ROOT accessable shared library"
544 cd ${toppath}/tpythia6_build
546 tar xzvf ${toppath}/download/pythia6.tar.gz pythia6/tpythia6_called_from_cc.F
547 tar xzvf ${toppath}/download/pythia6.tar.gz pythia6/pythia6_common_address.c
550 echo 'void MAIN__() {}' > main.c
551 gcc -c -fPIC -fcommon $m32flag main.c
552 gcc -c -fPIC -fcommon $m32flag pythia6_common_address.c
553 $FORT -c -fPIC -fno-second-underscore $m32flag tpythia6_called_from_cc.F
558 if [ ${arch} == "Linux" ] ; then
559 $FORT $m32flag -shared -Wl,-soname,libPythia6.so -o libPythia6.so \
560 ${toppath}/tpythia6_build/*.o ${toppath}/src/*.o ${CERNLINK}
562 if [ ${arch} == "Darwin" ] ; then
563 macosx_minor=`sw_vers | sed -n 's/ProductVersion://p' | cut -d . -f 2`
564 gcc $m32flag -dynamiclib -flat_namespace -single_module -undefined dynamic_lookup \
565 -install_name ${toppath}/lib/libPythia6.dylib -o libPythia6.dylib \
566 ${toppath}/tpythia6_build/*.o ${toppath}/src/*.o ${CERNLINK}
567 if [ $macosx_minor -ge 4 ]; then
568 ln -sf libPythia6.dylib libPythia6.so
570 gcc $m32flag -bundle -flat_namespace -undefined dynamic_lookup -o libPythia6.so \
571 ${toppath}/tpythia6_build/*.o ${toppath}/src/*.o ${CERNLINK}
575 ############################################################################
577 # create pythia6 include files for common blocks
579 # here we'd like to automate the extraction of the common common blocks
580 # into include files but it's non-trivial
582 echo "extract include files"
585 # define a #include that declares the types of all the pythia functions
586 cat > pyfunc.inc <<EOF
587 C...standard pythia functions
588 double precision PYFCMP,PYPCMP
589 double precision PYCTEQ,PYGRVV,PYGRVW,PYGRVS,PYCT5L,PYCT5M,PYHFTH
590 double precision PYGAMM,PYSPEN,PYTBHS,PYRNMQ,PYRNM3,PYFINT,PYFISB
591 double precision PYXXZ6,PYXXGA,PYX2XG,PYX2XH,PYH2XX
592 double precision PYGAUS,PYGAU2,PYSIMP,PYLAMF,PYTHAG
593 double precision PYRVSB,PYRVI1,PYRVI2,PYRVI3,PYRVG1,PYRVG2,PYRVG3
594 double precision PYRVG4,PYRVR, PYRVS, PY4JTW,PYMAEL
595 double precision PYMASS,PYMRUN,PYALEM,PYALPS,PYANGL
596 double precision PYR, PYP
597 integer PYK,PYCHGE,PYCOMP
600 external PYFCMP,PYPCMP
601 external PYCTEQ,PYGRVV,PYGRVW,PYGRVS,PYCT5L,PYCT5M,PYHFTH
602 external PYGAMM,PYSPEN,PYTBHS,PYRNMQ,PYRNM3,PYFINT,PYFISB
603 external PYXXZ6,PYXXGA,PYX2XG,PYX2XH,PYH2XX
604 external PYGAUS,PYGAU2,PYSIMP,PYLAMF,PYTHAG
605 external PYRVSB,PYRVI1,PYRVI2,PYRVI3,PYRVG1,PYRVG2,PYRVG3
606 external PYRVG4,PYRVR, PYRVS, PY4JTW,PYMAEL
607 external PYMASS,PYMRUN,PYALEM,PYALPS,PYANGL
609 external PYK,PYCHGE,PYCOMP
613 # how to "automate" the others ... including declaring the types
614 # without using the IMPLICIT DOUBLE PRECISION etc.
615 # NEUGEN3 needs pydat1.inc pydat3.inc pyjets.inc at a minimum
616 # !!!! for now just hard-code them !!!
618 cat > pydat1.inc <<EOF
621 double precision PARU, PARJ
622 COMMON/PYDAT1/MSTU(200),PARU(200),MSTJ(200),PARJ(200)
625 cat > pydat2.inc <<EOF
626 C...Particle properties + some flavour parameters.
628 double precision PMAS, PARF, VCKM
629 COMMON/PYDAT2/KCHG(500,4),PMAS(500,4),PARF(2000),VCKM(4,4)
632 cat > pydat3.inc <<EOF
633 C...Decay information
634 integer MDCY, MDME, KFDP
635 double precision BRAT
636 COMMON/PYDAT3/MDCY(500,3),MDME(8000,2),BRAT(8000),KFDP(8000,5)
639 cat > pyjets.inc <<EOF
640 C...The event record.
642 double precision P, V
643 COMMON/PYJETS/N,NPAD,K(4000,5),P(4000,5),V(4000,5)
647 cat > pypars.inc <<EOF
650 double precision PARP, PARI
651 COMMON/PYPARS/MSTP(200),PARP(200),MSTI(200),PARI(200)
654 cat > pysubs.inc <<EOF
655 C...Selection of hard scattering subprocesses
656 integer MSEL,MSELPD,MSUB, KFIN
657 double precision CKIN
658 COMMON/PYSUBS/MSEL,MSELPD,MSUB(500),KFIN(2,-40:40),CKIN(200)
661 ############################################################################
665 echo "end-of-script $0"