Current section

Files

Jump to
Raw

mix.exs

defmodule Rclex.MixProject do
  use Mix.Project

  @description """
  Experimental ROS 2 Client Library for Elixir.
  """

  @app :rclex
  @version "0.12.21"
  @source_url "https://github.com/FelixPe/rclex"

  def project do
    [
      app: @app,
      version: @version,
      elixir: "~> 1.14",
      elixirc_paths: elixirc_paths(Mix.env()),
      start_permanent: Mix.env() == :prod,
      deps: deps(),
      make_clean: ["clean"],
      make_env: make_env(),
      compilers: [:elixir_make] ++ Mix.compilers(),
      aliases: [format: [&format_c/1, "format"], iwyu: [&iwyu/1]],
      test_ignore_filters: [&String.starts_with?(&1, "test/expected_files/")],
      test_coverage: test_coverage(),
      dialyzer: dialyzer(),
      # for hex
      description: @description,
      package: package(),
      # for ex_doc
      name: "Rclex (Experimental)",
      docs: docs()
    ]
  end

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      extra_applications:
        [:logger] ++
          case Mix.target() do
            :host -> [:runtime_tools, :wx, :observer]
            _ -> []
          end,
      mod: {Rclex.Application, []}
    ]
  end

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      {:elixir_make, "~> 0.9", runtime: false},
      {:credo, "~> 1.7", only: [:dev, :test], runtime: false},
      {:dialyxir, "~> 1.4", only: [:dev], runtime: false},
      {:benchee, "~> 1.0", only: :dev},
      {:nimble_parsec, "~> 1.4"},
      {:jason, "~> 1.4"},
      {:mix_test_watch, "~> 1.3", only: [:dev, :test], runtime: false},
      {:ex_doc, "~> 0.38", only: :dev, runtime: false},
      {:telemetry, "~> 1.0", optional: true}
    ]
  end

  defp elixirc_paths(:test), do: ["lib", "test/support"]
  defp elixirc_paths(_env), do: ["lib"]

  defp package() do
    %{
      name: "#{@app}_experimental",
      files: [
        "lib",
        "priv",
        "src",
        "mix.exs",
        "README.md",
        "README_ja.md",
        "LICENSE",
        "CHANGELOG.md",
        "Makefile"
      ],
      licenses: ["Apache-2.0"],
      links: %{"Github" => @source_url}
    }
  end

  defp docs() do
    [
      extras: ["README.md", "README_ja.md", "USE_ON_NERVES.md", "CHANGELOG.md"],
      main: "readme",
      source_ref: "v#{@version}",
      source_url: @source_url,
      groups_for_docs: [
        Client: &(&1[:section] == :client),
        Graph: &(&1[:section] == :graph),
        Node: &(&1[:section] == :node),
        Publisher: &(&1[:section] == :publisher),
        Service: &(&1[:section] == :service),
        Subscription: &(&1[:section] == :subscription),
        Timer: &(&1[:section] == :time),
        Clock: &(&1[:section] == :clock),
        Lifecycle_Node: &(&1[:section] == :lifecycle_node),
        Action_Server: &(&1[:section] == :action_server),
        Action_Client: &(&1[:section] == :action_client),
        Parameter: &(&1[:section] == :parameter),
        Parameter_Client: &(&1[:section] == :parameter_client)
      ]
    ]
  end

  defp format_c(_args) do
    file_names = File.ls!("src") |> Enum.filter(&String.ends_with?(&1, [".c", ".h"]))
    [formatter | args] = ~w"clang-format -i --Werror" ++ file_names

    case System.find_executable(formatter) do
      nil ->
        Mix.Shell.IO.info("Install C code formatter: #{formatter}.")

      bin ->
        System.cmd(bin, args, into: IO.stream(:stdio, :line), cd: "src")
    end
  end

  defp iwyu(_args) do
    script_path = Path.join(File.cwd!(), "scripts/iwyu.sh")

    case System.find_executable("include-what-you-use") do
      nil ->
        Mix.Shell.IO.info("Install include-what-you-use.")

      _ ->
        Enum.each(
          c_src_paths(),
          fn file_path ->
            case System.cmd(script_path, [file_path], stderr_to_stdout: true) do
              {_, 2} -> nil
              {return, _} -> Mix.Shell.IO.error("#{return}")
            end
          end
        )
    end
  end

  defp c_src_paths() do
    File.ls!("src")
    |> Enum.map(&Path.join("src", &1))
    |> Enum.filter(&String.ends_with?(&1, ".c"))
  end

  defp dialyzer() do
    [
      plt_local_path: "priv/plts/rclex.plt",
      plt_core_path: "priv/plts/core.plt",
      plt_add_apps: [:mix, :eex]
    ]
  end

  defp test_coverage() do
    [
      ignore_modules: [
        Rclex.Nif,
        Rclex.Generators.MsgC.Acc,
        ~r/Rclex\.Pkgs.+/,
        ~r/Mix\.Tasks\.Rclex.+/
      ]
    ]
  end

  defp make_env do
    config_path = Path.join(File.cwd!(), "config/config.exs")

    rclex_config =
      if File.exists?(config_path) do
        Keyword.get(Config.Reader.read!(config_path), :rclex, [])
      else
        []
      end

    ros2_directories = Keyword.get(rclex_config, :ros2_directories, [])
    %{"ROS2_DIRECTORIES" => Enum.join(ros2_directories, ":")}
  end
end