Skip to content

Instantly share code, notes, and snippets.

@bcardarella
Created December 27, 2023 04:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bcardarella/f4b2402867ec2645000987cddd31b7dc to your computer and use it in GitHub Desktop.
Save bcardarella/f4b2402867ec2645000987cddd31b7dc to your computer and use it in GitHub Desktop.

Section

# The dependency chain is a bit complex, but think of Foo and a

defmodule Lib.Foo do
  defmacro __using__(opts) do
    quote do
      @foo_opts unquote(opts)
      @before_compile Lib.Foo
    end
  end

  defmacro __before_compile__(%{module: module} = _env) do
    other_module = Module.get_attribute(module, :foo_opts)[:mod]
    :ok = Module.get_attribute(other_module, :bar_opts)
  end
end

defmodule Lib.Bar do
  defmacro __using__(_) do
    quote do
      @bar_opts :ok
    end
  end
end

defmodule MyApp.Baz do
  use Lib.Foo, mod: MyApp.Quux
end

defmodule MyApp.Qux do
  use Lib.Baz
end
** (ArgumentError) could not call Module.get_attribute/2 because the module MyApp.Quux is already compiled. Use the Module.__info__/1 callback or Code.fetch_docs/1 instead
(elixir 1.15.5) lib/module.ex:2295: Module.assert_not_compiled!/3
(elixir 1.15.5) lib/module.ex:1918: Module.get_attribute/7
expanding macro: Lib.Foo.__before_compile__/1
#cell:ckp37qhzqhfllf3wteg4gxw7ptyait2c:25: (file)
@oliver-kriska
Copy link

I had same issue and this worked for me, I hope it will help you

defmodule MyModule do

  defmacro required_attrs(attrs) do
    caller = __CALLER__.module

    Module.register_attribute(caller, :required_attrs, accumulate: false)
    Module.put_attribute(caller, :required_attrs, attrs)
  end

  defmacro __using__(_) do
    quote do
      import MyModule

      Module.register_attribute(__MODULE__, :required_attrs, accumulate: false)
      .....
      defp validate_required_attrs(%__MODULE__{} = s, true) do
        [@required_attrs | []]
       # usage of attribute with @
      end
      ....
    end
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment