defmodule Evision.MixProject do use Mix.Project require Logger @app :evision @version "0.1.7" @last_released_version "0.1.7" @github_url "https://github.com/cocoa-xu/evision" @opencv_version "4.6.0" # only means compatible. need to write more tests @compatible_opencv_versions ["4.5.3", "4.5.4", "4.5.5", "4.6.0"] @source_url "#{@github_url}/tree/v#{@last_released_version}" def project do {cmake_options, enabled_modules} = generate_cmake_options() opencv_ver = opencv_versions(System.get_env("OPENCV_VER", @opencv_version)) ninja = System.find_executable("ninja") target_abi = List.last(String.split(to_string(:erlang.system_info(:system_architecture)), "-")) target_abi = case target_abi do "darwin" <> _ -> "darwin" "win32" -> {compiler_id, _} = :erlang.system_info(:c_compiler_used) case compiler_id do :msc -> "msvc" _ -> to_string(compiler_id) end _ -> target_abi end [ app: @app, name: "Evision", version: @version, elixir: "~> 1.11", deps: deps(), docs: docs(), compilers: [:elixir_make] ++ Mix.compilers(), source_url: @github_url, description: description(), package: package(), make_executable: make_executable(), make_makefile: make_makefile(), make_env: %{ "HAVE_NINJA" => "#{ninja != nil}", "OPENCV_VER" => opencv_ver, "MAKE_BUILD_FLAGS" => System.get_env("MAKE_BUILD_FLAGS", "-j#{System.schedulers_online()}"), "CMAKE_OPTIONS" => cmake_options, "ENABLED_CV_MODULES" => enabled_modules, "EVISION_PREFER_PRECOMPILED" => System.get_env("EVISION_PREFER_PRECOMPILED", "true"), "EVISION_PRECOMPILED_VERSION" => @last_released_version, "TARGET_ABI" => System.get_env("TARGET_ABI", target_abi), "EVISION_GENERATE_LANG" => System.get_env("EVISION_GENERATE_LANG", "elixir"), } ] end def make_executable() do case :os.type() do {:win32, _} -> "nmake" _ -> "make" end end def make_makefile() do case :os.type() do {:win32, _} -> "Makefile.win" _ -> "Makefile" end end def opencv_versions(version) do if Enum.member?(@compatible_opencv_versions, version) do version else Logger.warning( "OpenCV version #{version} is not in the compatible list, you may encounter compile errors" ) Logger.warning( "Compatible OpenCV versions: " <> (@compatible_opencv_versions |> Enum.join(", ")) ) version end end def application do [ extra_applications: [:logger] ] end @all_modules [ :calib3d, :core, :features2d, :flann, :highgui, :imgcodecs, :imgproc, :ml, :photo, :stitching, :ts, :video, :videoio, :dnn, :gapi, :world, :python2, :python3 ] @enabled_modules [ :calib3d, :core, :features2d, :flann, :highgui, :imgcodecs, :imgproc, :ml, :photo, :stitching, :ts, :video, :videoio, :dnn ] @disabled_modules [ # not supported yet :gapi, # no need for this :world, # no need for this :python2, # no need for this :python3, # no need for this :java ] @enabled_img_codecs [ :png, :jpeg, :tiff, :webp, :openjpeg, :jasper, :openexr ] # To make things easier, you can set `compile_mode` to `only_enabled_modules` so # that only modules specified in `enabled_modules` will be compiled. Like-wise, # set `except_disabled_modules` to only exclude modules in `disabled_modules`. # By default, the value of `compile_mode` is `auto`, which means to leave unspecified # modules to CMake to decide. @compile_mode :auto defp generate_cmake_options() do enabled_modules = Application.get_env(:evision, :enabled_modules, @enabled_modules) disabled_modules = Application.get_env(:evision, :disabled_modules, @disabled_modules) enabled_img_codecs = Application.get_env(:evision, :enabled_img_codecs, @enabled_img_codecs) compile_mode = Application.get_env(:evision, :compile_mode, @compile_mode) {cmake_options, enabled_modules} = case compile_mode do :auto -> cmake_options = (enabled_modules |> Enum.map(&"-D BUILD_opencv_#{Atom.to_string(&1)}=ON") |> Enum.join(" ")) <> " " <> (disabled_modules |> Enum.map(&"-D BUILD_opencv_#{&1}=OFF") |> Enum.join(" ")) {cmake_options, enabled_modules} :only_enabled_modules -> cmake_options = "-D BUILD_LIST=" <> (enabled_modules |> Enum.map(&Atom.to_string(&1)) |> Enum.join(",")) {cmake_options, enabled_modules} :except_disabled_modules -> enabled_modules = @all_modules -- disabled_modules cmake_options = "-D BUILD_LIST=" <> (enabled_modules |> Enum.map(&Atom.to_string(&1)) |> Enum.join(",")) {cmake_options, enabled_modules} unrecognised_mode -> Mix.raise("unrecognised compile_mode for evision: #{inspect(unrecognised_mode)}") end options = cmake_options <> " " <> (enabled_img_codecs |> Enum.map(&"-D BUILD_#{Atom.to_string(&1) |> String.upcase()}=ON") |> Enum.join(" ")) <> " " {options, enabled_modules |> Enum.map(&Atom.to_string(&1)) |> Enum.join(",")} end defp deps do [ # compilation {:elixir_make, "~> 0.6", runtime: false}, # runtime {:dll_loader_helper, "~> 0.1"}, {:nx, "~> 0.3"}, # optional {:kino, "~> 0.7", optional: true}, # docs {:ex_doc, "~> 0.28", only: :docs, runtime: false}, # test {:scidata, "~> 0.1", only: :test}, {:castore, "~> 0.1", only: :test, override: true} ] end defp docs do [ main: "Evision", source_ref: "v#{@version}", source_url: @source_url, before_closing_body_tag: &before_closing_body_tag/1, groups_for_functions: [ cv: &(&1[:namespace] == :cv), "cv.Mat": &(&1[:namespace] == :"cv.Mat"), "cv.highgui": &(&1[:namespace] == :"cv.highgui"), external: &(&1[:namespace] == :external), "cv.Error": &(&1[:namespace] == :"cv.Error"), "cv.ipp": &(&1[:namespace] == :"cv.ipp"), "cv.utils": &(&1[:namespace] == :"cv.utils"), "cv.utils.fs": &(&1[:namespace] == :"cv.utils.fs"), "cv.detail": &(&1[:namespace] == :"cv.detail"), "cv.cuda": &(&1[:namespace] == :"cv.cuda"), "cv.ocl": &(&1[:namespace] == :"cv.ocl"), "cv.ogl": &(&1[:namespace] == :"cv.ogl"), "cv.parallel": &(&1[:namespace] == :"cv.parallel"), "cv.samples": &(&1[:namespace] == :"cv.samples"), "cv.flann": &(&1[:namespace] == :"cv.flann"), "cv.segmentation": &(&1[:namespace] == :"cv.segmentation"), "cv.ml": &(&1[:namespace] == :"cv.ml"), "cv.videoio_registry": &(&1[:namespace] == :"cv.videoio_registry"), "cv.fisheye": &(&1[:namespace] == :"cv.fisheye"), Constants: &(&1[:type] == :constants) ] ] end defp before_closing_body_tag(:html) do ~S( ) end defp before_closing_body_tag(_), do: "" defp description() do "OpenCV-Erlang/Elixir binding." end defp package() do [ name: "evision", # These are the default files included in the package files: ~w( c_src/evision_custom_headers c_src/modules c_src/ArgInfo.hpp c_src/erlcompat.hpp c_src/evision.cpp c_src/evision_custom_headers.h c_src/nif_utils.hpp py_src/*.py scripts patches cc_toolchain Makefile Makefile.win CMakeLists.txt lib/*.ex lib/evision .formatter.exs mix.exs src/evision_mat.erl src/evision_highgui.erl src/evision.app.src rebar.config README* LICENSE* CHANGELOG*), licenses: ["Apache-2.0"], links: %{"GitHub" => @github_url} ] end end