Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: build for windows #35

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
95 changes: 75 additions & 20 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,17 @@ SCons construction environment can be customized in sconscript.local script.
"""

import os
from os.path import join as pjoin
import platform

def subdictionary(d, keyset):
return dict(kv for kv in d.items() if kv[0] in keyset)

def getsyspaths(*names):
pall = sum((os.environ.get(n, '').split(os.pathsep) for n in names), [])
rv = [p for p in pall if os.path.exists(p)]
return rv

# copy system environment variables related to compilation
DefaultEnvironment(ENV=subdictionary(os.environ, '''
PATH CPATH CPLUS_INCLUDE_PATH LIBRARY_PATH LD_RUN_PATH
Expand All @@ -43,26 +49,71 @@ env.EnsureSConsVersion(0, 98, 1)
# Customizable compile variables
vars = Variables('sconsvars.py')

vars.Add(PathVariable(
'prefix',
'installation prefix directory',
'/usr/local'))
vars.Update(env)
vars.Add(PathVariable(
'libdir',
'installation directory for compiled library [prefix/lib]',
env['prefix'] + '/lib',
PathVariable.PathAccept))
vars.Add(PathVariable(
'includedir',
'installation directory for C++ header files [prefix/include]',
env['prefix'] + '/include',
PathVariable.PathAccept))
vars.Add(PathVariable(
'datadir',
'installation directory for architecture independent data [prefix/share]',
env['prefix'] + '/share',
PathVariable.PathAccept))
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 platform.system().lower() == 'windows':
vars.Add(PathVariable(
'libdir',
'installation directory for compiled programs [prefix/Library/lib]',
pjoin(env['prefix'], 'Library', 'Lib'),
PathVariable.PathAccept))
vars.Add(PathVariable(
'includedir',
'installation directory for C++ header files [prefix/Library/include]',
pjoin(env['prefix'], 'Library', 'include'),
PathVariable.PathAccept))
vars.Add(PathVariable(
'datadir',
'installation directory for architecture independent data [prefix/share]',
pjoin(env['prefix'], 'Library', 'share'),
PathVariable.PathAccept))

env['ENV']['TMP'] = os.environ['TMP']
env.Append(CPPPATH=[pjoin(env['prefix'], 'Library', 'include')])
env.Append(LIBPATH=pjoin(env['prefix'], 'Library', 'lib'))

env.Append(CPPDEFINES=['_USE_MATH_DEFINES'])

else:
# Installation paths
vars.Add(PathVariable(
'libdir',
'installation directory for compiled library [prefix/lib]',
pjoin(env['prefix'], 'lib'),
PathVariable.PathAccept))
vars.Add(PathVariable(
'includedir',
'installation directory for C++ header files [prefix/include]',
pjoin(env['prefix'], 'include'),
PathVariable.PathAccept))
vars.Add(PathVariable(
'datadir',
'installation directory for architecture independent data [prefix/share]',
pjoin(env['prefix'], 'share'),
PathVariable.PathAccept))

env.Append(CPPPATH=[pjoin(env['prefix'], 'include')])
env.Append(LIBPATH=[pjoin(env['prefix'], 'lib')])



vars.Add(EnumVariable(
'build',
'compiler settings',
Expand All @@ -83,9 +134,13 @@ 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.PrependUnique(LIBPATH=getsyspaths('LIBRARY_PATH'))
env.AppendUnique(CPPDEFINES='BOOST_ALL_NO_LIB')

env['has_objcryst'] = None
btags = [env['build'], platform.machine()]
if env['profile']: btags.append('profile')
Expand Down
71 changes: 41 additions & 30 deletions src/SConscript
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import platform

Import('env')

Expand All @@ -21,8 +22,6 @@ fast_linkflags = ['-s']

# 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)

# Platform specific intricacies.
if env['PLATFORM'] == 'darwin':
env.AppendUnique(CXXFLAGS='-ftemplate-depth-256')
Expand All @@ -31,31 +30,39 @@ if env['PLATFORM'] == 'darwin':
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 platform.system().lower() == "windows":
# Visual c++
env.PrependUnique(CCFLAGS=['/Ox', '/EHsc', '/MD', '/std:c++14', '/Wall'])
env.AppendUnique(CPPDEFINES={'NDEBUG': None})
env.AppendUnique(LINKFLAGS=['/OPT:NOREF', '/OPT:NOICF', '/WHOLEARCHIVE:diffpy.lib'])
# env.AppendUnique(LINKFLAGS='/EXPORT')
else:
env.PrependUnique(CXXFLAGS='-std=c++11')
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')


# configure boost and ObjCryst libraries unless non-relevant.
Expand Down Expand Up @@ -117,11 +124,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'])
env_lib.AppendUnique(LIBS=['dl', 'gsl', 'gslcblas'])

if platform.system().lower() == "windows":
# Use a static library (does not require __declspec(dllexport) all over the code)
libdiffpy = env_lib.StaticLibrary('diffpy', env['lib_sources'])
else:
libdiffpy = env_lib.SharedLibrary('diffpy', env['lib_sources'])

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 Down
17 changes: 15 additions & 2 deletions src/SConscript.configure
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ def CheckBoostVersion(context, version):
context.Result(rv)
return rv

def CheckBoostSerialization(context):
context.Message('Checking for boost_serialization... ')
test_code = '''
#include <boost/serialization/serialization.hpp>
int main() { return 0; }
'''
rv = context.TryCompile(test_code, '.cpp')
context.Result(rv)
return rv

# Helper functions -----------------------------------------------------------

boostlibtags = ['', '-mt']
Expand All @@ -40,10 +50,12 @@ def configure_boost_library(libname):
print('This program requires %r library' % libname)
Exit(1)


# Start configuration --------------------------------------------------------

conf = Configure(env, custom_tests={
'CheckBoostVersion' : CheckBoostVersion,
'CheckBoostSerialization': CheckBoostSerialization
})

# serialization of unordered_map requires boost 1.56.0
Expand All @@ -52,8 +64,9 @@ if not conf.CheckBoostVersion(boost_required):
print('This software requires Boost %s or later.' % boost_required)
Exit(1)

# boost_serialization
configure_boost_library('boost_serialization')
if not conf.CheckBoostSerialization():
print('Boost.Serialization library not found!')
Exit(1)

# ObjCryst - assume a no-objcryst fallback configuration.
conf.env['has_objcryst'] = False
Expand Down
4 changes: 4 additions & 0 deletions src/diffpy/SConscript
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import platform

Import('env', 'GlobSources')

Expand All @@ -7,6 +8,9 @@ env['lib_sources'] += [f for f in GlobSources('*.cpp')
if str(f) != 'runtimepath.cpp']

rtrp = os.path.relpath(env['runtimepath'], env['libdir'])
if platform.system().lower() == 'windows':
rtrp = rtrp.replace('\\', '/')

env_rt = env.Clone()
env_rt.AppendUnique(CPPDEFINES=dict(DIFFPYRUNTIMERELPATH=rtrp))
rtso = env_rt.SharedObject('runtimepath', 'runtimepath.cpp')
Expand Down
10 changes: 10 additions & 0 deletions src/diffpy/boost_throw_exception.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <stdexcept>
#include <boost/throw_exception.hpp>

namespace boost {
void throw_exception(std::exception const & e)
{
// You can also customize the behavior here if needed.
throw e;
}
}
6 changes: 0 additions & 6 deletions src/diffpy/mathutils.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@ inline double remainder(double x, double y)
fmod(x, y) : (fmod(x, y) + y);
}


inline double log2(double x)
{
return log(x) / log(2.0);
}

#endif // _MSC_VER

namespace diffpy {
Expand Down
51 changes: 50 additions & 1 deletion src/diffpy/runtimepath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,57 @@
#include <sstream>
#include <stdexcept>
#include <sys/stat.h>
#include <dlfcn.h>
#include <dlfcn.h> // not available on Windows, conda install dlfcn-win32

// libgen.h is not available on Windows
#ifdef _WIN32
#include <string>
#include <algorithm>

// A simple replacement for dirname() on Windows.
inline std::string win_dirname(const std::string& path)
{
// Find the last occurrence of either '\' or '/'
size_t pos = path.find_last_of("\\/");
if (pos == std::string::npos)
return "."; // No directory found, return current directory
return path.substr(0, pos);
}

// Overload to match the expected C-style interface if needed:
inline char* dirname(char* path)
{
static std::string dir;
dir = win_dirname(std::string(path));
return const_cast<char*>(dir.c_str());
}
#else
#include <libgen.h>
#endif

// S_ISDIR, PATH_MAX, realpath, etc.
#ifdef _WIN32
#include <windows.h>
#include <stdlib.h> // for _fullpath
#include <sys/stat.h> // for _stat
#include <direct.h> // for _getcwd, etc.

// Define S_ISDIR using the Windows _S_IFDIR flag from sys/stat.h.
#ifndef S_ISDIR
#define S_ISDIR(mode) (((mode) & _S_IFDIR) == _S_IFDIR)
#endif

// Use MAX_PATH from <windows.h> as PATH_MAX if not defined.
#ifndef PATH_MAX
#define PATH_MAX MAX_PATH
#endif

// Define realpath in terms of _fullpath.
// _fullpath returns a pointer to the resolved path in the buffer you provide.
// The usage should be nearly equivalent.
#define realpath(N, R) _fullpath((R), (N), PATH_MAX)
#endif


#include <diffpy/version.hpp>
#include <diffpy/runtimepath.hpp>
Expand Down
10 changes: 7 additions & 3 deletions src/diffpy/srreal/StructureAdapter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
#include <diffpy/srreal/R3linalg.hpp>
#include <diffpy/srreal/BaseBondGenerator.hpp>

#ifdef _MSC_VER
#define DEPRECATED __declspec(deprecated)
#else
#define DEPRECATED __attribute__((deprecated))
#endif

namespace diffpy {
namespace srreal {

Expand Down Expand Up @@ -89,9 +95,7 @@ class StructureAdapter :

/// this method allows custom special configuration for a concrete
/// pair of StructureAdapter and PairQuantity objects.
virtual void customPQConfig(PairQuantity* pq) const
__attribute__ ((deprecated))
{ }
virtual DEPRECATED void customPQConfig(PairQuantity* pq) const { }

/// Return difference from the other StructureAdapter
virtual StructureDifference diff(StructureAdapterConstPtr) const;
Expand Down