Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

openmpi: migrate to Conan v2 #18980

Merged
merged 52 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
7f90c68
openmpi: migrate to Conan v2
valgur Jul 28, 2023
267deb3
openmpi: bump deps
valgur Dec 13, 2023
ffc2ff0
openmpi: do not print created env vars
valgur Dec 13, 2023
f96412f
openmpi: add v4.1.6
valgur Dec 13, 2023
83f202d
openmpi: improve options coverage
valgur Dec 13, 2023
eea27ca
openmpi: fix path env vars
valgur Dec 13, 2023
232a3cc
openmpi: fix a PMIX error
valgur Dec 13, 2023
0405382
openmpi: add MPI::MPI_CXX only if `cxx` is enabled
valgur Dec 14, 2023
2a60dbc
openmpi: fix static build issues, add external_hwloc option
valgur Dec 14, 2023
07412c9
openmpi: fix libltdl issue, replace AutotoolsDeps with PkgConfigDeps
valgur Dec 14, 2023
e4f89c3
openmpi: disable buildign of docs
valgur Dec 14, 2023
5bbcc3d
openmpi: drop libltdl dependency
valgur Dec 14, 2023
9c613ad
openmpi: external libevent does not really work
valgur Dec 14, 2023
7438020
openmpi: model components correctly
valgur Dec 15, 2023
79fcaab
openmpi: fix pkg-config names
valgur Dec 18, 2023
b937258
openmpi: disable armv8 for v4.1.0
valgur Mar 23, 2024
994dc3f
Merge remote-tracking branch 'upstream/master' into migrate/openmpi
valgur Mar 23, 2024
f6abe8f
openmpi: bump libnl
valgur Mar 23, 2024
46dd404
openmpi: enable with_verbs
valgur Apr 5, 2024
c741ec7
openmpi: use REQUIRED CONFIG in test_package for legacy generators
valgur Apr 5, 2024
f869e49
Merge branch 'master' into migrate/openmpi
valgur Apr 6, 2024
0f8dfad
bump rdma-core
valgur May 8, 2024
0de8688
Merge remote-tracking branch 'refs/remotes/upstream/master' into migr…
valgur Jul 15, 2024
376da44
openmpi: fix libibverbs.so not being found
valgur Jul 15, 2024
1844729
openmpi: drop test_v1_package
valgur Jul 15, 2024
a305afd
openmpi: fix apple-clang cross-compilation
valgur Jul 15, 2024
6f678da
openmpi: run autoreconf
valgur Jul 15, 2024
0461166
openmpi: drop v4.1.0
valgur Jul 15, 2024
14d9a89
openmpi: Revert "run autoreconf"
valgur Jul 15, 2024
4248462
openmpi: disable Clang on Conan v1
valgur Jul 15, 2024
e801dbf
openmpi: restore v4.1.0
valgur Jul 15, 2024
6b4bee7
openmpi: add --allow-run-as-root to test_package
valgur Jul 16, 2024
b43c87c
openmpi: adjust deps
valgur Aug 4, 2024
836ba2f
openmpi: enable cxx by default
valgur Aug 4, 2024
5d539eb
openmpi: drop external_hwloc option
valgur Aug 4, 2024
92a9411
openmpi: fix an invalid require name
valgur Aug 4, 2024
a08b957
openmpi: add missing requires
valgur Aug 4, 2024
92f78f2
openmpi: add VirtualRunEnv to fix ./configure
valgur Aug 25, 2024
d215365
openmpi: workaround for macOS build failure
valgur Aug 26, 2024
40d407e
openmpi: re-enable Clang/AppleClang for Conan v1
valgur Aug 26, 2024
186d7f0
Merge remote-tracking branch 'upstream/master' into migrate/openmpi
valgur Aug 26, 2024
84a9fce
openmpi: fix_apple_shared_install_name()
valgur Aug 26, 2024
6310f70
openmpi: apply review suggestions
valgur Aug 27, 2024
ce7bef0
openmpi: drop --with-libevent=internal
valgur Aug 27, 2024
5c2d0da
openmpi: drop --allow-run-as-root in test_package
valgur Aug 27, 2024
7e3fb74
openmpi: add a comment for pkg_config_name
valgur Aug 27, 2024
1d0251a
openmpi: get_safe("with_verbs")
valgur Aug 30, 2024
a26522c
openmpi: Revert "re-enable Clang/AppleClang for Conan v1"
valgur Aug 30, 2024
586cd9e
openmpi: VirtualRunEnv is required to find libhwloc.so during ./confi…
valgur Sep 3, 2024
d79c757
openmpi: macOS armv8 fails when shared=True
valgur Sep 3, 2024
2b728b5
Simplify test package to avoid networking usage
uilianries Sep 4, 2024
35520e7
Revert "openmpi: macOS armv8 fails when shared=True"
uilianries Sep 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions recipes/openmpi/all/conandata.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
sources:
"4.1.6":
url: "https://download.open-mpi.org/release/open-mpi/v4.1/openmpi-4.1.6.tar.bz2"
sha256: "f740994485516deb63b5311af122c265179f5328a0d857a567b85db00b11e415"
"4.1.0":
sha256: 73866fb77090819b6a8c85cb8539638d37d6877455825b74e289d647a39fd5b5
url: https://download.open-mpi.org/release/open-mpi/v4.1/openmpi-4.1.0.tar.bz2
url: "https://download.open-mpi.org/release/open-mpi/v4.1/openmpi-4.1.0.tar.bz2"
sha256: "73866fb77090819b6a8c85cb8539638d37d6877455825b74e289d647a39fd5b5"
284 changes: 223 additions & 61 deletions recipes/openmpi/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,97 +1,259 @@
from conans import ConanFile, tools, AutoToolsBuildEnvironment
from conans.errors import ConanInvalidConfiguration
import os

required_conan_version = ">=1.29.1"
from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
from conan.tools.apple import is_apple_os, fix_apple_shared_install_name
from conan.tools.env import VirtualRunEnv
from conan.tools.files import copy, get, rm, rmdir, save, replace_in_file
from conan.tools.gnu import Autotools, AutotoolsToolchain, AutotoolsDeps
from conan.tools.layout import basic_layout
from conan.tools.microsoft import unix_path

required_conan_version = ">=1.53.0"


class OpenMPIConan(ConanFile):
name = "openmpi"
homepage = "https://www.open-mpi.org"
url = "https://github.com/conan-io/conan-center-index"
topics = ("conan", "mpi", "openmpi")
description = "A High Performance Message Passing Library"
license = "BSD-3-Clause"
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://www.open-mpi.org"
topics = ("mpi", "openmpi")
provides = "mpi"
package_type = "library"
settings = "os", "arch", "compiler", "build_type"
options = {
"shared": [True, False],
"fPIC": [True, False],
"fortran": ["yes", "mpifh", "usempi", "usempi80", "no"]
"fortran": ["yes", "mpifh", "usempi", "usempi80", "no"],
"enable_cxx": [True, False],
"enable_cxx_exceptions": [True, False],
"with_verbs": [True, False],
}
default_options = {
"shared": False,
"fPIC": True,
"fortran": "no"
"fortran": "no",
"enable_cxx": False,
"enable_cxx_exceptions": False,
"with_verbs": False,
}

_autotools = None

@property
def _source_subfolder(self):
return "source_subfolder"
def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC

def configure(self):
if self.options.shared:
del self.options.fPIC
del self.settings.compiler.libcxx
del self.settings.compiler.cppstd
self.options.rm_safe("fPIC")
if not self.options.enable_cxx:
self.settings.rm_safe("compiler.libcxx")
self.settings.rm_safe("compiler.cppstd")
del self.options.enable_cxx_exceptions
valgur marked this conversation as resolved.
Show resolved Hide resolved
if is_apple_os(self):
# Unavailable due to dependency on libnl
del self.options.with_verbs

def layout(self):
basic_layout(self, src_folder="src")

def requirements(self):
# OpenMPI public headers don't include anything besides stddef.h.
# transitive_headers=True is not needed for any dependencies.
self.requires("hwloc/2.10.0")
self.requires("zlib/[>=1.2.11 <2]")
uilianries marked this conversation as resolved.
Show resolved Hide resolved
if self.settings.os == "Linux":
self.requires("libnl/3.8.0")
if self.options.get_safe("with_verbs"):
self.requires("rdma-core/52.0")

def validate(self):
if self.settings.os == "Windows":
# Requires Cygwin or WSL
raise ConanInvalidConfiguration("OpenMPI doesn't support Windows")

def requirements(self):
# FIXME : self.requires("libevent/2.1.12") - try to use libevent from conan
self.requires("zlib/1.2.11")
if self.version == "4.1.0" and is_apple_os(self) and self.settings.arch == "armv8":
# INFO: https://github.com/open-mpi/ompi/issues/8410
raise ConanInvalidConfiguration(f"{self.ref} is not supported in Mac M1. Use a newer version.")

def source(self):
tools.get(**self.conan_data["sources"][self.version])
extracted_dir = self.name + "-" + self.version
os.rename(extracted_dir, self._source_subfolder)

def _configure_autotools(self):
if self._autotools:
return self._autotools
self._autotools = AutoToolsBuildEnvironment(self)
args = ["--disable-wrapper-rpath", "--disable-wrapper-runpath"]
if self.settings.build_type == "Debug":
args.append("--enable-debug")
if self.options.shared:
args.extend(["--enable-shared", "--disable-static"])
else:
args.extend(["--enable-static", "--disable-shared"])
args.append("--with-pic" if self.options.get_safe("fPIC", True) else "--without-pic")
args.append("--enable-mpi-fortran={}".format(str(self.options.fortran)))
args.append("--with-zlib={}".format(self.deps_cpp_info["zlib"].rootpath))
args.append("--with-zlib-libdir={}".format(self.deps_cpp_info["zlib"].lib_paths[0]))
args.append("--datarootdir=${prefix}/res")
self._autotools.configure(args=args)
return self._autotools
get(self, **self.conan_data["sources"][self.version], strip_root=True)

def generate(self):
def root(pkg):
return unix_path(self, self.dependencies[pkg].package_folder)

def yes_no(v):
return "yes" if v else "no"

tc = AutotoolsToolchain(self)
tc.configure_args += [
f"--enable-mpi-fortran={self.options.fortran}",
f"--enable-mpi-cxx={yes_no(self.options.enable_cxx)}",
f"--enable-cxx-exceptions={yes_no(self.options.get_safe('enable_cxx_exceptions'))}",
f"--with-hwloc={root('hwloc')}",
f"--with-libnl={root('libnl') if not is_apple_os(self) else 'no'}",
f"--with-verbs={root('rdma-core') if self.options.get_safe('with_verbs') else 'no'}",
f"--with-zlib={root('zlib')}",
"--with-pic" if self.options.get_safe("fPIC", True) else "--without-pic",
"--disable-wrapper-rpath",
"--disable-wrapper-runpath",
"--exec-prefix=/",
"--datarootdir=${prefix}/res",
# Disable other external libraries explicitly
"--with-alps=no", # ALPS
"--with-cuda=no", # CUDA
"--with-fca=no", # FCA
"--with-gpfs=no", # Gpfs
"--with-hcoll=no", # hcoll
"--with-ime=no", # IME
"--with-lsf=no", # LSF
"--with-lustre=no", # Lustre
"--with-memkind=no", # memkind
"--with-moab=no", # Moab
"--with-mxm=no", # Mellanox MXM
"--with-ofi=no", # libfabric, TODO: enable once libfabric is available
"--with-pmi=no", # PMI
"--with-pmix=internal", # PMIx
"--with-portals4=no", # Portals4
"--with-psm2=no", # PSM2
"--with-psm=no", # PSM
"--with-pvfs2=no", # Pvfs2
"--with-treematch=no", # TreeMatch
"--with-ucx=no", # UCX
"--with-valgrind=no", # Valgrind
"--with-x=no", # X11
"--with-xpmem=no", # XPMEM
]
if is_apple_os(self):
if self.settings.arch == "armv8":
tc.configure_args.append("--host=aarch64-apple-darwin")
tc.extra_ldflags.append("-arch arm64")
# macOS has no libnl
tc.configure_args.append("--enable-mca-no-build=reachable-netlink")
# libtool's libltdl is not really needed, OpenMPI provides its own equivalent.
# Not adding it as it fails to be detected by ./configure in some cases.
# https://github.com/open-mpi/ompi/blob/v4.1.6/opal/mca/dl/dl.h#L20-L25
tc.configure_args.append("--with-libltdl=no")
tc.generate()

deps = AutotoolsDeps(self)
deps.generate()

# Needed for ./configure to find libhwloc.so and libibnetdisc.so
VirtualRunEnv(self).generate(scope="build")

# TODO: might want to enable reproducible builds by setting
# $SOURCE_DATE_EPOCH, $USER and $HOSTNAME

def _patch_sources(self):
# Not needed and fails with v5.0 due to additional Python dependencies
save(self, os.path.join(self.source_folder, "docs", "Makefile.in"), "all:\ninstall:\n")
# Workaround for <cstddef> trying to include VERSION from source dir due to a case-insensitive filesystem on macOS
# Based on https://github.com/macports/macports-ports/blob/22dded99ae76a287f04a9685bbc820ecaa397fea/science/openmpi/files/patch-configure.diff
replace_in_file(self, os.path.join(self.source_folder, "configure"),
"-I$(top_srcdir) ", "-idirafter$(top_srcdir) ")

def build(self):
with tools.chdir(self._source_subfolder):
autotools = self._configure_autotools()
autotools.make()
self._patch_sources()
autotools = Autotools(self)
autotools.configure()
autotools.make()

def package(self):
self.copy(pattern="LICENSE", src=self._source_subfolder, dst="licenses")
with tools.chdir(self._source_subfolder):
autotools = self._configure_autotools()
autotools.install()
tools.rmdir(os.path.join(self.package_folder, "lib", "pkgconfig"))
tools.rmdir(os.path.join(self.package_folder, "share"))
tools.rmdir(os.path.join(self.package_folder, "etc"))
tools.remove_files_by_mask(os.path.join(self.package_folder, "lib"), "*.la")
copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
autotools = Autotools(self)
autotools.install()
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
rmdir(self, os.path.join(self.package_folder, "etc"))
rmdir(self, os.path.join(self.package_folder, "res", "man"))
rm(self, "*.la", self.package_folder, recursive=True)
fix_apple_shared_install_name(self)

def package_info(self):
self.cpp_info.libs = ['mpi', 'open-rte', 'open-pal']
# Based on https://cmake.org/cmake/help/latest/module/FindMPI.html#variables-for-using-mpi
self.cpp_info.set_property("cmake_find_mode", "both")
self.cpp_info.set_property("cmake_file_name", "MPI")
# TODO: Use None when available as Conan feature.
self.cpp_info.set_property("pkg_config_name", "_ompi-do-not-use")
# TODO: export a .cmake module to correctly set all variables set by CMake's FindMPI.cmake
valgur marked this conversation as resolved.
Show resolved Hide resolved

requires = [
"hwloc::hwloc",
"zlib::zlib",
]
if self.settings.os == "Linux":
self.cpp_info.system_libs = ["dl", "pthread", "rt", "util"]
requires.append("libnl::libnl")
if self.options.get_safe("with_verbs"):
requires.extend(["rdma-core::libibverbs", "rdma-core::librdmacm"])

# The components are modelled based on OpenMPI's pkg-config files

self.output.info("Creating MPI_HOME environment variable: {}".format(self.package_folder))
# Run-time environment library
self.cpp_info.components["orte"].set_property("pkg_config_name", "orte")
self.cpp_info.components["orte"].libs = ["open-rte", "open-pal"]
self.cpp_info.components["orte"].includedirs.append(os.path.join("include", "openmpi"))
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.components["orte"].system_libs = ["dl", "pthread", "rt", "util"]
self.cpp_info.components["orte"].cflags = ["-pthread"]
if self.options.get_safe("enable_cxx_exceptions"):
self.cpp_info.components["orte"].cflags.append("-fexceptions")
self.cpp_info.components["orte"].requires = requires

self.cpp_info.components["ompi"].set_property("pkg_config_name", "ompi")
self.cpp_info.components["ompi"].libs = ["mpi"]
self.cpp_info.components["ompi"].requires = ["orte"]

self.cpp_info.components["ompi-c"].set_property("pkg_config_name", "ompi-c")
self.cpp_info.components["ompi-c"].set_property("cmake_target_name", "MPI::MPI_C")
self.cpp_info.components["ompi-c"].requires = ["ompi"]

self.cpp_info.components["ompitrace"].set_property("pkg_config_name", "ompitrace")
self.cpp_info.components["ompitrace"].libs = ["ompitrace"]
self.cpp_info.components["ompitrace"].requires = ["ompi"]

if self.options.enable_cxx:
self.cpp_info.components["ompi-cxx"].set_property("pkg_config_name", "ompi-cxx")
self.cpp_info.components["ompi-cxx"].set_property("cmake_target_name", "MPI::MPI_CXX")
self.cpp_info.components["ompi-cxx"].libs = ["mpi_cxx"]
self.cpp_info.components["ompi-cxx"].requires = ["ompi"]

if self.options.fortran != "no":
self.cpp_info.components["ompi-fort"].set_property("pkg_config_name", "ompi-fort")
self.cpp_info.components["ompi-fort"].set_property("cmake_target_name", "MPI::MPI_Fortran")
self.cpp_info.components["ompi-fort"].libs = ["mpi_mpifh"]
self.cpp_info.components["ompi-fort"].requires = ["ompi"]
# Aliases
self.cpp_info.components["ompi-f77"].set_property("pkg_config_name", "ompi-f77")
self.cpp_info.components["ompi-f77"].requires = ["ompi-fort"]
self.cpp_info.components["ompi-f90"].set_property("pkg_config_name", "ompi-f90")
self.cpp_info.components["ompi-f90"].requires = ["ompi-fort"]

bin_folder = os.path.join(self.package_folder, "bin")
# Prepend to PATH to avoid a conflict with system MPI
self.runenv_info.prepend_path("PATH", bin_folder)
self.runenv_info.define_path("MPI_BIN", bin_folder)
self.runenv_info.define_path("MPI_HOME", self.package_folder)
self.runenv_info.define_path("OPAL_PREFIX", self.package_folder)
self.runenv_info.define_path("OPAL_EXEC_PREFIX", self.package_folder)
self.runenv_info.define_path("OPAL_LIBDIR", os.path.join(self.package_folder, "lib"))
self.runenv_info.define_path("OPAL_DATADIR", os.path.join(self.package_folder, "res"))
self.runenv_info.define_path("OPAL_DATAROOTDIR", os.path.join(self.package_folder, "res"))

# TODO: Legacy, to be removed on Conan 2.0
self.env_info.PATH.append(bin_folder)
self.env_info.MPI_BIN = bin_folder
self.env_info.MPI_HOME = self.package_folder
self.output.info("Creating OPAL_PREFIX environment variable: {}".format(self.package_folder))
self.env_info.OPAL_PREFIX = self.package_folder
mpi_bin = os.path.join(self.package_folder, 'bin')
self.output.info("Creating MPI_BIN environment variable: {}".format(mpi_bin))
self.env_info.MPI_BIN = mpi_bin
self.output.info("Appending PATH environment variable: {}".format(mpi_bin))
self.env_info.PATH.append(mpi_bin)
self.env_info.OPAL_EXEC_PREFIX = self.package_folder
self.env_info.OPAL_LIBDIR = os.path.join(self.package_folder, "lib")
self.env_info.OPAL_DATADIR = os.path.join(self.package_folder, "res")
self.env_info.OPAL_DATAROOTDIR = os.path.join(self.package_folder, "res")

self.cpp_info.names["cmake_find_package"] = "MPI"
self.cpp_info.names["cmake_find_package_multi"] = "MPI"
self.cpp_info.components["ompi-c"].names["cmake_find_package"] = "MPI_C"
if self.options.enable_cxx:
self.cpp_info.components["ompi-cxx"].names["cmake_find_package"] = "MPI_CXX"
if self.options.fortran != "no":
self.cpp_info.components["ompi-fort"].names["cmake_find_package"] = "MPI_Fortran"
13 changes: 5 additions & 8 deletions recipes/openmpi/all/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
cmake_minimum_required(VERSION 3.1)
project(test_package)
cmake_minimum_required(VERSION 3.15)
project(test_package LANGUAGES C)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
find_package(MPI REQUIRED CONFIG)

find_package(MPI REQUIRED)

add_executable(${PROJECT_NAME} test_package.cpp)
target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS})
add_executable(${PROJECT_NAME} test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE MPI::MPI_C)
24 changes: 17 additions & 7 deletions recipes/openmpi/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
from conans import ConanFile, CMake, tools
import os

from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import cmake_layout, CMake


class TestPackageConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake"
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv"
test_type = "explicit"

def requirements(self):
self.requires(self.tested_reference_str)

def layout(self):
cmake_layout(self)

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

def test(self):
if not tools.cross_building(self.settings):
mpiexec = os.path.join(os.environ['MPI_BIN'], 'mpiexec')
command = '%s -mca plm_rsh_agent yes -np 2 %s' % (mpiexec, os.path.join("bin", "test_package"))
self.run(command, run_environment=True)
if can_run(self):
bin_path = os.path.join(self.cpp.build.bindir, "test_package")
command = f"mpiexec -mca plm_rsh_agent yes {bin_path}"
self.run(command, env="conanrun")
valgur marked this conversation as resolved.
Show resolved Hide resolved
13 changes: 13 additions & 0 deletions recipes/openmpi/all/test_package/test_package.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <stdio.h>
#include <stdlib.h>

#include <mpi.h>

int main(int argc, char* argv[])
{
char version[MPI_MAX_LIBRARY_VERSION_STRING] = {0};
int len = 0;
MPI_Get_library_version(version, &len);
printf("MPI version: %s\n", version);
return EXIT_SUCCESS;
}
Loading
Loading