~njansson/dolfin/hpc

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# -*- coding: utf-8 -*-

import os, os.path, sys
from distutils import sysconfig

# Make sure that we have a good scons-version
EnsureSConsVersion(0, 96)

# Import the local 'scons'
try:
  import simula_scons as scons
except ImportError:
  # Add simula-scons to sys.path and PYTHONPATH
  os.environ["PYTHONPATH"] = \
      os.pathsep.join([os.environ.get("PYTHONPATH",""),
                       os.path.join(os.getcwd(),"scons","simula-scons")])
  sys.path.insert(0, os.path.join(os.getcwd(),"scons","simula-scons"))
  import simula_scons as scons
 
# Import local exceptions
from simula_scons.Errors import PkgconfigError, PkgconfigMissing

# Create a SCons Environment based on the main os environment
env = Environment(ENV=os.environ)

# Set a projectname. Used in some places, like pkg-config generator
env["projectname"] = "dolfin"

scons.setDefaultEnv(env)

# Specify a file where SCons store file signatures, used to figure out what is
# changed. We store it in the 'scons' subdirectory to avoid mixing signatures
# with the files in dolfin. 
dolfin_sconsignfile = os.path.join(os.getcwd(), "scons", ".sconsign")
env.SConsignFile(dolfin_sconsignfile)

# -----------------------------------------------------------------------------
# Command line option handling
# -----------------------------------------------------------------------------

DefaultPackages = ""

# Build the commandline options for SCons:
options = [
    # configurable options for installation:
    scons.PathOption("prefix", "Installation prefix", "/usr/local"),
    scons.PathOption("libDir", "Library installation directory", "$prefix/lib"),
    scons.PathOption("includeDir", "C/C++ header installation directory", "$prefix/include"),
    scons.PathOption("pythonModuleDir", "Python module installation directory", 
                     scons.defaultPythonLib(prefix="$prefix")),
    scons.PathOption("pythonExtDir", "Python extension module installation directory", 
                     scons.defaultPythonLib(prefix="$prefix", plat_specific=True)),
    # configurable options for how we want to build:
    BoolOption("enableDebug", "Build with debug information", 1),
    BoolOption("enableDebugUblas", "Add some extra Ublas debug information", 0),
    BoolOption("enableOptimize", "Compile with optimization", 0),
    BoolOption("enableDocs", "Build documentation", 0),
    BoolOption("enableDemos", "Build demos", 0),
    # Enable or disable external packages.
    # These will also be listed in scons.cfg files, but if they are 
    # disabled here, that will override scons.cfg. Remark that unless the
    # module is listed as OptDependencies in scons.cfg, the whole module
    # will be turned off.
    BoolOption("enablePetsc", "Compile with support for PETSc linear algebra", "yes"),
    BoolOption("enableSlepc", "Compile with support for SLEPc", "yes"),
    BoolOption("enableScotch", "Compile with support for Scotch", "yes"),
    BoolOption("enableGts", "Compile with support for GTS", "yes"),
    BoolOption("enableUmfpack", "Compile with support for UMFPACK", "yes"),
    BoolOption("enablePydolfin", "Compile the python wrappers of Dolfin", "yes"),
    # some of the above may need extra options (like petscDir), should we
    # try to get that from pkg-config?
    #
    # a few more options originally from PyCC:
    #BoolOption("autoFetch", "Automatically fetch datafiles from (password protected) SSH repository", 0),
    BoolOption("cacheOptions", "Cache command-line options for later invocations", 1),
    BoolOption("veryClean", "Remove the sconsign file during clean, must be set during regular build", 0),
    # maybe we should do this more cleverly. The default in dolfin now is
    # to use mpicxx if that is available...:
    ("CXX", "Set C++ compiler",scons.defaultCxxCompiler()),
    #("FORTRAN", "Set FORTRAN compiler",scons.defaultFortranCompiler()),
    ("customCxxFlags", "Customize compilation of C++ code", ""),
    #("data", "Parameter to the 'fetch' target: comma-delimited list of directories/files to fetch, \
    #        relative to the `data' directory. An empty value means that everything will be fetched.", ""),
    #("sshUser", "Specify the user for the SSH connection used to retrieve data files", ""),
    #('usePackages','Override or add dependency packages, separate with comma', ""),
    #('customDefaultPackages','Override the default set of packages (%r), separate package names with commas' % (DefaultPackages,)),
    ("SSLOG", "Set Simula scons log file", os.path.join(os.getcwd(),"scons","simula_scons.log")),
    ]


# This Configure class handles both command-line options (which are merged into 
# the environment) and autoconf-style tests. A special feature is that it
# remembers configuration parameters (options and results from tests) between
# invocations so that they are re-used when cleaning after a previous build.
configure = scons.Configure(env, ARGUMENTS, options)

# Open log file for writing
scons.logOpen(env)
scons.log("=================== %s log ===================" % env["projectname"])
scons.logDate()

# Writing the simula_scons used to the log:
scons.log("Using simula_scons from: %s" % scons.__file__)


# If we are in very-clean mode, remove the sconsign file. 
if env.GetOption("clean"):
  if env["veryClean"]:
    os.unlink("%s.dblite" % (dolfin_sconsignfile))
    # FIXME: should we also remove the file scons/options.cache?
    
# Default CXX and FORTRAN flags
env["CXXFLAGS"] = "-Wall -pipe -ansi" # -Werror"
#env["SHFORTRANFLAGS"] = "-Wall -pipe -fPIC"

# If Debug is enabled, add -g:
if env["enableDebugUblas"]:
  env.Append(CXXFLAGS=" -DDEBUG -g -Werror")
elif env["enableDebug"]:
  env.Append(CXXFLAGS=" -DDEBUG -g -Werror -DNDEBUG")

# if Optimization is requested, use -O3
if env["enableOptimize"]:
  env.Append(CXXFLAGS=" -O3")
else:
  env.Append(CXXFLAGS=" -O2")

# Not sure we need this - but lets leave it for completeness sake - if people
# use if for PyCC, and know that dolfin use the same system, they will expect
# it to be here. We should probably discuss whether that is a good argument or
# not. 
# Append whatever custom flags given
if env["customCxxFlags"]:
  env.Append(CXXFLAGS=" " + env["customCxxFlags"])

# process list of packages to be included in allowed Dependencies.
# Do we need this any more? I think we rather pick up (external) packages from
# the scons.cfg files. Actually, I doubt usePackages is ever used?
#env["usePackages"] = scons.resolvePackages(env["usePackages"].split(','),\
#        env.get("customDefaultPackages", DefaultPackages).split(","))

# Figure out if we should fetch datafiles, and set an option in env. 
#doFetch = "fetch" in COMMAND_LINE_TARGETS or (env["autoFetch"]) and not env.GetOption("clean")
#env["doFetch"] = doFetch

# -----------------------------------------------------------------------------
# Call the main SConscript in the 'src' directory
# -----------------------------------------------------------------------------
try:
  # Invoke the SConscript as if it was situated in the build directory, this
  # tells SCons to build beneath this
  buildDataHash = env.SConscript(os.path.join("dolfin", "SConscript"), exports=["env", "configure"])
except PkgconfigError, err:
  sys.stderr.write("%s\n" % err)
  Exit(1)

# -----------------------------------------------------------------------------
# Set up build targets
# -----------------------------------------------------------------------------

# default build-targets: shared libs, extension modules, programs, demos, and
# documentation.
for n in buildDataHash["shlibs"] + buildDataHash["extModules"] + \
        buildDataHash["progs"] + buildDataHash["demos"], buildDataHash["docs"]:
  env.Default(n)

# -----------------------------------------------------------------------------
# Set up installation targets
# -----------------------------------------------------------------------------

# shared libraries goes into our libDir:
for l in buildDataHash["shlibs"]:
  env.Install(env["libDir"], l)

# install header files in the same structure as in the source tree, within
# includeDir/dolfin:
for h in buildDataHash["headers"]:
  # Get the module path relative to the "src" directory
  dpath = os.path.dirname(h.srcnode().path).split(os.path.sep, 1)[1]
  env.Install(os.path.join(env["includeDir"], "dolfin", dpath), h)
# Also, we want the special 'dolfin.h' file to be installed directly in the
# toplevel includeDir. 
if buildDataHash.has_key("main_header") and buildDataHash["main_header"] != "":
  env.Install(env["includeDir"], buildDataHash["main_header"])

## install python scripts in the bin directory
#for s in buildDataHash["pythonScripts"]:
#  env.Install(env["binDir"], s)

# install python modules, usually in site-packages/dolfin
for m in buildDataHash["pythonModules"]:
  env.Install(os.path.join(env["pythonModuleDir"], "dolfin"), m)

# install extension modules, usually in site-packages
for e in buildDataHash["extModules"]:
  env.Install(os.path.join(env["pythonExtDir"], "dolfin"), e)

# install created pkg-config files in prefix/lib/pkgconfig
#
for p in buildDataHash["pkgconfig"]:
  env.Install(os.path.join(env["libDir"], "pkgconfig"), p)

# grab prefix from the environment, substitute all scons construction variables
# (those prefixed with $...), and create a normalized path:
prefix = os.path.normpath(env.subst(env["prefix"]))
# add '/' (or similar) at the end of prefix if missing:
if not prefix[-1] == os.path.sep:
  prefix += os.path.sep

# not sure we need common.py for pydolfin.
#commonfile=os.path.join("site-packages", "pycc", "common.py")

installfiles = scons.buildFileList(
    buildDataHash["pythonPackageDirs"])

for f in installfiles:
  #installpath=os.path.sep.join(os.path.dirname(f).split(os.path.sep)[1:])
  env.Install(os.path.join(env["pythonModuleDir"],"dolfin"), f)

#env = scons.installCommonFile(env, commonfile, prefix)

# No data for dolfin?
_targetdir=os.path.join(prefix, "share", "dolfin", "data")
if 'install' in COMMAND_LINE_TARGETS and not os.path.isdir(_targetdir):
  os.makedirs(_targetdir)
env = scons.addInstallTargets(env, sourcefiles=buildDataHash["data"],
                              targetdir=_targetdir)

## No tests to install for dolfin?
## Not sure tests should be installed, have to check that.
#_targetdir=os.path.join(prefix, "share", "pycc", "tests")
#if 'install' in COMMAND_LINE_TARGETS and not os.path.isdir(_targetdir):
#  os.makedirs(_targetdir)
#env = scons.addInstallTargets(env, sourcefiles=buildDataHash["tests"],
#                              targetdir=_targetdir)

### I am not sure there are any docs to install with dolfin.
_targetdir=os.path.join(prefix, "share", "doc", "dolfin")
if 'install' in COMMAND_LINE_TARGETS and not os.path.isdir(_targetdir):
  os.makedirs(_targetdir)
env = scons.addInstallTargets(env, sourcefiles=buildDataHash["docs"],
                              targetdir=_targetdir)

# Instruct scons what to do when user requests 'install'
env.Alias("install", [env["libDir"], env["includeDir"],
                      env["pythonModuleDir"], env["pythonExtDir"]])

# _runTests used to use the global 'ret' (now buildDataHash). Therefore, we
# need to wrap _runTests in a closure, now that the functions is moved into
# 'scons'
_runTests = scons.gen_runTests(buildDataHash)

env.Command("runtests", buildDataHash["shlibs"] + buildDataHash["extModules"],
            Action(_runTests, scons._strRuntests))

# Create helper file for setting environment variables
pyversion=".".join([str(s) for s in sys.version_info[0:2]])
f = open('dolfin.conf', 'w')
f.write('export PATH="'            + prefix + 'bin:$PATH"\n')
f.write('export LD_LIBRARY_PATH="' + prefix + 'lib:$LD_LIBRARY_PATH"\n')
f.write('export PKG_CONFIG_PATH="' + prefix + 'lib/pkgconfig:$PKG_CONFIG_PATH"\n')
f.write('export PYTHONPATH="'      + prefix + 'lib/python'    + pyversion + '/site-packages:$PYTHONPATH"\n')
f.close()

# Close log file
scons.logClose()

# vim:ft=python ts=2 sw=2