diff --git a/packages/openbabel/package.py b/packages/openbabel/package.py new file mode 100644 index 0000000000000000000000000000000000000000..37be524cc8f9defeea12ee4ae805426267fa7aa5 --- /dev/null +++ b/packages/openbabel/package.py @@ -0,0 +1,92 @@ +# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) + +from spack.package import * + + +class Openbabel(CMakePackage): + """Open Babel is a chemical toolbox designed to speak the many languages + of chemical data. It's an open, collaborative project allowing anyone to + search, convert, analyze, or store data from molecular modeling, chemistry, + solid-state materials, biochemistry, or related areas.""" + + homepage = "https://openbabel.org/wiki/Main_Page" + url = "https://github.com/openbabel/openbabel/archive/openbabel-3-0-0.tar.gz" + git = "https://github.com/openbabel/openbabel.git" + + maintainers("RMeli") + + version("master", branch="master") + version("3.1.1", tag="openbabel-3-1-1") + version("3.1.0", tag="openbabel-3-1-0") + version("3.0.0", tag="openbabel-3-0-0") + version("2.4.1", tag="openbabel-2-4-1") + version("2.4.0", tag="openbabel-2-4-0") + + variant("python", default=True, description="Build Python bindings") + variant("gui", default=True, description="Build with GUI") + variant("cairo", default=True, description="Build with Cairo (PNG output support)") + variant("openmp", default=False, description="Build with OpenMP") + variant("maeparser", default=False, description="Built with MAE parser") + variant("coordgen", default=False, description="Build with Coordgen") + + extends("python", when="+python") + + depends_on("python", type=("build", "run"), when="+python") + depends_on("cmake@3.1:", type="build") + depends_on("pkgconfig", type="build") + depends_on("swig@2.0:", type="build", when="+python") + + depends_on("boost +filesystem +iostreams +test") + depends_on("cairo", when="+cairo") # required to support PNG depiction + depends_on("pango", when="+cairo") # custom cairo requires custom pango + depends_on("eigen@3.0:") # required if using the language bindings + depends_on("libxml2") # required to read/write CML files, XML formats + depends_on("zlib") # required to support reading gzipped files + depends_on("rapidjson") # required to support JSON + depends_on("libsm") + depends_on("uuid") + + depends_on("maeparser", when="+maeparser") + depends_on("coordgen", when="+coordgen") + + # Needed for Python 3.6 support + patch("python-3.6-rtld-global.patch", when="@:2.4.1+python") + + # Convert tabs to spaces. Allows unit tests to pass + patch("testpdbformat-tabs-to-spaces.patch", when="@:2.4.1") + + def cmake_args(self): + spec = self.spec + args = [] + + if "+python" in spec: + args.extend( + [ + "-DPYTHON_BINDINGS=ON", + "-DPYTHON_EXECUTABLE={0}".format(spec["python"].command.path), + "-DRUN_SWIG=ON", + ] + ) + else: + args.append("-DPYTHON_BINDINGS=OFF") + + args.append(self.define_from_variant("BUILD_GUI", "gui")) + args.append(self.define_from_variant("ENABLE_OPENMP", "openmp")) + args.append(self.define_from_variant("WITH_MAEPARSER", "maeparser")) + args.append(self.define_from_variant("WITH_COORDGEN", "coordgen")) + + return args + + @run_after("install") + @on_package_attributes(run_tests=True) + def check_install(self): + obabel = Executable(join_path(self.prefix.bin, "obabel")) + obabel("-:C1=CC=CC=C1Br", "-omol") + + if "+python" in self.spec: + python("-c", "import openbabel") + if self.spec.version < Version("3.0.0"): + python("-c", "import pybel") diff --git a/packages/openbabel/python-3.6-rtld-global.patch b/packages/openbabel/python-3.6-rtld-global.patch new file mode 100644 index 0000000000000000000000000000000000000000..68cd56a1f5c7dd66df0f76598b81a098c84d3f14 --- /dev/null +++ b/packages/openbabel/python-3.6-rtld-global.patch @@ -0,0 +1,42 @@ +The DLFCN module has been removed from python 3.6, as it is not +documented. Same funtionality can be achive with the os module +that makes available the os.RTLD_GLOBAL variable for dlopen() + +See https://github.com/openbabel/openbabel/pull/372 for the +source of this patch. The original patch only affects the CMake +file that SWIG uses to generate openbabel.py. This patch also +includes changes to openbabel.py. + +diff -Nuar a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt +--- a/scripts/CMakeLists.txt 2017-05-17 10:02:54.408527942 -0500 ++++ b/scripts/CMakeLists.txt 2017-05-17 10:04:09.701598715 -0500 +@@ -81,11 +81,8 @@ + COMMAND ${SWIG_EXECUTABLE} -python -c++ -small -O -templatereduce -naturalvar -I${openbabel_SOURCE_DIR}/include -I${openbabel_BINARY_DIR}/include -o ${openbabel_SOURCE_DIR}/scripts/python/openbabel-python.cpp ${eigen_define} -outdir ${openbabel_SOURCE_DIR}/scripts/python ${openbabel_SOURCE_DIR}/scripts/openbabel-python.i + COMMAND ${CMAKE_COMMAND} -E echo "import sys" > ob.py + COMMAND ${CMAKE_COMMAND} -E echo "if sys.platform.find('linux'\) != -1:" >> ob.py +- COMMAND ${CMAKE_COMMAND} -E echo " try:" >> ob.py +- COMMAND ${CMAKE_COMMAND} -E echo " import dl" >> ob.py +- COMMAND ${CMAKE_COMMAND} -E echo " except ImportError:" >> ob.py +- COMMAND ${CMAKE_COMMAND} -E echo " import DLFCN as dl" >> ob.py +- COMMAND ${CMAKE_COMMAND} -E echo " sys.setdlopenflags(sys.getdlopenflags() | dl.RTLD_GLOBAL)" >> ob.py ++ COMMAND ${CMAKE_COMMAND} -E echo " import os" >> ob.py ++ COMMAND ${CMAKE_COMMAND} -E echo " sys.setdlopenflags(sys.getdlopenflags() | os.RTLD_GLOBAL)" >> ob.py + COMMAND cat ${openbabel_SOURCE_DIR}/scripts/python/openbabel.py >> ob.py + COMMAND ${CMAKE_COMMAND} -E copy ob.py ${openbabel_SOURCE_DIR}/scripts/python/openbabel.py + COMMAND ${CMAKE_COMMAND} -E remove ob.py +diff -Nuar a/scripts/python/openbabel.py b/scripts/python/openbabel.py +--- a/scripts/python/openbabel.py 2017-05-17 10:02:54.398527534 -0500 ++++ b/scripts/python/openbabel.py 2017-05-17 10:04:26.705292138 -0500 +@@ -1,10 +1,7 @@ + import sys + if sys.platform.find('linux') != -1: +- try: +- import dl +- except ImportError: +- import DLFCN as dl +- sys.setdlopenflags(sys.getdlopenflags() | dl.RTLD_GLOBAL) ++ import os ++ sys.setdlopenflags(sys.getdlopenflags() | os.RTLD_GLOBAL) + # This file was automatically generated by SWIG (http://www.swig.org). + # Version 3.0.10 + # diff --git a/packages/openbabel/testpdbformat-tabs-to-spaces.patch b/packages/openbabel/testpdbformat-tabs-to-spaces.patch new file mode 100644 index 0000000000000000000000000000000000000000..0a71a72e014ad1b5cd895599c97cfa6e66eef582 --- /dev/null +++ b/packages/openbabel/testpdbformat-tabs-to-spaces.patch @@ -0,0 +1,47 @@ +From 08cd38485d4cf1df8802da540f3018921dbc735e Mon Sep 17 00:00:00 2001 +From: "Adam J. Stewart" <ajstewart426@gmail.com> +Date: Wed, 17 May 2017 10:56:23 -0500 +Subject: [PATCH] Convert tabs to spaces in testpdbformat.py + +See https://github.com/openbabel/openbabel/pull/1568 + +--- + test/testpdbformat.py | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/test/testpdbformat.py b/test/testpdbformat.py +index 40bd316..ceb8496 100644 +--- a/test/testpdbformat.py ++++ b/test/testpdbformat.py +@@ -24,12 +24,12 @@ class TestPDBFormat(BaseTest): + + def testInsertionCodes(self): + """ +- Testing a PDB entry with insertion codes to distinguish residues +- upon conversion to FASTA. ++ Testing a PDB entry with insertion codes to distinguish residues ++ upon conversion to FASTA. + """ + self.canFindExecutable("babel") + +- self.entryPDBwithInsertioncodes="""ATOM 406 N VAL L 29 58.041 17.797 48.254 1.00 0.00 N ++ self.entryPDBwithInsertioncodes="""ATOM 406 N VAL L 29 58.041 17.797 48.254 1.00 0.00 N + ATOM 407 CA VAL L 29 57.124 18.088 47.170 1.00 0.00 C + ATOM 408 C VAL L 29 55.739 17.571 47.538 1.00 0.00 C + ATOM 409 O VAL L 29 55.535 16.362 47.550 1.00 0.00 O +@@ -100,9 +100,9 @@ ATOM 473 HE1 TYR L 32 48.512 15.775 42.066 1.00 0.00 H + ATOM 474 HE2 TYR L 32 48.145 19.172 44.648 1.00 0.00 H + ATOM 475 HH TYR L 32 46.462 17.658 44.280 1.00 0.00 H + """ +- output, error = run_exec(self.entryPDBwithInsertioncodes, +- "babel -ipdb -ofasta") +- self.assertEqual(output.rstrip().rsplit("\n",1)[1], "VSSSY") ++ output, error = run_exec(self.entryPDBwithInsertioncodes, ++ "babel -ipdb -ofasta") ++ self.assertEqual(output.rstrip().rsplit("\n",1)[1], "VSSSY") + + if __name__ == "__main__": + testsuite = [] +-- +2.9.4 +