Skip to content

Commit a3247e9

Browse files
committed
[Bug #21111] Find C++ programs at runtime
1 parent 6018967 commit a3247e9

1 file changed

Lines changed: 76 additions & 4 deletions

File tree

lib/mkmf.rb

Lines changed: 76 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,83 @@ 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+
static std::nullptr_t const *const conftest_nullptr = nullptr;
3037+
CXX
3038+
[MAKEFILE_CONFIG, CONFIG].each do |conf|
3039+
conf['CXXFLAGS'] << " -DHAVE_NULLPTR"
3040+
end
3041+
end
30263042
end
30273043
@have_devel
30283044
end
30293045

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

0 commit comments

Comments
 (0)