Skip to content

[WIP] Use Cxx and BinaryBuilder #8

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

Merged
merged 22 commits into from
Sep 24, 2019
Merged
Show file tree
Hide file tree
Changes from all 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
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