Skip to content

Commit

Permalink
Progress on the installer!
Browse files Browse the repository at this point in the history
I think it should work for all platforms now using pip, including with
prefixes and staging. Next is to get the installed files locations.
  • Loading branch information
bryanwweber committed Jan 30, 2022
1 parent a5d5f99 commit 5a19786
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 61 deletions.
21 changes: 3 additions & 18 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,7 @@ env['cantera_short_version'] = re.match(r'(\d+\.\d+)', env['cantera_version']).g
try:
env["git_commit"] = get_command_output("git", "rev-parse", "--short", "HEAD")
logger.info(f"Building Cantera from git commit '{env['git_commit']}'")
except subprocess.CalledProcessError:
except (subprocess.CalledProcessError, FileNotFoundError):
env["git_commit"] = "unknown"

# Print values of all build options:
Expand Down Expand Up @@ -2066,23 +2066,6 @@ def getParentDirs(path, top=True):
# Files installed by SCons
allfiles = FindInstalledFiles()

# Files installed by the Python installer
if os.path.exists('build/python-installed-files.txt'):
with open('build/python-installed-files.txt', 'r') as f:
file_list = f.readlines()

install_base = os.path.dirname(file_list[0].strip())
if os.path.exists(install_base):
not_listed_files = [s for s in os.listdir(install_base) if not any(s in j for j in file_list)]
for f in not_listed_files:
f = pjoin(install_base, f)
if not os.path.isdir(f) and os.path.exists(f):
allfiles.append(File(f))
for f in file_list:
f = f.strip()
if not os.path.isdir(f) and os.path.exists(f):
allfiles.append(File(f))

# After removing files (which SCons keeps track of),
# remove any empty directories (which SCons doesn't track)
def removeDirectories(target, source, env):
Expand All @@ -2108,6 +2091,8 @@ def removeDirectories(target, source, env):

uninstall = env.Command("uninstall", None, Delete(allfiles))
env.AddPostAction(uninstall, Action(removeDirectories))
if env["python_package"] == "full":
env.AddPostAction(uninstall, Action("$python_cmd_esc -m pip uninstall Cantera"))

### Windows MSI Installer ###
if 'msi' in COMMAND_LINE_TARGETS:
Expand Down
93 changes: 50 additions & 43 deletions interfaces/cython/SConscript
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
"""Cython-based Python Module"""
from __future__ import annotations
from gettext import install
import re
from os.path import join as pjoin
import os
from os.path import normpath
from pathlib import Path
from threading import local
from pkg_resources import parse_version
import json
from buildutils import *
from textwrap import dedent

Import('env', 'build', 'install')

Expand All @@ -32,6 +36,9 @@ testFiles = localenv.RecursiveInstall('cantera/test/data',
'#test/data')
build(testFiles)

if localenv["python_prefix"]:
localenv["python_prefix"] = localenv.subst("$python_prefix")

# Get information needed to build the Python module
script = """\
from sysconfig import *
Expand Down Expand Up @@ -121,59 +128,59 @@ for f in (multi_glob(localenv, 'cantera', 'py') +
localenv.Depends(mod, f)

# Determine installation path and install the Python module
# IMO, if the Python we're installing for is the system Python,
# the default should be the user site directory.
python_prefix = "system"
install_cmd = ["$python_cmd_esc", "-m", "pip", "install"]


def get_install_location(user: bool = False, prefix: str = "", root: str = "") -> dict[str, str]:
install_script = dedent(f"""
from pip import __version__ as pip_version
from pkg_resources import parse_version
import json
pip_version = parse_version(pip_version)
if pip_version < parse_version("10.0.0"):
from pip.locations import distutils_scheme
scheme = distutils_scheme("Cantera", user={user}, root={root or "''"}, prefix={prefix or "''"})
else:
from pip._internal.locations import get_scheme
scheme = get_scheme("Cantera", user={user}, root={root or "''"}, prefix={prefix or "''"})
if not isinstance(scheme, dict):
scheme = {{k: getattr(scheme, k) for k in dir(scheme) if not k.startswith("_")}}
print(json.dumps(scheme))
""")
return json.loads(get_command_output(localenv["python_cmd"], "-c", install_script))


print(get_install_location())

if localenv['python_prefix'] == 'USER':
# Install to the OS-dependent user site-packages directory
extra = '--user'
install_path = Path(get_command_output(localenv["python_cmd"], "-c", "import site; print(site.getuserbase())")).resolve()
install_cmd.append("--user")
scheme = f"{os.name}_user"
install_dir = get_command_output(localenv["python_cmd"], "-c", f"import sysconfig; sysconfig.get_paths({scheme})")
# If prefix is set which implicitly sets python_prefix,
# or python_prefix is set explicitly, this path is followed.
elif localenv['python_prefix']:
# A specific location for the Cantera Python module has been given
if localenv['debian'] and localenv.subst('${python_prefix}') == '/usr/local':
# Installation to /usr/local is the default on Debian-based distributions
extra = ''
elif localenv['libdirname'] != 'lib':
# 64-bit RHEL / Fedora etc. or e.g. x32 Gentoo profile
extra = localenv.subst(
' --prefix=${{python_prefix}} --install-scripts=${{python_prefix}}/bin'
' --install-lib=${{python_prefix}}/${{libdirname}}/python{}/site-packages'.format(py_version_short))
else:
extra = '--user'
localenv.AppendENVPath(
'PYTHONUSERBASE',
normpath(localenv.subst('$python_prefix')))
install_cmd.append(f"--prefix={localenv['python_prefix']}")
else:
# Install Python module in the default location
extra = ''
install_dir = get_command_output(localenv["python_cmd"], "-c", "from sysconfig import get_paths; print(get_paths('posix_prefix')['platlib'])")

if env["stage_dir"]:
# Get the absolute path to the stage directory. If the stage directory is a relative
# path, consider it to be relative to the root of the Cantera source directory,
# which is two directories up from the current working directory of this SConscript
# file.
stage_absolute = Path.cwd().parents[1].joinpath(env['stage_dir']).resolve()
extra += f" --root={stage_absolute}"
# path, consider it to be relative to the root of the Cantera source directory.
stage_dir = Path(env["stage_dir"])
if not stage_dir.is_absolute():
stage_dir = Path(Dir("#").abspath) / stage_dir

install_cmd.append(f"--root={stage_dir.resolve()}")

env['python_module_loc'] = '<unspecified>'
install_cmd = "$python_cmd_esc -m pip install "

install_cmd.extend(("--no-build-isolation", "--no-deps", "-v", "--force-reinstall", "build/python"))
if localenv['PYTHON_INSTALLER'] == 'direct':
mod_inst = install(localenv.Command, 'dummy', mod,
install_cmd + extra +
" --no-build-isolation --no-deps -v --force-reinstall "
"build/python")
# this seems suboptimal, but easy_install with its --record option is deprecated and not used
# by pip. I need some way to figure out the install directory
if "--prefix" in extra:
install_path = Path(extra.split("=")[1])
elif "--user" in extra:
if localenv["python_prefix"]:
import os
os.environ["PYTHONUSERBASE"] = localenv.subst('$python_prefix')
install_path = Path(get_command_output(localenv["python_cmd"], "-c", "import site; print(site.getuserbase())"))
if env["stage_dir"]:
install_path = stage_absolute / install_path
env["python_module_loc"] = str(install_path)
" ".join(install_cmd))
env['install_python_action'] = mod_inst
elif localenv['PYTHON_INSTALLER'] == 'debian':
extra = localenv.subst(' --root=${python_prefix}')
Expand Down

0 comments on commit 5a19786

Please sign in to comment.