rakelib/compile.rake
author Jan Vrany <jan.vrany@fit.cvut.cz>
Fri, 21 Sep 2018 23:14:41 +0100
changeset 255 6d6880749905
parent 246 687c4889e2e6
child 261 9312db25c9f8
permissions -rw-r--r--
Add `tmp` to `.hgignore`

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


STX_TOP_DIR = BUILD_DIR / 'stx'
STX_CONF_DIR = BUILD_DIR
STX_RULES_DIR = BUILD_DIR / '..' / 'makelib'
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

# Return true if stx:stc and stx:librun sources should be removed as soon
# as STC or librun is built. False otherwise (sources are not removed by
# rakefiles)
#
# Indeed this is a feeble protection as it's easy to trick this method. But
# the goal is not to protect sources but rather have a secondaty measure to
# avoid sources to leak (for exaple, due to a bug in packaging scripts).
# Unathorized subjects should not be able to checkout sources in first instance.
def should_remove_librun_and_stc_sources
  !(core_developer? or ENV['RETAIN_STX_AND_LIBRUN_SOURCE'] == 'yespleaseretain!')
end

STC_BINARY_FILES = [
    'cpu_arm.h',
    'cpu_i386.h',
    'cpu_x86_64.h',
    'cpu_ia64.h',
    'stc.h',
    'stcIntern.h',
    'stcVMdata.h',
    'stcVMoffsets.h',
    'stxAsmMacros.h',
    'stxNames.h',
    'stxOSDefs.h',
    'stxTypeMacros.h',
    'thinlocks.h',
    'symbols.stc.seed',
    'version.h',
    'sha1.h',
    'sha1.c',
    'README',

    # UNIX specific
    'stx-config.sh',
    'linuxIntern.h',
    'freeBSDIntern.h',
    'macIntern.h',
    'Make.proto',
    'stc',
    'stc.1',

    # Windows specific
    'stx-config.bat',
    'mingwmake.bat',
    'ntIntern.h',
    'nt.h',
    'Make.proto',
    'stc.exe',
]

LIBRUN_BINARY_FILES = [
    'libffi-3.2.1',
    'md5.h',
    'mcompiler.h',
    'main.c',
    'hmm.h',
    'hmm.c',
    'jsupport.h',
    'debug.h',
    'debug.c',
    'librun-gdb.py',

    # UNIX specific
    'librun.so',
    'librun.a',
    'symlist.c',
    'Make.proto',
    'makefile',

    # Windows specific
    'bc.mak',
    'mingwmake.bat',
    'buildDate.h',
    'genDate.com',
    File.join('objmingw' , 'librun.dll'),
    File.join('objmingw' , 'librun.lib'),
]

def cleanup_stc
  if should_remove_librun_and_stc_sources
    puts 'Cleaning up stc...'
    begin
      rm_rf_ex STX_TOP_DIR / 'stc', exceptions: 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_ex STX_TOP_DIR / 'librun', exceptions: LIBRUN_BINARY_FILES
    rescue
      # When something goes wrong, be safe and remove whole directory...
      rm_rf    STX_TOP_DIR / 'librun'
    end
  end
end

namespace :compile do

  task :all => %i(prereq pre main post)

  task :pre
  task :post

  task :prereq => %i(setup)

  task :main => %i(
      config
      stc
      librun
      application
  )

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

  directory STX_TOP_DIR / 'include'

  task :application => :'setup:dependencies'


  task :config => [ STX_CONF_DIR / 'stx-config.make' ]
  task :config => [ BUILD_DIR / 'stx' / 'rules' / 'stmkmf' ] if unix?
  task :config => [ BUILD_DIR / 'stx' / 'rules' / 'stdHeader_bc' ] if win32?
  task :config => [ BUILD_DIR / 'stx' / 'rules' / 'stdRules_bc' ] if win32?


  directory STX_CONF_DIR do
    mkdir_p STX_CONF_DIR
  end

  file STX_CONF_DIR / 'stx-config.make' => STX_CONF_DIR  do
    makelib_dir = Pathname.new(File.expand_path('makelib')).relative_path_from(Pathname.new(BUILD_DIR / 'stx' ))
    File.open(STX_CONF_DIR / 'stx-config.make', 'w') do | f |
      f.puts "BUILD_TARGET ?= #{BUILD_TARGET}"
      if ENV['CC'] != nil then
        f.puts "ifeq ($(origin CC),default)"
        f.puts "  CC = #{CC}"
        f.puts "endif"
      end
    end
  end

  file BUILD_DIR / 'stx' / 'rules' / 'stmkmf' => [ BUILD_DIR / 'stx' / 'rules' ] do
    if not File.exist? BUILD_DIR / 'stx' / 'rules' / 'stmkmf'
      chdir BUILD_DIR / 'stx' / 'rules' do
        # Argh, cannot use ln_s as it cannot make symlinks with relative
        # paths. Sigh,     
        sh "ln -s \'../../../bin/stmkmf.rb\' stmkmf"
      end
    end
  end

  file BUILD_DIR / 'stx' / 'rules' / 'stdHeader_bc' => [ BUILD_DIR / 'stx' / 'rules' ] do
    top = "#{File.absolute_path(BUILD_DIR).gsub("/", "\\")}\\stx"
    File.open(BUILD_DIR / 'stx' / 'rules' / 'stdHeader_bc', "w") do | f |
      f.puts <<-CONTENTS      
# Do not edit! Automatically generated by rake (rakelib/#{File.basename(__FILE__)})
#
!IF !defined(TOP) 
TOP=#{top}
!ENDIF
MAKELIB = $(TOP)\\..\\..\\makelib
!INCLUDE $(MAKELIB)\\definitions-w.make
CONTENTS
    end
  end

  file BUILD_DIR / 'stx' / 'rules' / 'stdRules_bc' => [ BUILD_DIR / 'stx' / 'rules' ] do
    top = "#{File.absolute_path(BUILD_DIR).gsub("/", "\\")}\\stx"
    File.open(BUILD_DIR / 'stx' / 'rules' / 'stdRules_bc', "w") do | f |
      f.puts <<-CONTENTS      
# Do not edit! Automatically generated by rake (specs/#{File.basename(__FILE__)})
#
!IF !defined(TOP) 
TOP=#{top}
!ENDIF
MAKELIB = $(TOP)\\..\\..\\makelib
!INCLUDE $(MAKELIB)\\rules-w.make
CONTENTS
    end        
  end

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

  task :stc do
    chdir STX_TOP_DIR / 'stc' do
      begin
        make
        cleanup_stc
      rescue Exception => e
        cleanup_stc
        cleanup_librun
        error "Cannot compile stx:stc: #{e.message}"
      end
    end

    (cp STX_TOP_DIR / 'stc' / 'stx-config.h', STX_TOP_DIR / 'include' / 'stx-config.h') unless File.exist?(STX_TOP_DIR / 'include' / 'stx-config.h')

    unless 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?
            (mkdir 'libffi' / 'build_win32' / 'objbc') unless File.exist?('libffi' / 'build_win32' / 'objbc')
          end
          # A workaround for Windows 10 & ancient Borland make which
          # tend to crash there when trying to recompile already compiled
          # librun. Sigh, we have to move away from it as soon as possible!
          (touch 'stxmain.c') if (win32? and File.exist? 'stxmain.c')
          make
          cleanup_librun
        rescue Exception => e
          cleanup_stc
          cleanup_librun
          error "Cannot compile stx:librun: #{e.message}"
        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
end


task "stx:librun:symbols"

#
# Various compilation hacks here and there (sigh)
#
desc "Update the VM symbol database"
task 'stx:librun:symbols' do | task |
  symbols_stc = BUILD_DIR / 'stx' / 'include' / 'symbols.stc'
  if unix?
    # UNIX VMs have the symbol database built into the binary as
    # static data so we need to recompile the VM
    stx_librun = project.package('stx:librun')
    stx_librun_dll = BUILD_DIR / stx_librun.directory() / OBJ_DIR / stx_librun.dll_name()

    if not uptodate?(stx_librun_dll, [ symbols_stc ]) then
      Rake::Task["stx:librun"].reenable()
      Rake::Task["stx:librun"].invoke()
    end
  elsif win32?
    # Windows VM reads the symbol database from a file `symbols.stc` located
    # alongside the program executable so we need to copy that file
    app = project.application
    symbols_stc_in_app_directory = BUILD_DIR / app.directory() / 'symbols.stc'
    if not uptodate?(symbols_stc_in_app_directory, [ symbols_stc ]) then
      cp symbols_stc, symbols_stc_in_app_directory
    end
  end
  task.reenable()
end

if unix?
  # A hack for Debian (and possibly other Linux distros) that does not ship
  # 32bit libodbc.a / libodbcinst.a. Link directly against .so
  task :'stx:libdb/libodbc:pre' do
	  sed('-lodbc -lodbcinst' , '-l:libodbc.so.2 -l:libodbcinst.so.2', BUILD_DIR / 'stx' / 'libdb' / 'libodbc' / 'Make.proto', true)
  end
end