boost package: fix Windows build (#43732)
* Boost:Adjust bootstrapping/b2 options as needed for Windows (the bootstrapping phase sufficiently differs between Windows/Unix that it is handled entirely within its own branch). * Boost: Paths in user-config.jam should be POSIX, including on Windows * Python: `.libs` for the Python package should return link libraries on Windows. The libraries are also stored in a different directory.
This commit is contained in:
parent
e1da0a7312
commit
fc4a4ec70d
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from spack.package import *
|
from spack.package import *
|
||||||
|
|
||||||
@ -303,6 +304,11 @@ def libs(self):
|
|||||||
# safe to do so on affected platforms.
|
# safe to do so on affected platforms.
|
||||||
conflicts("+clanglibcpp", when="@1.85: +stacktrace")
|
conflicts("+clanglibcpp", when="@1.85: +stacktrace")
|
||||||
|
|
||||||
|
# On Windows, the signals variant is required when building any of
|
||||||
|
# the all_libs variants.
|
||||||
|
for lib in all_libs:
|
||||||
|
requires("+signals", when=f"+{lib} platform=windows")
|
||||||
|
|
||||||
# Patch fix from https://svn.boost.org/trac/boost/ticket/11856
|
# Patch fix from https://svn.boost.org/trac/boost/ticket/11856
|
||||||
patch("boost_11856.patch", when="@1.60.0%gcc@4.4.7")
|
patch("boost_11856.patch", when="@1.60.0%gcc@4.4.7")
|
||||||
|
|
||||||
@ -495,9 +501,9 @@ def bjam_python_line(self, spec):
|
|||||||
|
|
||||||
return "using python : {0} : {1} : {2} : {3} ;\n".format(
|
return "using python : {0} : {1} : {2} : {3} ;\n".format(
|
||||||
spec["python"].version.up_to(2),
|
spec["python"].version.up_to(2),
|
||||||
spec["python"].command.path,
|
Path(spec["python"].command.path).as_posix(),
|
||||||
spec["python"].headers.directories[0],
|
Path(spec["python"].headers.directories[0]).as_posix(),
|
||||||
spec["python"].libs[0],
|
Path(spec["python"].libs[0]).parent.as_posix(),
|
||||||
)
|
)
|
||||||
|
|
||||||
def determine_bootstrap_options(self, spec, with_libs, options):
|
def determine_bootstrap_options(self, spec, with_libs, options):
|
||||||
@ -521,6 +527,9 @@ def determine_bootstrap_options(self, spec, with_libs, options):
|
|||||||
else:
|
else:
|
||||||
options.append("--without-icu")
|
options.append("--without-icu")
|
||||||
|
|
||||||
|
self.write_jam_file(spec, boost_toolset_id)
|
||||||
|
|
||||||
|
def write_jam_file(self, spec, boost_toolset_id=None):
|
||||||
with open("user-config.jam", "w") as f:
|
with open("user-config.jam", "w") as f:
|
||||||
# Boost may end up using gcc even though clang+gfortran is set in
|
# Boost may end up using gcc even though clang+gfortran is set in
|
||||||
# compilers.yaml. Make sure this does not happen:
|
# compilers.yaml. Make sure this does not happen:
|
||||||
@ -535,7 +544,7 @@ def determine_bootstrap_options(self, spec, with_libs, options):
|
|||||||
# similar, but that doesn't work with the Cray compiler
|
# similar, but that doesn't work with the Cray compiler
|
||||||
# wrappers. Since Boost doesn't use the MPI C++ bindings,
|
# wrappers. Since Boost doesn't use the MPI C++ bindings,
|
||||||
# that can be used as a compiler option instead.
|
# that can be used as a compiler option instead.
|
||||||
mpi_line = "using mpi : %s" % spec["mpi"].mpicxx
|
mpi_line = "using mpi : %s" % Path(spec["mpi"].mpicxx).as_posix()
|
||||||
f.write(mpi_line + " ;\n")
|
f.write(mpi_line + " ;\n")
|
||||||
|
|
||||||
if spec.satisfies("+python"):
|
if spec.satisfies("+python"):
|
||||||
@ -608,6 +617,16 @@ def determine_b2_options(self, spec, options):
|
|||||||
|
|
||||||
options.extend(["link=%s" % ",".join(link_types), "--layout=%s" % layout])
|
options.extend(["link=%s" % ",".join(link_types), "--layout=%s" % layout])
|
||||||
|
|
||||||
|
if spec.satisfies("platform=windows"):
|
||||||
|
# The runtime link must either be shared or static, not both.
|
||||||
|
if "+shared" in spec:
|
||||||
|
options.append("runtime-link=shared")
|
||||||
|
else:
|
||||||
|
options.append("runtime-link=static")
|
||||||
|
for lib in self.all_libs:
|
||||||
|
if f"+{lib}" not in spec:
|
||||||
|
options.append(f"--without-{lib}")
|
||||||
|
|
||||||
if not spec.satisfies("@:1.75 %intel") and not spec.satisfies("platform=windows"):
|
if not spec.satisfies("@:1.75 %intel") and not spec.satisfies("platform=windows"):
|
||||||
# When building any version >= 1.76, the toolset must be specified.
|
# When building any version >= 1.76, the toolset must be specified.
|
||||||
# Earlier versions could not specify Intel as the toolset
|
# Earlier versions could not specify Intel as the toolset
|
||||||
@ -671,6 +690,23 @@ def add_buildopt_symlinks(self, prefix):
|
|||||||
prefix, remainder = lib.split(".", 1)
|
prefix, remainder = lib.split(".", 1)
|
||||||
symlink(lib, "%s-mt.%s" % (prefix, remainder))
|
symlink(lib, "%s-mt.%s" % (prefix, remainder))
|
||||||
|
|
||||||
|
def bootstrap_windows(self):
|
||||||
|
"""Run the Windows-specific bootstrap.bat. The only bootstrapping command
|
||||||
|
line option that is accepted by the bootstrap.bat script is the compiler
|
||||||
|
information: either the vc version (e.g. MSVC 14.3.x would be vc143)
|
||||||
|
or gcc or clang.
|
||||||
|
"""
|
||||||
|
bootstrap_options = list()
|
||||||
|
if self.spec.satisfies("%msvc"):
|
||||||
|
bootstrap_options.append(f"vc{self.compiler.platform_toolset_ver}")
|
||||||
|
elif self.spec.satisfies("%gcc"):
|
||||||
|
bootstrap_options.append("gcc")
|
||||||
|
elif self.spec.satisfies("%clang"):
|
||||||
|
bootstrap_options.append("clang")
|
||||||
|
|
||||||
|
bootstrap = Executable("cmd.exe")
|
||||||
|
bootstrap("/c", ".\\bootstrap.bat", *bootstrap_options)
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
def install(self, spec, prefix):
|
||||||
# On Darwin, Boost expects the Darwin libtool. However, one of the
|
# On Darwin, Boost expects the Darwin libtool. However, one of the
|
||||||
# dependencies may have pulled in Spack's GNU libtool, and these two
|
# dependencies may have pulled in Spack's GNU libtool, and these two
|
||||||
@ -710,16 +746,13 @@ def install(self, spec, prefix):
|
|||||||
if spec.satisfies("+graph") and spec.satisfies("+mpi"):
|
if spec.satisfies("+graph") and spec.satisfies("+mpi"):
|
||||||
with_libs.add("graph_parallel")
|
with_libs.add("graph_parallel")
|
||||||
|
|
||||||
# to make Boost find the user-config.jam
|
|
||||||
env["BOOST_BUILD_PATH"] = self.stage.source_path
|
|
||||||
|
|
||||||
bootstrap_options = ["--prefix=%s" % prefix]
|
|
||||||
self.determine_bootstrap_options(spec, with_libs, bootstrap_options)
|
|
||||||
|
|
||||||
if self.spec.satisfies("platform=windows"):
|
if self.spec.satisfies("platform=windows"):
|
||||||
bootstrap = Executable("cmd.exe")
|
self.bootstrap_windows()
|
||||||
bootstrap("/c", ".\\bootstrap.bat", *bootstrap_options)
|
|
||||||
else:
|
else:
|
||||||
|
# to make Boost find the user-config.jam
|
||||||
|
env["BOOST_BUILD_PATH"] = self.stage.source_path
|
||||||
|
bootstrap_options = ["--prefix=%s" % prefix]
|
||||||
|
self.determine_bootstrap_options(spec, with_libs, bootstrap_options)
|
||||||
bootstrap = Executable("./bootstrap.sh")
|
bootstrap = Executable("./bootstrap.sh")
|
||||||
bootstrap(*bootstrap_options)
|
bootstrap(*bootstrap_options)
|
||||||
|
|
||||||
@ -742,15 +775,24 @@ def install(self, spec, prefix):
|
|||||||
if jobs > 64 and spec.satisfies("@:1.58"):
|
if jobs > 64 and spec.satisfies("@:1.58"):
|
||||||
jobs = 64
|
jobs = 64
|
||||||
|
|
||||||
# Windows just wants a b2 call with no args
|
if self.spec.satisfies("platform=windows"):
|
||||||
b2_options = []
|
|
||||||
if not self.spec.satisfies("platform=windows"):
|
|
||||||
path_to_config = "--user-config=%s" % os.path.join(
|
|
||||||
self.stage.source_path, "user-config.jam"
|
|
||||||
)
|
|
||||||
b2_options = ["-j", "%s" % jobs]
|
|
||||||
b2_options.append(path_to_config)
|
|
||||||
|
|
||||||
|
def is_64bit():
|
||||||
|
# TODO: This method should be abstracted to a more general location
|
||||||
|
# as it is repeated in many places (msmpi.py for one)
|
||||||
|
return "64" in str(self.spec.target.family)
|
||||||
|
|
||||||
|
b2_options = [f"--prefix={self.prefix}", f"address-model={64 if is_64bit() else 32}"]
|
||||||
|
if not self.spec.satisfies("+python"):
|
||||||
|
b2_options.append("--without-python")
|
||||||
|
|
||||||
|
self.write_jam_file(self.spec)
|
||||||
|
else:
|
||||||
|
b2_options = ["-j", "%s" % jobs]
|
||||||
|
path_to_config = "--user-config=%s" % os.path.join(
|
||||||
|
self.stage.source_path, "user-config.jam"
|
||||||
|
)
|
||||||
|
b2_options.append(path_to_config)
|
||||||
threading_opts = self.determine_b2_options(spec, b2_options)
|
threading_opts = self.determine_b2_options(spec, b2_options)
|
||||||
|
|
||||||
# Create headers if building from a git checkout
|
# Create headers if building from a git checkout
|
||||||
|
@ -1023,8 +1023,13 @@ def find_library(self, library):
|
|||||||
win_root_dir,
|
win_root_dir,
|
||||||
]
|
]
|
||||||
|
|
||||||
# The Python shipped with Xcode command line tools isn't in any of these locations
|
if self.spec.satisfies("platform=windows"):
|
||||||
for subdir in ["lib", "lib64"]:
|
lib_dirs = ["libs"]
|
||||||
|
else:
|
||||||
|
# The Python shipped with Xcode command line tools isn't in any of these locations
|
||||||
|
lib_dirs = ["lib", "lib64"]
|
||||||
|
|
||||||
|
for subdir in lib_dirs:
|
||||||
directories.append(os.path.join(self.config_vars["base"], subdir))
|
directories.append(os.path.join(self.config_vars["base"], subdir))
|
||||||
|
|
||||||
directories = dedupe(directories)
|
directories = dedupe(directories)
|
||||||
@ -1067,14 +1072,16 @@ def libs(self):
|
|||||||
# The +shared variant isn't reliable, as `spack external find` currently can't
|
# The +shared variant isn't reliable, as `spack external find` currently can't
|
||||||
# detect it. If +shared, prefer the shared libraries, but check for static if
|
# detect it. If +shared, prefer the shared libraries, but check for static if
|
||||||
# those aren't found. Vice versa for ~shared.
|
# those aren't found. Vice versa for ~shared.
|
||||||
if "+shared" in self.spec:
|
if self.spec.satisfies("platform=windows"):
|
||||||
|
# Since we are searching for link libraries, on Windows search only for
|
||||||
|
# ".Lib" extensions by default as those represent import libraries for implict links.
|
||||||
|
candidates = static_libs
|
||||||
|
elif self.spec.satisfies("+shared"):
|
||||||
candidates = shared_libs + static_libs
|
candidates = shared_libs + static_libs
|
||||||
else:
|
else:
|
||||||
candidates = static_libs + shared_libs
|
candidates = static_libs + shared_libs
|
||||||
|
|
||||||
candidates = dedupe(candidates)
|
for candidate in dedupe(candidates):
|
||||||
|
|
||||||
for candidate in candidates:
|
|
||||||
lib = self.find_library(candidate)
|
lib = self.find_library(candidate)
|
||||||
if lib:
|
if lib:
|
||||||
return lib
|
return lib
|
||||||
|
Loading…
Reference in New Issue
Block a user