ext/extconf.rb

Summary

Maintainability
A
0 mins
Test Coverage
require "mkmf"

# add check for member function, does need default constructor for class
def have_member_func(klass,member,header, *args)
    if have_func("#{klass}().#{member}(#{args.join(', ')})",header)
        $defs[-1] = "-DHAVE_#{klass.tr_cpp}_#{member.tr_cpp}"
    end
end

def have_constructor(klass, header, *args)
    if have_func("#{klass}(#{args.join(', ')})",header)
        vargs = args.grep(String).flat_map {|s| s.scan(/\A\w+/) }.join
        $defs[-1] = "-DHAVE_#{klass.tr_cpp}_#{vargs.tr_cpp}"
    end
end


unless have_macro("HAVE_RB_DATA_TYPE_T_PARENT")
    abort("rb_data_type_t needs parent attribute!")
end


dir_config "rwx"

if(wxversion = pkg_config('wx', 'version'))
    
    if wxversion < "3.0.0"
        abort("wx version outdated, please update to 3.0.0 or newer")
    end
    
    ruby_cc = CONFIG["CC"]
    ruby_cxx = CONFIG["CXX"]
    # An ruby extension does need to be build against
    # the same compiler as ruby was
    unless ruby_cc && find_executable(ruby_cc)
        abort("C compiler not found!")
    end
    unless ruby_cxx && find_executable(ruby_cxx)
        abort("C++ compiler not found!")
    end
    
    wxcc = pkg_config('wx', 'cc')
# there's no actual need to check "compiler compatibility" because Linux compilers make
# compatible ABI calls anyway.
#    unless wxcc == ruby_cc
#        abort("CC compiler missmatch %s == %s" % [wxcc, ruby_cc])
#    end
    
    wxcxx = pkg_config('wx', 'cxx')
#    unless wxcxx == ruby_cxx
#        abort("CXX compiler missmatch %s == %s" % [wxcxx, ruby_cxx])
#    end
    
    #earlier versions of ruby does not have that constant
    $CXXFLAGS = CONFIG["CXXFLAGS"] unless defined?($CXXFLAGS)
    
    #for some function add the base classes
    extra_libs = []
    case pkg_config('wx', 'basename')
    when /gtk2/
        extra_libs << "gtk+-x11-2.0" << "gdk-x11-2.0"
    when /gtk3/
        extra_libs << "gtk+-x11-3.0" << "gdk-x11-3.0"
    end
    
    extra_libs.each {|l|
        pkg = pkg_config(l)
        #because pkg forgot to add the include paths to cxx flags
        $CXXFLAGS << " " << pkg[0] if pkg && !$CXXFLAGS[pkg[0]]
    }
    
    all = " -fvisibility-inlines-hidden"

    $CFLAGS << all << " -x c++ -g "
    $CXXFLAGS << all << " -g "
    $CPPFLAGS << all << " -g "
    $LDFLAGS << all << " "
    
    # add the wx-config flags
    $CFLAGS << pkg_config('wx', 'cflags')
    $CXXFLAGS << pkg_config('wx', 'cxxflags')
    $CPPFLAGS << pkg_config('wx', 'cppflags')
    $LDFLAGS << pkg_config('wx', 'libs all')
    
    # TODO add extra check if a lib of wx is missing
    
    c11 = ""

    # wxwidgets is build against c++11 need to do it too if possible
    if have_macro("HAVE_TYPE_TRAITS","wx/setup.h")
        c11 = "-std=c++11"
    end

    # when using clang forceunwind is not defined (forceunwind is only in stdc++)
    if CONFIG["CC"] =~ /clang/ and !have_macro("HAVE_ABI_FORCEDUNWIND","wx/setup.h")
        # try to set libc++ as stdlib
        with_cflags(" -x c++ #{c11} -stdlib=libc++") {
            # when it does find the version in ciso646 it was successful
            if have_macro("_LIBCPP_VERSION","ciso646")
                c11 << " -stdlib=libc++"
            end
        }
    end

    with_cflags(" -x c++ #{c11}") {
        # need c++ for some of the tests
        RbConfig::CONFIG["CC"] = CONFIG["CXX"]
        
        have_header("wx/preferences.h")
        
        #check for better Bind commmand
        unless have_macro("wxHAS_EVENT_BIND","wx/wx.h")
            abort("need wxHAS_EVENT_BIND, update your compiler!")
        end

        #check for Default-Constructors
        have_func("wxContextHelpButton()","wx/cshelp.h")
        have_func("wxNumberEntryDialog()","wx/numdlg.h")
        have_func("wxPasswordEntryDialog()","wx/textdlg.h")
        have_func("wxProgressDialog()","wx/progdlg.h")
        have_func("wxMessageDialog()","wx/msgdlg.h")
        have_func("wxGenericMessageDialog()",["wx/wx.h", "wx/generic/msgdlgg.h"])
        have_func("wxRichMessageDialog()","wx/richmsgdlg.h")
        have_func("wxBusyInfoFlags()","wx/busyinfo.h")
        have_func("wxCollapsibleHeaderCtrl()",["wx/wx.h", "wx/collheaderctrl.h"])

        #check for instance methods, that classes need to have default constuctor
        have_member_func("wxFontPickerCtrl","GetSelectedColour","wx/fontpicker.h")
        have_member_func("wxInfoBar","GetButtonCount","wx/infobar.h")

        have_member_func("wxOwnerDrawnComboBox","IsListEmpty","wx/odcombo.h")

        #check for enum flags
        have_const("wxFD_NO_FOLLOW","wx/filedlg.h")
        have_const("wxDIRCTRL_DEFAULT_STYLE",["wx/wx.h", "wx/dirctrl.h"])
        have_func("wxDirCtrl()",["wx/wx.h", "wx/dirctrl.h"])
        
        have_const("wxSTC_LEX_DMAP",["wx/wx.h", "wx/stc/stc.h"])
        have_const("wxSTC_LEX_TEHEX",["wx/wx.h", "wx/stc/stc.h"])

        have_constructor("wxBitmap",["wx/wx.h", "wx/bitmap.h"], "wxImage(10, 20)", 32, 1.0)

        have_member_func("wxColourData","GetChooseAlpha",["wx/wx.h", "wx/colourdata.h"])

        have_member_func("wxStyledTextCtrl","GetTargetText",["wx/wx.h", "wx/stc/stc.h"])
        have_member_func("wxStyledTextCtrl","IndicatorGetHoverStyle",["wx/wx.h", "wx/stc/stc.h"], 0)

        have_member_func("wxStyledTextCtrl","SetTargetRange",["wx/wx.h", "wx/stc/stc.h"], 0, 0)

        have_member_func("wxStyledTextCtrl","GetCaretLineVisibleAlways",["wx/wx.h", "wx/stc/stc.h"])

        have_member_func("wxStyledTextCtrl","GetLexerLanguage",["wx/wx.h", "wx/stc/stc.h"])

        have_member_func("wxListCtrl","HasCheckBoxes", ["wx/wx.h", "wx/listctrl.h"])

        have_member_func("wxScrollBar","SetThumbSize",["wx/wx.h", "wx/scrolbar.h"], 10)

        have_const("wxALIGN_CENTER_VERTICAL","wx/sizer.h")
        have_member_func("wxSizerFlags","CenterVertical","wx/sizer.h")
        have_member_func("wxWindow","FromDIP","wx/wx.h", 1)
        have_member_func("wxWindow","ToDIP","wx/wx.h", 1)

        have_member_func("wxTextCtrl","ForceUpper","wx/wx.h")
        have_member_func("wxTextEntryDialog","ForceUpper","wx/wx.h")
    }
else
        abort("wx-config executable not found!")

end

$defs.push("-DRUBY_UNTYPED_DATA_WARNING=1")

# sorry, unimplemented!
CONFIG["optflags"].gsub!("-fexcess-precision=standard", "")

drop_warn = [
    "-Wdeclaration-after-statement",
    "-Wimplicit-function-declaration",
    "-Wimplicit-int",
    "-Wextra",  #wxAUI is a bit buggy

    '-Wno-self-assign',
    '-Wno-constant-logical-operand',
    '-Wno-parentheses-equality',
    '-Wno-tautological-compare'
]

if CONFIG["CC"] =~ /clang/
    drop_warn << "-Wall"
    drop_warn << "-tokens" #clang dont like it
    drop_warn << "-Wshorten-64-to-32" #clang dont like it, and wx have to many
    drop_warn << "-Winconsistent-missing-override" #currently wx does have to many
    drop_warn << "-Wpotentially-evaluated-expression" #currently wx does have to many
end


#drop some of the warn flags because they are not valid for C++
negate_warn = drop_warn.reject {|s| CONFIG["warnflags"].gsub!(s, "") }

negate_warn.reject! {|s| s["-Wno-"] }

#negate some warn flags that i want to removed TODO need to test if that works
CONFIG["warnflags"] << " " << negate_warn.map {|s| s.gsub("-W", "-Wno-") }.join(" ")

with_cppflags(c11) {
    create_header
    create_makefile "rwx"
}