Module: RbSys::Mkmf

Defined in:
lib/rb_sys/mkmf.rb

Overview

Helper class for creating Rust Makefiles

Instance Method Summary collapse

Instance Method Details

#create_rust_makefile(target, srcprefix = nil) {|builder| ... } ⇒ Object

Helper for building Rust extensions by creating a Ruby compatible makefile for Rust. By using this class, your rust extension will be 100% compatible with the rake-compiler gem, which allows for easy cross compilation.

. require 'rb_sys/mkmf'

. create_rust_makefile("my_extension") #=> Generate a Makefile in the current directory

. require 'rb_sys/mkmf'

. create_rust_makefile("my_extension") do |r| . # All of these are optional . r.env = { 'FOO' => 'bar' } . r.profile = ENV.fetch('RB_SYS_CARGO_PROFILE', :dev).to_sym . r.features = %w . end

Examples:

Basic

require 'mkmf'

Configure a custom build profile

require 'mkmf'

Yields:

  • (builder)


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/rb_sys/mkmf.rb', line 31

def create_rust_makefile(target, srcprefix = nil, &blk)
  if target.include?("/")
    target_prefix, target = File.split(target)
    target_prefix[0, 0] = "/"
  else
    target_prefix = ""
  end

  spec = Struct.new(:name, :metadata).new(target, {})
  builder = CargoBuilder.new(spec)

  yield builder if blk

  srcprefix ||= "$(srcdir)/#{srcprefix}".chomp("/")
  RbConfig.expand(srcdir = srcprefix.dup)

  full_cargo_command = cargo_command(srcdir, builder)

  # rubocop:disable Style/GlobalVars
  make_install = +<<~MAKE
    RB_SYS_CARGO_PROFILE ?= #{builder.profile}
    RB_SYS_CARGO_FEATURES ?= #{builder.features.join(",")}
    CARGO ?= cargo

    ifeq ($(RB_SYS_CARGO_PROFILE),dev)
      RB_SYS_TARGET_DIR ?= debug
    else
      RB_SYS_TARGET_DIR ?= $(RB_SYS_CARGO_PROFILE)
    endif

    target_prefix = #{target_prefix}
    TARGET_NAME = #{target[/\A\w+/]}
    TARGET_ENTRY = #{RbConfig::CONFIG["EXPORT_PREFIX"]}Init_$(TARGET_NAME)
    CLEANLIBS = $(RUSTLIB) $(DLLIB) $(DEFFILE)
    DISTCLEANDIRS = target/
    RUBYARCHDIR   = $(sitearchdir)$(target_prefix)
    RUSTLIB = #{dllib_path(builder)}
    TARGET = #{target}
    DLLIB = $(TARGET).#{RbConfig::CONFIG["DLEXT"]}
    TARGET_DIR = #{Dir.pwd}/target/$(RB_SYS_TARGET_DIR)
    DEFFILE = $(TARGET_DIR)/$(TARGET)-$(arch).def
    #{base_makefile(srcdir)}
    #{env_vars(builder)}

    FORCE: ;

    $(TARGET_DIR):
    \t$(ECHO) creating target directory \\($(@)\\)
    \t$(Q) $(MAKEDIRS) $(TARGET_DIR)

    $(DEFFILE): $(TARGET_DIR)
    \t$(ECHO) generating $(@)
    \t$(Q) ($(COPY) $(srcdir)/$(TARGET).def $@ 2> /dev/null) || (echo EXPORTS && echo $(TARGET_ENTRY)) > $@

    $(DLLIB): $(DEFFILE) FORCE
    \t$(ECHO) generating $(@) \\("$(RB_SYS_CARGO_PROFILE)"\\)
    \t$(Q) #{full_cargo_command}
    \t$(Q) $(COPY) "$(RUSTLIB)" $@

    install: $(DLLIB) Makefile
    \t$(ECHO) installing $(DLLIB)
    \t$(Q) $(MAKEDIRS) $(RUBYARCHDIR)
    \t$(Q) $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)

    all: #{$extout ? "install" : "$(DLLIB)"}
  MAKE

  gsub_cargo_command!(make_install, builder: builder)

  File.write("Makefile", make_install)
end