#!/bin/env ruby require 'fileutils' require 'mkmf' gem 'mini_portile2', '~>2.1' require 'mini_portile2' $autodetected_fxscintilla = false def is_fxscintilla_build? # No means no return false if fxscintilla_support_suppressed? # Check arguments with_config("fxscintilla", false) || $autodetected_fxscintilla end def fxscintilla_support_suppressed? !with_config("fxscintilla", true) end LIBZ_VERSION = ENV['LIBZ_VERSION'] || '1.3.1' LIBZ_SOURCE_URI = "http://zlib.net/fossils/zlib-#{LIBZ_VERSION}.tar.gz" LIBPNG_VERSION = ENV['LIBPNG_VERSION'] || '1.6.42' # LIBPNG_SOURCE_URI = "http://prdownloads.sourceforge.net/libpng/libpng-#{LIBPNG_VERSION}.tar.gz" LIBPNG_SOURCE_URI = "https://netcologne.dl.sourceforge.net/project/libpng/libpng16/#{LIBPNG_VERSION}/libpng-#{LIBPNG_VERSION}.tar.xz" # LIBJPEG_VERSION = ENV['LIBJPEG_VERSION'] || '9b' # LIBJPEG_SOURCE_URI = "http://www.ijg.org/files/jpegsrc.v#{LIBJPEG_VERSION}.tar.gz" LIBJPEG_VERSION = ENV['LIBJPEG_VERSION'] || '3.0.2' LIBJPEG_SOURCE_URI = "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/#{LIBJPEG_VERSION}/libjpeg-turbo-#{LIBJPEG_VERSION}.tar.gz" LIBTIFF_VERSION = ENV['LIBTIFF_VERSION'] || '4.6.0' LIBTIFF_SOURCE_URI = "http://download.osgeo.org/libtiff/tiff-#{LIBTIFF_VERSION}.tar.gz" LIBFOX_VERSION = ENV['LIBFOX_VERSION'] || '1.6.57' LIBFOX_SOURCE_URI = "http://fox-toolkit.org/ftp/fox-#{LIBFOX_VERSION}.tar.gz" LIBFXSCINTILLA_VERSION = ENV['LIBFXSCINTILLA_VERSION'] || '2.28.0' LIBFXSCINTILLA_SOURCE_URI = "http://download.savannah.gnu.org/releases/fxscintilla/fxscintilla-#{LIBFXSCINTILLA_VERSION}.tar.gz" # LIBFXSCINTILLA_VERSION = ENV['LIBFXSCINTILLA_VERSION'] || '3.5.2' # LIBFXSCINTILLA_SOURCE_URI = "https://github.com/yetanothergeek/fxscintilla/archive/FXSCINTILLA-#{LIBFXSCINTILLA_VERSION.gsub(".","_")}.tar.gz" module BuildRecipeCommons def initialize(name, version, files) super(name, version) self.files = files rootdir = File.expand_path('../../..', __FILE__) self.target = File.join(rootdir, "ports") self.host = RbConfig::CONFIG["CC"].match(/(.*)-/)[1] self.patch_files = Dir[File.join(rootdir, "patches", self.name, self.version, "*.diff")].sort end def port_path "#{target}/#{RUBY_PLATFORM}" end # When using rake-compiler-dock on Windows, the underlying Virtualbox shared # folders don't support symlinks, but libiconv expects it for a build on # Linux. We work around this limitation by using the temp dir for cooking. def chdir_for_build build_dir = ENV['RCD_HOST_RUBY_PLATFORM'].to_s =~ /mingw|mswin|cygwin/ ? '/tmp' : '.' Dir.chdir(build_dir) do yield end end def cook_and_activate checkpoint = File.join(self.target, "#{self.name}-#{self.version}-#{RUBY_PLATFORM}.installed") unless File.exist?(checkpoint) chdir_for_build do self.cook end FileUtils.touch checkpoint end self.activate self end end class BuildRecipe < MiniPortile include BuildRecipeCommons def configure_defaults [ "--host=#{host}", # build for specific target (host) "--disable-static", "--enable-shared", ] end end class BuildRecipeCMake < MiniPortileCMake include BuildRecipeCommons def system_processor case host when /x86_64/ then "amd64" when /i686/ then "x86" else raise "unknown host #{host}" end end def configure_defaults [ "-DENABLE_STATIC=0", "-DENABLE_SHARED=1", "-DCMAKE_SYSTEM_NAME=Windows", "-DCMAKE_C_COMPILER=#{host}-gcc", "-DCMAKE_CXX_COMPILER=#{host}-g++", "-DCMAKE_SYSTEM_PROCESSOR=#{system_processor}", ] end def make_cmd ENV["MAKE"] || "make" end end def do_rake_compiler_setup if enable_config("win32-cross") dir_config("installed") libz_recipe = BuildRecipe.new("libz", LIBZ_VERSION, [LIBZ_SOURCE_URI]).tap do |recipe| class << recipe def configure Dir.chdir work_path do mk = File.read 'win32/Makefile.gcc' File.open 'win32/Makefile.gcc', 'wb' do |f| f.puts "BINARY_PATH = #{path}/bin" f.puts "LIBRARY_PATH = #{path}/lib" f.puts "INCLUDE_PATH = #{path}/include" mk.sub!(/^PREFIX\s*=\s*$/, "PREFIX = #{host}-") f.puts mk end end end def configured? Dir.chdir work_path do !! (File.read('win32/Makefile.gcc') =~ /^BINARY_PATH/) end end def compile execute "compile", "make -f win32/Makefile.gcc SHARED_MODE=1" end def install execute "install", "make -f win32/Makefile.gcc install SHARED_MODE=1" end end recipe.cook_and_activate end libpng_recipe = BuildRecipe.new("libpng", LIBPNG_VERSION, [LIBPNG_SOURCE_URI]).tap do |recipe| recipe.configure_options += [ "CPPFLAGS=-I#{libz_recipe.path}/include", "LDFLAGS=-L#{libz_recipe.path}/lib", ] recipe.cook_and_activate end libjpeg_recipe = BuildRecipeCMake.new("libjpeg", LIBJPEG_VERSION, [LIBJPEG_SOURCE_URI]).tap do |recipe| recipe.cook_and_activate end libtiff_recipe = BuildRecipe.new("libtiff", LIBTIFF_VERSION, [LIBTIFF_SOURCE_URI]).tap do |recipe| recipe.cook_and_activate end libfox_recipe = BuildRecipe.new("libfox", LIBFOX_VERSION, [LIBFOX_SOURCE_URI]).tap do |recipe| debug = enable_config("debug") recipe.configure_options += [ "--without-xft", "--without-x", debug ? "--enable-debug" : "--enable-release", "CPPFLAGS=-I#{libjpeg_recipe.path}/include -I#{libpng_recipe.path}/include -I#{libtiff_recipe.path}/include -I#{libz_recipe.path}/include -DUNICODE=1 #{debug ? "-ggdb" : ""} -D__USE_MINGW_ANSI_STDIO=1 -DHAVE_VSSCANF", "LDFLAGS=-L#{libjpeg_recipe.path}/lib -L#{libpng_recipe.path}/lib -L#{libtiff_recipe.path}/lib -L#{libz_recipe.path}/lib #{debug ? "-ggdb" : ""}", ] recipe.cook_and_activate end libfxscintills_recipe = BuildRecipe.new("libfxscintilla", LIBFXSCINTILLA_VERSION, [LIBFXSCINTILLA_SOURCE_URI]).tap do |recipe| class << recipe attr_accessor :libfox_path def mk "#{ENV['MAKE'] || "make"}" end # # This can be uncommented when fxscintilla is used from the source repository. # def configure # execute "bootstrap", "./bootstrap.sh" # super # end def compile execute "compile_lexers", "cd lexers && #{mk}" execute "compile_lexlib", "cd lexlib && #{mk}" execute "compile_src", "cd src && #{mk}" execute "compile_fox", "cd fox && #{mk} libfxscintilla_la_LDFLAGS='-version-info 23:0:3 -export-dynamic -no-undefined -L#{libfox_path}/lib -lFOX-1.6'" end def install execute "install", "cd fox && #{mk} install && cd ../include && #{mk} install" end end recipe.libfox_path = libfox_recipe.path recipe.configure_options += [ "PKG_CONFIG_PATH=#{libfox_recipe.path}/lib/pkgconfig", ] recipe.cook_and_activate end dir_config('libfox', "#{libfox_recipe.path}/include/fox-1.6", "#{libfox_recipe.path}/lib") dir_config('libfxscintilla', "#{libfxscintills_recipe.path}/include/fxscintilla", "#{libfxscintills_recipe.path}/lib") gcc_shared_dlls = %w[libwinpthread-1.dll libgcc_s_dw2-1.dll libgcc_s_sjlj-1.dll libgcc_s_seh-1.dll libstdc++-6.dll] gcc_shared_dlls.each do |dll| cmd = "#{CONFIG['CC']} -print-file-name=\"#{dll}\"" res = `#{cmd}`.chomp next if dll == res puts "#{cmd} => #{res}" FileUtils.cp `#{cmd}`.chomp, "#{libfox_recipe.path}/bin/", verbose: true end CONFIG['CXX'] = "#{libfox_recipe.host}-g++" # CXX setting must be prefixed for cross build CONFIG['CC'] += "\nCXX=#{CONFIG['CXX']}" # Hack CXX into Makefile for cross compilation CONFIG['LDSHARED'].gsub!('gcc', 'g++') # ensure C++ linker is used, so that libstdc++ is linked static $LDFLAGS += " -s" # remove symbol table informations from shared lib $libs = append_library($libs, "fxscintilla") elsif RUBY_PLATFORM =~ /mingw/ $CFLAGS = $CFLAGS + " -I/usr/local/include" $LDFLAGS = $LDFLAGS + " -I/usr/local/lib" %w{stdc++ glu32 opengl32 wsock32 comctl32 mpr gdi32 winspool}.each {|lib| $libs = append_library($libs, lib) } elsif RUBY_PLATFORM =~ /darwin/ $CFLAGS = $CFLAGS + " -I/usr/X11/include" # for built-in libpng $LDFLAGS = $LDFLAGS + " -L/usr/X11/lib" # for built-in libpng $CFLAGS = $CFLAGS + " -I/usr/local/include" # for libjpeg and libtiff $LDFLAGS = $LDFLAGS + " -L/usr/local/lib" # for libjpeg and libtiff %w{Xft}.each {|lib| $libs = append_library($libs, lib) } end $libs = append_library($libs, "stdc++") unless RUBY_PLATFORM =~ /mingw/ || enable_config("win32-static-build") have_header("sys/time.h") unless RUBY_PLATFORM =~ /mingw/ || enable_config("win32-static-build") have_header("signal.h") have_library("z", "deflate") have_library("png", "png_create_read_struct") have_library("jpeg", "jpeg_mem_init") have_library("tiff", "TIFFSetErrorHandler") have_library("Xft", "XftInit") find_library("Xext", "XShmQueryVersion", "/usr/X11R6/lib") find_library("X11", "XFindContext", "/usr/X11R6/lib") find_library("GL", "glXCreateContext", "/usr/X11R6/lib") find_library("GLU", "gluNewQuadric", "/usr/X11R6/lib") $libs = append_library($libs, "Xrandr") unless RUBY_PLATFORM =~ /mingw/ || enable_config("win32-static-build") $libs = append_library($libs, "Xcursor") unless RUBY_PLATFORM =~ /mingw/ || enable_config("win32-static-build") $libs = append_library($libs, "FOX-1.6") $INCFLAGS << " -I#{File.join(File.dirname(__FILE__), 'include')}" if is_fxscintilla_build? $CPPFLAGS = $CPPFLAGS + " -DWITH_FXSCINTILLA -DHAVE_FOX_1_6" end checking_for("thread local variables") do $defs.push( "-DHAVE___THREAD" ) if try_compile <<-EOT __thread int x=1; #if defined(__MINGW32__) #include #if !defined(__MINGW64_VERSION_MAJOR) #error "Old mingw32 compiler doesn't implement thread local variables properly." #endif #endif EOT end && have_func('rb_thread_call_without_gvl') && have_func('rb_thread_call_with_gvl') have_func('rb_during_gc') end # This directive processes the "--with-fox-include" and "--with-fox-lib" # command line switches and modifies the CFLAGS and LDFLAGS accordingly. dir_config('fox', '/usr/local/include/fox-1.6', '/usr/local/lib') # This directive processes the "--with-fxscintilla-include" and # "--with-fxscintilla-lib" command line switches and modifies the CFLAGS # and LDFLAGS accordingly. dir_config('fxscintilla', '/usr/local/include/fxscintilla', '/usr/local/lib') unless enable_config("win32-cross") checking_for "fox per pkg-config" do pkg_config("fox") end # # Check for FXScintilla header files, unless FXScintilla support has # been explicitly suppressed with the '--without-fxscintilla' flag. # unless fxscintilla_support_suppressed? checking_for "fxscintilla per pkg-config" do $autodetected_fxscintilla = pkg_config("fxscintilla") end unless $autodetected_fxscintilla checking_for "fxscintilla on Ubuntu with missing libfxscintilla.so link" do if find_library(":libfxscintilla.so.19", nil) && (cflags = RUBY_VERSION>="2.1" ? pkg_config("fxscintilla", "cflags") : `pkg-config --cflags fxscintilla`) $CXXFLAGS += " " + cflags $autodetected_fxscintilla = true end end end end checking_for "fxscintilla build" do is_fxscintilla_build? end end if enable_config("debug") $CPPFLAGS += " -ggdb" $LDFLAGS += " -ggdb" else $CPPFLAGS += " -DNDEBUG" end # Platform-specific modifications do_rake_compiler_setup if RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/ $CXXFLAGS += " -Wno-unused-function" $CXXFLAGS += " -Wno-maybe-uninitialized" end # Last step: build the makefile create_header create_makefile("fox16_c")