mirror of
https://github.com/schrodinger/pymol-open-source.git
synced 2026-06-03 19:54:24 +08:00
Replace monkeypatch distutils with CMake setuptools Extensions
This commit is contained in:
31
CMakeLists.txt
Normal file
31
CMakeLists.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
project(${TARGET_NAME})
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE on)
|
||||
|
||||
add_library(${TARGET_NAME} SHARED ${ALL_SRC})
|
||||
|
||||
target_compile_options(${TARGET_NAME} PRIVATE ${ALL_COMP_ARGS})
|
||||
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ${SHARED_SUFFIX})
|
||||
|
||||
target_compile_features(${TARGET_NAME} PRIVATE cxx_std_17)
|
||||
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
target_include_directories(${TARGET_NAME} PUBLIC ${ALL_INC_DIR})
|
||||
|
||||
target_link_directories(${TARGET_NAME} PUBLIC ${ALL_LIB_DIR})
|
||||
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -undefined dynamic_lookup")
|
||||
endif()
|
||||
|
||||
target_link_libraries(${TARGET_NAME}
|
||||
${ALL_LIB}
|
||||
${ALL_EXT_LINK}
|
||||
)
|
||||
|
||||
target_compile_definitions(${TARGET_NAME} PUBLIC ${ALL_DEF})
|
||||
1
INSTALL
1
INSTALL
@@ -8,6 +8,7 @@ See also: http://pymolwiki.org/index.php/Linux_Install
|
||||
REQUIREMENTS
|
||||
|
||||
- C++17 compiler (e.g. gcc 8+)
|
||||
- CMake (3.13+)
|
||||
- Python 3.6+
|
||||
- Pmw (Python Megawidgets) (optional, for legacy GUI/plugins)
|
||||
https://github.com/schrodinger/pmw-patched
|
||||
|
||||
@@ -1053,7 +1053,7 @@ static PyMethodDef champ_methods[] = {
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
PyObject * PyInit__champ(void)
|
||||
PyMODINIT_FUNC PyInit__champ(void)
|
||||
{
|
||||
static struct PyModuleDef moduledef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
|
||||
@@ -6531,7 +6531,7 @@ static PyMethodDef Cmd_methods[] = {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
PyObject * PyInit__cmd(void)
|
||||
PyMODINIT_FUNC PyInit__cmd(void)
|
||||
{
|
||||
static struct PyModuleDef moduledef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
|
||||
176
setup.py
176
setup.py
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# This script only applies if you are performing a Python Distutils-based
|
||||
# This script only applies if you are performing a Python setuptools-based
|
||||
# installation of PyMOL.
|
||||
#
|
||||
# It may assume that all of PyMOL's external dependencies are
|
||||
@@ -9,12 +9,16 @@
|
||||
import argparse
|
||||
import glob
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
import sysconfig
|
||||
import shutil
|
||||
|
||||
from distutils.core import setup, Extension
|
||||
from distutils.util import change_root
|
||||
from setuptools import setup, Extension
|
||||
from setuptools.command.build_ext import build_ext
|
||||
from setuptools.command.build_py import build_py
|
||||
from setuptools.command.install import install
|
||||
|
||||
import create_shadertext
|
||||
|
||||
@@ -33,7 +37,6 @@ class options:
|
||||
no_libxml = False
|
||||
no_glut = True
|
||||
use_msgpackc = 'guess'
|
||||
help_distutils = False
|
||||
testing = False
|
||||
openvr = False
|
||||
use_openmp = 'no' if MAC else 'yes'
|
||||
@@ -58,8 +61,6 @@ parser.add_argument('--use-vtkm', choices=('1.5', '1.6', '1.7', 'no'),
|
||||
parser.add_argument('--use-msgpackc', choices=('c++11', 'c', 'guess', 'no'),
|
||||
help="c++11: use msgpack-c header-only library; c: link against "
|
||||
"shared library; no: disable fast MMTF load support")
|
||||
parser.add_argument('--help-distutils', action="store_true",
|
||||
help="show help for distutils options and exit")
|
||||
parser.add_argument('--testing', action="store_true",
|
||||
help="Build C-level tests")
|
||||
parser.add_argument('--openvr', dest='openvr', action='store_true')
|
||||
@@ -68,10 +69,7 @@ parser.add_argument('--no-vmd-plugins', dest='vmd_plugins',
|
||||
help='Disable VMD molfile plugins (libnetcdf dependency)')
|
||||
options, sys.argv[1:] = parser.parse_known_args(namespace=options)
|
||||
|
||||
if options.help_distutils:
|
||||
sys.argv.append("--help")
|
||||
|
||||
if True:
|
||||
if False:
|
||||
import monkeypatch_distutils
|
||||
monkeypatch_distutils.set_parallel_jobs(options.jobs)
|
||||
|
||||
@@ -137,16 +135,104 @@ def guess_msgpackc():
|
||||
return 'no'
|
||||
|
||||
|
||||
# Important: import 'distutils.command' modules after monkeypatch_distutils
|
||||
from distutils.command.build_ext import build_ext
|
||||
from distutils.command.build_py import build_py
|
||||
from distutils.command.install import install
|
||||
class CMakeExtension(Extension):
|
||||
|
||||
def __init__(self,
|
||||
name,
|
||||
sources,
|
||||
include_dirs=[],
|
||||
libraries=[],
|
||||
library_dirs=[],
|
||||
define_macros=[],
|
||||
extra_link_args=[],
|
||||
extra_compile_args=[]):
|
||||
# don't invoke the original build_ext for this special extension
|
||||
super().__init__(name, sources=[])
|
||||
self.sources = sources
|
||||
self.include_dirs = include_dirs
|
||||
self.libraries = libraries
|
||||
self.library_dirs = library_dirs
|
||||
self.define_macros = define_macros
|
||||
self.extra_link_args = extra_link_args
|
||||
self.extra_compile_args = extra_compile_args
|
||||
|
||||
|
||||
class build_ext_pymol(build_ext):
|
||||
def initialize_options(self):
|
||||
build_ext.initialize_options(self)
|
||||
def initialize_options(self) -> None:
|
||||
super().initialize_options()
|
||||
if DEBUG and not WIN:
|
||||
self.debug = True
|
||||
self.debug = False
|
||||
|
||||
def run(self):
|
||||
for ext in self.extensions:
|
||||
self.build_cmake(ext)
|
||||
|
||||
def build_cmake(self, ext):
|
||||
cwd = pathlib.Path().absolute()
|
||||
|
||||
# these dirs will be created in build_py, so if you don't have
|
||||
# any python sources to bundle, the dirs will be missing
|
||||
name_split = ext.name.split('.')
|
||||
target_name = name_split[-1]
|
||||
build_temp = pathlib.Path(self.build_temp) / target_name
|
||||
build_temp.mkdir(parents=True, exist_ok=True)
|
||||
extdir = pathlib.Path(self.get_ext_fullpath(ext.name))
|
||||
extdirabs = extdir.absolute()
|
||||
|
||||
extdir.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def concat_paths(paths):
|
||||
return ''.join(path.replace('\\', '/') + ";" for path in paths)
|
||||
|
||||
config = 'Debug' if DEBUG else 'Release'
|
||||
lib_output_dir = str(extdir.parent.absolute())
|
||||
all_files = ext.sources
|
||||
all_src = concat_paths(all_files)
|
||||
all_defs = ''.join(mac[0] + ";" for mac in ext.define_macros)
|
||||
all_libs = ''.join(f"{lib};" for lib in ext.libraries)
|
||||
all_ext_link = ' '.join(ext.extra_link_args)
|
||||
all_comp_args = ''.join(f"{arg};" for arg in ext.extra_compile_args)
|
||||
all_lib_dirs = concat_paths(ext.library_dirs)
|
||||
all_inc_dirs = concat_paths(ext.include_dirs)
|
||||
|
||||
lib_mode = "RUNTIME" if WIN else "LIBRARY"
|
||||
|
||||
shared_suffix = sysconfig.get_config_var('EXT_SUFFIX')
|
||||
|
||||
cmake_args = [
|
||||
f"-DTARGET_NAME={target_name}",
|
||||
f"-DCMAKE_{lib_mode}_OUTPUT_DIRECTORY={lib_output_dir}",
|
||||
f"-DCMAKE_BUILD_TYPE={config}",
|
||||
f"-DALL_INC_DIR={all_inc_dirs}",
|
||||
f"-DALL_SRC={all_src}",
|
||||
f"-DALL_DEF={all_defs}",
|
||||
f"-DALL_LIB_DIR={all_lib_dirs}",
|
||||
f"-DALL_LIB={all_libs}",
|
||||
f"-DALL_COMP_ARGS={all_comp_args}",
|
||||
f"-DALL_EXT_LINK={all_ext_link}",
|
||||
f"-DSHARED_SUFFIX={shared_suffix}"
|
||||
]
|
||||
|
||||
# example of build args
|
||||
build_args = ['--config', config]
|
||||
if not WIN: # Win /MP flag on compilation level
|
||||
cpu_count = os.cpu_count() or 1
|
||||
build_args += [f'-j{cpu_count}']
|
||||
|
||||
os.chdir(str(build_temp))
|
||||
self.spawn(['cmake', str(cwd)] + cmake_args)
|
||||
if not self.dry_run:
|
||||
self.spawn(['cmake', '--build', '.'] + build_args)
|
||||
|
||||
if WIN:
|
||||
# Move up from VS release folder
|
||||
cmake_lib_loc = pathlib.Path(lib_output_dir, "Release", f"{target_name}{shared_suffix}")
|
||||
if cmake_lib_loc.exists():
|
||||
shutil.move(cmake_lib_loc, extdirabs)
|
||||
|
||||
# Troubleshooting: if fail on line above then delete all possible
|
||||
# temporary CMake files including "CMakeCache.txt" in top level dir.
|
||||
os.chdir(str(cwd))
|
||||
|
||||
|
||||
class build_py_pymol(build_py):
|
||||
@@ -175,10 +261,11 @@ class install_pymol(install):
|
||||
self.pymol_path = os.path.join(
|
||||
self.install_libbase, 'pymol', 'pymol_path')
|
||||
elif self.root is not None:
|
||||
self.pymol_path = change_root(self.root, self.pymol_path)
|
||||
self.pymol_path = install_pymol.change_root(
|
||||
self.root, self.pymol_path)
|
||||
|
||||
def run(self):
|
||||
install.run(self)
|
||||
super().run()
|
||||
self.install_pymol_path()
|
||||
|
||||
if not self.no_launcher:
|
||||
@@ -304,7 +391,7 @@ ext_comp_args = [
|
||||
'-Wno-char-subscripts',
|
||||
# optimizations
|
||||
"-Og" if DEBUG else "-O3",
|
||||
] if not WIN else []
|
||||
] if not WIN else ["/MP"]
|
||||
ext_link_args = []
|
||||
ext_objects = []
|
||||
data_files = []
|
||||
@@ -382,9 +469,9 @@ if MAC:
|
||||
|
||||
if options.osx_frameworks:
|
||||
ext_link_args += [
|
||||
"-framework", "OpenGL",
|
||||
"-framework OpenGL",
|
||||
] + (not options.no_glut) * [
|
||||
"-framework", "GLUT",
|
||||
"-framework GLUT",
|
||||
]
|
||||
def_macros += [
|
||||
("_PYMOL_OSX", None),
|
||||
@@ -527,22 +614,37 @@ package_dir = dict((x, os.path.join(base, x))
|
||||
for base in ['modules']
|
||||
for x in get_packages(base))
|
||||
|
||||
ext_modules += [
|
||||
Extension("pymol._cmd",
|
||||
get_sources(pymol_src_dirs),
|
||||
include_dirs=inc_dirs,
|
||||
libraries=libs,
|
||||
library_dirs=lib_dirs,
|
||||
define_macros=def_macros,
|
||||
extra_link_args=ext_link_args,
|
||||
extra_compile_args=ext_comp_args,
|
||||
extra_objects=ext_objects,
|
||||
),
|
||||
# Python includes
|
||||
inc_dirs.append(sysconfig.get_paths()['include'])
|
||||
inc_dirs.append(sysconfig.get_paths()['platinclude'])
|
||||
|
||||
Extension("chempy.champ._champ",
|
||||
get_sources(['contrib/champ']),
|
||||
include_dirs=["contrib/champ"],
|
||||
),
|
||||
champ_inc_dirs = ['contrib/champ']
|
||||
champ_inc_dirs.append(sysconfig.get_paths()['include'])
|
||||
champ_inc_dirs.append(sysconfig.get_paths()['platinclude'])
|
||||
|
||||
if WIN:
|
||||
# pyconfig.py forces linking against pythonXY.lib on MSVC
|
||||
py_lib = pathlib.Path(sysconfig.get_paths()['stdlib']).parent / 'libs'
|
||||
lib_dirs.append(str(py_lib))
|
||||
|
||||
ext_modules += [
|
||||
CMakeExtension(
|
||||
name="pymol._cmd",
|
||||
sources=get_sources(pymol_src_dirs),
|
||||
include_dirs=inc_dirs,
|
||||
libraries=libs,
|
||||
library_dirs=lib_dirs,
|
||||
define_macros=def_macros,
|
||||
extra_link_args=ext_link_args,
|
||||
extra_compile_args=ext_comp_args,
|
||||
),
|
||||
|
||||
CMakeExtension(
|
||||
name="chempy.champ._champ",
|
||||
sources=get_sources(['contrib/champ']),
|
||||
include_dirs=champ_inc_dirs,
|
||||
library_dirs=lib_dirs,
|
||||
),
|
||||
]
|
||||
|
||||
distribution = setup( # Distribution meta-data
|
||||
|
||||
Reference in New Issue
Block a user