rakelib/compile.rake
author Jan Vrany <jan.vrany@fit.cvut.cz>
Sun, 27 Nov 2016 22:57:33 +0000
changeset 87 a4637233f94f
parent 52 bcd6e68aa24e
child 93 650412e81596
child 91 76f23122e86a
permissions -rw-r--r--
Oops, hack to allow passing OPT & LIBRUN_OPT to make from command line Make sure OPT and LIBRUN_OPT is not set forcibly by myConf so it can be set on a command line. We need to tweak them ocasionally, for example to harden options when compiling various librun sources - basically for source files that have been cleaned up to prevent bugs creeping back!. This used to work some time ago but then somebody at eXept hacked makefiles and broke this. Sigh. Sigh. Sigh.


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 -fno-strict-aliasing -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)
      
      # Yet another hack to pass absolute filenames when compiling. This should help Jenkins's 
      # Warning plugin correctly locate files mentioned in compile log - it cannot deal with relative paths
      # (as it cannot track compilation process's working directory, naturally)
      sed(' $(STFILE)', ' $(PWD)/$(STFILE)', 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

      # Make sure OPT and LIBRUN_OPT is not set forcibly in myConf/vendorConf so it can be
      # set on a command line. We need to tweak them ocasionally, for example to
      # harden options when compiling various librun sources - basically for 
      # source files that have been cleaned up to prevent bugs creeping back!.
      # 
      # This used to work some time ago but then somebody at eXept hacked 
      # makefiles and broke this. Sigh. Sigh. Sigh.       
      sed(/^OPT=/, '#OPT=', STX_CONF_DIR / 'myConf', true)
      sed(/^LIBRUN_OPT=/, '#LIBRUN_OPT=', STX_CONF_DIR / 'myConf', true)      
      sed(/^OPT=/, '#OPT=', STX_CONF_DIR / 'vendorConf', true)
      sed(/^LIBRUN_OPT=/, '#LIBRUN_OPT=', STX_CONF_DIR / 'vendorConf', true)

      File.open(STX_CONF_DIR / 'myConf', 'a') do | f |
        if defined? STCCOMMONOPT
          f.puts "STCCOMMONOPT=#{STCCOMMONOPT}"
        end
        f.puts "#"
        f.puts "# following flags are defined in rakelib/compile.rake"
        f.puts "#"
        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