Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,10 @@ tags

# source distribution tarball
libdiffpy-*.tar.gz


.vs/*
.exp
.lib
.dll
.vscode/*
65 changes: 50 additions & 15 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ SCons construction environment can be customized in sconscript.local script.
"""

import os
import platform
from os.path import join as pjoin
from SCons.Script import *

def subdictionary(d, keyset):
return dict(kv for kv in d.items() if kv[0] in keyset)
Expand All @@ -37,40 +38,71 @@ DefaultEnvironment(ENV=subdictionary(os.environ, '''
# Create construction environment
env = DefaultEnvironment().Clone()

# Variables definitions below work only with 0.98.1 or later.
# Variables definitions below work only with 0.98.1 or later
env.EnsureSConsVersion(0, 98, 1)

# Customizable compile variables
vars = Variables('sconsvars.py')

vars.Add(PathVariable(
'prefix',
'installation prefix directory',
'/usr/local'))
vars.Update(env)
# Set PATHs
if 'PREFIX' in os.environ:
vars.Add(PathVariable(
'prefix',
'installation prefix directory',
os.environ['prefix']))
vars.Update(env)
elif 'CONDA_PREFIX' in os.environ:
vars.Add(PathVariable(
'prefix',
'installation prefix directory',
os.environ['CONDA_PREFIX']))
vars.Update(env)
else:
vars.Add(PathVariable(
'prefix',
'installation prefix directory',
'/usr/local'))
vars.Update(env)

if env['PLATFORM'] == "win32":
include_path = pjoin(env['prefix'], 'Library', 'include')
lib_path = pjoin(env['prefix'], 'Library', 'lib')
shared_path = pjoin(env['prefix'], 'Library', 'share')

env['ENV']['TMP'] = os.environ['TMP']
else:
include_path = pjoin(env['prefix'], 'include')
lib_path = pjoin(env['prefix'], 'lib')
shared_path = pjoin(env['prefix'], 'share')

vars.Add(PathVariable(
'libdir',
'installation directory for compiled library [prefix/lib]',
env['prefix'] + '/lib',
'installation directory for compiled programs',
lib_path,
PathVariable.PathAccept))
vars.Add(PathVariable(
'includedir',
'installation directory for C++ header files [prefix/include]',
env['prefix'] + '/include',
'installation directory for C++ header files',
include_path,
PathVariable.PathAccept))
vars.Add(PathVariable(
'datadir',
'installation directory for architecture independent data [prefix/share]',
env['prefix'] + '/share',
'installation directory for architecture independent data',
shared_path,
PathVariable.PathAccept))

env.AppendUnique(CPPPATH=[include_path])
env.AppendUnique(LIBPATH=[lib_path])

# Customizable build variables
vars.Add(EnumVariable(
'build',
'compiler settings',
'fast', allowed_values=('fast', 'debug', 'coverage')))
vars.Add(EnumVariable(
'tool',
'C++ compiler toolkit to be used',
'default', allowed_values=('default', 'intelc')))
'default', allowed_values=('default', 'clang', 'gcc', 'intelc')))
vars.Add(BoolVariable(
'enable_objcryst',
'enable objcryst support, when installed', None))
Expand All @@ -83,11 +115,14 @@ vars.Add(
vars.Add(BoolVariable(
'test_installed',
'build tests using the installed library.', False))

vars.Update(env)

env.Help(MY_SCONS_HELP % vars.GenerateHelpText(env))

env['has_objcryst'] = None
btags = [env['build'], platform.machine()]

btags = [env['build'], env['PLATFORM']]
if env['profile']: btags.append('profile')
builddir = env.Dir('build/' + '-'.join(btags))

Expand Down
161 changes: 111 additions & 50 deletions src/SConscript
Original file line number Diff line number Diff line change
@@ -1,66 +1,104 @@
import os
from SCons.Script import *
from os.path import join as pjoin

Import('env')

# Build environment configuration --------------------------------------------

# Insert LIBRARY_PATH explicitly because some compilers
# ignore it in the system environment.
env.PrependUnique(LIBPATH=env['ENV'].get('LIBRARY_PATH', '').split(':'))

# Use Intel C++ compiler if requested by the user.
icpc = None
# Use C++ compiler specified by the 'tool' option.
# Intel C++ compiler
if env['tool'] == 'intelc':
icpc = env.WhereIs('icpc')
if not icpc:
print("Cannot find the Intel C/C++ compiler 'icpc'.")
Exit(1)
env.Tool('intelc', topdir=icpc[:icpc.rfind('/bin')])
env=env.Clone()

fast_linkflags = ['-s']
# Clang++ compiler
if env['tool'] == 'clang':
llvm = env.WhereIs('clang++')
if not llvm:
print("Cannot find the clang++ compiler.")
Exit(1)
env=env.Clone(tools=['clangxx'])

# Specify minimum C++ standard. Allow later standard from sconscript.local.
# In case of multiple `-std` options the last option holds.
env.PrependUnique(CXXFLAGS='-std=c++11', delete_existing=1)
# g++ compiler
if env['tool'] == 'gcc':
gcc = env.WhereIs('g++')
if not gcc:
print("Cannot find the g++ compiler.")
Exit(1)
env=env.Clone(tools=['mingw'])

# Default use scons auto found compiler

# Platform specific intricacies.
fast_linkflags = ['-s']

# macOS specific options
if env['PLATFORM'] == 'darwin':
env.AppendUnique(CXXFLAGS='-ftemplate-depth-256')
env.Append(SHLINKFLAGS=['-install_name', '$TARGET.abspath'])
env.AppendUnique(SHLINKFLAGS=['-install_name', '$TARGET.abspath'])
env.AppendUnique(SHLINKFLAGS='-headerpad_max_install_names')
fast_linkflags[:] = []

# Compiler specific options
if icpc:
# options for Intel C++ compiler on hpc dev-intel07
env.PrependUnique(CCFLAGS=['-w1', '-fp-model', 'precise'])
env.PrependUnique(LIBS=['imf'])
fast_optimflags = ['-fast', '-no-ipo']
else:
# g++ options
env.PrependUnique(CCFLAGS=['-Wall'])
fast_optimflags = ['-ffast-math']

# Configure build variants
if env['build'] == 'debug':
env.Append(CCFLAGS='-g')
elif env['build'] == 'coverage':
env.CacheDir(None)
env.Append(CCFLAGS=['-g', '--coverage', '-O0'])
env.Append(LINKFLAGS='--coverage')
elif env['build'] == 'fast':
env.AppendUnique(CCFLAGS=['-O3'] + fast_optimflags)
env.AppendUnique(CPPDEFINES={'NDEBUG' : None})
env.AppendUnique(LINKFLAGS=fast_linkflags)

if env['profile']:
env.AppendUnique(CCFLAGS='-pg')
env.AppendUnique(LINKFLAGS='-pg')
if env['PLATFORM'] == "win32":
if env['tool'] == 'clang':
# clang++ on Windows
env['CC'] = 'clang'
env['CCFLAGS'] = ['-O3', '-ffast-math', '-std=c++14', '-m64', '-DBUILD_DLL']
env.PrependUnique(CPPDEFINES='_USE_MATH_DEFINES')
env['LINKFLAGS']= ['-fuse-ld=lld-link', '-m64', '-lstdc++']

elif env['tool'] == 'gcc':
# MinGW
env.PrependUnique(CCFLAGS=['-O3', '-std=c++14', '-m64', '-DBUILD_DLL'])
env.PrependUnique(CPPDEFINES='_USE_MATH_DEFINES')
env.AppendUnique(LINKFLAGS='-m64')

else:
# Visual c++
env.PrependUnique(CCFLAGS=['/Ox', '/EHsc', '/MD', '/std:c++14', '/Wall', '/DBUILD_DLL'])
env.AppendUnique(CPPDEFINES=[{'NDEBUG': None}, '_USE_MATH_DEFINES'])
env.AppendUnique(LINKFLAGS=['/OPT:NOREF', '/OPT:NOICF'])

else:
env.PrependUnique(CXXFLAGS='-std=c++11')
if env['tool'] == 'intelc':
# options for Intel C++ compiler on hpc dev-intel07
env.PrependUnique(CCFLAGS=['-w1', '-fp-model', 'precise'])
env.PrependUnique(LIBS=['imf'])
fast_optimflags = ['-fast', '-no-ipo']
else:
# g++ options
env.PrependUnique(CCFLAGS=['-Wall'])
fast_optimflags = ['-ffast-math']

# Configure build variants
if env['build'] == 'debug':
env.Append(CCFLAGS='-g')
elif env['build'] == 'coverage':
env.CacheDir(None)
env.Append(CCFLAGS=['-g', '--coverage', '-O0'])
env.Append(LINKFLAGS='--coverage')
elif env['build'] == 'fast':
env.AppendUnique(CCFLAGS=['-O3'] + fast_optimflags)
env.AppendUnique(CPPDEFINES={'NDEBUG' : None})
env.AppendUnique(LINKFLAGS=fast_linkflags)

if env['profile']:
env.AppendUnique(CCFLAGS='-pg')
env.AppendUnique(LINKFLAGS='-pg')


# configure boost and ObjCryst libraries unless non-relevant.
skip_configure = (GetOption('clean') or GetOption('help') or
(['sdist'] == list(COMMAND_LINE_TARGETS)))

# Check dependencies
if not skip_configure:
SConscript('SConscript.configure')

Expand Down Expand Up @@ -117,11 +155,15 @@ if 'sdist' in COMMAND_LINE_TARGETS:
# use new environment with extra libraries needed for libdiffpy.
env_lib = env.Clone()
# Setup GSL, the GNU Scientific library.
env_lib.ParseConfig("gsl-config --cflags --libs")
# The dladdr call in runtimepath.cpp requires the dl library.
env_lib.AppendUnique(LIBS=['dl'])
# The dladdr call in runtimepath.cpp requires the dl library for Windows.
if env['has_objcryst'] == True:
env_lib.AppendUnique(LIBS=['dl', 'gsl', 'gslcblas','boost_serialization', 'libobjcryst'])
else:
env_lib.AppendUnique(LIBS=['dl', 'gsl', 'gslcblas','boost_serialization'])


libdiffpy = env_lib.SharedLibrary('diffpy', env['lib_sources'])

# Clean up .gcda and .gcno files from coverage analysis.
env_lib.Clean(libdiffpy, Glob('diffpy/*.gc??'))
env_lib.Clean(libdiffpy, Glob('diffpy/srreal/*.gc??'))
Expand All @@ -141,17 +183,36 @@ if targets_that_test.intersection(COMMAND_LINE_TARGETS):
prefix = env['prefix']

# install-lib
install_lib = env.Install(env['libdir'], libdiffpy)
if env['PLATFORM'] == 'darwin':
# DARWIN_INSTALL_NAME can be pre-set in sconscript.local
env.SetDefault(DARWIN_INSTALL_NAME='$TARGET.abspath')
env.AddPostAction(install_lib,
'install_name_tool -id $DARWIN_INSTALL_NAME $TARGET')
if env['PLATFORM'] == 'posix' and WhereIs('ldconfig'):
opts = '' if os.getuid() == 0 else '-n'
env.AddPostAction(install_lib,
'ldconfig %s $TARGET.dir' % opts)
Alias('install-lib', install_lib)
if env['PLATFORM'] in ['darwin', 'posix']:
install_lib = env.Install(env['libdir'], libdiffpy)
if env['PLATFORM'] == 'darwin':
# DARWIN_INSTALL_NAME can be pre-set in sconscript.local
env.SetDefault(DARWIN_INSTALL_NAME='$TARGET.abspath')
env.AddPostAction(install_lib,
'install_name_tool -id $DARWIN_INSTALL_NAME $TARGET')
if env['PLATFORM'] == 'posix' and WhereIs('ldconfig'):
opts = '' if os.getuid() == 0 else '-n'
env.AddPostAction(install_lib,
'ldconfig %s $TARGET.dir' % opts)
Alias('install-lib', install_lib)

if env['PLATFORM'] == 'win32':
bindir = pjoin(prefix, 'Library', 'bin')
for node in libdiffpy:
ext = os.path.splitext(str(node))[1].lower()
if ext == '.dll':
dll_node = node
elif ext == '.lib':
lib_node = node

if dll_node is None:
print("Warning: DLL file not found in build outputs.")
if lib_node is None:
print("Warning: LIB file not found in build outputs.")

install_dll = env.Install(bindir, dll_node)
install_lib = env.Install(env['libdir'], lib_node)
Alias('install-lib', [install_dll, install_lib])

# install-include
ninc = len(Dir('.').path) + 1
Expand Down
Loading