msmpi package: fix build (#50263)

Restores ability to build MSMPI from source.

* Modernizes the MSMPI package
* Strips out MSMPI build system that is long deprecated
* Adds patches to re-introduce missing functionality from said build system
* Adds builds + support for dependencies no longer fetched by build system
This commit is contained in:
John W. Parent 2025-05-16 18:03:33 -04:00 committed by GitHub
parent 70f4eef020
commit b12a64d687
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 336 additions and 24 deletions

View File

@ -24,6 +24,10 @@ class MSBuildPackage(spack.package_base.PackageBase):
build_system("msbuild")
conflicts("platform=linux", when="build_system=msbuild")
conflicts("platform=darwin", when="build_system=msbuild")
conflicts("platform=freebsd", when="build_system=msbuild")
def define(self, msbuild_arg, value):
return define(msbuild_arg, value)
@spack.builder.builder("msbuild")
@ -87,7 +91,7 @@ def define_targets(self, *targets):
return "/target:" + ";".join(targets) if targets else ""
def define(self, msbuild_arg, value):
return "/p:{}={}".format(msbuild_arg, value)
return define(msbuild_arg, value)
def msbuild_args(self):
"""Define build arguments to MSbuild. This is an empty list by default.
@ -121,3 +125,7 @@ def install(
pkg.module.msbuild(
*self.msbuild_install_args(), self.define_targets(*self.install_targets)
)
def define(msbuild_arg, value):
return "/p:{}={}".format(msbuild_arg, value)

View File

@ -0,0 +1,84 @@
diff --git a/Directory.Build.props b/Directory.Build.props
index 3177de8..6b5ec9c 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -56,7 +56,6 @@
properties before or after it depending on what you're injecting. The "global" build.props will also import
files located in the $(CBTLocalPath) folder at certain points.
-->
- <Import Project="$(EnlistmentRoot)\.build\CBT\build.props" />
<!--
The NuProjPath property allows .nuproj projects to build without having NuProj installed.
@@ -114,9 +113,6 @@
<PropertyGroup>
<OutputPath>$(StagingOutputRootPath)$(MSBuildProjectName)\</OutputPath>
- <VCToolsVersion>14.15.26726</VCToolsVersion>
- <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
- <PlatformToolset>v141</PlatformToolset>
<OutDir>$(OutputPath)</OutDir>
<O>$(Platform)\$(Configuration)</O>
<O Condition="'$(Platform)' == 'x86'">$(Configuration)</O>
diff --git a/dirs.proj b/dirs.proj
index ba6a006..2631d04 100644
--- a/dirs.proj
+++ b/dirs.proj
@@ -4,6 +4,5 @@
<ItemGroup>
<ProjectFile Include="$(MSBuildThisFileDirectory)src\dirs.proj" />
</ItemGroup>
- <Import Project="$(TraversalTargets)" Condition=" '$(CBTModulesRestored)' == 'true' " />
</Project>
\ No newline at end of file
diff --git a/src/dirs.proj b/src/dirs.proj
index b53afb1..e0eeca2 100644
--- a/src/dirs.proj
+++ b/src/dirs.proj
@@ -8,5 +8,4 @@
<ProjectFile Include="$(MSBuildThisFileDirectory)launchSvc\msmpiLaunchSvcMc.vcxproj"/>
<ProjectFile Include="$(MSBuildThisFileDirectory)mpi\dirs.proj"/>
</ItemGroup>
- <Import Project="$(TraversalTargets)" Condition=" '$(CBTModulesRestored)' == 'true' " />
</Project>
diff --git a/src/mpi/dirs.proj b/src/mpi/dirs.proj
index d8e9358..a8c329a 100644
--- a/src/mpi/dirs.proj
+++ b/src/mpi/dirs.proj
@@ -12,5 +12,4 @@
<ProjectFile Include="$(MSBuildThisFileDirectory)stub\mpistub.vcxproj" />
</ItemGroup>
- <Import Project="$(TraversalTargets)" Condition=" '$(CBTModulesRestored)' == 'true' " />
</Project>
diff --git a/src/mpi/msmpi/dirs.proj b/src/mpi/msmpi/dirs.proj
index 9959160..548bc5b 100644
--- a/src/mpi/msmpi/dirs.proj
+++ b/src/mpi/msmpi/dirs.proj
@@ -14,5 +14,4 @@
<ProjectFile Include="$(MSBuildThisFileDirectory)util\mpiutil.vcxproj" />
</ItemGroup>
- <Import Project="$(TraversalTargets)" Condition=" '$(CBTModulesRestored)' == 'true' " />
</Project>
diff --git a/src/mpi/msmpi/fortran/dirs.proj b/src/mpi/msmpi/fortran/dirs.proj
index d92d7fd..35370b6 100644
--- a/src/mpi/msmpi/fortran/dirs.proj
+++ b/src/mpi/msmpi/fortran/dirs.proj
@@ -11,5 +11,4 @@
<ProjectFile Include="$(MSBuildThisFileDirectory)msmpifms\msmpifms.vcxproj" />
</ItemGroup>
- <Import Project="$(TraversalTargets)" Condition=" '$(CBTModulesRestored)' == 'true' " />
</Project>
diff --git a/src/mpi/pmilib/dirs.proj b/src/mpi/pmilib/dirs.proj
index a9c9a8a..3fe9821 100644
--- a/src/mpi/pmilib/dirs.proj
+++ b/src/mpi/pmilib/dirs.proj
@@ -8,5 +8,4 @@
<ProjectFile Include="$(MSBuildThisFileDirectory)lib\pmilib.vcxproj" />
</ItemGroup>
- <Import Project="$(TraversalTargets)" Condition=" '$(CBTModulesRestored)' == 'true' " />
</Project>

View File

@ -1,19 +1,28 @@
diff --git a/src/mpi/msmpi/dll/msmpi.vcxproj b/src/mpi/msmpi/dll/msmpi.vcxproj
index 255b9f5..cc4f096 100644
index 255b9f5..9eb7dff 100644
--- a/src/mpi/msmpi/dll/msmpi.vcxproj
+++ b/src/mpi/msmpi/dll/msmpi.vcxproj
@@ -57,6 +57,9 @@
@@ -45,6 +45,7 @@
$(PUBLIC_SDK_LIB)\Iphlpapi.lib;
$(PUBLIC_SDK_LIB)\authz.lib;
$(PUBLIC_SDK_LIB)\ntdsapi.lib;
+ $(ND_DIR)\ndutil.lib;
$(OutDir)\..\mpichannels\mpichannels.lib;
$(OutDir)\..\mpiio\mpiio.lib;
$(OutDir)\..\mpicommon\mpicommon.lib;
@@ -57,6 +58,10 @@
$(OutDir)\..\mpi_debugger\mpi_debugger.lib;
$(CRT_Libs);
</AdditionalDependencies>
+ <AdditionalLibraryDirectories>
+ $(SPACK_IFORT)compiler\lib\intel64
+ $(SPACK_IFORT)\lib;
+ $(ND_DIR);
+ </AdditionalLibraryDirectories>
<ModuleDefinitionFile>.\msmpi.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
diff --git a/src/mpi/msmpi/fortran/lib/mpifort.vcxproj b/src/mpi/msmpi/fortran/lib/mpifort.vcxproj
index 24bd29d..57d0292 100644
index 24bd29d..319153d 100644
--- a/src/mpi/msmpi/fortran/lib/mpifort.vcxproj
+++ b/src/mpi/msmpi/fortran/lib/mpifort.vcxproj
@@ -8,12 +8,12 @@
@ -28,7 +37,7 @@ index 24bd29d..57d0292 100644
+ <Fort_Flags>/D _WIN64=1 /D _AMD64_=1 /D AMD64=1</Fort_Flags>
</PropertyGroup>
- <Exec Command="$(GFORTRAN_BIN)\gfortran.exe -I$(MPI_INC_ROOT) -c %(ForCompile.Identity) $(Fort_Flags) -o $(O)\%(ForCompile.FileName).obj" />
+ <Exec Command="$(IFORT_BIN)\ifort.exe /I$(MPI_INC_ROOT) /c %(ForCompile.Identity) $(Fort_Flags) /names:lowercase /assume:nounderscore /o $(O)\%(ForCompile.FileName).obj" />
+ <Exec Command="$(IFORT_BIN)\ifx.exe /I$(MPI_INC_ROOT) /c %(ForCompile.Identity) $(Fort_Flags) /names:lowercase /assume:nounderscore /o $(O)\%(ForCompile.FileName).obj" />
<ItemGroup>
<Lib Condition="'$(ConfigurationType)'=='StaticLibrary'" Include="@(ForCompile->'$(O)\%(Filename).obj')" />
</ItemGroup>

View File

@ -0,0 +1,49 @@
# Patch partially based on: https://github.com/microsoft/vcpkg/pull/13218
diff --git a/src/launchSvc/msmpiLaunchSvcMc.vcxproj b/src/launchSvc/msmpiLaunchSvcMc.vcxproj
index 2a6952b..b9a9eba 100644
--- a/src/launchSvc/msmpiLaunchSvcMc.vcxproj
+++ b/src/launchSvc/msmpiLaunchSvcMc.vcxproj
@@ -15,12 +15,10 @@
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ItemGroup>
- <MessageCompile Include="launchsvcmsg.mc">
- <GeneratedHeaderPath>true</GeneratedHeaderPath>
- <HeaderFilePath>$(SrcRoot)\launchsvc\$(O)</HeaderFilePath>
- <GeneratedRCAndMessagesPath>true</GeneratedRCAndMessagesPath>
- <RCFilePath>$(SrcRoot)\launchsvc\$(O)</RCFilePath>
- </MessageCompile>
+ <CustomBuild Include="$(SrcRoot)\launchSvc\launchSvcMsg.mc">
+ <Command>mc.exe -um -h $(SrcRoot)\launchSvc\$(O) -r $(SrcRoot)\launchSvc\$(O) $(SrcRoot)\launchSvc\launchSvcMsg.mc</Command>
+ <Outputs>$(SrcRoot)\launchSvc\$(O)\launchSvcMsg.h;$(SrcRoot)\launchSvc\$(O)\launchSvcMsg.rc</Outputs>
+ </CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
\ No newline at end of file
diff --git a/src/mpi/common/traceManifest.vcxproj b/src/mpi/common/traceManifest.vcxproj
index f80e80b..eb9281d 100644
--- a/src/mpi/common/traceManifest.vcxproj
+++ b/src/mpi/common/traceManifest.vcxproj
@@ -15,16 +15,10 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ItemGroup>
- <MessageCompile Include="$(MPI_SRC_ROOT)\common\mpitrace.man">
- <GeneratedHeaderPath>true</GeneratedHeaderPath>
- <HeaderFilePath>$(MPI_SRC_ROOT)\common\$(O)</HeaderFilePath>
- <GeneratedRCAndMessagesPath>true</GeneratedRCAndMessagesPath>
- <RCFilePath>$(MPI_SRC_ROOT)\common\$(O)</RCFilePath>
- <GeneratedFilesBaseName>MpiTraceEvents</GeneratedFilesBaseName>
- <GenerateUserModeLoggingMacros>true</GenerateUserModeLoggingMacros>
- <PrefixMacroName>Trace</PrefixMacroName>
- <RemoveCharsFromSymbolName>EVENT_</RemoveCharsFromSymbolName>
- </MessageCompile>
+ <CustomBuild Include="$(MPI_SRC_ROOT)\common\mpitrace.man">
+ <Command>mc.exe -um -p Trace -P EVENT_ -h $(MPI_SRC_ROOT)\common\$(O) -r $(MPI_SRC_ROOT)\common\$(O) -z MpiTraceEvents $(MPI_SRC_ROOT)\common\mpitrace.man</Command>
+ <Outputs>$(MPI_SRC_ROOT)\common\$(O)\MpiTraceEvents.h;$(MPI_SRC_ROOT)\common\$(O)\MpiTraceEvents.rc</Outputs>
+ </CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
\ No newline at end of file

View File

@ -2,15 +2,16 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import glob
import os
import re
import sys
from spack.build_systems.generic import GenericBuilder
import spack.build_systems.msbuild as msbuild
from spack.package import *
class Msmpi(Package):
class Msmpi(MSBuildPackage):
"""MSMPI is a Windows port of MPICH provided by the Windows team"""
homepage = "https://docs.microsoft.com/en-us/message-passing-interface/microsoft-mpi"
@ -31,8 +32,24 @@ class Msmpi(Package):
depends_on("c", type="build")
depends_on("win-wdk")
depends_on("networkdirect")
depends_on("perl")
patch("ifort_compat.patch")
# MSMPI's build system is hard coded to assume
# paths to gfortran and network direct
# This patch makes the build compatible with
# ifort/ifx and allows for a dynamically located
# network direct install
patch("ifort_nd_compat.patch")
# the cbt msbuild extension ms-mspi's build sytem
# uses has been removed. This patch removes the
# associated functionality from the build system
patch("burn_cbt.patch")
# For whatever reason, specifying the platform toolset
# prevents message compiler (mc) detection
# We know its present because we have a WDK
# patches the build system to just directly call the MC
patch("no_mc.patch")
requires("platform=windows")
requires("%msvc")
@ -53,27 +70,48 @@ def setup_dependent_package(self, module, dependent_spec):
# Note: This is not typical of MPI installations
self.spec.mpicc = dependent_spec["c"].package.cc
self.spec.mpicxx = dependent_spec["cxx"].package.cxx
self.spec.mpifc = dependent_spec["fortran"].package.fortran
self.spec.mpif77 = dependent_spec["fortran"].package.fortran
if "fortran" in dependent_spec:
self.spec.mpifc = dependent_spec["fortran"].package.fc
self.spec.mpif77 = dependent_spec["fortran"].package.f77
class GenericBuilder(GenericBuilder):
class MSBuildBuilder(msbuild.MSBuildBuilder):
def setup_build_environment(self, env: EnvironmentModifications) -> None:
ifort_root = os.path.join(*self.pkg.compiler.fc.split(os.path.sep)[:-2])
# os.path.join interprets C: as an indicator of a relative path
# so we need to use the traditional string join here
ifort_root = "\\".join(self.pkg.compiler.fc.split(os.path.sep)[:-2])
env.set("SPACK_IFORT", ifort_root)
env.prepend_path("IncludePath", self.spec["networkdirect"].prefix.include)
env.set("ND_DIR", self.spec["networkdirect"].prefix.ndutil)
def is_64bit(self):
return "64" in str(self.pkg.spec.target.family)
@property
def std_msbuild_args(self):
return []
def build_command_line(self):
# We will need to burn out the CBT build system and associated files
# and instead directly invoke msbuild per sln we're interested in
# and generate our own installer
def msbuild_args(self):
pkg = self.pkg
args = ["-noLogo"]
ifort_bin = self.pkg.compiler.fc
args.append("/p:IFORT_BIN=%s" % os.path.dirname(ifort_bin))
args.append("/p:VCToolsVersion=%s" % self.pkg.compiler.msvc_version)
args.append("/p:WindowsTargetPlatformVersion=%s" % str(self.pkg.spec["wdk"].version))
args.append("/p:PlatformToolset=%s" % self.pkg.compiler.cc_version)
ifort_bin = '"' + os.path.dirname(pkg.compiler.fc) + '"'
args.append(self.define("IFORT_BIN", ifort_bin))
args.append(self.define("PlatformToolset", "v" + pkg["msvc"].platform_toolset_ver))
args.append(self.define("VCToolsVersion", pkg["msvc"].msvc_version))
args.append(
self.define("WindowsTargetPlatformVersion", str(pkg["win-sdk"].version) + ".0")
)
args.append(self.define("Configuration", "Release"))
args.append("src\\msmpi.sln")
return args
def install(self, spec, prefix):
with working_dir(self.pkg.stage.build_directory, create=True):
msbuild(*self.build_command_line())
def install(self, pkg, spec, prefix):
base_build = pkg.stage.source_path
out = os.path.join(base_build, "out")
build_configuration = glob.glob(os.path.join(out, "*"))[0]
for x in glob.glob(os.path.join(build_configuration, "**", "*.*")):
install_path = x.replace(build_configuration, prefix)
mkdirp(os.path.dirname(install_path))
install(x, install_path)
include_dir = os.path.join(os.path.join(base_build, "src"), "include")
install_tree(include_dir, prefix.include)

View File

@ -0,0 +1,52 @@
diff --git a/Directory.Build.props b/Directory.Build.props
index a5e937a..d24da7b 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -56,7 +56,7 @@
properties before or after it depending on what you're injecting. The "global" build.props will also import
files located in the $(CBTLocalPath) folder at certain points.
-->
- <Import Project="$(EnlistmentRoot)\.build\CBT\build.props" />
+ <!-- <Import Project="$(EnlistmentRoot)\.build\CBT\build.props" /> -->
<!--
The NuProjPath property allows .nuproj projects to build without having NuProj installed.
@@ -76,9 +76,9 @@
<PropertyGroup>
<OutputPath>$(StagingOutputRootPath)$(MSBuildProjectName)\</OutputPath>
<OutIncludePath>$(StagingOutputRootPath)include</OutIncludePath>
- <VCToolsVersion>14.15.26726</VCToolsVersion>
- <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
- <PlatformToolset>v141</PlatformToolset>
+ <!-- <VCToolsVersion>14.15.26726</VCToolsVersion> -->
+ <!-- <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> -->
+ <!-- <PlatformToolset>v141</PlatformToolset> -->
<CharacterSet>Unicode</CharacterSet>
<OutDir>$(OutputPath)</OutDir>
<ResolveNugetpackages>false</ResolveNugetpackages>
@@ -97,11 +97,12 @@
<ItemDefinitionGroup>
<ClCompile>
- <WarningLevel>Level3</WarningLevel>
+ <!-- <WarningLevel>Level3</WarningLevel> -->
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>26439</DisableSpecificWarnings>
+ <DisableSpecificWarnings>5205</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>;%(AdditionalDependencies)</AdditionalDependencies>
diff --git a/dirs.proj b/dirs.proj
index 5a19bbf..e6c815c 100644
--- a/dirs.proj
+++ b/dirs.proj
@@ -4,5 +4,5 @@
<ItemGroup>
<ProjectFile Include="$(MSBuildThisFileDirectory)src\dirs.proj" />
</ItemGroup>
- <Import Project="$(TraversalTargets)" Condition=" '$(CBTModulesRestored)' == 'true' " />
+ <!-- <Import Project="$(TraversalTargets)" Condition=" '$(CBTModulesRestored)' == 'true' " /> -->
</Project>
\ No newline at end of file

View File

@ -0,0 +1,72 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import glob
import os
import spack.build_systems.msbuild as msbuild
from spack.package import *
class Networkdirect(MSBuildPackage):
"""NetworkDirect is a user-mode programming interface specification
for Remote Direct Memory Access (RDMA)"""
homepage = "https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/hh997033(v=ws.11)"
url = "https://github.com/microsoft/NetworkDirect/archive/refs/tags/v2.0.zip"
maintainers("johnwparent")
license("MIT", checked_by="johnwparent")
version("2.0", sha256="ba05a9be32ff39e08766c5a726ee63d47ee3eb9cab53b2b4b656de2d9158460c")
requires("platform=windows")
depends_on("cxx")
requires("%msvc")
depends_on("win-sdk")
depends_on("win-wdk")
# Networkdirect uses a build system called CBT that is built on top of MSBuild
# CBT is entirely deprecated, and fully incompatible with modern dotnet versions
# so we disable the CBT system and drive the underlying MSBuild system directly
patch("no_cbt.patch")
class MSBuildBuilder(msbuild.MSBuildBuilder):
build_targets = ["ndutil"]
# Networkdirect is a unique package where providing
# typically required information actually
# breaks expected behavior, override the defaults
@property
def std_msbuild_args(self):
return []
def msbuild_args(self):
args = ["-noLogo"]
args.append(
self.define("WindowsTargetPlatformVersion", str(self.pkg["win-sdk"].version) + ".0")
)
# one of the headers we need isn't generated during release builds
args.append(self.define("Configuration", "Debug"))
args.append("src\\netdirect.sln")
return args
def install(self, pkg, spec, prefix):
base_build = pkg.stage.source_path
out = os.path.join(base_build, "out")
build_configuration = glob.glob(os.path.join(out, "*"))[0]
for x in glob.glob(os.path.join(build_configuration, "**", "*.lib")):
install_path = x.replace(build_configuration, prefix)
mkdirp(os.path.dirname(install_path))
install(x, install_path)
include_dir = os.path.join(build_configuration, "include")
install_tree(include_dir, prefix.include)
# for whatever reason this header is not moved to the "out" prefix
# with the rest of the headers, ensure its there
install(os.path.join(base_build, "src", "ndutil", "ndsupport.h"), prefix.include)