Skip to content

Commit 4bf6e78

Browse files
committed
[Bug #21111] Find C++ programs at runtime
1 parent feb8331 commit 4bf6e78

1 file changed

Lines changed: 77 additions & 4 deletions

File tree

lib/mkmf.rb

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2809,17 +2809,19 @@ def _libdir_basename
28092809
@libdir_basename ||= config_string("libdir") {|name| name[/\A\$\(exec_prefix\)\/(.*)/, 1]} || "lib"
28102810
end
28112811

2812-
def MAIN_DOES_NOTHING(*refs)
2812+
def MAIN_DOES_NOTHING(*refs) # :yield:
28132813
src = MAIN_DOES_NOTHING
28142814
unless refs.empty?
2815-
src = src.sub(/\{/) do
2816-
$& +
2817-
"\n if (argc > 1000000) {\n" +
2815+
src = src.sub(/\{\K/) do
2816+
"\n if (argc > 1000000) {\n" +
28182817
refs.map {|n|" int (* volatile #{n}p)(void)=(int (*)(void))&#{n};\n"}.join("") +
28192818
refs.map {|n|" printf(\"%d\", (*#{n}p)());\n"}.join("") +
28202819
" }\n"
28212820
end
28222821
end
2822+
if defined?(yield)
2823+
src = yield src
2824+
end
28232825
src
28242826
end
28252827

@@ -3020,13 +3022,84 @@ def self.[]=(name, mod)
30203022
"$(CXXFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
30213023

30223024
def have_devel?
3025+
if config_string('CXX') == 'false'
3026+
return @have_devel = false unless progs = find_cxx_progs
3027+
unless progs['LDSHAREDXX']&. != ''
3028+
progs['LDSHAREDXX'] = CONFIG['LDSHARED'].sub(/\$(?:\(CC\)|\{CC\}|CC)/, '$(CXX)')
3029+
end
3030+
progs.each_pair {|key, val| RbConfig.fire_update!(key, val)}
3031+
end
30233032
unless defined? @have_devel
30243033
@have_devel = true
30253034
@have_devel = try_link(MAIN_DOES_NOTHING)
3035+
if try_compile(MAIN_DOES_NOTHING {|src| <<~CXX + src })
3036+
#include <cstddef>
3037+
std::nullptr_t const *const conftest_nullptr = nullptr;
3038+
CXX
3039+
[RbConfig::MAKEFILE_CONFIG, RbConfig::CONFIG].each do |conf|
3040+
conf['CXXFLAGS'] << " -DHAVE_NULLPTR"
3041+
end
3042+
end
30263043
end
30273044
@have_devel
30283045
end
30293046

3047+
def check_prog_for_cc(stem, repl, cc)
3048+
cxx = cc.sub(/#{stem}(?=[^\/]*\z)/, repl)
3049+
cxx if find_executable0(cxx)
3050+
end
3051+
3052+
# Find C++ programs at runtime, according to CONFIG['CC'].
3053+
def find_cxx_progs
3054+
cc, = config_string('CC').shellsplit
3055+
case File.basename(cc)
3056+
when 'cc' # /(?:\A|[ \/])cc(?: |\z)/
3057+
# Don't try g++/clang++ when CC=cc
3058+
{
3059+
'CXX' => %w[cl.exe CC c++].find {|cc| find_executable0(cc)},
3060+
}
3061+
when /icc/
3062+
# Intel C++ has interprocedural optimizations. It tends to come with its
3063+
# own linker etc.
3064+
{
3065+
'AR' => check_prog_for_cc("icc", "xiar", cc),
3066+
'CXX' => check_prog_for_cc("icc", "icpc", cc),
3067+
'LD' => check_prog_for_cc("icc", "xild", cc),
3068+
}
3069+
when /gcc/
3070+
# Ditto for GCC.
3071+
{
3072+
'LD' => check_prog_for_cc("gcc", "ld", cc),
3073+
'AR' => check_prog_for_cc("gcc", "gcc-ar", cc),
3074+
'CXX' => check_prog_for_cc("gcc", "g++", cc),
3075+
'NM' => check_prog_for_cc("gcc", "gcc-nm", cc),
3076+
'RANLIB' => check_prog_for_cc("gcc", "gcc-ranlib", cc),
3077+
}
3078+
when /clang/
3079+
# Ditto for LLVM. Note however that llvm-as is a LLVM-IR to LLVM bitcode
3080+
# assembler that does not target your machine native binary.
3081+
3082+
# Xcode has its own version tools that may be incompatible with
3083+
# genuine LLVM tools, use the tools in the same directory.
3084+
3085+
llvm_prefix = IO.popen([cc, *%w"-E -dM -xc -"], in: :close, &:read)
3086+
llvm_prefix = llvm_prefix.include?("__apple_build_version__") ? "" : "llvm-"
3087+
{
3088+
'LD' => check_prog_for_cc("clang", "ld", cc), # ... maybe try lld ?
3089+
'AR' => check_prog_for_cc("clang", "#{llvm_prefix}ar", cc),
3090+
# 'AS' => check_prog_for_cc("clang", "#{llvm_prefix}as", cc),
3091+
'CXX' => check_prog_for_cc("clang", "clang++", cc),
3092+
'NM' => check_prog_for_cc("clang", "#{llvm_prefix}nm", cc),
3093+
'OBJCOPY' => check_prog_for_cc("clang", "#{llvm_prefix}objcopy", cc),
3094+
'OBJDUMP' => check_prog_for_cc("clang", "#{llvm_prefix}objdump", cc),
3095+
'RANLIB' => check_prog_for_cc("clang", "#{llvm_prefix}ranlib", cc),
3096+
'STRIP' => check_prog_for_cc("clang", "#{llvm_prefix}strip", cc),
3097+
}
3098+
else
3099+
return
3100+
end.compact
3101+
end
3102+
30303103
def conftest_source
30313104
CONFTEST_CXX
30323105
end

0 commit comments

Comments
 (0)