class Cxxproject::Linkable

Public Class Methods

new(name) click to toggle source
Calls superclass method Cxxproject::BuildingBlock::new
# File lib/cxxproject/buildingblocks/linkable.rb, line 30
def initialize(name)
  super(name)
  @linker_script = nil
  @mapfile = nil
end

Public Instance Methods

adapt_path(v, d, prefix) click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 75
def adapt_path(v, d, prefix)
  tmp = nil
  if File.is_absolute?(v)
    tmp = v
  else
    prefix ||= File.rel_from_to_project(@project_dir, d.project_dir)
    tmp = File.add_prefix(prefix, v)
  end
  [tmp, prefix]
end
calc_command_line() click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 162
def calc_command_line
  linker = @tcs[:LINKER]
  cmd = [linker[:COMMAND]] # g++
  cmd += linker[:MUST_FLAGS].split(" ")
  cmd += linker[:FLAGS]
  cmd += get_flags_for_output(linker)
  cmd << executable_name() # debug/x.exe # OK
  cmd += @objects
  cmd << linker[:SCRIPT] if @linker_script # -T
  cmd << @linker_script if @linker_script # xy/xy.dld
  cmd << linker[:MAP_FILE_FLAG] if @mapfile # -Wl,-m6
  cmd += linker[:LIB_PREFIX_FLAGS].split(" ") # TODO ... is this still needed e.g. for diab
  cmd += linker_lib_string(target_os(), @tcs[:LINKER])
  cmd += linker[:LIB_POSTFIX_FLAGS].split(" ") # TODO ... is this still needed e.g. for diab
  cmd
end
cmd_lib_string(target_os) click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 93
def cmd_lib_string(target_os)
  libraries=''
  deps.each do |d|
    if HasLibraries === d
      d.lib_elements.each do |elem|
        case elem[0]
        when HasLibraries::SEARCH_PATH
          tmp, prefix = adapt_path(elem[1], d, prefix)
          libraries << tmp
          libraries << File::PATH_SEPARATOR
        end
      end
    end
  end
  libraries
end
collect_unique(array, set) click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 65
def collect_unique(array, set)
  ret = []
  array.each do |v|
    if set.add?(v)
      ret << v
    end
  end
  ret
end
convert_to_rake() click to toggle source

create a task that will link an executable from a set of object files

# File lib/cxxproject/buildingblocks/linkable.rb, line 181
def convert_to_rake()
  object_multitask = prepare_tasks_for_objects()

  res = typed_file_task get_rake_task_type(), get_task_name => object_multitask do
    cmd = calc_command_line
    Dir.chdir(@project_dir) do
      mapfileStr = @mapfile ? " >#{@mapfile}" : ""
      rd, wr = IO.pipe
      cmdLinePrint = cmd
      printCmd(cmdLinePrint, "Linking #{executable_name}", false) #OK
      cmd << {
        :out=> @mapfile ? "#{@mapfile}" : wr, # > xy.map
        :err=>wr
      }
      sp = spawn(*cmd)
      cmd.pop
      # for console print
      cmd << " >#{@mapfile}" if @mapfile
      consoleOutput = ProcessHelper.readOutput(sp, rd, wr)

      process_result(cmdLinePrint, consoleOutput, @tcs[:LINKER][:ERROR_PARSER], nil)
      check_config_file()
      post_link_hook(@tcs[:LINKER])
    end
  end
  res.tags = tags
  res.immediate_output = true
  res.enhance(@config_files)
  res.enhance([@project_dir + "/" + @linker_script]) if @linker_script

  add_output_dir_dependency(get_task_name, res, true)
  add_grouping_tasks(get_task_name)
  setup_rake_dependencies(res, object_multitask)

  # check that all source libs are checked even if they are not a real rake dependency (can happen if "build this project only")
  begin
    libChecker = task get_task_name+"LibChecker" do
      if File.exists?(get_task_name) # otherwise the task will be executed anyway
        all_dependencies.each do |bb|
          if bb and StaticLibrary === bb
            f = bb.get_task_name # = abs path of library
            if not File.exists?(f) or File.mtime(f) > File.mtime(get_task_name)
              def res.needed?
                true
              end
              break
            end
          end
        end
      end
    end
  rescue
    def res.needed?
      true
    end
  end
  libChecker.transparent_timestamp = true
  res.enhance([libChecker])

  return res
end
create_run_task(executable, name) click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 243
def create_run_task(executable, name)
  namespace 'run' do
    desc "run executable #{executable}"
    res = task name => executable do |t|
      lib_var = @tcs[:ENV][:LIB_VAR][@tcs[:TARGET_OS]]
      if lib_var != ''
        ENV[lib_var] = cmd_lib_string(@tcs[:TARGET_OS])
      end
      sh ["\"#{executable}\"", ENV['args']].compact.join(' ')
    end
    res.type = Rake::Task::RUN
    res
  end
end
deps() click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 86
def deps # OK
  if @deps == nil
    @deps = collect_dependencies
  end
  @deps
end
executable_name() click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 45
def executable_name() # relative path OK
  return @exe_name if @exe_name

  parts = [@output_dir]

  if @output_dir_abs
    parts = [@output_dir_relPath] if @output_dir_relPath
    parts += additional_path_components()
  end
  linker = @tcs[:LINKER]
  parts << get_output_name(linker)

  @exe_name = File.join(parts)
  @exe_name
end
get_output_name(linker) click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 40
def get_output_name(linker)
  prefix = get_output_prefix(linker)
  suffix = get_output_suffix(linker)
  return "#{prefix}#{name}#{suffix}"
end
get_task_name() click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 61
def get_task_name() # full path
  @project_dir + "/" + executable_name # OK
end
get_temp_filename() click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 258
def get_temp_filename
  Dir.tmpdir + "/lake.tmp"
end
handle_whole_archive(building_block, res, linker, flag) click to toggle source

res the array with command line arguments that is used as result linker the linker hash sym the symbol that is used to fish out a value from the linker

# File lib/cxxproject/buildingblocks/linkable.rb, line 152
def handle_whole_archive(building_block, res, linker, flag)
  if is_whole_archive(building_block)
    res.push(flag) if flag and !flag.empty?
  end
end
is_whole_archive(building_block) click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 158
def is_whole_archive(building_block)
  return building_block.instance_of?(StaticLibrary) && building_block.whole_archive
end
linker_lib_string(target_os, linker) click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 110
def linker_lib_string(target_os, linker)
  lib_path_set = Set.new
  res = []
  deps.each do |d|
    handle_whole_archive(d, res, linker, linker[:START_OF_WHOLE_ARCHIVE][target_os])
    if HasLibraries === d and d != self #OK
      d.lib_elements.each do |elem|
        case elem[0]
        when HasLibraries::LIB
          if not is_whole_archive(d)
            res.push("#{linker[:LIB_FLAG]}#{elem[1]}")
          end
        when HasLibraries::USERLIB
          res.push("#{linker[:USER_LIB_FLAG]}#{elem[1]}")
        when HasLibraries::LIB_WITH_PATH
          if is_whole_archive(d)
            res.push(d.get_archive_name)
          else
            tmp, prefix = adapt_path(elem[1], d, prefix)
            res.push(tmp)
          end
        when HasLibraries::SEARCH_PATH
          if is_whole_archive(d)
            res.push(d.get_archive_name)
          else
            tmp, prefix = adapt_path(elem[1], d, prefix)
            if not lib_path_set.include?(tmp)
              lib_path_set << tmp
              res.push("#{linker[:LIB_PATH_FLAG]}#{tmp}")
            end
          end
        end
      end
    end
    handle_whole_archive(d, res, linker, linker[:END_OF_WHOLE_ARCHIVE][target_os])
  end
  res
end
no_sources_found() click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 262
def no_sources_found()
end
set_executable_name(name) click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 36
def set_executable_name(name) # ensure it's relative
  @exe_name = name
end
set_linker_script(x) click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 20
def set_linker_script(x)
  @linker_script = x
  self
end
set_mapfile(x) click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 25
def set_mapfile(x)
  @mapfile = x
  self
end
target_os() click to toggle source
# File lib/cxxproject/buildingblocks/linkable.rb, line 265
def target_os
  @tcs[:TARGET_OS]
end