{"id":18352797,"url":"https://github.com/membraneframework/bundlex","last_synced_at":"2025-05-16T06:07:24.435Z","repository":{"id":26185662,"uuid":"79900140","full_name":"membraneframework/bundlex","owner":"membraneframework","description":"Multiplatform app bundler tool for Elixir","archived":false,"fork":false,"pushed_at":"2025-02-21T16:29:27.000Z","size":486,"stargazers_count":79,"open_issues_count":0,"forks_count":19,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-08T16:06:13.734Z","etag":null,"topics":["c","cnode","compilation","elixir","nif"],"latest_commit_sha":null,"homepage":null,"language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/membraneframework.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-01-24T10:11:02.000Z","updated_at":"2025-03-22T21:03:47.000Z","dependencies_parsed_at":"2023-10-02T10:58:18.904Z","dependency_job_id":"4ad00b77-1a01-42b2-a51e-d1619d4e7fe9","html_url":"https://github.com/membraneframework/bundlex","commit_stats":{"total_commits":301,"total_committers":30,"mean_commits":"10.033333333333333","dds":0.6578073089700996,"last_synced_commit":"240f889a26c3e974d3faea36a27849bdd6c27ff2"},"previous_names":[],"tags_count":43,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/membraneframework%2Fbundlex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/membraneframework%2Fbundlex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/membraneframework%2Fbundlex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/membraneframework%2Fbundlex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/membraneframework","download_url":"https://codeload.github.com/membraneframework/bundlex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254478190,"owners_count":22077676,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","cnode","compilation","elixir","nif"],"created_at":"2024-11-05T21:37:26.430Z","updated_at":"2025-05-16T06:07:24.379Z","avatar_url":"https://github.com/membraneframework.png","language":"Elixir","readme":"# Bundlex\n\n[![Hex.pm](https://img.shields.io/hexpm/v/bundlex.svg)](https://hex.pm/packages/bundlex)\n[![API Docs](https://img.shields.io/badge/api-docs-yellow.svg?style=flat)](https://hexdocs.pm/bundlex/)\n[![CircleCI](https://circleci.com/gh/membraneframework/bundlex.svg?style=svg)](https://circleci.com/gh/membraneframework/bundlex)\n\nBundlex is a multi-platform tool for compiling C and C++ code along with elixir projects, for use in NIFs, CNodes and Ports. The tool also provides a convenient way of accessing compiled code in elixir modules.\n\nBundlex has been tested on Linux, Mac OS and FreeBSD. There's some support for Windows as well, but it's experimental and unstable (see issues for details).\n\nBundlex also supports cross-compilation and has been tested with platforms running Nerves.\n\nThis tool is maintained by the [Membrane Framework](https://membraneframework.org/) team.\n\n## Installation\n\nTo install, you need to configure Mix project as follows:\n\n```elixir\ndefmodule MyApp.Mixfile do\n  use Mix.Project\n\n  def project do\n    [\n      app: :my_app,\n      compilers: [:bundlex] ++ Mix.compilers, # add bundlex to compilers\n      deps: deps(),\n      # ...\n   ]\n  end\n\n  defp deps() do\n    [\n      {:bundlex, \"~\u003e 1.5\"}\n    ]\n  end\nend\n```\n\nand create `bundlex.exs` file in the project root folder, containing Bundlex project module:\n\n```elixir\ndefmodule MyApp.BundlexProject do\n  use Bundlex.Project\n\n  def project() do\n    []\n  end\nend\n```\n\nNow your project does not contain any C sources, but should compile successfully, and some Bundlex messages should be printed while compilation proceeds.\n\n## Usage\n\n### Adding natives to project\n\nAdding natives can be done in `project/0` function of Bundlex project module in the following way:\n\n```elixir\ndefmodule MyApp.BundlexProject do\n  use Bundlex.Project\n\n  def project() do\n    [\n      natives: natives(Bundlex.platform),\n      libs: libs()\n    ]\n  end\n\n  defp natives(:linux) do\n    [\n      my_native: [\n        sources: [\"something.c\", \"linux_specific.c\"],\n        interface: :nif\n      ],\n      my_other_native: [\n        sources: [\"something_other.c\", \"linux_specific.c\"],\n        interface: :cnode\n      ],\n      my_other_native: [\n        sources: [\"something_more_other.c\", \"linux_specific.c\"],\n        interface: :port\n      ]\n    ]\n  end\n\n  defp natives(_platform) do\n    [\n      my_native: [\n        sources: [\"something.c\", \"multiplatform.c\"],\n        interface: :nif\n      ],\n      my_other_native: [\n        sources: [\"something_other.c\", \"multiplatform.c\"],\n        interface: :cnode\n      ],\n      my_other_native: [\n        sources: [\"something_more_other.c\", \"multiplatform.c\"],\n        interface: :port\n      ]\n    ]\n  end\n\n  defp libs() do\n    [\n      my_lib: [\n        sources: [\"something.c\"],\n        interface: :nif\n      ],\n      my_lib: [\n        sources: [\"something_other.c\"],\n        interface: :cnode\n      ]\n    ]\n  end\nend\n```\n\nAs we can see, we can specify two types of resources:\n- natives - code implemented in C that will be used within Elixir code\n- libs - can be used by natives or other libs as [dependencies](#Dependencies)\n\nBy default, the sources should reside in `project_root/c_src/my_app` directory.\n\nFor more details and available options, see [Bundlex.Project.native_config](https://hexdocs.pm/bundlex/Bundlex.Project.html#t:native_config/0).\n\n### Dependencies\n\nEach native can have dependencies - libs that are statically linked to it and can be included in its native code like `#include lib_name/some_header.h`. The following rules apply:\n- To add dependencies from a separate project, it must be available via Mix. \n- Only libs can be added as dependencies.\n- Each dependency of a native must specify the same or no interface. If there exist multiple versions of dependency with different interfaces, the proper version is selected automatically.\n- A lib that specifies no interface can depend on libs with no interfaces only.\n\n### Compilation options\n\nThe following command-line arguments can be passed:\n- `--store-scripts` - if set, shell scripts are stored in the project\nroot folder for further analysis.\n\n### Loading NIFs in modules\n\nNIFs compiled with Bundlex can be loaded the same way as any other NIFs (see [`:erlang.load_nif/2`](http://erlang.org/doc/man/erlang.html#load_nif-2)), but Bundlex provides `Bundlex.Loader` module to save you some boilerplate:\n\n```elixir\ndefmodule MyApp.SomeNativeStuff do\n  use Bundlex.Loader, nif: :my_nif\n\n  def normal_function(a, b, c, d) do\n    private_native_function(a+b, c+d)\n  end\n\n  defnif native_function(a, b)\n\n  defnifp private_native_function(x, y)\n\nend\n```\n\nNote that unlike when using `:erlang.load_nif/2`, here `def`s and `defp`s can be used to create usual functions, native ones are declared with `defnif` and `defnifp`. This is achieved by creating a new module under the hood, and that is why the module passed to C macro `ERL_NIF_INIT` has to be succeeded by `.Nif`, i.e.\n```C\nERL_NIF_INIT(MyApp.SomeNativeStuff.Nif, funs, load, NULL, upgrade, unload)\n```\n\nDespite this, any native erlang macros and functions shall be used as usual, as described at http://erlang.org/doc/man/erl_nif.html\n\n### Interacting with CNodes\n\nAs in the case of NIFs, CNodes compiled with Bundlex can be used like any other CNodes (see built-in `Node` module), while some useful stuff for interacting with them is provided. `Bundlex.CNode` module contains utilities that make it easier to spawn and control CNodes, and allow them to treat them more like usual Elixir processes. Check out the documentation for more details.\n\n### Interacting with Ports\n\nSimilarly to CNodes Bundlex provides `Bundlex.Port` module for a little easier interacting with Ports.\nPlease refer to the module's documentation to see how to use it.\n\n### Cross-compilation\n\nWith proper setup, Bundlex can support cross-compilation. When using Nerves it should work out of the box. \n\nNot relying on Nerves and using your own toolchain is also possible, although it wasn't tested. In this scenario, the following environment variables need to be set during compilation (when changing the target bundlex also needs to be recompiled):\n- `CROSSCOMPILE` - value is not important, just needs to be set\n- `CC` - path to the C compiler for cross-compiling to the target\n- `CFLAGS` - C compilation flags\n- `CXX` - path to the C++ compiler for cross-compiling to the target \n- `CXXFLAGS` - C++ compilation flags\n- `LDFLAGS` - Linker flags\n\nIf you wish for `Bundlex.get_target/0` to return accurate information about your target, set the following environment variables:\n- `TARGET_ARCH` - The target CPU architecture (e.g., `arm`, `aarch64`, `mipsel`, `x86_64`, `riscv64`)\n- `TARGET_VENDOR` - Vendor of your target platform\n- `TARGET_OS` - The targes OS (e.g. `linux`)\n- `TARGET_ABI` - The target ABI (e.g., `gnueabihf`, `musl`)\n\nWhen cross-compiling some warnings may be raised about not being able to load nifs, but that's expected, since they are most likely built for different architecture.\n\n### Documentation of the native code\n\nBundlex provides a way to generate documentation of the native code. The documentation is generated using [Doxygen](http://www.doxygen.nl/).\n\nTo do so, run `$ mix bundlex.doxygen` command. The documentation is generated for each native separately. The documentation of the native `project_name` will be generated in `doc/bundlex/project_name` directory. Additionally, hex doc page with the link to the Doxygen documentation is generated in the `pages/doxygen/project_name.md` and should be included in the `mix.exs` file: \n\n```elixir\ndefp docs do\n  [\n    extras: [\n      \"pages/doxygen/project_name.md\",\n      ...\n    ],\n    ...\n  ]\nend\n```\nIf you want to keep own changes in the `pages/doxygen/project_name.md` file, you can use `--no` option to skip the generation of this file. Otherwise, if you want the file to be always overwritten, use `--yes` option.\n\nAfter that, the documentation can be generated with `mix docs` command.\n\n### Include native documentation in the hex docs\n\nTo include the native documentation in the hex docs, you need to generate the documentation with `$ mix bundlex.doxygen` command and include hex page in the `extras`, before running `$ mix hex.publish` command.\n\n## More examples\n\nMore advanced examples can be found in our [test_projects](https://github.com/membraneframework/bundlex/tree/master/test_projects)\nor in our [repositories](https://github.com/membraneframework) where we use Bundlex e.g. in [Unifex](https://github.com/membraneframework/unifex).\n\n## Copyright and License\n\nCopyright 2018, [Software Mansion](https://swmansion.com/?utm_source=git\u0026utm_medium=readme\u0026utm_campaign=membrane)\n\n[![Software Mansion](https://logo.swmansion.com/logo?color=white\u0026variant=desktop\u0026width=200\u0026tag=membrane-github)](https://swmansion.com/?utm_source=git\u0026utm_medium=readme\u0026utm_campaign=membrane)\n\nLicensed under the [Apache License, Version 2.0](LICENSE)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmembraneframework%2Fbundlex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmembraneframework%2Fbundlex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmembraneframework%2Fbundlex/lists"}