My experiences in installing IPOPT on Mac OS X
by Peter Carbonetto
Dept. of Computer Science
University of British Columbia
IPOPT is a
software package for solving nonlinear objectives subject to nonlinear
constraints. It uses primal-dual interior point
methodology. Importantly, it is open source.
After a great deal of time and trouble, I managed to get in working
on my laptop which is running the Mac OS X operating system.1 In the following, I detail my
experiences in installing the IPOPT package.
Succinctly put, the configure script did not work for IPOPT, so I
had to install everything from scratch. While this was really quite a
labourous process, I didn't know any other way of installing the
package. On the bright side, I learned a lot about compiling fortran
and C++, and linking object code, libraries and executables
1. Installing the Fortran compiler
The first problem I encounter is that I do not have a Fortran 77
compiler installed on my machine. I do have the GNU C and C++
compilers installed on my computer already (the programs
gcc and g++ ), but the Fortran 77 compiler is
also needed to compile the BLAS, LAPACK and HSL routines. A lot of
people are upset that the GNU Fortran compiler g77 was
not included with the Apple
Developer Tools because installing it ourselves causes many extra
headaches. But we'll have to make do.
There are several ways I can install a Fortran compiler. One is by
downloading GNU Fortran compiler from the High Performance Computing
webpage. Another route is to install g77 via Fink. Instead, I'm going to
follow the route that gives me the most control: I will download and
build the entire GNU
Compiler Collection (GCC), then put the necessary files in the
appropriate places. Even though this route is considerably more
complicated, it will allow me to ensure that I have the correct
version of the compiler. You see, since I'm running Mac OS X 10.3.9 I
already have gcc 3.3 installed on my computer in the
/usr/bin/ directory. (It is easy to check the version by
typing gcc --version .) It is important that the compilers
I'm using all belong from the same collection otherwise it is very
likely that I will undercover linking errors. I've decided to
download GCC 3.3.6 from my local university FTP mirror.
It is crucial that I do not follow the default installation
for GCC, because I may end up overwriting important files. The GCC
installation instructions advise the same thing. Suppose that I've
chosen to install to the directory
gcc-install . I've done so simply by passing
the option --prefix=gcc-install to the
configure script. After following the correct
installation steps and waiting a couple hours for the entire package
to be built, I now have a whole bunch of files and subdirectories in
gcc-install . I'm only really interested in
the programs and libraries necessary for compiling and linking Fortran
code. I start by installing the Fortran 77 compiler with the
command
sudo mv gcc-install/bin/g77 /usr/bin/g77
In the end, I had installed the following files:
/usr/bin/g77
/usr/lib/libg2c.a
/usr/lib/libg2c.la
/usr/lib/libfrtlegin.a
2. Building the BLAS, LAPACK and HSL libraries
Now that I have a Fortran 77 compiler installed on my system, I
proceed to build the libraries needed by IPOPT from scratch. First, I
download the latest BLAS and LAPACK tarballs from the Netlib FTP repository. The BLAS
package just consists of a bunch of Fortran files. I compile each of
the individual files into object code, starting with the file
caxpy.f :
g77 -funroll-all-loops -O3 -x f77-cpp-input -c caxpy.f
This creates an object file caxpy.o . The rest of the
files are compiled similarly. If you want to produce a shared library,
you will want to include the -fPIC option. Also, I've
noticed that the -fexceptions option should not be used
as it causes linking errors down the road. Once I've compiled all the
Fortran code, I create a static library via the following commands:
ar cr libblas.a *.o
ranlib libblas.a
I create the LAPACK library in precisely the same fashion, with the
same options passed to g77 . The only difference is that
the files in the LAPACK tarball are strewn about in various
subdirectories. In brief, the quickest way to build the LAPACK library
is to use the existing Makefile and type
make ../liblapack.a
at the command prompt with lapack/SRC being the
current directory. Before we do that, however, we need to modify a few
of the options passed to the Makefile. First, I move
lapack/make.inc.example to
lapack/make.inc . Looking at this file, I see that it
specifies among other things the program used to compile the Fortran
code, which is g77 , exactly as I want it. Near the bottom
of this text file, I change the variable LAPACKLIB to
LAPACKLIB = liblapack.a
Now, I can type the make command in the
SRC subdirectory and it should proceed to automatically
create the library (this takes about ten minutes on my computer).
Lastly, I create a library with the HSL subroutines. After
following the instructions in the IPOPT document for downloading the
code from the HSL Archive, I create the library with the following
commands:
g77 -funroll-all-loops -O3 -x f77-cpp-input -c ma27ad.f
g77 -funroll-all-loops -O3 -x f77-cpp-input -c mc19ad.f
ar cr libhsl.a ma27ad.o mc19ad.o
ranlib libhsl.a
Now I'm ready to create the IPOPT library.
3. Building the IPOPT library
I will elect not to follow the standard installation instructions
(since they didn't work) and instead build the IPOPT library by
hand. Basically, I'm going to follow almost the same steps as I did
before. The trickiest part is that I need to modify the file
Ipopt/inc/config_ipopt.h manually; the configure script
does this automatically. My file looked like
#define COIN_HAS_BLAS 1
#define COIN_HAS_IPOPT 1
#define COIN_HAS_LAPACK 1
#define COIN_IPOPT_CHECKLEVEL 0
#define COIN_IPOPT_VERBOSITY 0
#define F77_FUNC(name,NAME) name ## _
#define F77_FUNC_(name,NAME) name ## __
#define FORTRAN_INTEGER_TYPE int
#define HAVE_CASSERT 1
#define HAVE_CCTYPE 1
#define HAVE_CFLOAT 1
#define HAVE_CMATH 1
#define HAVE_CSTDARG 1
#define HAVE_CSTDIO 1
#define HAVE_CSTDLIB 1
#define HAVE_CTIME 1
#define HAVE_DLFCN_H 1
#define HAVE_INTTYPES_H 1
#define HAVE_MA27 1
#define HAVE_MC19 1
#define HAVE_MEMORY_H 1
#define HAVE_STDINT_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRINGS_H 1
#define HAVE_STRING_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_UNISTD_H 1
#define MY_C_FINITE finite
#define PACKAGE "ipopt"
#define PACKAGE_BUGREPORT "http://projects.coin-or.org/..."
#define PACKAGE_NAME "Ipopt"
#define PACKAGE_STRING "Ipopt 3.2.3"
#define PACKAGE_TARNAME "ipopt"
#define PACKAGE_VERSION "3.2.3"
#define SIZEOF_INT_P sizeof(int*)
#define STDC_HEADERS 1
#define VERSION "3.2.3"
Next, I compile the C and C++ source files into object files. For
instance, a create the object file IpAdaptiveMuUpdate.o
with the command
g++ -O3 -Iipopt-include-dir -c IpAdaptiveMuUpdate.cpp
where ipopt-include-dir is the directory containing
all the .h and .hpp header files. And so
on. Once I've compiled all the source files, I create the static
library with the commands
ar cr libipopt.a *.o
ranlib libipopt.a
Note that in most cases it will not make sense to archive
all the object files into the library. For instance, you
should not include IpMa57TSolverInterface.o unless you
have downloaded that solver (I didn't). By the same token, I didn't
include the code for interfacing with the AMPL and CUTEr.
4. Testing the installation with an example
I can't be positive that we built the libraries correctly without
trying to run a program that actually uses IPOPT. I try the Hock and
Schittkowski nonlinear programming test example no. 71, which is
included with the IPOPT tarball. After copying all the static
libraries to libhome , I compile and link the code
with the following sequence of commands:
g++ -Iipopt-include-dir -c hs071_nlp.cpp
g++ -Iipopt-include-dir -c hs071_main.cpp
g++ -o hs071 hs071_nlp.o hs071_main.o libhome/libipopt.a \
libhome/liblapack.a libhome/libblas.a libhome/libhsl.a \
-lg2c -lm
Now have a program which is executed by typing
./hs071 . Note that the order in which I included the
object files and libraries in the above lines is important. The
g2c library helps us link the Fortran object code to the
C++ object code (recall that I placed this library in
/usr/lib ).
Footnotes
1 More precisely, I'm using Mac
OS X version 10.3.9 (Panther), and I have a PowerPC G4 processor. You
may find that the steps I follow apply to your system, even if it
isn't the same process or version of the operating system.
|