summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Test/CMock/scripts/create_makefile.rb
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Plus/Test/CMock/scripts/create_makefile.rb')
-rw-r--r--FreeRTOS-Plus/Test/CMock/scripts/create_makefile.rb203
1 files changed, 203 insertions, 0 deletions
diff --git a/FreeRTOS-Plus/Test/CMock/scripts/create_makefile.rb b/FreeRTOS-Plus/Test/CMock/scripts/create_makefile.rb
new file mode 100644
index 000000000..56cb78e90
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/scripts/create_makefile.rb
@@ -0,0 +1,203 @@
+require 'fileutils'
+ABS_ROOT = FileUtils.pwd
+CMOCK_DIR = File.expand_path(ENV.fetch('CMOCK_DIR', File.join(ABS_ROOT, '..', '..')))
+require "#{CMOCK_DIR}/lib/cmock"
+UNITY_DIR = File.join(CMOCK_DIR, 'vendor', 'unity')
+require "#{UNITY_DIR}/auto/generate_test_runner"
+
+SRC_DIR = ENV.fetch('SRC_DIR', './src')
+TEST_DIR = ENV.fetch('TEST_DIR', './test')
+UNITY_SRC = File.join(UNITY_DIR, 'src')
+CMOCK_SRC = File.join(CMOCK_DIR, 'src')
+BUILD_DIR = ENV.fetch('BUILD_DIR', './build')
+TEST_BUILD_DIR = ENV.fetch('TEST_BUILD_DIR', File.join(BUILD_DIR, 'test'))
+OBJ_DIR = File.join(TEST_BUILD_DIR, 'obj')
+UNITY_OBJ = File.join(OBJ_DIR, 'unity.o')
+CMOCK_OBJ = File.join(OBJ_DIR, 'cmock.o')
+RUNNERS_DIR = File.join(TEST_BUILD_DIR, 'runners')
+MOCKS_DIR = File.join(TEST_BUILD_DIR, 'mocks')
+TEST_BIN_DIR = TEST_BUILD_DIR
+MOCK_PREFIX = ENV.fetch('TEST_MOCK_PREFIX', 'mock_')
+MOCK_SUFFIX = ENV.fetch('TEST_MOCK_SUFFIX', '')
+TEST_MAKEFILE = ENV.fetch('TEST_MAKEFILE', File.join(TEST_BUILD_DIR, 'MakefileTestSupport'))
+MOCK_MATCHER = /#{MOCK_PREFIX}[A-Za-z_][A-Za-z0-9_\-\.]+#{MOCK_SUFFIX}/
+
+[TEST_BUILD_DIR, OBJ_DIR, RUNNERS_DIR, MOCKS_DIR, TEST_BIN_DIR].each do |dir|
+ FileUtils.mkdir_p dir
+end
+
+all_headers_to_mock = []
+
+suppress_error = !ARGV.nil? && !ARGV.empty? && (ARGV[0].casecmp('--SILENT') == 0)
+
+File.open(TEST_MAKEFILE, 'w') do |mkfile|
+ # Define make variables
+ mkfile.puts 'CC ?= gcc'
+ mkfile.puts "BUILD_DIR = #{BUILD_DIR}"
+ mkfile.puts "SRC_DIR = #{SRC_DIR}"
+ mkfile.puts "TEST_DIR = #{TEST_DIR}"
+ mkfile.puts 'TEST_CFLAGS ?= -DTEST'
+ mkfile.puts "CMOCK_DIR ?= #{CMOCK_DIR}"
+ mkfile.puts "UNITY_DIR ?= #{UNITY_DIR}"
+ mkfile.puts 'TEST_BUILD_DIR ?= ${BUILD_DIR}/test'
+ mkfile.puts 'TEST_MAKEFILE = ${TEST_BUILD_DIR}/MakefileTestSupport'
+ mkfile.puts 'OBJ ?= ${BUILD_DIR}/obj'
+ mkfile.puts 'OBJ_DIR = ${OBJ}'
+ mkfile.puts ''
+
+ # Build Unity
+ mkfile.puts "#{UNITY_OBJ}: #{UNITY_SRC}/unity.c"
+ mkfile.puts "\t${CC} -o $@ -c $< -I #{UNITY_SRC}"
+ mkfile.puts ''
+
+ # Build CMock
+ mkfile.puts "#{CMOCK_OBJ}: #{CMOCK_SRC}/cmock.c"
+ mkfile.puts "\t${CC} -o $@ -c $< -I #{UNITY_SRC} -I #{CMOCK_SRC}"
+ mkfile.puts ''
+
+ test_sources = Dir["#{TEST_DIR}/**/test_*.c"]
+ test_targets = []
+ generator = UnityTestRunnerGenerator.new
+
+ # headers that begin with prefix or end with suffix are not included
+ all_headers = Dir["#{SRC_DIR}/**/*.h*"]
+
+ def reject_mock_files(file)
+ extn = File.extname file
+ filename = File.basename file, extn
+ if MOCK_SUFFIX.empty?
+ return filename.start_with? MOCK_PREFIX
+ end
+
+ (filename.start_with?(MOCK_PREFIX) || filename.end_with?(MOCK_SUFFIX))
+ end
+
+ all_headers = all_headers.reject { |f| reject_mock_files(f) }
+
+ makefile_targets = []
+
+ test_sources.each do |test|
+ module_name = File.basename(test, '.c')
+ src_module_name = module_name.sub(/^test_/, '')
+ test_obj = File.join(OBJ_DIR, "#{module_name}.o")
+ runner_source = File.join(RUNNERS_DIR, "runner_#{module_name}.c")
+ runner_obj = File.join(OBJ_DIR, "runner_#{module_name}.o")
+ test_bin = File.join(TEST_BIN_DIR, module_name)
+ test_results = File.join(TEST_BIN_DIR, module_name + '.testresult')
+
+ cfg = {
+ src: test,
+ includes: generator.find_includes(File.readlines(test).join(''))
+ }
+
+ # Build main project modules, with TEST defined
+ module_src = File.join(SRC_DIR, "#{src_module_name}.c")
+ module_obj = File.join(OBJ_DIR, "#{src_module_name}.o")
+ unless makefile_targets.include? module_obj
+ makefile_targets.push(module_obj)
+ mkfile.puts "#{module_obj}: #{module_src}"
+ mkfile.puts "\t${CC} -o $@ -c $< ${TEST_CFLAGS} -I ${SRC_DIR} ${INCLUDE_PATH}"
+ mkfile.puts ''
+ end
+
+ # process link-only files
+ linkonly = cfg[:includes][:linkonly]
+ linkonly_objs = []
+ linkonly.each do |linkonlyfile|
+ linkonlybase = File.basename(linkonlyfile, '.*')
+ linkonlymodule_src = File.join(SRC_DIR, linkonlyfile.to_s)
+ linkonlymodule_obj = File.join(OBJ_DIR, "#{linkonlybase}.o")
+ linkonly_objs.push(linkonlymodule_obj)
+ # only create the target if we didn't already
+ next if makefile_targets.include? linkonlymodule_obj
+
+ makefile_targets.push(linkonlymodule_obj)
+ mkfile.puts "#{linkonlymodule_obj}: #{linkonlymodule_src}"
+ mkfile.puts "\t${CC} -o $@ -c $< ${TEST_CFLAGS} -I ${SRC_DIR} ${INCLUDE_PATH}"
+ mkfile.puts ''
+ end
+
+ # Create runners
+ mkfile.puts "#{runner_source}: #{test}"
+ mkfile.puts "\t@UNITY_DIR=${UNITY_DIR} ruby ${CMOCK_DIR}/scripts/create_runner.rb #{test} #{runner_source}"
+ mkfile.puts ''
+
+ # Build runner
+ mkfile.puts "#{runner_obj}: #{runner_source}"
+ mkfile.puts "\t${CC} -o $@ -c $< ${TEST_CFLAGS} -I #{SRC_DIR} -I #{MOCKS_DIR} -I #{UNITY_SRC} -I #{CMOCK_SRC} ${INCLUDE_PATH}"
+ mkfile.puts ''
+
+ # Collect mocks to generate
+ system_mocks = cfg[:includes][:system].select { |name| name =~ MOCK_MATCHER }
+ raise 'Mocking of system headers is not yet supported!' unless system_mocks.empty?
+
+ local_mocks = cfg[:includes][:local].select { |name| name =~ MOCK_MATCHER }
+
+ module_names_to_mock = local_mocks.map { |name| name.sub(/#{MOCK_PREFIX}/, '').to_s }
+ headers_to_mock = []
+ module_names_to_mock.each do |name|
+ header_to_mock = nil
+ all_headers.each do |header|
+ if header =~ /[\/\\]?#{name}$/
+ header_to_mock = header
+ break
+ end
+ end
+ raise "Module header '#{name}' not found to mock!" unless header_to_mock
+
+ headers_to_mock << header_to_mock
+ end
+
+ all_headers_to_mock += headers_to_mock
+ mock_objs = headers_to_mock.map do |hdr|
+ mock_name = MOCK_PREFIX + File.basename(hdr, '.*')
+ File.join(MOCKS_DIR, mock_name + '.o')
+ end
+ all_headers_to_mock.uniq!
+
+ # Build test suite
+ mkfile.puts "#{test_obj}: #{test} #{module_obj} #{mock_objs.join(' ')}"
+ mkfile.puts "\t${CC} -o $@ -c $< ${TEST_CFLAGS} -I #{SRC_DIR} -I #{UNITY_SRC} -I #{CMOCK_SRC} -I #{MOCKS_DIR} ${INCLUDE_PATH}"
+ mkfile.puts ''
+
+ # Build test suite executable
+ test_objs = "#{test_obj} #{runner_obj} #{module_obj} #{mock_objs.join(' ')} #{linkonly_objs.join(' ')} #{UNITY_OBJ} #{CMOCK_OBJ}"
+ mkfile.puts "#{test_bin}: #{test_objs}"
+ mkfile.puts "\t${CC} -o $@ ${LDFLAGS} #{test_objs}"
+ mkfile.puts ''
+
+ # Run test suite and generate report
+ mkfile.puts "#{test_results}: #{test_bin}"
+ mkfile.puts "\t-#{test_bin} > #{test_results} 2>&1"
+ mkfile.puts ''
+
+ test_targets << test_bin
+ end
+
+ # Generate and build mocks
+ all_headers_to_mock.each do |hdr|
+ mock_name = MOCK_PREFIX + File.basename(hdr, '.*')
+ mock_header = File.join(MOCKS_DIR, mock_name + File.extname(hdr))
+ mock_src = File.join(MOCKS_DIR, mock_name + '.c')
+ mock_obj = File.join(MOCKS_DIR, mock_name + '.o')
+
+ mkfile.puts "#{mock_src}: #{hdr}"
+ mkfile.puts "\t@CMOCK_DIR=${CMOCK_DIR} ruby ${CMOCK_DIR}/scripts/create_mock.rb #{hdr}"
+ mkfile.puts ''
+
+ mkfile.puts "#{mock_obj}: #{mock_src} #{mock_header}"
+ mkfile.puts "\t${CC} -o $@ -c $< ${TEST_CFLAGS} -I #{MOCKS_DIR} -I #{SRC_DIR} -I #{UNITY_SRC} -I #{CMOCK_SRC} ${INCLUDE_PATH}"
+ mkfile.puts ''
+ end
+
+ # Create test summary task
+ mkfile.puts 'test_summary:'
+ mkfile.puts "\t@UNITY_DIR=${UNITY_DIR} ruby ${CMOCK_DIR}/scripts/test_summary.rb #{suppress_error ? '--silent' : ''}"
+ mkfile.puts ''
+ mkfile.puts '.PHONY: test_summary'
+ mkfile.puts ''
+
+ # Create target to run all tests
+ mkfile.puts "test: #{test_targets.map { |t| t + '.testresult' }.join(' ')} test_summary"
+ mkfile.puts ''
+end