rakelib/compile.rake
author Jan Vrany <jan.vrany@fit.cvut.cz>
Mon, 05 Sep 2016 09:49:38 +0100
changeset 51 05b2c72ee5a9
parent 45 5d8bcdc92f85
child 52 bcd6e68aa24e
permissions -rw-r--r--
Cleanup: do not use `stdRules_alt_GNU`, use original `stdRules` This makes things little easier to manage though we need to introduce another hacks. In future, we may need to fork whole stx/rules anyway. For now, use the original one and give up on some advantages GNU make gives us.


desc "Compile project"
task :'compile' => :'compile:all'


STX_TOP_DIR = BUILD_DIR / 'stx'
STX_CONF_DIR = STX_TOP_DIR / 'configurations'
STX_RULES_DIR = STX_TOP_DIR / 'rules'
if win32?
  STC = STX_TOP_DIR / 'stc' / 'stc.exe'
  LIBRUN = STX_TOP_DIR / 'librun' / 'objmingw' / 'librun.dll'
else
  STC = STX_TOP_DIR / 'stc' / 'stc'
  LIBRUN = STX_TOP_DIR / 'librun' / 'librun.so'
end

def should_remove_librun_and_stc_sources
    return ! core_developer?
end

def make_or_raise_error(args = '')
  cmd = "#{MAKE} #{args}"
  if not system cmd
    raise Exception.new("make failed: #{cmd}");
  end
end

def rm_rf_all_in_except(directory, exceptions = [])
  if File.directory? directory then
    Dir.foreach(directory) do | each |
      if each != '.' and each != '..' and not exceptions.include? each
        rm_rf File.join(directory, each)
      end
    end
  else
    rm_f directory
  end
end

if unix? 
  STC_BINARY_FILES = [    
    'cpu_alpha.h',
    'cpu_arm.h',
    'cpu_hppa.h',
    'cpu_i386.h',
    'cpu_x86_64.h',
    'cpu_ia64.h',
    'cpu_mc68k.h',
    'cpu_mc88k.h',
    'cpu_mips.h',
    'cpu_ns32k.h',
    'cpu_power.h',
    'cpu_s390.h',
    'cpu_sparc.h',
    'cpu_vax.h',
    'stc.h',
    'stcIntern.h',
    'stcVMdata.h',
    'stcVMoffsets.h',
    'stxAsmMacros.h',
    'stxNames.h',
    'stxOSDefs.h',
    'stxTypeMacros.h',     
    'symbols.stc.seed',
    'version.h',
    'README',

    #unix specific
    'stx-config.sh',
    'linuxIntern.h',
    'macIntern.h',        
    'Make.proto',
    'stc',
    'stc.1',    
  ]
  LIBRUN_BINARY_FILES1 = [    
    'libffi-3.2.1',
    'md5.h',
    'mcompiler.h',
    'main.c',
    'librun.so',
    'librun.a',
    'symlist.c',
    'Make.proto',
    'Makefile',
  ]
  LIBRUN_BINARY_FILES2 = []
elsif win32?
  STC_BINARY_FILES = [    
    'cpu_alpha.h',
    'cpu_arm.h',
    'cpu_hppa.h',
    'cpu_i386.h',
    'cpu_x86_64.h',
    'cpu_ia64.h',
    'cpu_mc68k.h',
    'cpu_mc88k.h',
    'cpu_mips.h',
    'cpu_ns32k.h',
    'cpu_power.h',
    'cpu_s390.h',
    'cpu_sparc.h',
    'cpu_vax.h',
    'stc.h',
    'stcIntern.h',
    'stcVMdata.h',
    'stcVMoffsets.h',
    'stxAsmMacros.h',
    'stxNames.h',
    'stxOSDefs.h',
    'stxTypeMacros.h', 
    'symbols.stc.seed',
    'version.h',
    'README',

    #windows specific
    'stx-config.bat',
    'mingwmake.bat',
    'ntIntern.h',
    'nt.h',
    'Make.proto',
    'stc.exe',
  ]  
  LIBRUN_BINARY_FILES1 = [    
    'libffi-3.2.1',
    'md5.h',
    'mcompiler.h',
    'main.c',
    'objmingw', 
    'bc.mak',
    'mingwmake.bat',
    'buildDate.h',
    'genDate.com',
  ]
  LIBRUN_BINARY_FILES2 = [
    'librun.dll',
    'librun.lib',
  ]
else
  raise Exception.new("Unsupported platform")
end

def cleanup_stc()  
  if should_remove_librun_and_stc_sources()
    puts "Cleaning up stc..."
    begin
      rm_rf_all_in_except(STX_TOP_DIR / 'stc', STC_BINARY_FILES)    
    rescue
      # When something goes wrong, be safe and remove whole directory
      rm_rf STX_TOP_DIR / 'stc'
    end
  end
end

def cleanup_librun()
  if should_remove_librun_and_stc_sources()
    puts "Cleaning up librun..."
    begin
      rm_rf_all_in_except(STX_TOP_DIR / 'librun', LIBRUN_BINARY_FILES1)
      if win32? then
        rm_rf_all_in_except(STX_TOP_DIR / 'librun' / 'objmingw', LIBRUN_BINARY_FILES2)
      end
    rescue
      # When something goes wrong, be safe and remove whole directory
      rm_rf STX_TOP_DIR / 'librun'
    end      
  end
end

# Setup flags for GCC (both, real GCC and MinGW)
GCC_CFLAGS_OPT = ARCH == 'i386' ? '-O' : ''
GCC_CFLAGS_DBG = core_developer? ? '-ggdb3' : ''
GCC_CFLAGS_PIC = win32? ? '' : '-fPIC'
GCC_CFLAGS = "-pipe -fno-omit-frame-pointer -fno-stack-protector -fwrapv #{GCC_CFLAGS_PIC} #{GCC_CFLAGS_OPT} #{GCC_CFLAGS_DBG}"

# Sigh, for MINGW 5.x.x coming with MSYS2 we have to force C language as 
# Borland make and build files are using funny suffixes to confuse GCC's 
# language detection. Triple sigh here!
GCC_CFLAGS += " -x c" if win32?

namespace :'compile' do

  task :'all' => [ :'prereq', :'pre', :'main', :'post' ]

  task :'pre'
  task :'post'

  task :'prereq' => [ :'setup' ]

  task :'main' => [ 
        :'config',
        :'libraries',
        :'stc',       
        :'librun',
        :'application',                
      ]

  task :'config' => STX_TOP_DIR / 'include'

  directory STX_TOP_DIR / 'include'

  case
  when linux?
    task :'config' => [ STX_CONF_DIR / 'vendorConf',
      STX_CONF_DIR / 'myConf' ,
      STX_RULES_DIR / 'stdRules' ]


    task STX_RULES_DIR / 'stdRules' do
      # Sigh, yet another hack here. For a funny reason, target newobj depends on .o files
      # and not on target objs. The problem is that some of the .o may need some third party
      # library being built before (for example, stx:libview2 requires libjpeg-9 being built 
      # before!). To workaround this, we have to patch the rule so it depends on target `objs`
      # which depends on `pre_objs` that builds libraries. Triple sigh here. I should fork rules
      # directory...
      sed('newobj: $(LIBNAME)Init.c $(LINKOBJS)' , 'newobj: $(LIBNAME)Init.c objs $(LINKOBJS)', STX_RULES_DIR / 'stdRules', true)
    end

    task STX_CONF_DIR / 'vendorConf' do
      cp STX_CONF_DIR / 'linux-elf' / 'COMMON' / 'defines' , STX_CONF_DIR / 'vendorConf'
      # Sigh, another hack here. For an unknown reason eXept added -Wl,--wrap=memcpy linker
      # flag. This not only hinders performace [*] but also causes infinite recursion when
      # in use. Wonder if it ever worked. So, yet another hack here: remove the 
      # `--wrap=memcpy` from linker flags.
      #
      # [*] under GCC, memcpy() translates to a rather fast intrinsic. 
      sed(',--wrap=memcpy', '', STX_CONF_DIR / 'vendorConf', true)
    end

    task STX_CONF_DIR / 'myConf' do
      if x86_64? 
        if ARCH == 'x86_64'
          cp STX_CONF_DIR / 'linux-elf' / 'x86_64' / 'defines' , STX_CONF_DIR / 'myConf'
        else
          cp STX_CONF_DIR / 'linux-elf' / 'amd64_mode32' / 'defines' , STX_CONF_DIR / 'myConf'
        end
      else
        cp STX_CONF_DIR / 'linux-elf' / 'opt-cs-oc' / 'defines' , STX_CONF_DIR / 'myConf'
      end

      File.open(STX_CONF_DIR / 'myConf', 'a') do | f |
        if defined? STCCOMMONOPT
          f.puts "STCCOMMONOPT=#{STCCOMMONOPT}"
        end
        f.puts "OPT=#{GCC_CFLAGS}"
        f.puts "LIBRUN_OPT=$(OPT)"
        f.puts "O_RULE=__STANDARD_O_RULE__"
        f.puts "EXTRA_LIBS=-ldl -lX11 -lXext"
        f.puts "XDEFS+=-DHAVE_FONTCONFIG -DXFT"
        f.puts "XINCLUDE+=$(shell pkg-config --cflags xft)"
        f.puts "LIB_XFT=-l:libXft.so.2 -l:libfontconfig.so.1"
        if x86_64? and ARCH == 'x86_64' then
          f.puts 'MAKE_ZLIB_ARG= "CFLAGS=-fPIC -O3 -DUSE_MMAP"'
          # Hack to build FFI for 64-bit Linux builds
          f.puts 'FFI_OBJS=$(FFI_DIR)/build/src/*.o $(FFI_DIR)/build/src/x86/*.o'
          f.puts 'FFI_DIR=libffi-3.0.10rc8'
          f.puts 'OPTIONAL_HAVE_FFI_ARG=-DHAVE_FFI -I$(TOP)/librun/$(FFI_DIR)/build/include'
          f.puts 'OPTIONAL_FFI_TARGET_IN_LIBRUN=ffi'
          f.puts 'FFI_CC="$(CC) -m64 -fPIC"'
          f.puts 'FFI_LD="ld -m elf_x84_64"'
        end
      end
    end
  when win32?
    task :'config' => [ STX_RULES_DIR / 'stdRules_bc_mingwhack.txt' ]

    file STX_RULES_DIR / 'stdRules_bc_mingwhack.txt' do
      File.open( STX_RULES_DIR / 'stdRules_bc', 'a') do | f |
        f.puts "!if defined(USEMINGW32) || defined(USEMINGW64)"
        f.puts "CFLAGS=#{GCC_CFLAGS} $(CFLAGS1) $(CFLAGS2) $(LOCALINCLUDES) $(CLOCAL_INCL) $(CFLAGS_LOCAL)"
        f.puts "!endif"
      end
      File.open( STX_RULES_DIR / 'stdRules_bc_mingwhack.txt', 'a') do | f |
        f.puts "stdRules_bc CFLAGS already fixed"
      end
    end
  else
    error "Unsuported platform: #{Config::CONFIG['host_os']}"
  end

  rule 'makefile' do | t |
    if File.exist?(File.dirname(t.name) / 'GNUmakefile')
  rm (File.dirname(t.name) / 'GNUmakefile')
    end

    chdir File.dirname(t.name) do
      sh "'#{STX_TOP_DIR / 'rules' / 'stmkmf'}'"
    end
  end

  task :stc do
    if linux? and x86_64? and ARCH == 'i386'
      stx_make_flags="STC_LEXLIB=libfl/libfl_pic.a"
    else
      stx_make_flags=""
    end

    chdir STX_TOP_DIR / 'stc' do      
      begin
        make_or_raise_error stx_make_flags
        cleanup_stc()
      rescue Exception => e
        cleanup_stc()
        cleanup_librun()
        error "Cannot compile stx:stc: #{e.description}"
      end  
    end
  
    if not File.exist? STX_TOP_DIR / 'include' / 'stx-config.h' then
      cp STX_TOP_DIR / 'stc' / 'stx-config.h' , STX_TOP_DIR / 'include' / 'stx-config.h'
    end

    if not File.exist? STC
      cleanup_stc()
      cleanup_librun()
      error "Cannot compile stx:stc"
    end
  end

 task :librun do
    chdir STX_TOP_DIR / 'librun' do
      begin
        begin
            if win32_wine?
              if not File.exist? 'libffi' / 'build_win32' / 'objbc'
                mkdir 'libffi' / 'build_win32' / 'objbc'
              end
            end
          make_or_raise_error
          cleanup_librun()
        rescue Exception => e
          cleanup_stc()
          cleanup_librun()
          error "Cannot compile stx:librun: #{e.description}"
        end
      end
    end
  end

  if unix?
    task :stc => STX_TOP_DIR / 'stc' / 'makefile'
    task :librun => STX_TOP_DIR / 'librun' / 'makefile'
  end

  if win32? and TOOLCHAIN == 'bcc'
    directory STX_TOP_DIR / 'lib' / 'bc'
    task :librun => STX_TOP_DIR / 'lib' / 'bc'
  end

  task :'libraries'

  if unix?
    vogl_dir = STX_TOP_DIR / 'support' / 'VGL' / 'vogl'

    task 'libraries' => [ vogl_dir / 'src' / 'libvogl.a' ]

    file vogl_dir / 'src' / 'libvogl.a' => [ vogl_dir / 'makefile'  ] do
      chdir STX_TOP_DIR / 'support' / 'VGL' / 'vogl' do
        make
      end
    end
  end
  
  if win32? and TOOLCHAIN == 'bcc'
    libbc = STX_TOP_DIR / 'lib' / 'bc'

    task :'libraries' => [  libbc / 'cs32i.lib' ,
            libbc / 'stxc32i.lib' ,
            libbc / 'X11omf.lib' ,
            libbc / 'Xextomf.lib' ,
            STX_TOP_DIR / 'support' / 'zlib-1.2.3' / 'objbc' / 'zlib.lib'
         ]

    file libbc / 'cs32i.lib' => libbc do | t |
      cp STX_TOP_DIR / 'support' / 'win32' /  'borland' / (File.basename(t.name)), libbc
    end

    file libbc / 'stxc32i.lib' => libbc do | t |
    cp STX_TOP_DIR / 'support' / 'win32' /  'borland' / (File.basename(t.name)), libbc
    end

    file libbc / 'X11omf.lib' => libbc do | t |
    cp STX_TOP_DIR / 'support' / 'win32' /  'borland' / (File.basename(t.name)), libbc
    end


    file libbc / 'Xextomf.lib' => libbc do | t |
    cp STX_TOP_DIR / 'support' / 'win32' /  'borland' / (File.basename(t.name)), libbc
    end

    directory libbc

    file STX_TOP_DIR / 'support' / 'zlib-1.2.3' / 'objbc' / 'zlib.lib' do
      chdir STX_TOP_DIR / 'support' / 'zlib-1.2.3' do
        make
      end
    end

  end

end


if unix?
    #task :'stx:libview2:pre' => STX_TOP_DIR / 'support' / 'libjpeg-7' / 'libjpeg.a'

    #file STX_TOP_DIR / 'support' / 'libjpeg-7/libjpeg.a' => STX_TOP_DIR / 'support' / 'libjpeg-7' / '.libs' / 'libjpeg.a' do
    #    cp STX_TOP_DIR / 'support' / 'libjpeg-7' / '.libs' / 'libjpeg.a',
    #        STX_TOP_DIR / 'support' / 'libjpeg-7' / 'libjpeg.a'
    #end
    #
    #file STX_TOP_DIR / 'support' / 'libjpeg-7' / '.libs' / 'libjpeg.a' do
    #    chdir STX_TOP_DIR / 'libview2' do
    #        make '../support/libjpeg-7/.libs/libjpeg.a'
    #    end
    #end

end