Skip to content

Commit

Permalink
Merge pull request #8 from sisl/binarybuilder
Browse files Browse the repository at this point in the history
[WIP] Use Cxx and BinaryBuilder
  • Loading branch information
MaximeBouton authored Sep 24, 2019
2 parents 408e862 + 752dcaf commit e897273
Show file tree
Hide file tree
Showing 15 changed files with 1,524 additions and 681 deletions.
90 changes: 40 additions & 50 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,50 +1,40 @@
# Documentation: http://docs.travis-ci.com/user/languages/julia/
language: julia
os:
- linux
julia:
- 1.0
- 1.1
- nightly

env:
- CONDA_JL_VERSION="3" PYTHON=""

addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-7
- python3-dev
- clang-3.9
- graphviz

matrix:
allow_failures:
- julia: nightly
fast_finish: true

notifications:
email: false
before_script:
- sudo apt-get -qq update
- sudo apt-get install -y pdf2svg
- sudo apt-get install -y texlive-latex-base
- sudo apt-get install -y texlive-binaries
- sudo apt-get install -y texlive-pictures
- sudo apt-get install -y texlive-latex-extra
- sudo pip install dot2tex
# Every 30 seconds, look for the build log file. If it exists, then
# start watching its contents and printing them to stdout as they
# change. This has two effects:
# 1. it avoids Travis timing out because the build outputs nothing
# 2. it makes it more obvious what part of the build, if any, gets stuck
- while sleep 3; do tail ~/build/sisl/Spot.jl/deps/build.log -f ; done &
- sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 90
script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
- julia --project --color=yes -e 'import Pkg; Pkg.build(); Pkg.test(coverage=true)'
after_success:
- julia --project -e 'import Pkg; Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
- julia --project -e 'import Pkg; Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())'

# Documentation: http://docs.travis-ci.com/user/languages/julia/
language: julia
os:
- linux
julia:
- 1.2
- nightly

addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-7
- clang-3.9
- graphviz

matrix:
allow_failures:
- julia: nightly
fast_finish: true

notifications:
email: false
before_script:
- sudo apt-get -qq update
- sudo apt-get install -y pdf2svg
- sudo apt-get install -y texlive-latex-base
- sudo apt-get install -y texlive-binaries
- sudo apt-get install -y texlive-pictures
- sudo apt-get install -y texlive-latex-extra
- sudo pip install dot2tex
- sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 90
script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
- julia --project --color=yes -e 'import Pkg; Pkg.build(); Pkg.test(coverage=true)'
after_success:
- julia --project -e 'import Pkg; Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
- julia --project -e 'import Pkg; Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())'
9 changes: 6 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ repo = "https://github.com/sisl/Spot.jl"
version = "0.0.0"

[deps]
Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d"
BinaryProvider = "b99e7846-7c00-51b0-8f62-c81ae34c0232"
Cxx = "a0b5b9ef-44b7-5148-a2d1-f6db19f3c3d2"
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
LightGraphs = "093fc24a-ae57-5d10-9952-331d41423f4d"
MetaGraphs = "626554b9-1ddb-594c-aa3c-2596fe9399a5"
Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
TikzPictures = "37f6aa50-8035-52d0-81c2-5a1d08754b2d"

[extras]
NBInclude = "0db19996-df87-5ea3-a455-e3a50d440464"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["NBInclude", "Test"]
test = ["NBInclude", "Test"]
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@
[![CodeCov](https://codecov.io/gh/sisl/Spot.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/sisl/Spot.jl)
[![Coveralls](https://coveralls.io/repos/github/sisl/Spot.jl/badge.svg?branch=master)](https://coveralls.io/github/sisl/Spot.jl?branch=master)

This package provides Julia bindings to the [Spot](https://spot.lrde.epita.fr/index.html) library for LTL and automata manipulation.
It requires the python bindings of spot to be correctly installed and accessible via [PyCall.jl](https://github.com/JuliaPy/PyCall.jl)
This package provides Julia bindings to the [Spot](https://spot.lrde.epita.fr/index.html) library for LTL and automata manipulation. It relies on [Cxx.jl](https://github.com/JuliaInterop/Cxx.jl) to interface julia with the Spot c++ library.

If you wish to use `PyCall` instead and interact with the spot python bindings you should checkout the branch `pycall` (linux only).

## Installation

For the rendering, Spot requires [GraphViz](https://graphviz.gitlab.io/) and [dot2tex](https://dot2tex.readthedocs.io/en/latest/index.html) to be installed.
For the rendering, Spot requires [GraphViz](https://graphviz.gitlab.io/) and [dot2tex](https://dot2tex.readthedocs.io/en/latest/index.html) to be installed. In addition, the precompile binaries require `gcc` 7 or 8 (not needed for Mac).

```julia
using Pkg; Pkg.add("https://github.com/sisl/Spot.jl")
```

Python dependencies:
- IPython (for visualization in jupyter notebook)
**Windows support:** The registered version of Cxx.jl is currently broken for Windows. However, the branch `gn-patch-crash` is working for now. The build script should checkout the right branch. Otherwise run `] add Cxx#gn-patch-crash` in the julia environment where you wish to install Spot.

## Usage

Expand Down Expand Up @@ -46,11 +46,11 @@ a = translate(translator, ltl)

A basic tutorial is available in [docs/spot_basic_tutorial.ipynb](https://github.com/sisl/Spot.jl/blob/master/docs/spot_basic_tutorial.ipynb)

### Notes

## TODOs

- [ ] Use CXXWrap.jl to avoid relying on a third language (python) and automatically import all the spot functions.
- [ ] Try using BinaryBuilder. A first experiment was not successful, the path to `libspot.so` in the python bindings is wrong.
Right now, the wrapping of all the c++ functions present in `libspot` is not automatic.
Every function can be called using the Cxx interface.
If you need to wrap a function that has not been wrapped yet, feel free to submit a Pull Request.

## Acknowledgement

Expand Down
95 changes: 39 additions & 56 deletions deps/build.jl
Original file line number Diff line number Diff line change
@@ -1,62 +1,45 @@
using PyCall
using Conda
using BinaryProvider # requires BinaryProvider 0.3.0 or later

const SPOT_DEV_URL = "https://gitlab.lrde.epita.fr/spot/spot/-/jobs/21743/artifacts/download"
# const SPOT_DEV_URL = "https://gitlab.lrde.epita.fr/spot/spot/-/jobs/21303/artifacts/download"
# 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 = [
LibraryProduct(prefix, ["libspot"], :libspot),
]

const SPOT_VERSION = "spot-2.6.3.dev"
const GCC_MAJOR_VERSION = parse(Int,Char(read(`g++ -dumpversion | cut -f1 -d.`)[1])) # get g++ major version
if Sys.iswindows()
using Pkg
Pkg.add(PackageSpec(name="Cxx", rev="gn-patch-crash"))
end

# Download binaries from hosted location
bin_prefix = "https://github.com/MaximeBouton/SpotBuilder/releases/download/v2.8.1"

if !Sys.isunix()
throw("Windows not supported")
# Listing of files generated by BinaryBuilder:
download_info = Dict(
MacOS(:x86_64) => ("$bin_prefix/Spot.v2.8.1.x86_64-apple-darwin14.tar.gz", "de9236acab1975a06f218d2939f6c319fb0bc67546e89cdc5c85ef90be509cb4"),
Linux(:x86_64, libc=:glibc, compiler_abi=CompilerABI(:gcc7)) => ("$bin_prefix/Spot.v2.8.1.x86_64-linux-gnu-gcc7.tar.gz", "2fd4429180f94e67284ae37704aa22bed357e2a356062f8af0cd39397a173f4c"),
Linux(:x86_64, libc=:glibc, compiler_abi=CompilerABI(:gcc8)) => ("$bin_prefix/Spot.v2.8.1.x86_64-linux-gnu-gcc8.tar.gz", "7caaa648e059c354892a5503b30bf3b2d368469b4295f54564f8a212fa3e2893"),
Windows(:x86_64, compiler_abi=CompilerABI(:gcc7)) => ("$bin_prefix/Spot.v2.8.1.x86_64-w64-mingw32-gcc7.tar.gz", "782f52898e81c51abd8930c34184a6f99d78e4a49e7a6c753b9eb0741e8bcdfc"),
Windows(:x86_64, compiler_abi=CompilerABI(:gcc8)) => ("$bin_prefix/Spot.v2.8.1.x86_64-w64-mingw32-gcc8.tar.gz", "283473593d120f968366f85da52bd4341ac94715c49476adf9bdd1688b445411"),
)

# Install unsatisfied or updated dependencies:
unsatisfied = any(!satisfied(p; verbose=verbose) for p in products)
dl_info = choose_download(download_info, platform_key_abi())
if dl_info === nothing && unsatisfied
# If we don't have a compatible .tar.gz to download, complain.
# Alternatively, you could attempt to install from a separate provider,
# build from source or something even more ambitious here.
error("Your platform (\"$(Sys.MACHINE)\", parsed as \"$(triplet(platform_key_abi()))\") is not supported by this package!")
end

# borrowed from TensorFlow.jl
if PyCall.conda
println("Building Spot from source...")
pyversion = PyCall.pyversion
base = dirname(@__FILE__)
println("Switching to directory $base")
cd(base)
isfile("$SPOT_VERSION.zip") ? nothing : run(`wget -O $SPOT_VERSION.zip $SPOT_DEV_URL`)
run(`unzip $SPOT_VERSION.zip`)
run(`rm $SPOT_VERSION.zip`)
run(`tar -xzf $SPOT_VERSION.tar.gz`) # extract
isdir("spot") ? mkdir("spot") : nothing
cd(SPOT_VERSION)
if GCC_MAJOR_VERSION < 5
println("g++ version must be at least 5.0.0")
end
run(`./configure CXX=g++-7 PYTHON=$(Conda.PYTHONDIR)/python --prefix $(joinpath(base, "spot"))`)
run(`make`)
run(`make install`)
println(readdir(joinpath(base, "spot", "lib")))
@assert isdir(joinpath(base, "spot"))
@assert isdir(joinpath(base, "spot", "lib", "python"*string(pyversion.major)*"."*string(pyversion.minor), "site-packages"))
println("Python bindings located at: ", joinpath(base, "spot", "lib", "python"*string(pyversion.major)*"."*string(pyversion.minor), "site-packages"))
println("build successful")
println("Linking python bindings to Conda.jl")
conda_path = joinpath(Conda.ROOTENV, "lib", "python"*string(pyversion.major)*"."*string(pyversion.minor), "site-packages")
pythonspot = joinpath(base, "spot", "lib","python"*string(pyversion.major)*"."*string(pyversion.minor), "site-packages")
cd(conda_path)
run(`ln -sf $pythonspot/spot`)
run(`ln -sf $pythonspot/_buddy.a`)
run(`ln -sf $pythonspot/_buddy.la`)
run(`ln -sf $pythonspot/_buddy.so`)
run(`ln -sf $pythonspot/buddy.py`)
else
try
pyimport("spot")
catch ee
typeof(ee) <: PyCall.PyError || rethrow(ee)
error("""
Python Spot not installed
Please either:
- Rebuild PyCall to use Conda, by running in the julia REPL:
- `ENV["PYTHON"]=""; Pkg.build("PyCall"); Pkg.build("Spot")`
- Or install the python binding yourself:
Install Spot from https://spot.lrde.epita.fr/install.html
Find the python bindings in path/to/spot/lib/python3.x/site-packages
""")
end
# If we have a download, and we are unsatisfied (or the version we're
# trying to install is not itself installed) then load it up!
if unsatisfied || !isinstalled(dl_info...; prefix=prefix)
# Download and install binaries
install(dl_info...; prefix=prefix, force=true, verbose=verbose)
end

# Write out a deps.jl file that will contain mappings for our products
write_deps_file(joinpath(@__DIR__, "deps.jl"), products, verbose=verbose)
Loading

0 comments on commit e897273

Please sign in to comment.