module RbSys::Mkmf

def create_rust_makefile(target, &blk)

Other tags:
    Example: Configure a custom build profile -
    Example: Basic -
def create_rust_makefile(target, &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, {})
  cargo_builder = CargoBuilder.new(spec)
  builder = Config.new(cargo_builder)
  yield builder if blk
  srcprefix = "$(srcdir)/#{builder.ext_dir}".chomp("/")
  RbConfig.expand(srcdir = srcprefix.dup)
  full_cargo_command = cargo_command(srcdir, builder)
  # rubocop:disable Style/GlobalVars
  make_install = +<<~MAKE
    RB_SYS_BUILD_DIR ?= #{File.join(Dir.pwd, ".rb-sys")}
    CARGO ?= cargo
    CARGO_BUILD_TARGET ?= #{builder.target}
    SOEXT ?= #{builder.so_ext}
    # Determine the prefix Cargo uses for the lib.
    ifneq ($(SOEXT),dll)
      SOEXT_PREFIX ?= lib
    endif
    RB_SYS_CARGO_PROFILE ?= #{builder.profile}
    RB_SYS_CARGO_FEATURES ?= #{builder.features.join(",")}
    RB_SYS_EXTRA_RUSTFLAGS ?= #{builder.extra_rustflags.join(" ")}
    # Set dirname for the profile, since the profiles do not directly map to target dir (i.e. dev -> debug)
    ifeq ($(RB_SYS_CARGO_PROFILE),dev)
      RB_SYS_CARGO_PROFILE_DIR ?= debug
    else
      RB_SYS_CARGO_PROFILE_DIR ?= $(RB_SYS_CARGO_PROFILE)
    endif
    # Set the build profile (dev, release, etc.) Compat with Rust 1.51.
    ifeq ($(RB_SYS_CARGO_PROFILE),release)
      RB_SYS_CARGO_PROFILE_FLAG = --release
    else
      RB_SYS_CARGO_PROFILE_FLAG = --profile $(RB_SYS_CARGO_PROFILE)
    endif
    # Account for sub-directories when using `--target` argument with Cargo
    ifneq ($(CARGO_BUILD_TARGET),)
      RB_SYS_CARGO_BUILD_TARGET_DIR ?= target/$(CARGO_BUILD_TARGET)
    else
      RB_SYS_CARGO_BUILD_TARGET_DIR ?= target
    endif
    target_prefix = #{target_prefix}
    TARGET_NAME = #{target[/\A\w+/]}
    TARGET_ENTRY = #{RbConfig::CONFIG["EXPORT_PREFIX"]}Init_$(TARGET_NAME)
    RUBYARCHDIR   = $(sitearchdir)$(target_prefix)
    TARGET = #{target}
    DLLIB = $(TARGET).#{RbConfig::CONFIG["DLEXT"]}
    TARGET_DIR = #{Dir.pwd}/$(RB_SYS_CARGO_BUILD_TARGET_DIR)/$(RB_SYS_CARGO_PROFILE_DIR)
    RUSTLIB = $(TARGET_DIR)/$(SOEXT_PREFIX)$(TARGET_NAME).$(SOEXT)
    CLEANOBJS = $(TARGET_DIR)/.fingerprint $(TARGET_DIR)/incremental $(TARGET_DIR)/examples $(TARGET_DIR)/deps $(TARGET_DIR)/build $(TARGET_DIR)/.cargo-lock $(TARGET_DIR)/*.d $(TARGET_DIR)/*.rlib $(RB_SYS_BUILD_DIR)
    DEFFILE = $(TARGET_DIR)/$(TARGET)-$(arch).def
    CLEANLIBS = $(DLLIB) $(RUSTLIB) $(DEFFILE)
    #{base_makefile(srcdir)}
    ifneq ($(RB_SYS_VERBOSE),)
      Q = $(0=@)
    endif
    #{env_vars(builder)}
    $(RUSTLIB): export RUSTFLAGS := $(RUSTFLAGS) $(RB_SYS_EXTRA_RUSTFLAGS)
    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)) > $@
    #{optional_rust_toolchain(builder)}
    $(RUSTLIB): $(DEFFILE) FORCE
    \t$(ECHO) generating $(@) \\("$(RB_SYS_CARGO_PROFILE)"\\)
    \t$(Q) #{full_cargo_command}
    $(DLLIB): $(RUSTLIB)
    \t$(Q) $(COPY) "$(RUSTLIB)" $@
    install-so: $(DLLIB)
    \t$(ECHO) installing $(DLLIB) to $(RUBYARCHDIR)
    \t$(Q) $(MAKEDIRS) $(RUBYARCHDIR)
    \t$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
    install: #{builder.clean_after_install ? "install-so realclean" : "install-so"}
    all: #{$extout ? "install" : "$(DLLIB)"}
  MAKE
  gsub_cargo_command!(make_install, builder: builder)
  File.write("Makefile", make_install)
end