Skip to content

Commit

Permalink
New CMakeLists file to facilitate HDF5 library finding and building o…
Browse files Browse the repository at this point in the history
…f pyprismatic; new pyprismatic setup script to utilize CMake
  • Loading branch information
lerandc committed Jul 10, 2019
1 parent ca0b56a commit 6d85459
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 86 deletions.
87 changes: 66 additions & 21 deletions CMakeLists.txt
@@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.5)
message("CMake prefix path: " ${CMAKE_PREFIX_PATH})
project(PRISM)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_BUILD_TYPE RELEASE)
Expand All @@ -15,8 +16,10 @@ endif ( MSVC )
set(PRISMATIC_ENABLE_GUI 0 CACHE BOOL PRISMATIC_ENABLE_GUI)
set(PRISMATIC_ENABLE_GPU 0 CACHE BOOL PRISMATIC_ENABLE_GPU)
set(PRISMATIC_ENABLE_CLI 1 CACHE BOOL PRISMATIC_ENABLE_GPU)
set(PRISMATIC_ENABLE_PYTHON_GPU 0 CACHE BOOL PRISMATIC_ENABLE_PYTHON_GPU)
#set(PRISMATIC_ENABLE_PYTHON_GPU 0 CACHE BOOL PRISMATIC_ENABLE_PYTHON_GPU)
set(PRISMATIC_ENABLE_DOUBLE_PRECISION 0 CACHE BOOL PRISMATIC_ENABLE_DOUBLE_PRECISION)
set(PRISMATIC_ENABLE_PYPRISMATIC 0 CACHE BOOL PRISMATIC_ENABLE_PYPRISMATIC)
set(PRISMATIC_USE_HDF5_STATIC 0 CACHE BOOL PRISMATIC_USE_HDF5_STATIC)

#set (CMAKE_BUILD_TYPE DEBUG)
if (PRISMATIC_ENABLE_GPU)
Expand Down Expand Up @@ -68,16 +71,25 @@ endif (PRISMATIC_ENABLE_GPU)
find_package (Threads REQUIRED)
find_package (Boost REQUIRED)
find_package (FFTW3 REQUIRED)
find_package (HDF5 REQUIRED)

find_library(HDF5_HL_LIBRARY hdf5_hl)
find_library(HDF5_LIBRARY hdf5)
find_library(HDF5_HL_CPP_LIBRARY hdf5_hl_cpp)
find_library(HDF5_CPP_LIBRARY hdf5_cpp)
if(PRISMATIC_ENABLE_PYPRISMATIC)
find_package (PythonInterp 3.5 REQUIRED)
find_package (PythonLibs 3.5 REQUIRED)
endif(PRISMATIC_ENABLE_PYPRISMATIC)

set(HDF5_LIBRARIES ${HDF5_HL_LIBRARY} ${HDF5_LIBRARY} ${HDF5_HL_CPP_LIBRARY} ${HDF5_CPP_LIBRARY})
#set(HDF5_LIBRARIES ${HDF5_LIBRARIES})
if (PRISMATIC_USE_HDF5_STATIC)
message("entered")
set(HDF5_USE_STATIC_LIBRARIES ON)
endif (PRISMATIC_USE_HDF5_STATIC)

set(HDF5_FIND_COMPONENTS "C" "HL" "CXX")
find_package (HDF5 REQUIRED ${HDF5_FIND_COMPONENTS})
find_library(HDF5_C_HL_LIBRARIES hdf5_hl)
find_library(HDF5_C_LIBRARIES hdf5)
find_library(HDF5_CXX_HL_LIBRARIES hdf5_hl_cpp)
find_library(HDF5_CXX_LIBRARIES hdf5_cpp)

set(HDF5_LIBRARIES ${HDF5_C_HL_LIBRARIES} ${HDF5_C_LIBRARIES} ${HDF5_CXX_HL_LIBRARIES} ${HDF5_CXX_LIBRARIES})

message("Boost dir " ${Boost_INCLUDE_DIRS})
include_directories(${CMAKE_SOURCE_DIR}/include
Expand Down Expand Up @@ -233,16 +245,49 @@ if (PRISMATIC_ENABLE_CLI)
install(TARGETS prismatic RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
endif(PRISMATIC_ENABLE_CLI)

if (PRISMATIC_ENABLE_PYTHON_GPU AND PRISMATIC_ENABLE_GPU)
cuda_add_library(cuprismatic SHARED
${SOURCE_FILES}
${CUDA_SOURCE_FILES})
cuda_add_cufft_to_target(cuprismatic)
target_link_libraries(cuprismatic
${FFTW_LIBRARIES}
${HDF5_LIBRARIES})
target_compile_definitions(cuprismatic PRIVATE PRISMATIC_ENABLE_GPU=1 BUILDING_CUPRISMATIC=1 CUPRISMATIC_EXPORT=1)
install(TARGETS cuprismatic
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif(PRISMATIC_ENABLE_PYTHON_GPU AND PRISMATIC_ENABLE_GPU)
# if (PRISMATIC_ENABLE_PYTHON_GPU AND PRISMATIC_ENABLE_GPU)
# cuda_add_library(cuprismatic SHARED
# ${SOURCE_FILES}
# ${CUDA_SOURCE_FILES})
# cuda_add_cufft_to_target(cuprismatic)
# target_link_libraries(cuprismatic
# ${FFTW_LIBRARIES}
# ${HDF5_LIBRARIES})
# target_compile_definitions(cuprismatic PRIVATE PRISMATIC_ENABLE_GPU=1 BUILDING_CUPRISMATIC=1 CUPRISMATIC_EXPORT=1)
# install(TARGETS cuprismatic
# ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
# LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
# endif(PRISMATIC_ENABLE_PYTHON_GPU AND PRISMATIC_ENABLE_GPU)

if(PRISMATIC_ENABLE_PYPRISMATIC)

include_directories(${PYTHON_INCLUDE_DIRS})
if (PRISMATIC_ENABLE_GPU)
cuda_add_library(pyprismatic_core SHARED pyprismatic/core.cpp ${SOURCE_FILES} ${CUDA_SOURCE_FILES})
cuda_add_cufft_to_target(pyprismatic_core)
else (PRISMATIC_ENABLE_GPU)
add_library(pyprismatic_core SHARED pyprismatic/core.cpp ${SOURCE_FILES})
endif(PRISMATIC_ENABLE_GPU)

target_link_libraries(pyprismatic_core
${CMAKE_THREAD_LIBS_INIT}
${FFTW_LIBRARIES}
${HDF5_LIBRARIES}
${PYTHON_LIBRARIES})

set_target_properties(
pyprismatic_core
PROPERTIES
PREFIX ""
OUTPUT_NAME "core"
LINKER_LANGUAGE CXX
)

if(NOT UNIX)
set_target_properties(
pyprismatic_core
PROPERTIES
SUFFIX ".pyd"
)
endif(NOT UNIX)
endif(PRISMATIC_ENABLE_PYPRISMATIC)
158 changes: 93 additions & 65 deletions setup.py
Expand Up @@ -14,57 +14,37 @@
from setuptools import setup, Extension
from setuptools.command.install import install
from setuptools.command.develop import develop
from setuptools.command.build_ext import build_ext
import sys
import os
import platform
import subprocess

#os.environ['CC'] = 'gcc-7'
#os.environ['CXX'] = 'g++-7'
# Filename for the C extension module library
c_module_name = 'pyprismatic.core'

prismatic_extra_definitions = []
prismatic_libs = []
# Parse command line flags
options = {k: 'OFF' for k in ['--opt', '--debug', '--enable-gpu']}
for flag in options.keys():
if flag in sys.argv:
options[flag] = 'ON'
sys.argv.remove(flag)

# Command line flags forwarded to CMake
cmake_cmd_args = []
for f in sys.argv:
if f.startswith('-D'):
cmake_cmd_args.append(f)

for f in cmake_cmd_args:
sys.argv.remove(f)

# In CPU-only mode, all Prismatic C++ source files will be compiled into the Python package. For GPU support, a shared library is
# built from the CUDA/C++ sources and the Python package links against it. The C++ files that are potentially compiled into
# the shared library (along with CUDA files) are the "extra" sources and in CPU-mode they are added to the Python package sources.
# The reason for doing it this way is for user convenience so that compiling/linking to an extra Prismatic library is not required until
# enabling for GPU, at which point it is already necessary for the other CUDA libraries.

prismatic_sources_base = ["pyprismatic/core.cpp"]
obj_prefix = "build/CMakeFiles/prismatic.dir/src/"
prismatic_gpu_objects = ["prismatic_generated_Multislice_calcOutput.cu.o",
"prismatic_generated_PRISM02_calcSMatrix.cu.o",
"prismatic_generated_PRISM03_calcOutput.cu.o",
"prismatic_generated_utility.cu.o",
]

prismatic_gpu_objects = [obj_prefix + obj for obj in prismatic_gpu_objects]
prismatic_sources_extra = [
"src/go.cpp",
"src/atom.cpp",
"src/configure.cpp",
"src/Multislice_calcOutput.cpp",
"src/Multislice_entry.cpp", #
"src/parseInput.cpp", #
"src/PRISM01_calcPotential.cpp",
"src/PRISM02_calcSMatrix.cpp", #
"src/PRISM03_calcOutput.cpp", #
"src/PRISM_entry.cpp",
"src/projectedPotential.cpp", #
"src/utility.cpp", #
"src/WorkDispatcher.cpp",
]

prismatic_sources = prismatic_sources_base
prismatic_include_dirs = ["./include"]
prismatic_library_dirs = []
prismatic_extra_objects = [] #"/usr/local/hdf/lib/libhdf5_hl.so","/usr/local/hdf/lib/libhdf5.so","/usr/local/hdf/lib/libhdf5_hl_cpp.so","/usr/local/hdf/lib/libhdf5_cpp.so"]

if os.name == "nt": # check for Windows OS
prismatic_libs = ["libfftw3f-3"]
else:
prismatic_libs = ["fftw3f", "fftw3f_threads","hdf5_hl","hdf5","hdf5_hl_cpp","hdf5_cpp","pthread","dl","m"]
prismatic_extra_compile_defs = ["-std=c++11"]

class InstallCommand(install):
user_options = install.user_options + [("enable-gpu", None, None)]

Expand All @@ -91,38 +71,86 @@ def finalize_options(self):
def run(self):
develop.run(self)

if (
"--enable-gpu" in sys.argv
): # GPU-mode, add some macro definitions and link with the CUDA libraries
prismatic_extra_definitions.extend(
[("PRISMATIC_ENABLE_GPU", 1), ("BUILDING_CUPRISMATIC", 1)]
)
prismatic_libs.extend(["cufft", "cudart"])
prismatic_sources.extend(prismatic_sources_extra)
prismatic_extra_objects.extend(prismatic_gpu_objects)
else: # CPU-only mode, add the extra C++ sources to the python package
prismatic_sources.extend(prismatic_sources_extra)

pyprimsatic_core = Extension(
"pyprismatic.core",
sources=prismatic_sources,
include_dirs=prismatic_include_dirs,
extra_compile_args=prismatic_extra_compile_defs,
define_macros=prismatic_extra_definitions,
library_dirs=prismatic_library_dirs,
libraries=prismatic_libs,
extra_objects=prismatic_extra_objects,
)
class CMakeExtension(Extension):
def __init__(self, name, cmake_lists_dir='.', **kwa):
Extension.__init__(self, name, sources=[], **kwa)
self.cmake_lists_dir = os.path.abspath(cmake_lists_dir)

class cmake_build_ext(build_ext):
def build_extensions(self):
# Ensure that CMake is present and working
try:
out = subprocess.check_output(['cmake', '--version'])
except OSError:
raise RuntimeError('Cannot find CMake executable')

for ext in self.extensions:

extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
cfg = 'Debug' if options['--debug'] == 'ON' else 'Release'
if options['--enable-gpu'] == 'ON':
gpu_enable = '1'
else:
gpu_enable = '0'

cmake_args = [
'-DCMAKE_BUILD_TYPE=%s' % cfg,
# Ask CMake to place the resulting library in the directory
# containing the extension
'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir),
# Other intermediate static libraries are placed in a
# temporary build directory instead
'-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), self.build_temp),
# Hint CMake to use the same Python executable that
# is launching the build, prevents possible mismatching if
# multiple versions of Python are installed
'-DPYTHON_EXECUTABLE={}'.format(sys.executable),
'-DPRISMATIC_ENABLE_PYPRISMATIC=1',
'-DPRISMATIC_ENABLE_CLI=0',
'-DPRISMATIC_ENABLE_GPU={}'.format(gpu_enable)
]

# We can handle some platform-specific settings at our discretion
if platform.system() == 'Windows':
plat = ('x64' if platform.architecture()[0] == '64bit' else 'Win32')
cmake_args += [
# These options are likely to be needed under Windows
'-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE',
'-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir),
]
# Assuming that Visual Studio and MinGW are supported compilers
if self.compiler.compiler_type == 'msvc':
cmake_args += [
'-DCMAKE_GENERATOR_PLATFORM=%s' % plat,
]
else:
cmake_args += [
'-G', 'MinGW Makefiles',
]

cmake_args += cmake_cmd_args

if not os.path.exists(self.build_temp):
os.makedirs(self.build_temp)

# Config
subprocess.check_call(['cmake', ext.cmake_lists_dir] + cmake_args,
cwd=self.build_temp)

# Build
subprocess.check_call(['cmake', '--build', '.', '--config', cfg],
cwd=self.build_temp)

setup(
name="PyPrismatic",
author="Alan (AJ) Pryor, Jr.",
author_email="apryor6@gmail.com",
version="1.2.0",
description="Python wrapper for Prismatic package for fast image simulation using the PRISM and multislice algorithms in Scanning Transmission Electron Microscopy (STEM)",
ext_modules=[pyprimsatic_core],
ext_modules=[CMakeExtension(c_module_name)],
packages=["pyprismatic"],
install_requires=["numpy>=1.13.0", "matplotlib>=2.0.2","h5py>=2.9.0"],
cmdclass={"install": InstallCommand,
"develop":DevelopCommand},
)
"develop":DevelopCommand,
"build_ext":cmake_build_ext},
)

0 comments on commit 6d85459

Please sign in to comment.