Skip to content

Commit

Permalink
Use Xpress_jll for binaries
Browse files Browse the repository at this point in the history
  • Loading branch information
odow committed Mar 25, 2024
1 parent ceb9df8 commit 2e40dd5
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 41 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ jobs:
fail-fast: false
matrix:
version: ['1.6', '1'] # Test against LTS and current minor release
os: [ubuntu-latest, macOS-latest]
os: [ubuntu-latest, macOS-latest, windows-latest]
arch: [x64]
include:
- version: '1'
os: macos-14
arch: aarch64
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v1
Expand All @@ -26,6 +30,8 @@ jobs:
arch: ${{ matrix.arch }}
- uses: julia-actions/cache@v1
- uses: julia-actions/julia-buildpkg@v1
env:
XPRESS_JL_SKIP_LIB_CHECK: "true"
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v1
Expand Down
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ url = "https://github.com/jump-dev/Xpress.jl"
version = "0.16.2"

[deps]
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"

[compat]
Downloads = "<0.0.1, 1"
Libdl = "<0.0.1, 1.6"
MathOptInterface = "1"
Test = "<0.0.1, 1.6"
Xpress_jll = "=9.3.0"
julia = "1.6"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Xpress_jll = "308bddfa-7f95-4fa6-a557-f2c7addc1869"

[targets]
test = ["Test"]
test = ["Test", "Xpress_jll"]
48 changes: 45 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ The underlying solver is a closed-source commercial product for which you must

First, obtain a license of Xpress and install Xpress solver, following the
[instructions on the FICO website](https://www.fico.com/products/fico-xpress-solver).
Ensure that the `XPRESSDIR` license variable is set to the install location by
checking the output of:
```julia
julia> ENV["XPRESSDIR"]
```

Then, install this package using:
```julia
Expand All @@ -46,12 +51,47 @@ import Pkg
Pkg.add("Xpress")
```

### Skipping installation

By default, building Xpress.jl will fail if the Xpress library is not found.

This may not be desirable in certain cases, for example when part of a package's
test suite uses Xpress as an optional test dependency, but Xpress cannot be
installed on a CI server running the test suite. To support this use case, the
`XPRESS_JL_SKIP_LIB_CHECK` environment variable may be set (to any value) to
make Xpress.jl installable (but not usable).
installed on a CI server running the test suite.

To skip the error, set the `XPRESS_JL_SKIP_LIB_CHECK` environment variable to
`true` to make Xpress.jl installable (but not usable).

```julia
ENV["XPRESS_JL_SKIP_LIB_CHECK"] = true
import Pkg
Pkg.add("Xpress")
```

## Use with Xpress_jll

Instead of manually installing Xpress, you can use the binaries provided by the
[Xpress_jll.jl](https://github.com/jump-dev/Xpress_jll.jl) package.

By using Xpress_jll, you agree to certain license conditions. See the
[Xpress_jll.jl README](https://github.com/jump-dev/Xpress_jll.jl/tree/master?tab=readme-ov-file#license)
for more details.

By default, `Xpress_jll` includes a limited size community license. If you have
purchased a license for FICO Xpress, you should additionally set the
`XPAUTH_PATH` environment variable to point to your license file.

```julia
import Xpress_jll
# This environment variable must be set _before_ loading Xpress.jl
ENV["XPRESS_JL_LIBRARY"] = Xpress_jll.libxprs
# Optional: point to the location of your license file
ENV["XPAUTH_PATH"] = "/path/to/xpauth.xpr"
using Xpress
```

If you plan to use Xpress_jll, `Pkg.add("Xpress")` will fail because it cannot
find a local installation of Xpress. Therefore, you should

## Use with JuMP

Expand Down Expand Up @@ -102,6 +142,8 @@ current implementation should be considered experimental.
- `XPRESS_JL_NO_DEPS_ERROR`: Disable error when do deps.jl file is found.
- `XPRESS_JL_NO_AUTO_INIT`: Disable automatic run of `Xpress.initialize()`.
Specially useful for explicitly loading the dynamic library.
- `XPRESS_JL_LIBRARY`: Provide a custom path to `libxprs`
- `XPAUTH_PATH`: Provide a custom path to the license file

## C API

Expand Down
21 changes: 0 additions & 21 deletions deps/build.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
# Use of this source code is governed by an MIT-style license that can be found
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.

import Downloads
import Libdl

const DEPS_FILE = joinpath(dirname(@__FILE__), "deps.jl")
Expand Down Expand Up @@ -41,24 +40,6 @@ function local_installation()
""")
end

function ci_installation()
url = if Sys.islinux()
"https://anaconda.org/fico-xpress/xpress/9.3.0/download/linux-64/xpress-9.3.0-py310ha14b774_0.tar.bz2"
else
@assert Sys.isapple()
"https://anaconda.org/fico-xpress/xpress/9.3.0/download/osx-64/xpress-9.3.0-py310h9b76c6a_0.tar.bz2"
end
Downloads.download(url, "xpress.tar.bz2")
run(`tar -xjf xpress.tar.bz2`)
root = "lib/python3.10/site-packages/xpress"
run(`cp $root/license/community-xpauth.xpr $root/lib/xpauth.xpr`)
if Sys.islinux()
run(`cp $root/lib/libxprs.so.42 $root/lib/libxprs.so`)
end
write_deps_file(joinpath(@__DIR__, root, "lib"))
return
end

if isfile(DEPS_FILE)
rm(DEPS_FILE)
end
Expand All @@ -67,8 +48,6 @@ if haskey(ENV, "XPRESS_JL_SKIP_LIB_CHECK")
# Skip!
elseif get(ENV, "JULIA_REGISTRYCI_AUTOMERGE", "false") == "true"
write_deps_file("julia_registryci_automerge")
elseif get(ENV, "CI", "") == "true"
ci_installation()
else
local_installation()
end
4 changes: 3 additions & 1 deletion src/Lib/Lib.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
module Lib

import ..Xpress
const libxprs = Xpress.libxprs
global libxprs = Xpress.libxprs

set_libxprs(libxprs_) = (global libxprs = libxprs_)

include("common.jl")
include("xprs.jl")
Expand Down
19 changes: 11 additions & 8 deletions src/Xpress.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,14 @@ const depsjl_path = joinpath(@__DIR__, "..", "deps", "deps.jl")

if isfile(depsjl_path)
include(depsjl_path)
elseif !haskey(ENV, "XPRESS_JL_NO_DEPS_ERROR")
error("XPRESS cannot be loaded. Please run Pkg.build(\"Xpress\").")
global libxprs = joinpath(
xpressdlpath,
string(Sys.iswindows() ? "" : "lib", "xprs", ".", Libdl.dlext),
)
else
const xpressdlpath = ""
global libxprs = ""
end

const libxprs = joinpath(
xpressdlpath,
string(Sys.iswindows() ? "" : "lib", "xprs", ".", Libdl.dlext),
)

include("Lib/Lib.jl")
include("helper.jl")
include("api.jl")
Expand All @@ -42,6 +39,12 @@ include("MOI/MOI_wrapper.jl")
include("MOI/MOI_callbacks.jl")

function __init__()
if haskey(ENV, "XPRESS_JL_LIBRARY")
global libxprs = ENV["XPRESS_JL_LIBRARY"]
Lib.set_libxprs(libxprs)
elseif isempty(libxprs) && !haskey(ENV, "XPRESS_JL_NO_DEPS_ERROR")
error("XPRESS cannot be loaded. Please run Pkg.build(\"Xpress\").")

Check warning on line 46 in src/Xpress.jl

View check run for this annotation

Codecov / codecov/patch

src/Xpress.jl#L45-L46

Added lines #L45 - L46 were not covered by tests
end
if !haskey(ENV, "XPRESS_JL_NO_AUTO_INIT") &&
get(ENV, "JULIA_REGISTRYCI_AUTOMERGE", "false") != "true"
initialize()
Expand Down
7 changes: 6 additions & 1 deletion src/license.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ function get_xpauthpath(xpauth_path = "", verbose::Bool = true)

# user´s lib dir
push!(candidates, joinpath(dirname(dirname(libxprs)), "bin", XPAUTH))

# Add the license location of Xpress_jll. Make sure this is last, so that we
# find the user's license if one exists.
push!(
candidates,
joinpath(dirname(dirname(libxprs)), "license", "community-xpauth.xpr"),
)
for i in candidates
if isfile(i)
if verbose && !haskey(ENV, "XPRESS_JL_NO_INFO")
Expand Down
3 changes: 3 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
# Use of this source code is governed by an MIT-style license that can be found
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.

import Xpress_jll
ENV["XPRESS_JL_LIBRARY"] = Xpress_jll.libxprs

using Test
using Xpress

Expand Down
7 changes: 4 additions & 3 deletions test/test_helper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ function test_show_xpress_error()
end

function test_xpress_problem_logfile()
p = Xpress.XpressProblem(; logfile = "test.log")
@test isfile("test.log")
rm("test.log")
# Use mktempdir so that the file is removed on process exit
filename = joinpath(mktempdir(), "test.log")
p = Xpress.XpressProblem(; logfile = filename)
@test isfile(filename)
return
end

Expand Down

0 comments on commit 2e40dd5

Please sign in to comment.