diff --git a/lib/ceedling/configurator.rb b/lib/ceedling/configurator.rb index c3ff8d3e..52c1db16 100644 --- a/lib/ceedling/configurator.rb +++ b/lib/ceedling/configurator.rb @@ -353,35 +353,47 @@ def standardize_paths(config) def validate(config) - # collect felonies and go straight to jail - raise CeedlingException.new("ERROR: Ceedling configuration failed validation") if (not @configurator_setup.validate_required_sections( config )) - - # collect all misdemeanors, everybody on probation - blotter = [] - blotter << @configurator_setup.validate_required_section_values( config ) - blotter << @configurator_setup.validate_paths( config ) - blotter << @configurator_setup.validate_tools( config ) - blotter << @configurator_setup.validate_threads( config ) - blotter << @configurator_setup.validate_plugins( config ) - - raise CeedlingException.new("ERROR: Ceedling configuration failed validation") if (blotter.include?( false )) + # Collect felonies and go straight to jail + if (not @configurator_setup.validate_required_sections( config )) + raise CeedlingException.new("ERROR: Ceedling configuration failed validation") + end + + # Collect all misdemeanors, everybody on probation + blotter = true + blotter &= @configurator_setup.validate_required_section_values( config ) + blotter &= @configurator_setup.validate_paths( config ) + blotter &= @configurator_setup.validate_tools( config ) + blotter &= @configurator_setup.validate_threads( config ) + blotter &= @configurator_setup.validate_plugins( config ) + + if !blotter + raise CeedlingException.new("ERROR: Ceedling configuration failed validation") + end end - # create constants and accessors (attached to this object) from given hash + # Create constants and accessors (attached to this object) from given hash def build(config, *keys) - # create flattened & expanded configuration hash - built_config = @configurator_setup.build_project_config( config, @configurator_builder.flattenify( config ) ) + flattened_config = @configurator_builder.flattenify( config ) + + @configurator_setup.build_project_config( flattened_config ) + + @configurator_setup.build_directory_structure( flattened_config ) + + # Copy Unity, CMock, CException into vendor directory within build directory + @configurator_setup.vendor_frameworks( flattened_config ) - @project_config_hash = built_config.clone + @configurator_setup.build_project_collections( flattened_config ) + + @project_config_hash = flattened_config.clone store_config() - @configurator_setup.build_constants_and_accessors(built_config, binding()) + @configurator_setup.build_constants_and_accessors( flattened_config, binding() ) - # top-level keys disappear when we flatten, so create global constants & accessors to any specified keys + # Top-level keys disappear when we flatten, so create global constants & accessors to any specified keys keys.each do |key| hash = { key => config[key] } - @configurator_setup.build_constants_and_accessors(hash, binding()) + @configurator_setup.build_constants_and_accessors( hash, binding() ) end end @@ -430,24 +442,6 @@ def build_supplement(config_base, config_more) end - # Many of Configurator's dynamically attached collections are Rake FileLists. - # Rake FileLists are not thread safe with respect to resolving patterns into specific file lists. - # Unless forced, file patterns are resolved upon first access. - # This method forces resolving of all FileList-based collections and can be called in the build - # process at a moment after any file creation operations are complete but before first access - # inside a thread. - # TODO: Remove this once a thread-safe version of FileList has been brought into the project. - def resolve_collections() - collections = self.methods.select { |m| m =~ /^collection_/ } - collections.each do |collection| - ref = self.send(collection.to_sym) - if ref.class == FileList - ref.resolve() - end - end - end - - def insert_rake_plugins(plugins) plugins.each do |plugin| @project_config_hash[:project_rakefile_component_files] << plugin diff --git a/lib/ceedling/configurator_setup.rb b/lib/ceedling/configurator_setup.rb index 2ec29328..35daee01 100644 --- a/lib/ceedling/configurator_setup.rb +++ b/lib/ceedling/configurator_setup.rb @@ -12,7 +12,7 @@ def <=>(other) class ConfiguratorSetup - constructor :configurator_builder, :configurator_validator, :configurator_plugins, :streaminator + constructor :configurator_builder, :configurator_validator, :configurator_plugins, :streaminator, :file_wrapper # Override to prevent exception handling from walking & stringifying the object variables. @@ -23,35 +23,70 @@ def inspect end - def build_project_config(config, flattened_config) + def build_project_config(flattened_config) ### flesh out config - @configurator_builder.cleanup(flattened_config) - @configurator_builder.set_exception_handling(flattened_config) + @configurator_builder.cleanup( flattened_config ) + @configurator_builder.set_exception_handling( flattened_config ) ### add to hash values we build up from configuration & file system contents - flattened_config.merge!(@configurator_builder.set_build_paths(flattened_config)) - flattened_config.merge!(@configurator_builder.set_rakefile_components(flattened_config)) - flattened_config.merge!(@configurator_builder.set_release_target(flattened_config)) - flattened_config.merge!(@configurator_builder.set_build_thread_counts(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_project_options(flattened_config)) + flattened_config.merge!( @configurator_builder.set_build_paths( flattened_config ) ) + flattened_config.merge!( @configurator_builder.set_rakefile_components( flattened_config ) ) + flattened_config.merge!( @configurator_builder.set_release_target( flattened_config ) ) + flattened_config.merge!( @configurator_builder.set_build_thread_counts( flattened_config ) ) + return flattened_config + end + + def build_directory_structure(flattened_config) + flattened_config[:project_build_paths].each do |path| + puts(path) + @file_wrapper.mkdir( path ) + end + end + + def vendor_frameworks(flattened_config) + # Copy Unity C files into build/vendor directory structure + @file_wrapper.cp_r( + # '/.' to cause cp_r to copy directory contents + File.join( flattened_config[:unity_vendor_path], UNITY_LIB_PATH, '/.' ), + flattened_config[:project_build_vendor_unity_path] + ) + + # Copy CMock C files into build/vendor directory structure + @file_wrapper.cp_r( + # '/.' to cause cp_r to copy directory contents + File.join( flattened_config[:cmock_vendor_path], CMOCK_LIB_PATH, '/.' ), + flattened_config[:project_build_vendor_cmock_path] + ) if flattened_config[:project_use_mocks] + + # Copy CException C files into build/vendor directory structure + @file_wrapper.cp_r( + # '/.' to cause cp_r to copy directory contents + File.join( flattened_config[:cexception_vendor_path], CEXCEPTION_LIB_PATH, '/.' ), + flattened_config[:project_build_vendor_cexception_path] + ) if flattened_config[:project_use_exceptions] + end + + def build_project_collections(flattened_config) + flattened_config.merge!( @configurator_builder.collect_project_options( flattened_config ) ) + ### iterate through all entries in paths section and expand any & all globs to actual paths - flattened_config.merge!(@configurator_builder.expand_all_path_globs(flattened_config)) - - flattened_config.merge!(@configurator_builder.collect_vendor_paths(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_source_and_include_paths(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_source_include_vendor_paths(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_test_support_source_include_paths(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_test_support_source_include_vendor_paths(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_tests(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_assembly(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_source(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_headers(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_release_build_input(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_existing_test_build_input(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_release_artifact_extra_link_objects(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_test_fixture_extra_link_objects(flattened_config)) - flattened_config.merge!(@configurator_builder.collect_vendor_framework_sources(flattened_config)) + flattened_config.merge!( @configurator_builder.expand_all_path_globs( flattened_config ) ) + + flattened_config.merge!( @configurator_builder.collect_vendor_paths( flattened_config ) ) + flattened_config.merge!( @configurator_builder.collect_source_and_include_paths( flattened_config ) ) + flattened_config.merge!( @configurator_builder.collect_source_include_vendor_paths( flattened_config ) ) + flattened_config.merge!( @configurator_builder.collect_test_support_source_include_paths( flattened_config ) ) + flattened_config.merge!( @configurator_builder.collect_test_support_source_include_vendor_paths( flattened_config ) ) + flattened_config.merge!( @configurator_builder.collect_tests( flattened_config ) ) + flattened_config.merge!( @configurator_builder.collect_assembly( flattened_config ) ) + flattened_config.merge!( @configurator_builder.collect_source( flattened_config ) ) + flattened_config.merge!( @configurator_builder.collect_headers( flattened_config ) ) + flattened_config.merge!( @configurator_builder.collect_release_build_input( flattened_config ) ) + flattened_config.merge!( @configurator_builder.collect_existing_test_build_input( flattened_config ) ) + flattened_config.merge!( @configurator_builder.collect_release_artifact_extra_link_objects( flattened_config ) ) + flattened_config.merge!( @configurator_builder.collect_test_fixture_extra_link_objects( flattened_config ) ) + flattened_config.merge!( @configurator_builder.collect_vendor_framework_sources( flattened_config ) ) return flattened_config end diff --git a/lib/ceedling/objects.yml b/lib/ceedling/objects.yml index 5f46eeeb..c12e47b8 100644 --- a/lib/ceedling/objects.yml +++ b/lib/ceedling/objects.yml @@ -106,6 +106,7 @@ configurator_setup: - configurator_validator - configurator_plugins - streaminator + - file_wrapper configurator_plugins: compose: diff --git a/lib/ceedling/rules_tests.rake b/lib/ceedling/rules_tests.rake index 3e6df28c..345b5bc9 100644 --- a/lib/ceedling/rules_tests.rake +++ b/lib/ceedling/rules_tests.rake @@ -41,7 +41,7 @@ namespace TEST_SYM do @ceedling[:file_finder].find_test_from_file_path(test) end ]) do |test| - @ceedling[:rake_wrapper][:test_deps].invoke + @ceedling[:rake_wrapper][:directories].invoke @ceedling[:test_invoker].setup_and_invoke(tests:[test.source], options:{:force_run => true, :build_only => false}.merge(TOOL_COLLECTION_TEST_RULES)) end end diff --git a/lib/ceedling/tasks_base.rake b/lib/ceedling/tasks_base.rake index ea297bbe..81eda6f3 100644 --- a/lib/ceedling/tasks_base.rake +++ b/lib/ceedling/tasks_base.rake @@ -48,7 +48,6 @@ end # Non-advertised debug task task :debug do - Rake::Task[:verbosity].invoke(Verbosity::DEBUG) Rake.application.options.trace = true end diff --git a/lib/ceedling/tasks_filesystem.rake b/lib/ceedling/tasks_filesystem.rake index db1f7e46..b27a6c6d 100644 --- a/lib/ceedling/tasks_filesystem.rake +++ b/lib/ceedling/tasks_filesystem.rake @@ -51,7 +51,9 @@ task :directories => PROJECT_BUILD_PATHS # list paths discovered at load time namespace :paths do standard_paths = ['test', 'source', 'include', 'support'] + paths = @ceedling[:setupinator].config_hash[:paths].keys.map{|n| n.to_s.downcase} + paths.each do |name| desc "List all collected #{name} paths." if standard_paths.include?(name) task(name.to_sym) do @@ -68,7 +70,6 @@ end # list files & file counts discovered at load time namespace :files do - categories = ['tests', 'source', 'assembly', 'headers', 'support'] categories.each do |category| diff --git a/lib/ceedling/tasks_release.rake b/lib/ceedling/tasks_release.rake index 4e3e05a4..730c91a5 100644 --- a/lib/ceedling/tasks_release.rake +++ b/lib/ceedling/tasks_release.rake @@ -10,11 +10,6 @@ task RELEASE_SYM => [:directories] do begin @ceedling[:plugin_manager].pre_release - # FileList-based collections are not thread safe. - # Force file pattern resolution before any FileList first accesses inside concurrent threads. - # TODO: Remove this once a thread-safe version of FileList has been brought into the project. - @ceedling[:configurator].resolve_collections() - core_objects = [] extra_objects = @ceedling[:file_path_utils].form_release_build_objects_filelist( COLLECTION_RELEASE_ARTIFACT_EXTRA_LINK_OBJECTS ) diff --git a/lib/ceedling/tasks_tests.rake b/lib/ceedling/tasks_tests.rake index 72350f4f..2f9f2b67 100644 --- a/lib/ceedling/tasks_tests.rake +++ b/lib/ceedling/tasks_tests.rake @@ -1,26 +1,6 @@ require 'ceedling/constants' -task :test_deps => [:directories] do - # Copy Unity C files into build/vendor directory structure - @ceedling[:file_wrapper].cp_r( - # '/.' to cause cp_r to copy directory contents - File.join( UNITY_VENDOR_PATH, UNITY_LIB_PATH, '/.' ), - PROJECT_BUILD_VENDOR_UNITY_PATH ) - - # Copy CMock C files into build/vendor directory structure - @ceedling[:file_wrapper].cp_r( - # '/.' to cause cp_r to copy directory contents - File.join( CMOCK_VENDOR_PATH, CMOCK_LIB_PATH, '/.' ), - PROJECT_BUILD_VENDOR_CMOCK_PATH ) if PROJECT_USE_MOCKS - - # Copy CException C files into build/vendor directory structure - @ceedling[:file_wrapper].cp_r( - # '/.' to cause cp_r to copy directory contents - File.join( CEXCEPTION_VENDOR_PATH, CEXCEPTION_LIB_PATH, '/.' ), - PROJECT_BUILD_VENDOR_CEXCEPTION_PATH ) if PROJECT_USE_EXCEPTIONS -end - -task :test => [:test_deps] do +task :test => [:directories] do Rake.application['test:all'].invoke end @@ -34,7 +14,7 @@ namespace TEST_SYM do } desc "Run all unit tests (also just 'test' works)." - task :all => [:test_deps] do + task :all => [:directories] do @ceedling[:test_invoker].setup_and_invoke( tests:COLLECTION_ALL_TESTS, options:{:force_run => true, :build_only => false}.merge(TOOL_COLLECTION_TEST_TASKS)) @@ -50,12 +30,12 @@ namespace TEST_SYM do end desc "Just build tests without running." - task :build_only => [:test_deps] do + task :build_only => [:directories] do @ceedling[:test_invoker].setup_and_invoke(tests:COLLECTION_ALL_TESTS, options:{:build_only => true}.merge(TOOL_COLLECTION_TEST_TASKS)) end desc "Run tests by matching regular expression pattern." - task :pattern, [:regex] => [:test_deps] do |t, args| + task :pattern, [:regex] => [:directories] do |t, args| matches = [] COLLECTION_ALL_TESTS.each { |test| matches << test if (test =~ /#{args.regex}/) } @@ -68,7 +48,7 @@ namespace TEST_SYM do end desc "Run tests whose test path contains [dir] or [dir] substring." - task :path, [:dir] => [:test_deps] do |t, args| + task :path, [:dir] => [:directories] do |t, args| matches = [] COLLECTION_ALL_TESTS.each { |test| matches << test if File.dirname(test).include?(args.dir.gsub(/\\/, '/')) } diff --git a/lib/ceedling/test_invoker.rb b/lib/ceedling/test_invoker.rb index e05d3854..8a556960 100644 --- a/lib/ceedling/test_invoker.rb +++ b/lib/ceedling/test_invoker.rb @@ -34,11 +34,6 @@ def setup def setup_and_invoke(tests:, context:TEST_SYM, options:{}) # Wrap everything in an exception handler begin - # FileList-based collections are not thread safe. - # Force file pattern resolution before any FileList first accesses inside concurrent threads. - # TODO: Remove this once a thread-safe version of FileList has been brought into the project. - @configurator.resolve_collections() - # Begin fleshing out the testables data structure @batchinator.build_step("Preparing Build Paths", heading: false) do results_path = File.join( @configurator.project_build_root, context.to_s, 'results' ) diff --git a/plugins/bullseye/bullseye.rake b/plugins/bullseye/bullseye.rake index 52d95208..aa78b812 100755 --- a/plugins/bullseye/bullseye.rake +++ b/plugins/bullseye/bullseye.rake @@ -82,7 +82,7 @@ namespace BULLSEYE_SYM do task source_coverage: COLLECTION_ALL_SOURCE.pathmap("#{BULLSEYE_BUILD_OUTPUT_PATH}/%n#{@ceedling[:configurator].extension_object}") desc 'Run code coverage for all tests' - task all: [:test_deps] do + task all: [:directories] do @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config) @ceedling[BULLSEYE_SYM].enableBullseye(true) @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, TOOL_COLLECTION_BULLSEYE_TASKS) @@ -99,7 +99,7 @@ namespace BULLSEYE_SYM do end desc 'Run tests by matching regular expression pattern.' - task :pattern, [:regex] => [:test_deps] do |_t, args| + task :pattern, [:regex] => [:directories] do |_t, args| matches = [] COLLECTION_ALL_TESTS.each do |test| @@ -117,7 +117,7 @@ namespace BULLSEYE_SYM do end desc 'Run tests whose test path contains [dir] or [dir] substring.' - task :path, [:dir] => [:test_deps] do |_t, args| + task :path, [:dir] => [:directories] do |_t, args| matches = [] COLLECTION_ALL_TESTS.each do |test| @@ -135,7 +135,7 @@ namespace BULLSEYE_SYM do end desc 'Run code coverage for changed files' - task delta: [:test_deps] do + task delta: [:directories] do @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config) @ceedling[BULLSEYE_SYM].enableBullseye(true) @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, {:force_run => false}.merge(TOOL_COLLECTION_BULLSEYE_TASKS)) @@ -151,7 +151,7 @@ namespace BULLSEYE_SYM do @ceedling[:file_finder].find_test_from_file_path(test) end ]) do |test| - @ceedling[:rake_wrapper][:test_deps].invoke + @ceedling[:rake_wrapper][:directories].invoke @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config) @ceedling[BULLSEYE_SYM].enableBullseye(true) @ceedling[:test_invoker].setup_and_invoke([test.source], TOOL_COLLECTION_BULLSEYE_TASKS) diff --git a/plugins/dependencies/dependencies.rake b/plugins/dependencies/dependencies.rake index 87ab4b95..2b88714a 100644 --- a/plugins/dependencies/dependencies.rake +++ b/plugins/dependencies/dependencies.rake @@ -144,4 +144,4 @@ namespace :files do end # Make sure that we build dependencies before attempting to tackle any of the unit tests -Rake::Task[:test_deps].enhance ['dependencies:make'] +Rake::Task[:directories].enhance ['dependencies:make'] diff --git a/plugins/gcov/gcov.rake b/plugins/gcov/gcov.rake index c43c3e78..8d688d63 100755 --- a/plugins/gcov/gcov.rake +++ b/plugins/gcov/gcov.rake @@ -29,7 +29,7 @@ task directories: [GCOV_BUILD_OUTPUT_PATH, GCOV_RESULTS_PATH, GCOV_DEPENDENCIES_ namespace GCOV_SYM do desc 'Run code coverage for all tests' - task all: [:test_deps] do + task all: [:directories] do @ceedling[:test_invoker].setup_and_invoke(tests:COLLECTION_ALL_TESTS, context:GCOV_SYM, options:TOOL_COLLECTION_GCOV_TASKS) end @@ -43,7 +43,7 @@ namespace GCOV_SYM do end desc 'Run tests by matching regular expression pattern.' - task :pattern, [:regex] => [:test_deps] do |_t, args| + task :pattern, [:regex] => [:directories] do |_t, args| matches = [] COLLECTION_ALL_TESTS.each do |test| @@ -58,7 +58,7 @@ namespace GCOV_SYM do end desc 'Run tests whose test path contains [dir] or [dir] substring.' - task :path, [:dir] => [:test_deps] do |_t, args| + task :path, [:dir] => [:directories] do |_t, args| matches = [] COLLECTION_ALL_TESTS.each do |test| @@ -80,7 +80,7 @@ namespace GCOV_SYM do @ceedling[:file_finder].find_test_from_file_path(test) end ]) do |test| - @ceedling[:rake_wrapper][:test_deps].invoke + @ceedling[:rake_wrapper][:directories].invoke @ceedling[:test_invoker].setup_and_invoke(tests:[test.source], context:GCOV_SYM, options:TOOL_COLLECTION_GCOV_TASKS) end end