evision
evision copied to clipboard
Getting evision up and running on FreeBSD
Setup
- Running an Elixir Phoenix App that uses Image
- Image makes use of
Image.Videoand thus needsevisionas dependency - The setup works perfect on local development machine (macOS), but I totally forgot to test if its seamlessly deployable to my infrastructure, running on FreeBSD... well, it isn't... ;-)
Goals
- A precompiled version for FreeBSD 14.2
Current State and Progress
- I created a small mix project with little dependency
def deps do [ {:evision, "~> 0.2"} ] end - I compiled evision on a FreeBSD 14.2 remote machine
pkg install cmake gmake python bash opencvmix deps.get && env MAKE=gmake env MIX_ENV=prod mix deps.compile
- I guess the crucial part is:
_build/prod/lib/evision/ebin/ _build/prod/lib/evision/priv/ _build/prod/lib/evision/cmake_evision/ _build/prod/lib/evision/cmake_opencv_4.11.0/ _build/prod/lib/evision/.mix - Next question: how to make this available for my or other projects
Info
- I update this during my findings
- Looping in @dch as this is again a FreeBSD thingy...
what sort of errors did you get? setup in 14.2-RELEASE amd64 jail:
setup
- ports has v5 ffmpeg, opencv 4.9
# pkg install -yr FreeBSD ninja multimedia/ffmpeg lang/erlang-runtime27 lang/elixir-devel gmake python bash opencv cmake
# export PATH=$PATH:/usr/local/lib/erlang27/bin
# export LANG=en_US.UTF-8
# export LC_ALL=$LANG
# git clone https://github.com/cocoa-xu/evision
# cd evision
build
- note it insists on fetching opencv again itself
# env MAKE=gmake \
EVISION_ENABLE_CONTRIB=false \
EVISION_ENABLE_CUDA=false \
OPENCV_VER=4.9.0 \
mix do deps.get, compile
I'd suggest diving through mix.exs and seeing if you can skip download, and use prebuilt opencv from ports.
Here's what opencv4.pc has:
/usr/local/libdata/pkgconfig/opencv4.pc
# Package Information for pkg-config
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include/opencv4
Name: OpenCV
Description: Open Source Computer Vision Library
Version: 4.9.0
Libs: -L${exec_prefix}/lib -lopencv_stitching -lopencv_alphamat -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib -lopencv_dnn_objdetect -lopencv_dnn_superres -lopencv_dpm -lopencv_face -lopencv_freetype -lopencv_fuzzy -lopencv_hdf -lopencv_hfs -lopencv_img_hash -lopencv_intensity_transform -lopencv_line_descriptor -lopencv_mcc -lopencv_quality -lopencv_rapid -lopencv_reg -lopencv_rgbd -lopencv_saliency -lopencv_sfm -lopencv_stereo -lopencv_structured_light -lopencv_phase_unwrapping -lopencv_superres -lopencv_optflow -lopencv_surface_matching -lopencv_tracking -lopencv_highgui -lopencv_datasets -lopencv_text -lopencv_plot -lopencv_videostab -lopencv_videoio -lopencv_wechat_qrcode -lopencv_xfeatures2d -lopencv_shape -lopencv_ml -lopencv_ximgproc -lopencv_video -lopencv_xobjdetect -lopencv_objdetect -lopencv_calib3d -lopencv_imgcodecs -lopencv_features2d -lopencv_dnn -lopencv_flann -lopencv_xphoto -lopencv_photo -lopencv_imgproc -lopencv_core
Libs.private: -lm -lpthread
Cflags: -I${includedir}
BTW definitely the longest mix.exs I've ever seen ;-)
Hi @marschro @dch, just let you know that I saw this issue this morning. I'm on vacation this week but please feel free to drop a PR that brings the pre-compile support for AMD64 FreeBSD. I'll review/help on this when I'm back. :)
Besides that, this library does not use existing OpenCV on the host because when there's no pre-built support, it needs some build-time metadata to generate corresponding binding files, which doesn't exist in these packages (from the pkg repo).
@dch - I actually did not have any errors. It compiled successfully.
But when re-doing that, I recognized, that I had some errors in the first post. cmake was also needed.
I updated the pkg's, that where needed (of course elixir also, I had that in the jail already...) and also updated the command, that I successfully used to compile the little project, that contains evision
Hey @marschro, v0.2.12 is shipped, which has precompiled binaries for x86_64 FreeBSD systems!
iex> Mix.install([{:evision, "~> 0.2.12"}])
...
10:13:36.261 [info] EVISION_PREFER_PRECOMPILED: true; try to download and use the precompiled library.
10:13:36.261 [info] Current target `x86_64-unknown-freebsd` has precompiled binaries.
10:13:36.261 [info] Current host NIF version is `2.17`, will use precompiled binaries with NIF version 2.16.
==> evision
Downloading precompiled tarball from: https://github.com/cocoa-xu/evision/releases/download/v0.2.12/evision-nif_2.16-x86_64-unknown-freebsd-contrib-0.2.12.tar.gz
10:13:39.092 [info] Precompiled binary tarball downloaded and saved to /root/.cache/evision-nif_2.16-x86_64-unknown-freebsd-contrib-0.2.12.tar.gz, sha256=d6f3afa242c3911a485a38720fd550e8970dadb71805c126512f2dc582369211
10:13:39.692 [info] Copying priv directory: /root/.cache/evision-nif_2.16-x86_64-unknown-freebsd-contrib-0.2.12/priv => /root/.cache/mix/installs/elixir-1.18.3-erts-15.1.1/01c0587d0b475ad2cc86d574549cedad/_build/dev/lib/evision/priv
10:13:39.768 [info] Copying generated Elixir binding files: /root/.cache/evision-nif_2.16-x86_64-unknown-freebsd-contrib-0.2.12/elixir_generated => /root/.cache/mix/installs/elixir-1.18.3-erts-15.1.1/01c0587d0b475ad2cc86d574549cedad/deps/evision/lib/generated
Compiling 676 files (.ex)
Generated evision app
What ? crazy in no time? Would like to know more - but will test it first :)
Hi @cocoa-xu
I just tested this in a FreeBSD jail with 14.2-RELEASE.
That's what I got - somehow it wants to compile it...
Maybe I forgot something obvious.
iex should be started with EVISION_PREFER_PRECOMPILED=true iex I guess?
UPDATE: Ah just saw default for EVISION_PREFER_PRECOMPILED is true
So should not be the cause.
Setting it explicit like:
Mix.install([{:evision, "0.2.12"}], system_env: [{"EVISION_PREFER_PRECOMPILED", "true"}])
ends up in same issue below.
Erlang/OTP 26 [erts-14.2.5.5] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [jit:ns] [dtrace] [sharing-preserving]
Interactive Elixir (1.17.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Mix.install([{:evision, "~> 0.2.12"}])
* creating /root/.mix/archives/hex-2.1.1
Resolving Hex dependencies...
Resolution completed in 0.058s
New:
castore 1.0.12
complex 0.6.0
elixir_make 0.9.0
evision 0.2.12
nx 0.9.2
telemetry 1.3.0
* Getting evision (Hex package)
* Getting castore (Hex package)
* Getting elixir_make (Hex package)
* Getting nx (Hex package)
* Getting complex (Hex package)
* Getting telemetry (Hex package)
* creating /root/.mix/elixir/1-17/rebar3
===> Analyzing applications...
===> Compiling telemetry
==> complex
Compiling 2 files (.ex)
Generated complex app
==> nx
Compiling 36 files (.ex)
Generated nx app
==> castore
Compiling 1 file (.ex)
Generated castore app
==> elixir_make
Compiling 8 files (.ex)
Generated elixir_make app
==> evision
could not compile dependency :evision, "mix compile" failed. Errors may have been logged above. You can recompile this dependency with "mix deps.compile evision --force", update it with "mix deps.update evision" or clean it with "mix deps.clean evision"
** (Mix.Error) "gmake" not found in the path. If you have set the MAKE environment variable, please make sure it is correct.
(mix 1.17.3) lib/mix.ex:588: Mix.raise/2
(elixir_make 0.9.0) lib/elixir_make/compiler.ex:117: ElixirMake.Compiler.cmd/5
(elixir_make 0.9.0) lib/elixir_make/compiler.ex:92: ElixirMake.Compiler.make/2
(elixir_make 0.9.0) lib/elixir_make/compiler.ex:53: ElixirMake.Compiler.compile/1
(mix 1.17.3) lib/mix/task.ex:495: anonymous fn/3 in Mix.Task.run_task/5
(mix 1.17.3) lib/mix/tasks/compile.all.ex:108: Mix.Tasks.Compile.All.run_compiler/2
(mix 1.17.3) lib/mix/tasks/compile.all.ex:88: Mix.Tasks.Compile.All.compile/4
In the .mix file in 859 you have the run function:
@impl true
def run(_args) do
{target, [_arch, os, _abi]} = get_target()
evision_so_file =
if os == "windows" do
"evision.dll"
else
"evision.so"
end
windows_fix_so_file =
if os == "windows" do
"windows_fix.dll"
else
"windows_fix.so"
end
evision_so_file = Path.join([app_priv(), evision_so_file])
windows_fix_so_file = Path.join([app_priv(), windows_fix_so_file])
if !File.exists?(evision_so_file) or !File.exists?(windows_fix_so_file) do
with {:precompiled, _} <- deploy_type(true) do
version = Metadata.version()
nif_version = get_compile_nif_version()
enable_contrib = System.get_env("EVISION_ENABLE_CONTRIB", "true") == "true"
enable_cuda = System.get_env("EVISION_ENABLE_CUDA", "false") == "true"
{default_cuda_version, default_cudnn_version} = Metadata.default_cuda_version()
cuda_version = System.get_env("EVISION_CUDA_VERSION", default_cuda_version)
cudnn_version = System.get_env("EVISION_CUDNN_VERSION", default_cudnn_version)
prepare(
target,
os,
version,
nif_version,
enable_contrib,
enable_cuda,
cuda_version,
cudnn_version
)
else
_ ->
raise RuntimeError, "Cannot use precompiled binaries."
end
else
:ok
end
end
end
- there I see its checking if
evision_so_fileexists. if so it checks for deploy_type etc... - I wonder why I do not run into this. Because I also do not get any logging from
use_precompiled?/1in 224 which itself is called byreply_type/1. - And you are searching for the
evision_so_fileinPath.join([app_priv(), evision_so_file])... wich resolves to the local build path. - It's all fine if I mix install local on macOS for example. Then all is created and
evision.sois created.
So from log above, it raises in lib/mix.ex:588
=> Might there be an issue with getting/creating the cache directory for FreeBSD?
That sounds weird, might be because it's in the jail?
@cocoa-xu I checked again and did on the FreeBSD host - not in a jail:
- ran the
Mix.install([{:evision, "~> 0.2.12"}])in the host system. - I also created a little mix project with evision as dependency on the latest 14.2-RELEASE-p3 FreeBSD and tried to compile it.
Outcome:
- Same error, it tries to compile and misses gmake but should download. It does not reach the point in the mix file to start the precompiled ...