Skip to content

Commit eb3a75d

Browse files
committed
mkmf: split try_link0 into separate compile and link steps
When `mkmf.rb` checks for functions via `have_func`, it compiles and links a test program in a single clang invocation. On macOS, passing a source file together with `-lruby.4.1-static` (28MB static archive) to clang in one command triggers a ~1.4s overhead per invocation. Splitting into two steps (compile `.c` to `.o`, then link `.o`) reduces this to ~0.14s — a 10x improvement per check. This dramatically speeds up extension configuration: - `ext/io/console`: 12.1s → 1.8s (6.7x faster) - `ext/openssl`: 8.3s → 3.0s (2.8x faster) - `ext/json`: 6.6s → 1.4s (4.7x faster) - `ext/strscan`: 5.0s → 0.6s (8.3x faster) Overall clean build: 52s → 44s (16% faster)
1 parent 3b62455 commit eb3a75d

1 file changed

Lines changed: 19 additions & 3 deletions

File tree

lib/mkmf.rb

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -606,19 +606,35 @@ def with_werror(opt, opts = nil)
606606

607607
def try_link0(src, opt = "", ldflags: "", **opts, &b) # :nodoc:
608608
exe = CONFTEST+$EXEEXT
609-
cmd = link_command(ldflags, opt)
609+
obj = "#{CONFTEST}.#{$OBJEXT}"
610+
cc = cc_command(opt)
611+
conf = link_config(ldflags, opt)
612+
conf['src'] = obj
613+
ld = RbConfig::expand(TRY_LINK.dup, conf)
614+
try_do2 = proc do
615+
unless have_devel?
616+
raise "The compiler failed to generate an executable file.\n" \
617+
"You have to install development tools first.\n"
618+
end
619+
begin
620+
src2 = create_tmpsrc(src, &b)
621+
xsystem(cc, **opts) and xsystem(ld, **opts)
622+
ensure
623+
log_src(src2)
624+
end
625+
end
610626
if $universal
611627
require 'tmpdir'
612628
Dir.mktmpdir("mkmf_", oldtmpdir = ENV["TMPDIR"]) do |tmpdir|
613629
begin
614630
ENV["TMPDIR"] = tmpdir
615-
try_do(src, cmd, **opts, &b)
631+
try_do2.call
616632
ensure
617633
ENV["TMPDIR"] = oldtmpdir
618634
end
619635
end
620636
else
621-
try_do(src, cmd, **opts, &b)
637+
try_do2.call
622638
end and File.executable?(exe) or return nil
623639
exe
624640
ensure

0 commit comments

Comments
 (0)