How to export :xmlElement in elixir 1.17

In elixir 1.17, I can not export :xmlElement from xmerl like this:

  require Record

  Record.defrecord(:xmlElement, Record.extract(:xmlElement, from_lib: "xmerl/include/xmerl.hrl"))

why ?

the error is :

== Compilation error in file lib/demo2.ex ==
** (ArgumentError) lib file xmerl/include/xmerl.hrl could not be found
    (elixir 1.17.3) lib/record/extractor.ex:41: Record.Extractor.from_lib_file/1
    (elixir 1.17.3) lib/record/extractor.ex:18: Record.Extractor.from_or_from_lib_file/1
    (elixir 1.17.3) lib/record/extractor.ex:5: Record.Extractor.extract/2
    lib/demo2.ex:10: (module)

but I do have this file.

It seems like this is an issue with Mix,and the error only occurs when using iex -S mix or mix compile.

Hello,

It works on my machine. Are you able to call :xmerl.module_info() or any other function from your code?

Maybe your installation of Erlang is incomplete, I know some OS use several packages for the different Erlang applications.

yes,I can execute :xmerl.module_info(), like this:

iex(1)> :xmerl.module_info()
[
  module: :xmerl,
  exports: [
    export: 2,
    export: 3,
    export_simple: 2,
    export_simple: 3,
    export_simple_content: 2,
    export_content: 2,
    export_simple_element: 2,
    export_element: 2,
    export_element: 3,
    callbacks: 1,
    module_info: 0,
    module_info: 1
  ],
  attributes: [vsn: [181604813240717407542086469561436575646]],
  compile: [
    version: ~c"8.2.2",
    options: [
      :debug_info,
      {:i, ~c"/daily_build/otp_src/lib/xmerl/src/../include"},
      :warn_unused_vars
    ],
    source: ~c"/daily_build/otp_src/lib/xmerl/src/xmerl.erl"
  ],
  md5: <<136, 159, 208, 149, 217, 90, 208, 236, 10, 71, 75, 7, 168, 103, 151,
    158>>
]

And I can run extract in fresh iex shell:

iex(1)> import Record
Record
iex(2)> defmodule MyModule do
...(2)> defrecord :xmlElement, extract(:xmlElement, from_lib: "xmerl/include/xmerl.hrl")
...(2)> end
{:module, MyModule,
 <<70, 79, 82, 49, 0, 0, 8, 136, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 240,
   0, 0, 0, 22, 15, 69, 108, 105, 120, 105, 114, 46, 77, 121, 77, 111, 100, 117,
   108, 101, 8, 95, 95, 105, 110, 102, 111, ...>>, {:xmlElement, 2}}

I can also use iex parser.ex to compile file contains extract code, but that does not work with mix , neither mix compile nor iex -S mix.

This is so strange. How did you install Elixir and Erlang?

I successfully compiled my code by mix compile --no-prune-code-paths, that’s the problem!

However, thanks a lot.

1 Like

I’m wondering if you’re running into code path purging there. That’s been in elixir since 1.15 though.

In that case you should declare the dependency on :xmerl correctly in mix.exs.

I install them with Pre-built Binary Packages, I guess mix removes some erlang libraries by default.

1 Like

Yes. Elixir prunes all OTP applications not setup as dependencies in the mix.exs from the code paths.

  def application do
    [
      extra_applications: [:logger, :runtime_tools, …]
    ]
  end

That doesn’t happen if you start iex without the context of a mix project, as there’s simply no place to define such dependencies in the first place.

1 Like

Yes it is.
I tried to add xmerl to deps

defp deps do
    [
      {:xmerl, "~> 1.13.0"}
    ]
  end

But it doesn’t work. Instead, I disabled code path prune in project:

def project do
  [
    ... ...
    prune_code_paths: false
  ]
end

That’s work.

yes,I can execute :xmerl.module_info() , like this:

Can you run :xmerl.module_info() with mix though? (without prune_code_paths: false)

I tried mix run -e ":xmerl.module_info()" --no-mix-exs , and there is no output.

You are right. I tried

def application do
  [
    extra_applications: [:logger, :xmerl]
  ]
end

That’s work too. It is better than prune_code_paths: false.
Thank you for your help and support. I truly appreciate it.

You depend on otp applications using the extra_applications setting, not the deps. The built in nature of those means they need to be handled separately.

Yes, I realize my problem, thank you so much!