Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Elixir.mk - Allows for use of Elixir deps within an Erlang project. #979

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

artman41
Copy link
Contributor

@artman41 artman41 commented Jun 4, 2023

This change introduces a new core plugin called elixir.mk.

This change accomplishes the following:

  • Converts mix.exs projects to use erlang.mk
  • Compiles .ex files, allowing for a project to use either Erlang, Elixir or a combination of both
  • Properly configures paths so that Elixir dependencies are added to the $(PROJECT).app
  • Treats Elixir as a dependency & fetches it as such, rather than relying on a system installation

This change makes use of hex.mk

@artman41
Copy link
Contributor Author

artman41 commented Jun 4, 2023

Currently rebasing the change :)

@artman41
Copy link
Contributor Author

artman41 commented Jun 4, 2023

@essen I've added a test under test/core_elixir.mk though I've been testing locally with a sample project.

@essen
Copy link
Member

essen commented Jun 5, 2023

Hello! I've not had a good look yet but I doubt this works with some Elixir NIFs since they often have a Makefile and thus wouldn't enter the elixir autopatch.

@artman41
Copy link
Contributor Author

artman41 commented Jun 5, 2023

Hello! I've not had a good look yet but I doubt this works with some Elixir NIFs since they often have a Makefile and thus wouldn't enter the elixir autopatch.

Damn, that's a good shout - any idea of an elixir lib which uses NIFs?

@essen
Copy link
Member

essen commented Jun 5, 2023

There's a few in this search but gotta filter. Oftentimes if the page says mix + make as a build tool, that's an Elixir NIF. But not always.

https://hex.pm/packages?search=nif&sort=total_downloads

@artman41
Copy link
Contributor Author

artman41 commented Jun 5, 2023

There's a few in this search but gotta filter. Oftentimes if the page says mix + make as a build tool, that's an Elixir NIF. But not always.

https://hex.pm/packages?search=nif&sort=total_downloads

I've just commited a change which should now make it support Elixir Nifs (assuming they use elixir_make - I'm not 100% familiar with the Elixir NIF ecosystem so not quite sure if I've accounted for the right things there).

I've added an additional test which will attempt to compile libsalty2, though this depends on libsodium.

If you've any more suggestions @essen, I'm more than happy to add them 👍

@artman41
Copy link
Contributor Author

Any chance I could poke you to look this over @essen? 😄

core/elixir.mk Outdated
$(verbose) $(MAKE) --no-print-directory $(PROJECT).d
$(verbose) $(MAKE) --no-print-directory app-build

app-build: ebin/$(PROJECT).app
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be app-build::.

@essen
Copy link
Member

essen commented Jun 26, 2023

Does this work even if using local system installed Elixir?

@artman41
Copy link
Contributor Author

Does this work even if using local system installed Elixir?

In what sense @essen?

I'm expecting elixir to always be loaded as a dep of the project rather than as an installed version on the system - I can try and account for this though if you'd prefer that functionality to be in there.

I'll edit this for confirmation but the only thing I think that could be problematic with an installed version of elixir is if code:get_path() returned paths to the installed elixir version, though I wouldn't ever expect that to be the case with a standard install.

@essen
Copy link
Member

essen commented Jun 27, 2023

I think we should take the dep Elixir if one is available as a dep, and the system Elixir otherwise. Basically the dep can be used as an override.

Most projects don't require a specific version of Elixir, and for example in RabbitMQ we explicitly use the system Elixir (we even build packages for it).

@artman41
Copy link
Contributor Author

artman41 commented Jul 2, 2023

@essen could you have a look over when you have chance?

Based on your feedback, I've updated the MR to default to using the System Install of Elixir if available. This can be manually overriden by a user-set var though (ELIXIR_USE_SYSTEM)

Let me know what you think :)

@artman41
Copy link
Contributor Author

artman41 commented Jul 5, 2023

@essen could you have a look over when you have chance?

Based on your feedback, I've updated the MR to default to using the System Install of Elixir if available. This can be manually overriden by a user-set var though (ELIXIR_USE_SYSTEM)

Let me know what you think :)

just poking you 😄

@essen
Copy link
Member

essen commented Jul 5, 2023

I'll get to it no need to remind so often.

@artman41
Copy link
Contributor Author

artman41 commented Sep 2, 2023

@essen sorry to poke on this one again, any idea when you'll be able to get round to it? :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think these log files should be commited.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

core/elixir.mk Outdated
|| git describe --dirty --abbrev=7 --tags --always 2>/dev/null || true))
$(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename \
$(filter-out $(ELIXIRC_EXCLUDE_PATHS), $(ERL_FILES) $(CORE_FILES) $(BEAM_FILES)))))))
$(eval MODULES := $(call UNIQUE,$(MODULES) $(foreach file, \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering why the unique filter is necessary? I don't think modules should have duplicates.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's a fair point, likely more safety/fear on my part 👍

core/deps.mk Outdated
@@ -148,7 +148,7 @@ endif

# Core targets.

ALL_APPS_DIRS_TO_BUILD = $(if $(LOCAL_DEPS_DIRS)$(IS_APP),$(LOCAL_DEPS_DIRS),$(ALL_APPS_DIRS))
ALL_APPS_DIRS_TO_BUILD = $(if $(filter-out $(ELIXIR_BUILTINS),$(LOCAL_DEPS_DIRS))$(IS_APP),$(filter-out $(ELIXIR_BUILTINS),$(LOCAL_DEPS_DIRS)),$(ALL_APPS_DIRS))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think Elixir builtins should be in LOCAL_DEPS_DIRS to begin with. It's defined as:

LOCAL_DEPS_DIRS = $(foreach a,$(LOCAL_DEPS),$(if $(wildcard $(APPS_DIR)/$(a)),$(APPS_DIR)/$(a)))

It's not meant to contain applications the user didn't write.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

likely a misunderstanding on my part - I'd assumed they needed adding to the LOCAL_DEPS_DIRS var since I was adding them to LOCAL_DEPS

@@ -778,14 +780,16 @@ define dep_fetch_ln
ln -s $(call dep_repo,$(1)) $(DEPS_DIR)/$(call dep_name,$(1));
endef

HEX_REPO = https://repo.hex.pm
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not extract that into a variable. We want to use hex_core.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only pushback against that would be for if someone is using an internal mirror within a corporate setting - it's likely they'd want to instead have the hex side of erlang.mk pointing at whatever their mirror is

looking back at it, I think I'd likely want to change this to be

HEX_REPO ?= https://repo.hex.pm

@@ -86,7 +86,7 @@ define app_file
endef
endif

app-build: ebin/$(PROJECT).app
app-build:: ebin/$(PROJECT).app
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is necessary? I don't think the app-build:: ... rule in the elixir.mk file does anything more than we do here. It doesn't need to be defined in two places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a fair point, I've also removed the $(PROJECT).d target & the body of the app:: target above this

core/elixir.mk Outdated
@@ -0,0 +1,334 @@
ifeq ($(pkg_elixir_commit),master)
pkg_elixir_commit = main
endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should just change the commit in the package.

$(if $(PROJECT_MOD),{mod$(comma) {'$(PROJECT_MOD)'$(comma) []}}$(comma),)
{env, $(subst \,\\,$(PROJECT_ENV))}$(if $(findstring {,$(PROJECT_APP_EXTRA_KEYS)),$(comma)$(newline)$(tab)$(subst \,\\,$(PROJECT_APP_EXTRA_KEYS)),)
]}.
endef
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why this was redeclared either.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for this redeclaration was to have .app files generate where the mod may actually be an elixir module

Currently, the mod prop only gets inserted if an erlang file exists.

In efforts to separate erlc.mk from elixir.mk, I opted to redefine the macro - if you'd prefer, I could add a condition to the definition in erlc.mk?

core/elixir.mk Outdated
erlang:halt(1)
end,
maps:get(version, PackageInfo)
end,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be moved to the hex part so we can use it for Erlang deps as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming you meant the GetDeps fun, I've moved that to elixir_get_deps.erl within elixir.mk - if you meant the macro itself, let me know and I'll move it over 👍

@essen
Copy link
Member

essen commented Sep 4, 2023

Is the thing that transforms paths like Elixir/MyApp/MyMod.ex into module name Elixir.MyApp.MyMod something the compiler does, or am I just blind and I missed it?

@artman41 artman41 force-pushed the elixir.mk branch 2 times, most recently from 74a2fa0 to d141f2c Compare October 8, 2024 23:41
@artman41
Copy link
Contributor Author

artman41 commented Oct 8, 2024

@essen had some time recently so will be picking this one back up 👍

@artman41
Copy link
Contributor Author

artman41 commented Oct 9, 2024

Is the thing that transforms paths like Elixir/MyApp/MyMod.ex into module name Elixir.MyApp.MyMod something the compiler does, or am I just blind and I missed it?

Compiler magic 🪄

@essen
Copy link
Member

essen commented Nov 5, 2024

I will try to make this work with RabbitMQ CLI which is (currently) in Elixir. Could you rebase to run CI now that I fixed it? Also you will need to edit the workflow to add/change the new suites here https://github.com/ninenines/erlang.mk/blob/master/.github/workflows/ci.yaml#L27

@artman41
Copy link
Contributor Author

@essen rebased, hopefully ci should work as expected 👍

@essen
Copy link
Member

essen commented Nov 28, 2024

I'm looking to merge this now. No need to rebase, I am probably going to cherry-pick parts of the code while I try to make things work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants