2022-12-08 09:59:02 +07:00

238 lines
8.6 KiB
Ruby

require 'ceedling/plugin'
require 'ceedling/constants'
DEPENDENCIES_ROOT_NAME = 'dependencies'
DEPENDENCIES_TASK_ROOT = DEPENDENCIES_ROOT_NAME + ':'
DEPENDENCIES_SYM = DEPENDENCIES_ROOT_NAME.to_sym
class Dependencies < Plugin
def setup
@plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
# Set up a fast way to look up dependencies by name or static lib path
@dependencies = {}
@dynamic_libraries = []
DEPENDENCIES_LIBRARIES.each do |deplib|
@dependencies[ deplib[:name] ] = deplib.clone
all_deps = get_static_libraries_for_dependency(deplib) +
get_dynamic_libraries_for_dependency(deplib) +
get_include_directories_for_dependency(deplib) +
get_source_files_for_dependency(deplib)
all_deps.each do |key|
@dependencies[key] = @dependencies[ deplib[:name] ]
end
@dynamic_libraries += get_dynamic_libraries_for_dependency(deplib)
end
end
def config
updates = {
:collection_paths_include => COLLECTION_PATHS_INCLUDE,
:collection_all_headers => COLLECTION_ALL_HEADERS,
}
@ceedling[DEPENDENCIES_SYM].get_include_directories_for_dependency(deplib).each do |incpath|
updates[:collection_paths_include] << incpath
Dir[ File.join(incpath, "*#{EXTENSION_HEADER}") ].each do |f|
updates[:collection_all_headers] << f
end
end
return updates
end
def get_name(deplib)
raise "Each dependency must have a name!" if deplib[:name].nil?
return deplib[:name].gsub(/\W*/,'')
end
def get_source_path(deplib)
return deplib[:source_path] || File.join('dependencies', get_name(deplib))
end
def get_build_path(deplib)
return deplib[:build_path] || deplib[:source_path] || File.join('dependencies', get_name(deplib))
end
def get_artifact_path(deplib)
return deplib[:artifact_path] || deplib[:source_path] || File.join('dependencies', get_name(deplib))
end
def get_working_paths(deplib)
paths = [deplib[:source_path], deplib[:build_path], deplib[:artifact_paths]].compact.uniq
paths = [ File.join('dependencies', get_name(deplib)) ] if (paths.empty?)
return paths
end
def get_static_libraries_for_dependency(deplib)
(deplib[:artifacts][:static_libraries] || []).map {|path| File.join(get_artifact_path(deplib), path)}
end
def get_dynamic_libraries_for_dependency(deplib)
(deplib[:artifacts][:dynamic_libraries] || []).map {|path| File.join(get_artifact_path(deplib), path)}
end
def get_source_files_for_dependency(deplib)
(deplib[:artifacts][:source] || []).map {|path| File.join(get_artifact_path(deplib), path)}
end
def get_include_directories_for_dependency(deplib)
paths = (deplib[:artifacts][:includes] || []).map {|path| File.join(get_artifact_path(deplib), path)}
@ceedling[:file_system_utils].collect_paths(paths)
end
def set_env_if_required(lib_path)
blob = @dependencies[lib_path]
raise "Could not find dependency '#{lib_path}'" if blob.nil?
return if (blob[:environment].nil?)
return if (blob[:environment].empty?)
blob[:environment].each do |e|
m = e.match(/^(\w+)\s*(\+?\-?=)\s*(.*)$/)
unless m.nil?
case m[2]
when "+="
ENV[m[1]] = (ENV[m[1]] || "") + m[3]
when "-="
ENV[m[1]] = (ENV[m[1]] || "").gsub(m[3],'')
else
ENV[m[1]] = m[3]
end
end
end
end
def fetch_if_required(lib_path)
blob = @dependencies[lib_path]
raise "Could not find dependency '#{lib_path}'" if blob.nil?
return if (blob[:fetch].nil?)
return if (blob[:fetch][:method].nil?)
return if (directory(blob[:source_path]) && !Dir.empty?(blob[:source_path]))
steps = case blob[:fetch][:method]
when :none
return
when :zip
[ "gzip -d #{blob[:fetch][:source]}" ]
when :git
branch = blob[:fetch][:tag] || blob[:fetch][:branch] || ''
branch = ("-b " + branch) unless branch.empty?
unless blob[:fetch][:hash].nil?
# Do a deep clone to ensure the commit we want is available
retval = [ "git clone #{branch} #{blob[:fetch][:source]} ." ]
# Checkout the specified commit
retval << "git checkout #{blob[:fetch][:hash]}"
else
# Do a thin clone
retval = [ "git clone #{branch} --depth 1 #{blob[:fetch][:source]} ." ]
end
when :svn
revision = blob[:fetch][:revision] || ''
revision = ("--revision " + branch) unless branch.empty?
retval = [ "svn checkout #{revision} #{blob[:fetch][:source]} ." ]
retval
when :custom
blob[:fetch][:executable]
else
raise "Unknown fetch method '#{blob[:fetch][:method].to_s}' for dependency '#{blob[:name]}'"
end
# Perform the actual fetching
@ceedling[:streaminator].stdout_puts("Fetching dependency #{blob[:name]}...", Verbosity::NORMAL)
Dir.chdir(get_source_path(blob)) do
steps.each do |step|
@ceedling[:tool_executor].exec( step )
end
end
end
def build_if_required(lib_path)
blob = @dependencies[lib_path]
raise "Could not find dependency '#{lib_path}'" if blob.nil?
# We don't clean anything unless we know how to fetch a new copy
if (blob[:build].nil? || blob[:build].empty?)
@ceedling[:streaminator].stdout_puts("Nothing to build for dependency #{blob[:name]}", Verbosity::NORMAL)
return
end
# Perform the build
@ceedling[:streaminator].stdout_puts("Building dependency #{blob[:name]}...", Verbosity::NORMAL)
Dir.chdir(get_build_path(blob)) do
blob[:build].each do |step|
@ceedling[:tool_executor].exec( step )
end
end
end
def clean_if_required(lib_path)
blob = @dependencies[lib_path]
raise "Could not find dependency '#{lib_path}'" if blob.nil?
# We don't clean anything unless we know how to fetch a new copy
if (blob[:fetch].nil? || blob[:fetch][:method].nil? || (blob[:fetch][:method] == :none))
@ceedling[:streaminator].stdout_puts("Nothing to clean for dependency #{blob[:name]}", Verbosity::NORMAL)
return
end
# Perform the actual Cleaning
@ceedling[:streaminator].stdout_puts("Cleaning dependency #{blob[:name]}...", Verbosity::NORMAL)
get_working_paths(blob).each do |path|
FileUtils.rm_rf(path) if File.directory?(path)
end
end
def deploy_if_required(lib_path)
blob = @dependencies[lib_path]
raise "Could not find dependency '#{lib_path}'" if blob.nil?
# We don't need to deploy anything if there isn't anything to deploy
if (blob[:artifacts].nil? || blob[:artifacts][:dynamic_libraries].nil? || blob[:artifacts][:dynamic_libraries].empty?)
@ceedling[:streaminator].stdout_puts("Nothing to deploy for dependency #{blob[:name]}", Verbosity::NORMAL)
return
end
# Perform the actual Deploying
@ceedling[:streaminator].stdout_puts("Deploying dependency #{blob[:name]}...", Verbosity::NORMAL)
FileUtils.cp( lib_path, File.dirname(PROJECT_RELEASE_BUILD_TARGET) )
end
def add_headers_and_sources()
# Search for header file paths and files to add to our collections
DEPENDENCIES_LIBRARIES.each do |deplib|
get_include_directories_for_dependency(deplib).each do |header|
cfg = @ceedling[:configurator].project_config_hash
cfg[:collection_paths_include] << header
cfg[:collection_paths_source_and_include] << header
cfg[:collection_paths_test_support_source_include] << header
cfg[:collection_paths_test_support_source_include_vendor] << header
cfg[:collection_paths_release_toolchain_include] << header
Dir[ File.join(header, "*#{EXTENSION_HEADER}") ].each do |f|
cfg[:collection_all_headers] << f
end
end
get_source_files_for_dependency(deplib).each do |source|
cfg = @ceedling[:configurator].project_config_hash
cfg[:collection_paths_source_and_include] << source
cfg[:collection_paths_test_support_source_include] << source
cfg[:collection_paths_test_support_source_include_vendor] << source
cfg[:collection_paths_release_toolchain_include] << source
Dir[ File.join(source, "*#{EXTENSION_SOURCE}") ].each do |f|
cfg[:collection_all_source] << f
end
end
end
# Make all these updated files findable by Ceedling
@ceedling[:file_finder].prepare_search_sources()
end
end
# end blocks always executed following rake run
END {
}