xref: /petsc/config/BuildSystem/config/packages/TetGen.py (revision 7b2fcb5d6efa604aac62606659be4a62fc8a0438)
1import config.package
2
3class Configure(config.package.Package):
4  def __init__(self, framework):
5    config.package.Package.__init__(self, framework)
6    self.download     = ['http://www.tetgen.org/1.5/src/tetgen1.6.0.tar.gz',
7                         'https://web.cels.anl.gov/projects/petsc/download/externalpackages/tetgen1.6.0.tar.gz']
8    self.liblist      = [['libtet.a']]
9    self.includes     = ['tetgen.h']
10    self.buildLanguage= 'Cxx'
11    return
12
13  def setupHelp(self, help):
14    import nargs
15    config.package.Package.setupHelp(self, help)
16    help.addArgument('TETGEN', '-download-tetgen-build-exec=<bool>', nargs.ArgBool(None, False, 'Build and install the tetgen executable in addition to the library'))
17    return
18
19  def setupDependencies(self, framework):
20    config.package.Package.setupDependencies(self, framework)
21    self.languages       = framework.require('PETSc.options.languages',   self)
22    self.sharedLibraries = framework.require('PETSc.options.sharedLibraries', self)
23    self.mathlib         = framework.require('config.packages.mathlib',self)
24    self.deps            = [self.mathlib]
25    return
26
27  def Install(self):
28    import os, sys
29    import config.base
30    import fileinput
31
32    libDir         = self.libDir
33    includeDir     = os.path.join(self.installDir, 'include')
34    binDir     = os.path.join(self.installDir, 'bin')
35    makeinc        = os.path.join(self.packageDir, 'make.inc')
36    configheader   = os.path.join(self.packageDir, 'configureheader.h')
37
38    # This make.inc stuff is completely unnecessary for compiling TetGen. It is
39    # just here for comparing different PETSC_ARCH's
40    self.pushLanguage('C++')
41    g = open(makeinc,'w')
42    g.write('SHELL            = '+self.programs.SHELL+'\n')
43    g.write('CP               = '+self.programs.cp+'\n')
44    g.write('RM               = '+self.programs.RM+'\n')
45    g.write('MKDIR            = '+self.programs.mkdir+'\n')
46    g.write('OMAKE            = '+self.make.make+' '+self.make.noprintdirflag+'\n')
47
48    g.write('CLINKER          = '+self.getLinker()+'\n')
49    g.write('AR               = '+self.setCompilers.AR+'\n')
50    g.write('ARFLAGS          = '+self.setCompilers.AR_FLAGS+'\n')
51    g.write('AR_LIB_SUFFIX    = '+self.setCompilers.AR_LIB_SUFFIX+'\n')
52    g.write('RANLIB           = '+self.setCompilers.RANLIB+'\n')
53    g.write('SL_LINKER_SUFFIX = '+self.setCompilers.sharedLibraryExt+'\n')
54
55    g.write('TETGEN_ROOT      = '+self.packageDir+'\n')
56    g.write('PREFIX           = '+self.installDir+'\n')
57    g.write('LIBDIR           = '+libDir+'\n')
58    g.write('INSTALL_LIB_DIR  = '+libDir+'\n')
59    g.write('TETGENLIB        = $(LIBDIR)/libtet.$(AR_LIB_SUFFIX)\n')
60    g.write('SHLIB            = libtet\n')
61
62    cflags = self.updatePackageCFlags(self.getCompilerFlags())
63    cflags += ' '+self.headers.toString('.')
64    cflags += ' -fPIC'
65    cflags_exe = cflags
66    cflags += ' -DTETLIBRARY'
67    predcflags = '-O0 -fPIC'    # Need to compile without optimization
68
69    g.write('CC             = '+self.getCompiler()+'\n')
70    g.write('CFLAGS         = '+cflags+'\n')
71    g.write('PREDCXXFLAGS   = '+predcflags+'\n')
72    g.close()
73
74    # Now compile & install
75    if self.installNeeded('make.inc'):
76      self.framework.outputHeader(configheader)
77      try:
78        self.logPrintBox('Compiling & installing TetGen; this may take several minutes')
79        output,err,ret = config.package.Package.executeShellCommand('mkdir -p '+os.path.join(self.installDir,'lib'), timeout=2500, log=self.log)
80        output,err,ret = config.package.Package.executeShellCommand('mkdir -p '+os.path.join(self.installDir,'include'), timeout=2500, log=self.log)
81        output1,err1,ret1  = config.package.Package.executeShellCommand('cd '+self.packageDir+' && make CXX="'+ self.getCompiler() + '" CXXFLAGS="' + cflags + '" PREDCXXFLAGS="' + predcflags + '" tetlib && cp *.a ' + libDir + ' && rm *.a *.o', timeout=2500, log = self.log)
82        if self.argDB['download-tetgen-build-exec']:
83          output2,err2,ret2  = config.package.Package.executeShellCommand('cd '+self.packageDir+' && make CXX="'+ self.getCompiler() + '" CXXFLAGS="' + cflags_exe + '" PREDCXXFLAGS="' + predcflags + '" tetgen && cp tetgen ' + binDir + ' && rm tetgen', timeout=2500, log = self.log)
84      except RuntimeError as e:
85        raise RuntimeError('Error running make on TetGen: '+str(e))
86      output2,err2,ret2  = config.package.Package.executeShellCommand('cp -f '+os.path.join(self.packageDir, 'tetgen.h')+' '+includeDir, timeout=60, log = self.log)
87      self.postInstall(output1+err1+output2+err2,'make.inc')
88
89    self.popLanguage()
90    return self.installDir
91
92  def configureLibrary(self):
93    config.package.Package.configureLibrary(self)
94    include = '#include <tetgen.h>'
95    body = \
96'''
97  char args[] = "";
98  tetgenio in,out;
99  tetrahedralize(args, &in, &out);
100'''
101    self.pushLanguage('Cxx')
102    oldFlags = self.compilers.CXXPPFLAGS
103    oldLibs  = self.compilers.LIBS
104    self.compilers.CXXPPFLAGS += ' '+self.headers.toString(self.include)
105    self.compilers.LIBS = self.libraries.toString(self.lib)+' '+self.compilers.LIBS
106    if not self.checkCompile(include,body):
107      self.compilers.CXXPPFLAGS += ' -DTETLIBRARY'
108      if self.checkCompile(include,body):
109        self.addDefine('HAVE_TETGEN_TETLIBRARY_NEEDED',1)
110      else:
111        raise RuntimeError('Unable to compile with TetGen')
112    if not self.checkLink(include,body):
113      raise RuntimeError('Unable to link TetGen')
114    self.compilers.CXXPPFLAGS = oldFlags
115    self.compilers.LIBS = oldLibs
116    self.popLanguage()
117