# frozen_string_literal: true RSpec.describe "installing a gem with native extensions", :ruby_repo do it "installs" do build_repo2 do build_gem "c_extension" do |s| s.extensions = ["ext/extconf.rb"] s.write "ext/extconf.rb", <<-E require "mkmf" name = "c_extension_bundle" dir_config(name) raise "OMG" unless with_config("c_extension") == "hello" create_makefile(name) E s.write "ext/c_extension.c", <<-C #include "ruby.h" VALUE c_extension_true(VALUE self) { return Qtrue; } void Init_c_extension_bundle() { VALUE c_Extension = rb_define_class("CExtension", rb_cObject); rb_define_method(c_Extension, "its_true", c_extension_true, 0); } C s.write "lib/c_extension.rb", <<-C require "c_extension_bundle" C end end gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "c_extension" G bundle "config set build.c_extension --with-c_extension=hello" bundle "install" expect(out).to include("Installing c_extension 1.0 with native extensions") run "Bundler.require; puts CExtension.new.its_true" expect(out).to eq("true") end it "installs from git" do build_git "c_extension" do |s| s.extensions = ["ext/extconf.rb"] s.write "ext/extconf.rb", <<-E require "mkmf" name = "c_extension_bundle" dir_config(name) raise "OMG" unless with_config("c_extension") == "hello" create_makefile(name) E s.write "ext/c_extension.c", <<-C #include "ruby.h" VALUE c_extension_true(VALUE self) { return Qtrue; } void Init_c_extension_bundle() { VALUE c_Extension = rb_define_class("CExtension", rb_cObject); rb_define_method(c_Extension, "its_true", c_extension_true, 0); } C s.write "lib/c_extension.rb", <<-C require "c_extension_bundle" C end bundle "config set build.c_extension --with-c_extension=hello" install_gemfile <<-G gem "c_extension", :git => #{lib_path("c_extension-1.0").to_s.dump} G expect(err).to_not include("warning: conflicting chdir during another chdir block") run "Bundler.require; puts CExtension.new.its_true" expect(out).to eq("true") end it "installs correctly from git when multiple gems with extensions share one repository" do build_repo2 do ["one", "two"].each do |n| build_lib "c_extension_#{n}", "1.0", :path => lib_path("gems/c_extension_#{n}") do |s| s.extensions = ["ext/extconf.rb"] s.write "ext/extconf.rb", <<-E require "mkmf" name = "c_extension_bundle_#{n}" dir_config(name) raise "OMG" unless with_config("c_extension_#{n}") == "#{n}" create_makefile(name) E s.write "ext/c_extension_#{n}.c", <<-C #include "ruby.h" VALUE c_extension_#{n}_value(VALUE self) { return rb_str_new_cstr("#{n}"); } void Init_c_extension_bundle_#{n}() { VALUE c_Extension = rb_define_class("CExtension_#{n}", rb_cObject); rb_define_method(c_Extension, "value", c_extension_#{n}_value, 0); } C s.write "lib/c_extension_#{n}.rb", <<-C require "c_extension_bundle_#{n}" C end end build_git "gems", :path => lib_path("gems"), :gemspec => false end bundle "config set build.c_extension_one --with-c_extension_one=one" bundle "config set build.c_extension_two --with-c_extension_two=two" # 1st time, require only one gem -- only one of the extensions gets built. install_gemfile <<-G gem "c_extension_one", :git => #{lib_path("gems").to_s.dump} G # 2nd time, require both gems -- we need both extensions to be built now. install_gemfile <<-G gem "c_extension_one", :git => #{lib_path("gems").to_s.dump} gem "c_extension_two", :git => #{lib_path("gems").to_s.dump} G run "Bundler.require; puts CExtension_one.new.value; puts CExtension_two.new.value" expect(out).to eq("one\ntwo") end it "install with multiple build flags" do build_git "c_extension" do |s| s.extensions = ["ext/extconf.rb"] s.write "ext/extconf.rb", <<-E require "mkmf" name = "c_extension_bundle" dir_config(name) raise "OMG" unless with_config("c_extension") == "hello" && with_config("c_extension_bundle-dir") == "hola" create_makefile(name) E s.write "ext/c_extension.c", <<-C #include "ruby.h" VALUE c_extension_true(VALUE self) { return Qtrue; } void Init_c_extension_bundle() { VALUE c_Extension = rb_define_class("CExtension", rb_cObject); rb_define_method(c_Extension, "its_true", c_extension_true, 0); } C s.write "lib/c_extension.rb", <<-C require "c_extension_bundle" C end bundle "config set build.c_extension --with-c_extension=hello --with-c_extension_bundle-dir=hola" install_gemfile <<-G gem "c_extension", :git => #{lib_path("c_extension-1.0").to_s.dump} G run "Bundler.require; puts CExtension.new.its_true" expect(out).to eq("true") end end