Skip to content

Commit

Permalink
Simplify Boost easyblock
Browse files Browse the repository at this point in the history
Followup to #2456
This now saves some work by building Boost.MPI with the main build and
installing directly into the final folder without an intermediate copy
step
Also a bit of cleanup, fixing comments, ...
  • Loading branch information
Flamefire committed Jul 14, 2021
1 parent 09c8b6c commit 13a07d0
Showing 1 changed file with 44 additions and 49 deletions.
93 changes: 44 additions & 49 deletions easybuild/easyblocks/b/boost.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def __init__(self, *args, **kwargs):
"""Initialize Boost-specific variables."""
super(EB_Boost, self).__init__(*args, **kwargs)

self.objdir = None
self.prefixdir = None

self.pyvers = []

Expand Down Expand Up @@ -134,9 +134,11 @@ def configure_step(self):
if self.cfg['boost_mpi'] and not self.toolchain.options.get('usempi', None):
raise EasyBuildError("When enabling building boost_mpi, also enable the 'usempi' toolchain option.")

# create build directory (Boost doesn't like being built in source dir)
self.objdir = os.path.join(self.builddir, 'obj')
mkdir(self.objdir)
if self.cfg['only_python_bindings']:
# Use temporary directory and copy only Python files later
self.prefixdir = os.path.join(self.builddir, 'obj')
else:
self.prefixdir = self.installdir

# generate config depending on compiler used
toolset = self.cfg['toolset']
Expand All @@ -149,7 +151,7 @@ def configure_step(self):
raise EasyBuildError("Unknown compiler used, don't know what to specify to --with-toolset, aborting.")

cmd = "%s ./bootstrap.sh --with-toolset=%s --prefix=%s %s"
tup = (self.cfg['preconfigopts'], toolset, self.objdir, self.cfg['configopts'])
tup = (self.cfg['preconfigopts'], toolset, self.prefixdir, self.cfg['configopts'])
run_cmd(cmd % tup, log_all=True, simple=True)

# Use build_toolset if specified or the bootstrap toolset without the OS suffix
Expand Down Expand Up @@ -204,22 +206,10 @@ def configure_step(self):

write_file('user-config.jam', '\n'.join(user_config), append=True)

def build_boost_variant(self, bjamoptions, paracmd):
"""Build Boost library with specified options for bjam."""
# build with specified options
cmd = "%s ./%s %s %s %s" % (self.cfg['prebuildopts'], self.bjamcmd, bjamoptions, paracmd, self.cfg['buildopts'])
run_cmd(cmd, log_all=True, simple=True)
# install built Boost library
cmd = "%s ./%s %s install %s %s" % (
self.cfg['preinstallopts'], self.bjamcmd, bjamoptions, paracmd, self.cfg['installopts'])
run_cmd(cmd, log_all=True, simple=True)
# clean up before proceeding with next build
run_cmd("./%s %s --clean-all" % (self.bjamcmd, bjamoptions), log_all=True, simple=True)

def build_step(self):
"""Build Boost with bjam tool."""

self.bjamoptions = " --prefix=%s --user-config=user-config.jam" % self.objdir
self.bjamoptions = " --prefix=%s --user-config=user-config.jam" % self.prefixdir
if 'toolset=' not in self.cfg['buildopts']:
self.bjamoptions += " toolset=" + self.toolset

Expand All @@ -232,10 +222,10 @@ def build_step(self):
cxxflags += '1'
else:
cxxflags += '0'
if cxxflags is not None:
if cxxflags:
self.bjamoptions += " cxxflags='%s'" % cxxflags
ldflags = os.getenv('LDFLAGS')
if ldflags is not None:
if ldflags:
self.bjamoptions += " linkflags='%s'" % ldflags

# specify path for bzip2/zlib if module is loaded
Expand All @@ -245,19 +235,16 @@ def build_step(self):
self.bjamoptions += " -s%s_INCLUDE=%s/include" % (lib.upper(), libroot)
self.bjamoptions += " -s%s_LIBPATH=%s/lib" % (lib.upper(), libroot)

self.paracmd = ''
if self.cfg['parallel']:
self.paracmd = "-j %s" % self.cfg['parallel']
else:
self.paracmd = ''

if self.cfg['only_python_bindings']:
# magic incantation to only install Boost Python bindings is... --with-python
# see http://boostorg.github.io/python/doc/html/building/installing_boost_python_on_your_.html
self.bjamoptions += " --with-python"

# Default threading since at least 1.47.0 is multi with system layout
threading = " threading=multi"
layout = " --layout=system"

if LooseVersion(self.version) >= LooseVersion("1.69.0"):
# As of 1.69.0 we build with layout tagged and both single and multi threading
# Linking default libraries to multi-threaded versions.
Expand All @@ -266,20 +253,25 @@ def build_step(self):
if self.cfg['single_threaded'] is None:
self.cfg['single_threaded'] = True

# Default threading since at least 1.47.0 is multi with system layout

if self.cfg['tagged_layout']:
layout = " --layout=tagged"
layout = "tagged"
else:
layout = "system"

if self.cfg['single_threaded']:
if not self.cfg['tagged_layout']:
raise EasyBuildError("Singled threaded build requires tagged layout.")
threading = " threading=single,multi"
threading = "single,multi"
else:
threading = "multi"

self.bjamoptions += threading + layout
self.bjamoptions += " threading=" + threading + " --layout=" + layout

if self.cfg['boost_mpi']:
self.log.info("Building boost_mpi library")
mpi_bjamoptions = " --with-mpi"
self.build_boost_variant(self.bjamoptions + mpi_bjamoptions, self.paracmd)
if not self.cfg['boost_mpi']:
# Default but avoids a warning. Building Boost.MPI is actually enabled by `using mpi` in the user-config
self.bjamoptions += " --without-mpi"

self.log.info("Building Boost libraries")
# build with specified options
Expand Down Expand Up @@ -308,13 +300,12 @@ def install_step(self):
])
run_cmd(cmd, log_all=True, simple=True)

self.log.info("Copying %s to installation dir %s", self.objdir, self.installdir)
if self.cfg['only_python_bindings'] and 'Python' in self.cfg['multi_deps'] and self.iter_idx > 0:
self.log.info("Main installation should already exist, only copying over missing Python libraries.")
copy(glob.glob(os.path.join(self.objdir, 'lib', 'libboost_python*')), os.path.join(self.installdir, 'lib'),
self.log.info("Main installation should already exist, only copying over missing Python libraries "
"from %s to installation dir %s.", self.prefixdir, self.installdir)
copy(glob.glob(os.path.join(self.prefixdir, 'lib', 'libboost_python*')),
os.path.join(self.installdir, 'lib'),
symlinks=True)
else:
copy(glob.glob(os.path.join(self.objdir, '*')), self.installdir, symlinks=True)

if self.cfg['tagged_layout']:
if LooseVersion(self.version) >= LooseVersion("1.69.0") or not self.cfg['single_threaded']:
Expand All @@ -334,32 +325,36 @@ def sanity_check_step(self):
'files': [],
'dirs': ['include/boost']
}
if self.cfg['tagged_layout']:
lib_mt_suffix = '-mt'
# Architecture tags introduced in 1.69.0
if LooseVersion(self.version) >= LooseVersion("1.69.0"):
if get_cpu_architecture() == AARCH64:
lib_mt_suffix += '-a64'
elif get_cpu_architecture() == POWER:
lib_mt_suffix += '-p64'
else:
lib_mt_suffix += '-x64'

if self.cfg['only_python_bindings']:
for pyver in self.pyvers:
pymajorver = pyver.split('.')[0]
pyminorver = pyver.split('.')[1]
pymajorver, pyminorver = pyver.split('.')[:2]
if LooseVersion(self.version) >= LooseVersion("1.67.0"):
suffix = '%s%s' % (pymajorver, pyminorver)
elif int(pymajorver) >= 3:
suffix = pymajorver
else:
suffix = ''
custom_paths['files'].append(os.path.join('lib', 'libboost_python%s.%s' % (suffix, shlib_ext)))
if self.cfg['tagged_layout']:
custom_paths['files'].append(
os.path.join('lib', 'libboost_python%s%s.%s' % (suffix, lib_mt_suffix, shlib_ext)))

else:
custom_paths['files'].append(os.path.join('lib', 'libboost_system.%s' % shlib_ext))

if self.cfg['tagged_layout']:
lib_mt_suffix = '-mt'
# MT libraries gained an extra suffix from v1.69.0 onwards
if LooseVersion(self.version) >= LooseVersion("1.69.0"):
if get_cpu_architecture() == AARCH64:
lib_mt_suffix += '-a64'
elif get_cpu_architecture() == POWER:
lib_mt_suffix += '-p64'
else:
lib_mt_suffix += '-x64'

custom_paths['files'].append(os.path.join('lib', 'libboost_system%s.%s' % (lib_mt_suffix, shlib_ext)))
custom_paths['files'].append(os.path.join('lib', 'libboost_thread%s.%s' % (lib_mt_suffix, shlib_ext)))

if self.cfg['boost_mpi']:
Expand Down

0 comments on commit 13a07d0

Please sign in to comment.