class Rmk::LD
Linker tool for creating binaries and shared #libraries
Attributes
query generated executables
linker binary
force linking project library to #libraries
#libraries (base names without prefix or suffix)
library paths
#projects that will be linked
enable #transitive linking for used #projects (#add_project)
use +-Wl,rpath=+ option for shared binaries
Public Class Methods
# File tools/ld.rb, line 34 def initialize super data = tool_params(:LD, generator.configuration) @flags.add(data[:flags]) @ld = data[:ld] @use_rpath = data[:use_rpath] || true @lib_in_lib = data[:lib_in_lib] || false @transitive = data[:transitive] || false @library_paths = [] @libraries = [] @projects = [] end
Public Instance Methods
add a library (or list of #libraries), base name w/o prefix or suffix
# File tools/ld.rb, line 56 def add_library(*lib) @libraries += lib end
add a library path (or list of paths)
# File tools/ld.rb, line 51 def add_path(*path) @library_paths += path end
add a project that should be used/linked
# File tools/ld.rb, line 67 def add_project(proj, options = {}) super(proj, options) return if options[:no_library] cfg = options[:config] || generator.configuration path = generator.proj_build_directory(proj, cfg) add_path(path) lib = generator.proj_library_base_name(proj) add_library(lib) po = @projects.find { |p, _o| p == proj } if !po @projects << [proj, options] else # We don't want to have the same project in different configurations! pocfg = po[1][:config] || generator.configuration if pocfg != cfg @@log.warn "ignore new configuration '#{pocfg}' " \ "for project '#{proj}' (have '#{cfg}')" end end end
# File tools/ld.rb, line 163 def command_link_executable '$ld $ldflags -o $out $in $libs' end
# File tools/ld.rb, line 28 def ld=(cmd) @vendor=nil @ld=cmd end
# File tools/ld.rb, line 150 def libraries_text(with_projlib = true) libs = if lib_object_files.empty? || !with_projlib @libraries else [generator.lib_base_name] + @libraries end (['-Wl,--start-group'] + libs.map { |name| "-l#{name}" } + ['-Wl,--end-group']).join(' ') end
# File tools/ld.rb, line 128 def library_paths_text(with_projlib = true) paths = if with_projlib ['$builddir'] + @library_paths else @library_paths end paths.map do |p| q = if p.to_s =~ /\$builddir/ next if lib_object_files.empty? p else Pathname.new(p).expand_path end if use_rpath "-L#{q} -Wl,-rpath,#{q}" else "-L#{q}" end end.join(' ') end
# File tools/ld.rb, line 180 def ninja_begin(writer = generator.ninja) super transitive_add! if transitive unique! end
# File tools/ld.rb, line 210 def ninja_build(writer = generator.ninja) sublibs = generator.subproject_targets # conservative: build all # add all used project libraries as dependencies # # TODO: Do we want this only for sub-projects? (Which would be a # "heuristic" and does not generally solve the 'no rule' problem # for external dependencies (rationale: order matters only # within subprojects) # projects.each do |p, opts| dir = generator.proj_build_directory(p, opts[:config]) file = generator.proj_shared_object_file_name(p) sublibs << "#{dir}/#{file}" end sublibs = stable_unique(sublibs) unless lib_object_files.empty? lib = "$builddir/#{generator.this_shared_object_file_name}" writer.build(lib, 'ld_shared', lib_object_files, order_only: sublibs) generator.add_to_intermediate_target(:libraries, lib) generator.add_to_toplevel_target(%i[all default], :libraries) end exe_targets = [] exe_object_files.each do |f| base = strip_extension(f) exe = generator.exe(base).to_s writer.build(exe, 'ld_bin', [f], implicit: lib, order_only: sublibs) exe_targets << exe end unless exe_targets.empty? generator.add_to_intermediate_target(:binaries, exe_targets) end @generated_executables = exe_targets shx_targets = [] shx_object_files.each do |f| base = strip_extension(f[:file]) shx = "#{f[:prefix]}#{base}#{f[:suffix]}" writer.build(shx, 'ld_shx', [f[:file]], implicit: lib, order_only: sublibs) shx_targets << shx end unless shx_targets.empty? generator.add_to_intermediate_target(:binaries, shx_targets) end return if exe_targets.empty? && shx_targets.empty? generator.add_to_toplevel_target(%i[all default], :binaries) end
# File tools/ld.rb, line 270 def ninja_end(writer = generator.ninja) super end
# File tools/ld.rb, line 198 def ninja_rules(writer = generator.ninja) writer.rule('ld_shared', command_link_shared_object, description: 'LD $out') writer.rule('ld_bin', command_link_executable, description: 'LD $out') return if shx_object_files.empty? writer.rule('ld_shx', command_link_shared_main_object, description: 'LD $out') end
# File tools/ld.rb, line 186 def ninja_variables(writer = generator.ninja) writer.comment 'LD' writer.variable('ld', @ld) writer.variable('ldflags', flags.text) writer.variable('libs', [library_paths_text, libraries_text]) if lib_in_lib writer.variable('extlibs', [library_paths_text(false), libraries_text(false)]) end writer.newline end
remove #libraries (by pattern)
# File tools/ld.rb, line 61 def remove_library(pattern) pattern = Regexp.new(pattern) unless pattern.is_a?(Regexp) @libraries = @libraries.select { |lib| lib !~ pattern } end
Called by generator: apply #transitive linking. Simple
“transitive linking”: add #libraries and library paths from
other #projects (one hop is
enough as they should store their #libraries). Currently, this works
only on system library level and not on packages level
(generator.use_package).
# File tools/ld.rb, line 105 def transitive_add! @@log.debug 'transitive add libraries' @projects.each do |p, opts| @@log.debug "- from '#{p}' with options=#{opts.inspect}" cfg = opts[:config] || generator.configuration begin plibs = generator.proj_libraries(p, cfg) rescue StandardError => e @@log.error e next end next unless transitive && (opts[:transitive].nil? || opts[:transitive]) @@log.debug " - libraries: #{plibs[:libraries].inspect}" @@log.debug ' - paths: ' \ "#{plibs[:library_paths].map(&:to_s).inspect}" add_library(*plibs[:libraries]) add_path(*plibs[:library_paths]) end end
# File tools/ld.rb, line 93 def unique! @libraries = stable_unique(@libraries) @library_paths = stable_unique_paths(@library_paths) @projects = stable_unique(@projects) end