module RbSys::Mkmf
def create_rust_makefile(target, &blk)
- 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 = File.join("$(srcdir)", builder.ext_dir.gsub(/\A\.\/?/, "")).chomp("/") RbConfig.expand(srcdir = srcprefix.dup) full_cargo_command = cargo_command(srcdir, builder) global_rustflags = [] # Re-enable if this causes issues, but it should be fine and it prevents unnecessary recompilation # global_rustflags << "--cfg=rb_sys_gem" unless builder.use_cargo_build global_rustflags << "--cfg=rb_sys_use_stable_api_compiled_fallback" if builder.use_stable_api_compiled_fallback? make_install = +<<~MAKE #{conditional_assign("RB_SYS_BUILD_DIR", File.join(Dir.pwd, ".rb-sys"))} #{conditional_assign("CARGO", "cargo")} #{conditional_assign("CARGO_BUILD_TARGET", builder.target)} #{conditional_assign("SOEXT", builder.so_ext)} #{try_load_bundled_libclang(builder)} # Determine the prefix Cargo uses for the lib. #{if_neq_stmt("$(SOEXT)", "dll")} #{conditional_assign("SOEXT_PREFIX", "lib", indent: 1)} #{endif_stmt} #{set_cargo_profile(builder)} #{conditional_assign("RB_SYS_CARGO_FEATURES", builder.features.join(","))} #{conditional_assign("RB_SYS_GLOBAL_RUSTFLAGS", global_rustflags.join(" "))} #{conditional_assign("RB_SYS_EXTRA_RUSTFLAGS", builder.extra_rustflags.join(" "))} #{conditional_assign("RB_SYS_EXTRA_CARGO_ARGS", builder.extra_cargo_args.join(" "))} #{conditional_assign("RB_SYS_CARGO_MANIFEST_DIR", builder.manifest_dir)} # Set dirname for the profile, since the profiles do not directly map to target dir (i.e. dev -> debug) #{if_eq_stmt("$(RB_SYS_CARGO_PROFILE)", "dev")} #{conditional_assign("RB_SYS_CARGO_PROFILE_DIR", "debug", indent: 1)} #{else_stmt} #{conditional_assign("RB_SYS_CARGO_PROFILE_DIR", "$(RB_SYS_CARGO_PROFILE)", indent: 1)} #{endif_stmt} # Set the build profile (dev, release, etc.). #{assign_stmt("RB_SYS_CARGO_PROFILE_FLAG", "--profile $(RB_SYS_CARGO_PROFILE)", indent: 1)} # Account for sub-directories when using `--target` argument with Cargo #{conditional_assign("RB_SYS_CARGO_TARGET_DIR", "target")} #{if_neq_stmt("$(CARGO_BUILD_TARGET)", "")} #{assign_stmt("RB_SYS_FULL_TARGET_DIR", "$(RB_SYS_CARGO_TARGET_DIR)/$(CARGO_BUILD_TARGET)", indent: 1)} #{else_stmt} #{assign_stmt("RB_SYS_FULL_TARGET_DIR", "$(RB_SYS_CARGO_TARGET_DIR)", indent: 1)} #{endif_stmt} 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"]} RUSTLIBDIR = $(RB_SYS_FULL_TARGET_DIR)/$(RB_SYS_CARGO_PROFILE_DIR) RUSTLIB = $(RUSTLIBDIR)/$(SOEXT_PREFIX)$(TARGET_NAME).$(SOEXT) TIMESTAMP_DIR = . POSTLINK = #{RbConfig::CONFIG["POSTLINK"] || "$(ECHO) skipping postlink"} CLEANOBJS = $(RUSTLIBDIR) $(RB_SYS_BUILD_DIR) CLEANLIBS = $(DLLIB) $(RUSTLIB) RUBYGEMS_CLEAN_DIRS = $(CLEANOBJS) $(CLEANFILES) #{builder.rubygems_clean_dirs.join(" ")} #{base_makefile(srcdir)} .PHONY: gemclean #{if_neq_stmt("$(RB_SYS_VERBOSE)", "")} #{assign_stmt("Q", "$(0=@)", indent: 1)} #{endif_stmt} #{env_vars(builder)} #{export_env("RUSTFLAGS", "$(RB_SYS_GLOBAL_RUSTFLAGS) $(RB_SYS_EXTRA_RUSTFLAGS) $(RUSTFLAGS)")} FORCE: ; #{optional_rust_toolchain(builder)} #{timestamp_file("sitearchdir")}: \t$(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR) \t$(Q) $(TOUCH) $@ $(RUSTLIB): FORCE \t$(ECHO) generating $(@) \\("$(RB_SYS_CARGO_PROFILE)"\\) \t#{full_cargo_command} $(DLLIB): $(RUSTLIB) \t$(Q) $(COPY) "$(RUSTLIB)" $@ \t$(Q) $(POSTLINK) install-so: $(DLLIB) #{timestamp_file("sitearchdir")} \t$(ECHO) installing $(DLLIB) to $(RUBYARCHDIR) \t#{fixup_libnames} \t$(Q) $(MAKEDIRS) $(RUBYARCHDIR) \t$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR) gemclean: \t$(ECHO) Cleaning gem artifacts \t-$(Q)$(RM_RF) $(RUBYGEMS_CLEAN_DIRS) 2> /dev/null || true install: #{builder.clean_after_install ? "install-so gemclean" : "install-so"} all: #{$extout ? "install" : "$(DLLIB)"} MAKE gsub_cargo_command!(make_install, builder: builder) File.write("Makefile", make_install) end