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

[WIP] fix issues with dependencies build with Macs with arm64 #3192

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
155 changes: 115 additions & 40 deletions dependencies/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -210,26 +210,36 @@ option(OPENSIM_WITH_TROPTER


if(OPENSIM_WITH_TROPTER OR OPENSIM_WITH_CASADI)
AddDependency(NAME eigen
DEFAULT ON
URL https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.zip)

mark_as_advanced(SUPERBUILD_eigen)

AddDependency(NAME colpack
DEFAULT ON
GIT_URL https://github.com/opensim-org/colpack.git
GIT_TAG 72f691e91d59e8eb2123f258e67a4ddc72d105ee
CMAKE_ARGS -DCMAKE_DEBUG_POSTFIX:STRING=_d
-DENABLE_EXAMPLES:BOOL=OFF
-DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON)

mark_as_advanced(SUPERBUILD_colpack)
AddDependency(NAME eigen
DEFAULT ON
URL https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.zip)

mark_as_advanced(SUPERBUILD_eigen)

AddDependency(NAME colpack
DEFAULT ON
GIT_URL https://github.com/opensim-org/colpack.git
GIT_TAG 72f691e91d59e8eb2123f258e67a4ddc72d105ee
CMAKE_ARGS -DCMAKE_DEBUG_POSTFIX:STRING=_d
-DENABLE_EXAMPLES:BOOL=OFF
-DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON)

mark_as_advanced(SUPERBUILD_colpack)

CMAKE_DEPENDENT_OPTION(SUPERBUILD_adolc "Automatically download, configure, build and install adolc" ON
"OPENSIM_WITH_TROPTER" OFF)
CMAKE_DEPENDENT_OPTION(SUPERBUILD_ipopt "Automatically download, configure, build and install ipopt" ON
"OPENSIM_WITH_TROPTER OR OPENSIM_WITH_CASADI" OFF)
CMAKE_DEPENDENT_OPTION(USE_IPOPT_INSTALL "Use an ipopt install folder instead of using the superbuild option." OFF
"OPENSIM_WITH_TROPTER OR OPENSIM_WITH_CASADI" OFF)
set(IPOPT_INSTALL_DIR "" CACHE STRING "Path to the ipopt install folder when USE_IPOPT_INSTALL is ON")

mark_as_advanced(USE_IPOPT_INSTALL)
mark_as_advanced(IPOPT_INSTALL_DIR)
endif()

CMAKE_DEPENDENT_OPTION(SUPERBUILD_adolc "Automatically download, configure, build and install adolc" ON
"OPENSIM_WITH_TROPTER" OFF)
CMAKE_DEPENDENT_OPTION(SUPERBUILD_ipopt "Automatically download, configure, build and install ipopt" ON
"OPENSIM_WITH_TROPTER OR OPENSIM_WITH_CASADI" OFF)
if (SUPERBUILD_ipopt AND USE_IPOPT_INSTALL)
message(FATAL_ERROR "SUPERBUILD_ipopt and USE_IPOPT_INSTALL cannot both be ON")
endif()

if (OPENSIM_WITH_CASADI)
Expand Down Expand Up @@ -319,34 +329,99 @@ else()
--with-colpack=${CMAKE_INSTALL_PREFIX}/colpack
--with-boost=no
BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} ${BUILD_FLAGS}
INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} install)
INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} install
)
endif()

if(SUPERBUILD_ipopt)
# TODO --enable-debug if building in Debug.
# TODO must have gfortran for MUMPS (brew install gcc).
# TODO CMake documentation says "Whether the current working directory
# is preserved between commands is not defined. Behavior of shell
# operators like && is not defined."
# Patch the scripts that download Metis and MUMPS to use our
# Sourceforge mirror. The original links are not reliable.
ExternalProject_Add(ipopt
URL https://www.coin-or.org/download/source/Ipopt/Ipopt-3.12.8.zip
INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/ipopt"
PATCH_COMMAND cd <SOURCE_DIR>/ThirdParty/Metis && patch < ${CMAKE_SOURCE_DIR}/get.Metis.patch
COMMAND cd <SOURCE_DIR>/ThirdParty/Metis && ./get.Metis
COMMAND cd <SOURCE_DIR>/ThirdParty/Mumps && patch < ${CMAKE_SOURCE_DIR}/get.Mumps.patch
COMMAND cd <SOURCE_DIR>/ThirdParty/Mumps && ./get.Mumps
# GCC 10 generates a warning when compling MUMPS that we must suppress using
# -fallow-argument-mismatch.
# Suppress warnings treated as errors in Clang/LLVM with -Wno-error=implicit-function-declaration
CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR> ADD_FFLAGS=-fallow-argument-mismatch ADD_CFLAGS=-Wno-error=implicit-function-declaration
BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} ${BUILD_FLAGS}
INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} install)

# Check for arm64 architecture
execute_process(
COMMAND uname -m
OUTPUT_VARIABLE MACHINE_ARCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)

# For ARM-based Macs, use different version of METIS and MUMPS than
# those automatically pulled from IPOPT's ThirdParty submodules.
if(APPLE AND MACHINE_ARCH STREQUAL "arm64")

# Homebrew dir is /opt/homebrew for arm64 (/usr/local for x86_64).
# Use METIS from Homebrew, which is currently 5.1.0 (IPOPT 3.12.8
# automatically pulls 4.10.0, which had some segfault issues)
set(HOMEBREW_DIR "/opt/homebrew")
set(METIS_INSTALL_DIR "${HOMEBREW_DIR}/opt/metis")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is homebrew the only way to get metis and are these directories hardcoded/unchangeable by users?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is homebrew the only way to get metis

There are a few ways to get metis, but there seemed to be issues with using anything but the homebrew version:

  1. Building from source from here: This built properly, however, the library that comes out does not seem to have the correct path stored in the .dylib when using otool -L libmetis.dylib to check dependencies (e.g., it seems relative rather than absolute), so there are linking problems downstream. I suspect there is some issue with the provided configure/cmake step and RPATH, as there is a warning about MACOS_RPATH.
  2. Building from coin-or's repo ThirdParty-Metis (link). The latest version here, however, is only 4.10.0, which had segfault issues downstream at runtime.
  3. homebrew: automatically installs 5.1.0, and using this resolved segfaults.

are these directories hardcoded/unchangeable by users

With homebrew, the directory structure is set by homebrew. For arm64 installation, the base directory is /opt/homebrew. For x86_64, these are kept separately in /usr/local. From there, the relative directory of opt/metis should also be the same. These directories are set by homebrew when installing without any input from users. Whether users could change these afterwards, I'm not sure, but my understanding is that that would not be a typical use of homebrew.


# For MUMPS, use a tag from stable/2.1 branch instead of what
# IPOPT 3.12.8 automatically pulls (stable/1.6). Both branches
# use MUMPS 4.10.0. This avoid some linker issues with Homebrew METIS.
set(MUMPS_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/mumps")
ExternalProject_Add(mumps
GIT_REPOSITORY https://github.com/coin-or-tools/ThirdParty-Mumps.git
GIT_TAG f4ad789112161f73b2a3daf1c586f7de85cd7043 #from stable/2.1 branch
INSTALL_DIR ${MUMPS_INSTALL_DIR}
PATCH_COMMAND cd <SOURCE_DIR> && ./get.Mumps
CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR> ADD_FFLAGS=-fallow-argument-mismatch ADD_CFLAGS=-Wno-error=implicit-function-declaration
--with-metis-cflags=-I${METIS_INSTALL_DIR}/include
"--with-metis-lflags=-L${METIS_INSTALL_DIR}/lib -lmetis"
BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} ${BUILD_FLAGS}
INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} install
)

# Can still use IPOPT 3.12.8, with a small patch.
set(IPOPT_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/ipopt")
ExternalProject_Add(ipopt
DEPENDS mumps
URL https://www.coin-or.org/download/source/Ipopt/Ipopt-3.12.8.zip
INSTALL_DIR ${IPOPT_INSTALL_DIR}
# For Ipopt 3.12, patch a file so that it can find the proper MUMPS flags/variables.
PATCH_COMMAND cd <SOURCE_DIR> && patch -p0 < ${CMAKE_SOURCE_DIR}/ipopt.patch
CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR>
--with-mumps-incdir=${MUMPS_INSTALL_DIR}/include/coin-or/mumps
"--with-mumps-lib=-L${MUMPS_INSTALL_DIR}/lib -lcoinmumps"
BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} ${BUILD_FLAGS}
INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} install
)

else()
# TODO --enable-debug if building in Debug.
# TODO must have gfortran for MUMPS (brew install gcc).
# TODO CMake documentation says "Whether the current working directory
# is preserved between commands is not defined. Behavior of shell
# operators like && is not defined."
# Patch the scripts that download Metis and MUMPS to use our
# Sourceforge mirror. The original links are not reliable.
ExternalProject_Add(ipopt
URL https://www.coin-or.org/download/source/Ipopt/Ipopt-3.12.8.zip
INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/ipopt"
PATCH_COMMAND cd <SOURCE_DIR>/ThirdParty/Metis && patch < ${CMAKE_SOURCE_DIR}/get.Metis.patch
COMMAND cd <SOURCE_DIR>/ThirdParty/Metis && ./get.Metis
COMMAND cd <SOURCE_DIR>/ThirdParty/Mumps && patch < ${CMAKE_SOURCE_DIR}/get.Mumps.patch
COMMAND cd <SOURCE_DIR>/ThirdParty/Mumps && ./get.Mumps
# GCC 10 generates a warning when compling MUMPS that we must suppress using
# -fallow-argument-mismatch.
# Suppress warnings treated as errors in Clang/LLVM with -Wno-error=implicit-function-declaration
CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR> ADD_FFLAGS=-fallow-argument-mismatch ADD_CFLAGS=-Wno-error=implicit-function-declaration
BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} ${BUILD_FLAGS}
INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} install)
endif()
endif()

endif()

# Use a pre-built IPOPT installation folder instead of using the superbuild.
if (USE_IPOPT_INSTALL)
set(IPOPT_INSTALL_CMD "${CMAKE_COMMAND}" -E copy_directory
"${IPOPT_INSTALL_DIR}"
"${CMAKE_INSTALL_PREFIX}/ipopt")
ExternalProject_Add(ipopt
DOWNLOAD_COMMAND ""
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${IPOPT_INSTALL_CMD}
)
endif()

if(SUPERBUILD_casadi)
AddDependency(NAME casadi
DEFAULT ON
Expand Down
10 changes: 10 additions & 0 deletions dependencies/ipopt.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--- Ipopt/src/Algorithm/LinearSolvers/IpMumpsSolverInterface.cpp 2022-04-13 11:59:52.000000000 -0700
+++ Ipopt/src/Algorithm/LinearSolvers/IpMumpsSolverInterface.cpp 2022-04-13 11:59:37.000000000 -0700
@@ -16,6 +16,7 @@
// The first header to include is the one for MPI.
// In newer ThirdParty/Mumps, mpi.h is renamed to mumps_mpi.h.
// We get informed about this by having COIN_USE_MUMPS_MPI_H defined.
+#include "mumps_compat.h"
#ifdef COIN_USE_MUMPS_MPI_H
#include "mumps_mpi.h"
#else