Skip to content

Commit

Permalink
New build.jl using BinaryBuilder (#98)
Browse files Browse the repository at this point in the history
* New build.jl using BinaryBuilder

* update build.jl

* update build.jl to v3.12.8-9

* amplexe now defined in deps.jl

* linux binaries require 0.6.2

* BinDeps no longer needed

* test binary on travis

* fix library paths for the ipopt binary

* remove stale comment

* try DYLD_LIBRARY_PATH

* document custom installation
  • Loading branch information
mlubin committed Mar 1, 2018
1 parent 6de0898 commit b51624e
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 108 deletions.
3 changes: 0 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ julia:
notifications:
email: false
sudo: false
addons:
apt_packages:
- gfortran
script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
- julia -e 'Pkg.clone(pwd()); Pkg.build("Ipopt")'
Expand Down
57 changes: 50 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,62 @@ Ipopt.jl
[![Build Status](https://travis-ci.org/JuliaOpt/Ipopt.jl.svg?branch=master)](https://travis-ci.org/JuliaOpt/Ipopt.jl)
[![Coverage Status](https://img.shields.io/coveralls/JuliaOpt/Ipopt.jl.svg)](https://coveralls.io/r/JuliaOpt/Ipopt.jl)

[![Ipopt](http://pkg.julialang.org/badges/Ipopt_0.5.svg)](http://pkg.julialang.org/?pkg=Ipopt&ver=0.5)
[![Ipopt](http://pkg.julialang.org/badges/Ipopt_0.6.svg)](http://pkg.julialang.org/?pkg=Ipopt&ver=0.6)
[![Ipopt](http://pkg.julialang.org/badges/Ipopt_0.7.svg)](http://pkg.julialang.org/?pkg=Ipopt&ver=0.7)

**Ipopt.jl** is a [Julia](http://julialang.org/) interface to the [Ipopt](http://www.coin-or.org/Ipopt/documentation/documentation.html) nonlinear solver.

**Installation**: `julia> Pkg.add("Ipopt")`
**Default Installation**: `julia> Pkg.add("Ipopt")`

This will install Ipopt.jl, as well as Ipopt itself. A binary will be downloaded on Windows and
on OSX (via Homebrew), but it will be built from source on Linux. You should make sure you have
the required packages before installing, e.g.
This will install Ipopt.jl, as well as Ipopt itself. A binary will be downloaded
by default on all supported platforms (Linux, macOS, and Windows). If your
platform is not supported, or if you prefer to compile your own version of Ipopt
in order to use commercial sparse linear algebra libraries, use the instructions
below.

**Custom Installation**:

Make sure you have the required packages before installing, e.g.,

```bash
sudo apt-get install build-essential gfortran pkg-config liblapack-dev libblas-dev
```

The script below was tested successfully for installing Ipopt. You may modify
the configuration options, but be sure to install Ipopt into the correct
prefix location. The Julia package will only search in `deps/usr` within the
package directory; it will not detect system installs.

```bash
sudo apt-get install build-essential gfortran pkg-config
wget https://www.coin-or.org/download/source/Ipopt/Ipopt-3.12.8.tgz
tar xvzf Ipopt-3.12.8.tgz
cd Ipopt-3.12.8/
# Blas and Lapack must be installed already. If not, run
# ThirdParty/Blas/get.Blas and ThirdParty/Lapack/get.Lapack.
# ASL is required even if you do not plan to use it.
cd ThirdParty/ASL/
./get.ASL
cd ..
cd Mumps
# Compiling Mumps requires gfortran.
./get.Mumps
cd ../..
# Update the prefix location! The following is correct only for Julia 0.6.
./configure --prefix=$HOME/.julia/v0.6/Ipopt/deps/usr
make
make test
make install
```

Now in Julia:

```julia
julia> Pkg.build("Ipopt")
INFO: Building Ipopt

julia> Pkg.test("Ipopt")
...
INFO: Ipopt tests passed
```

MathProgBase Interface
Expand All @@ -29,4 +73,3 @@ C Interface Wrapper
-------------------

Full documentation for the Ipopt C wrapper is available [here](http://ipoptjl.readthedocs.org/en/latest/ipopt.html). Use of the [nonlinear MathProgBase interface](http://mathprogbasejl.readthedocs.org/en/latest/nlp.html) is recommended over the low-level C interface because it permits one to easily switch between solvers.

7 changes: 3 additions & 4 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
julia 0.6
BinDeps
julia 0.6.2
MathProgBase 0.5 0.8
@osx Homebrew
@windows WinRPM
BinaryProvider
Compat
131 changes: 39 additions & 92 deletions deps/build.jl
Original file line number Diff line number Diff line change
@@ -1,93 +1,40 @@
using BinDeps
using Compat

@BinDeps.setup

windllname = "libipopt-1"
libipopt = library_dependency("libipopt", aliases=[windllname])

ipoptname = "Ipopt-3.12.8"

provides(Sources, URI("http://www.coin-or.org/download/source/Ipopt/$ipoptname.tgz"),
libipopt, os = :Unix)

prefix=joinpath(BinDeps.depsdir(libipopt),"usr")
patchdir=BinDeps.depsdir(libipopt)
srcdir = joinpath(BinDeps.depsdir(libipopt),"src",ipoptname)

# fpu_control flag for building on ARM
if Sys.ARCH == :arm
fpu_control = "ADD_CFLAGS=-DNO_fpu_control"
else
fpu_control = ""
end

provides(SimpleBuild,
(@build_steps begin
GetSources(libipopt)
@build_steps begin
ChangeDirectory(srcdir)
@build_steps begin
ChangeDirectory(joinpath(srcdir,"ThirdParty","Blas"))
CreateDirectory("build", true)
`sed -i.backup 's/wget"/wget --no-check-certificate"/g' get.Blas`
`./get.Blas`
end
@build_steps begin
ChangeDirectory(joinpath(srcdir,"ThirdParty","Blas","build"))
`../configure --prefix=$prefix --disable-shared --with-pic`
`make install`
end
@build_steps begin
ChangeDirectory(joinpath(srcdir,"ThirdParty","Lapack"))
CreateDirectory("build", true)
`sed -i.backup 's/wget"/wget --no-check-certificate"/g' get.Lapack`
`./get.Lapack`
end
@build_steps begin
ChangeDirectory(joinpath(srcdir,"ThirdParty","Lapack","build"))
`../configure --prefix=$prefix --disable-shared --with-pic
--with-blas="$prefix/lib/libcoinblas.a -lgfortran"`
`make install`
end
@build_steps begin
ChangeDirectory(joinpath(srcdir,"ThirdParty","ASL"))
`./get.ASL`
end
@build_steps begin
ChangeDirectory(joinpath(srcdir,"ThirdParty","Mumps"))
`./get.Mumps`
end
`./configure --prefix=$prefix coin_skip_warn_cxxflags=yes
--with-blas="$prefix/lib/libcoinblas.a -lgfortran"
--with-lapack=$prefix/lib/libcoinlapack.a
$fpu_control`
`make`
`make test`
`make -j1 install`
end
end),libipopt, os = :Unix)

# OS X
if is_apple()
using Homebrew
provides(Homebrew.HB, "staticfloat/juliadeps/ipopt", libipopt, os = :Darwin)
end

# Windows
if is_windows()
using WinRPM
provides(WinRPM.RPM, "Ipopt", [libipopt], os = :Windows)
end

# Avoid Issue #62, building into /lib64 on OpenSUSE
configsite = nothing
if haskey(ENV, "CONFIG_SITE")
configsite = pop!(ENV, "CONFIG_SITE")
end

@BinDeps.install Dict(:libipopt => :libipopt)

if configsite !== nothing
ENV["CONFIG_SITE"] = configsite
using BinaryProvider

# Parse some basic command-line arguments
const verbose = "--verbose" in ARGS
const prefix = Prefix(get([a for a in ARGS if a != "--verbose"], 1, joinpath(@__DIR__, "usr")))
products = Product[
LibraryProduct(prefix, String["libipopt"], :libipopt),
ExecutableProduct(prefix, "ipopt", :amplexe),
]

# Download binaries from hosted location
bin_prefix = "https://github.com/staticfloat/IpoptBuilder/releases/download/v3.12.8-9"

# Listing of files generated by BinaryBuilder:
download_info = Dict(
BinaryProvider.Linux(:aarch64, :glibc) => ("$bin_prefix/Ipopt.aarch64-linux-gnu.tar.gz", "ea4b4ed7612d3603307f9a9aaa298c558abcc1c07378bacc5eb0520477f23adf"),
BinaryProvider.Linux(:armv7l, :glibc) => ("$bin_prefix/Ipopt.arm-linux-gnueabihf.tar.gz", "23410ee354456e86294123cd641a01e6062bbc2fe9244f099bd3f06647ce3f3c"),
BinaryProvider.Linux(:i686, :glibc) => ("$bin_prefix/Ipopt.i686-linux-gnu.tar.gz", "7ddb2d3791fe7b8252c074f9bb77cd4094d2a38c9fdcc139ab392a200e17b22b"),
BinaryProvider.Windows(:i686) => ("$bin_prefix/Ipopt.i686-w64-mingw32.tar.gz", "91c2c70b1a4de58e0b3f512b28bcc88594489d64e721557385744e8994189f2e"),
BinaryProvider.MacOS() => ("$bin_prefix/Ipopt.x86_64-apple-darwin14.tar.gz", "8e979f6ac782af6836425bc60f594054cc7644dfc59fb9b0a19fb7a1e3b2ae24"),
BinaryProvider.Linux(:x86_64, :glibc) => ("$bin_prefix/Ipopt.x86_64-linux-gnu.tar.gz", "d3d8f69278905ea8cab23193cf03b49ac30837bcbfab67de377e4c58ec48de46"),
BinaryProvider.Windows(:x86_64) => ("$bin_prefix/Ipopt.x86_64-w64-mingw32.tar.gz", "d967b152449659591095458594948f74981fc0b772cbf3f333a9a24676beab80"),
)

# First, check to see if we're all satisfied
if any(!satisfied(p; verbose=verbose) for p in products)
if haskey(download_info, platform_key())
# Download and install binaries
url, tarball_hash = download_info[platform_key()]
install(url, tarball_hash; prefix=prefix, force=true, verbose=verbose)

# Write out a deps.jl file that will contain mappings for our products
write_deps_file(joinpath(@__DIR__, "deps.jl"), products)
else
# If we don't have a BinaryProvider-compatible .tar.gz to download, complain.
# Alternatively, you could attempt to install from a separate provider,
# build from source or something more even more ambitious here.
error("Your platform $(Sys.MACHINE) is not supported by this package!")
end
end
15 changes: 14 additions & 1 deletion src/Ipopt.jl
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
__precompile__()

module Ipopt
using Compat

if isfile(joinpath(dirname(@__FILE__),"..","deps","deps.jl"))
include("../deps/deps.jl")
else
error("Ipopt not properly installed. Please run Pkg.build(\"Ipopt\")")
end
amplexe = joinpath(dirname(libipopt), "..", "bin", "ipopt")

export createProblem, addOption
export openOutputFile, setProblemScaling, setIntermediateCallback
export solveProblem
export IpoptProblem

function __init__()
check_deps()
# Sets up the library paths so that we can run the ipopt binary from Julia.
# TODO: Restructure into a function that wraps the call to the binary and
# doesn't leave environment variables changed.
julia_libdir = joinpath(dirname(first(filter(x -> contains(x, "libjulia"), Sys.Libdl.dllist()))), "julia")
@static if Compat.Sys.isapple()
ENV["DYLD_LIBRARY_PATH"] = string(get(ENV, "DYLD_LIBRARY_PATH", ""), ":", julia_libdir)
elseif Compat.Sys.islinux()
ENV["LD_LIBRARY_PATH"] = string(get(ENV, "LD_LIBRARY_PATH", ""), ":", julia_libdir)
end
end


mutable struct IpoptProblem
ref::Ptr{Void} # Reference to the internal data structure
Expand Down
5 changes: 4 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ qpdualtest(IpoptSolver())

# Test retoration only options
#
# Warm start with infeasible solution, force restoration on initial iteration.
# Warm start with infeasible solution, force restoration on initial iteration.
# But limit to 0 iterations. Forces :UserLimit exit.
m = MathProgBase.NonlinearModel(IpoptSolver(start_with_resto="yes", resto_max_iter=0))
l = [1,1,1,1]
Expand All @@ -74,3 +74,6 @@ MathProgBase.loadproblem!(m, 4, 2, l, u, lb, ub, :Min, HS071())
MathProgBase.setwarmstart!(m,[0,15,15,11])
MathProgBase.optimize!(m)
@test MathProgBase.status(m) == :UserLimit

# Test that the ipopt binary works
@test success(`$(Ipopt.amplexe) -v`)

0 comments on commit b51624e

Please sign in to comment.