mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-02-08 16:31:52 +08:00
177 lines
6.9 KiB
Lua
177 lines
6.9 KiB
Lua
|
|
-- This file contains support functions for Tupfile.lua
|
|
|
|
function trim(s)
|
|
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
|
end
|
|
|
|
function string:split(sep)
|
|
local sep, fields = sep or ":", {}
|
|
local pattern = string.format("([^%s]+)", sep)
|
|
self:gsub(pattern, function(c) fields[#fields+1] = c end)
|
|
return fields
|
|
end
|
|
|
|
-- Very basic parser to retrieve variables from a Makefile
|
|
function parse_makefile_vars(makefile)
|
|
vars = {}
|
|
current_var = nil
|
|
for line in io.lines(tup.getcwd()..'/'..makefile) do
|
|
if current_var == nil then
|
|
i,j = string.find(line, "+=")
|
|
if not i then
|
|
i,j = string.find(line, "=")
|
|
end
|
|
if i then
|
|
current_var = trim(string.sub(line, 1, i-1))
|
|
vars[current_var] = vars[current_var] or ''
|
|
line = string.sub(line, j+1, -1)
|
|
--print("varname: "..varname.." the rest: "..line)
|
|
end
|
|
end
|
|
|
|
if current_var != nil then
|
|
--print("append chunk "..trim(line).." to "..current_var)
|
|
vars[current_var] = vars[current_var]..' '..trim(line)
|
|
if string.sub(vars[current_var], -1) == '\\' then
|
|
vars[current_var] = string.sub(vars[current_var], 1, -2)
|
|
else
|
|
current_var = nil
|
|
end
|
|
end
|
|
end
|
|
return vars
|
|
end
|
|
|
|
|
|
|
|
|
|
function GCCToolchain(prefix, builddir, compiler_flags, linker_flags)
|
|
|
|
-- add some default compiler flags
|
|
-- -fstack-usage gives a warning for some functions containing inline assembly (prvPortStartFirstTask in particular)
|
|
-- so for now we just disable it
|
|
calculate_stack_usage = false
|
|
if calculate_stack_usage then
|
|
compiler_flags += '-fstack-usage'
|
|
end
|
|
|
|
gcc_generic_compiler = function(compiler, compiler_flags, gen_su_file, src, flags, includes, outputs)
|
|
-- convert include list to flags
|
|
inc_flags = {}
|
|
for _,inc in pairs(includes) do
|
|
inc_flags += "-I"..inc
|
|
end
|
|
-- todo: vary build directory
|
|
obj_file = builddir.."/"..src:gsub("/","_")..".o"
|
|
outputs.object_files += obj_file
|
|
if gen_su_file then
|
|
su_file = builddir.."/"..src:gsub("/","_")..".su"
|
|
extra_outputs = { su_file }
|
|
outputs.su_files += su_file
|
|
else
|
|
extra_outputs = {}
|
|
end
|
|
if src == 'communication/communication.cpp' then extra_inputs = 'build/version.h' end -- TODO: fix hack
|
|
tup.frule{
|
|
inputs= { src, extra_inputs=extra_inputs },
|
|
command=compiler..' -c %f '..
|
|
tostring(compiler_flags)..' '.. -- CFLAGS for this compiler
|
|
tostring(inc_flags)..' '.. -- CFLAGS for this translation unit
|
|
tostring(flags).. -- CFLAGS for this translation unit
|
|
' -o %o',
|
|
outputs={obj_file,extra_outputs=extra_outputs}
|
|
}
|
|
end
|
|
return {
|
|
compile_c = function(src, flags, includes, outputs) gcc_generic_compiler(prefix..'gcc -std=c99', compiler_flags, calculate_stack_usage, src, flags, includes, outputs) end,
|
|
compile_cpp = function(src, flags, includes, outputs) gcc_generic_compiler(prefix..'g++ -std=c++14', compiler_flags, calculate_stack_usage, src, flags, includes, outputs) end,
|
|
compile_asm = function(src, flags, includes, outputs) gcc_generic_compiler(prefix..'gcc -x assembler-with-cpp', compiler_flags, false, src, flags, includes, outputs) end,
|
|
link = function(objects, output_name)
|
|
output_name = builddir..'/'..output_name
|
|
tup.frule{
|
|
inputs=objects,
|
|
command=prefix..'g++ %f '..
|
|
tostring(linker_flags)..' '..
|
|
'-Wl,-Map=%O.map'..
|
|
' -o %o',
|
|
outputs={output_name..'.elf', extra_outputs={output_name..'.map'}}
|
|
}
|
|
-- display the size
|
|
tup.frule{inputs={output_name..'.elf'}, command=prefix..'size %f'}
|
|
-- generate disassembly
|
|
tup.frule{inputs={output_name..'.elf'}, command=prefix..'objdump %f -dSC > %o', outputs={output_name..'.asm'}}
|
|
-- create *.hex and *.bin output formats
|
|
tup.frule{inputs={output_name..'.elf'}, command=prefix..'objcopy -O ihex %f %o', outputs={output_name..'.hex'}}
|
|
tup.frule{inputs={output_name..'.elf'}, command=prefix..'objcopy -O binary -S %f %o', outputs={output_name..'.bin'}}
|
|
end
|
|
}
|
|
end
|
|
|
|
all_packages = {}
|
|
|
|
-- toolchains: Each element of this list is a collection of functions, such as compile_c, link, ...
|
|
-- You can create a new toolchain object for each platform you want to build for.
|
|
function build(args)
|
|
if args.toolchain == nil then args.toolchain = {} end
|
|
if args.sources == nil then args.sources = {} end
|
|
if args.includes == nil then args.includes = {} end
|
|
if args.packages == nil then args.packages = {} end
|
|
if args.c_flags == nil then args.c_flags = {} end
|
|
if args.cpp_flags == nil then args.cpp_flags = {} end
|
|
if args.asm_flags == nil then args.asm_flags = {} end
|
|
if args.ld_flags == nil then args.ld_flags = {} end
|
|
if args.linker_objects == nil then args.linker_objects = {} end
|
|
|
|
-- add includes of other packages
|
|
for _,pkg_name in pairs(args.packages) do
|
|
--print('depend on package '..pkg_name)
|
|
pkg = all_packages[pkg_name]
|
|
if pkg == nil then
|
|
error("unknown package "..pkg_name)
|
|
end
|
|
-- add path of each include
|
|
for _,inc in pairs(pkg.includes or {}) do
|
|
args.includes += tostring(inc)
|
|
end
|
|
tup.append_table(args.linker_objects, pkg.object_files)
|
|
end
|
|
|
|
-- run everything once for every toolchain
|
|
for _,toolchain in pairs(args.toolchains) do
|
|
-- compile
|
|
outputs = {}
|
|
for _,src in pairs(args.sources) do
|
|
--print("compile "..src)
|
|
if tup.ext(src) == 'c' then
|
|
toolchain.compile_c(src, args.c_flags, args.includes, outputs)
|
|
elseif tup.ext(src) == 'cpp' then
|
|
toolchain.compile_cpp(src, args.cpp_flags, args.includes, outputs)
|
|
elseif tup.ext(src) == 's' or tup.ext(src) == 'asm' then
|
|
toolchain.compile_asm(src, args.asm_flags, args.includes, outputs)
|
|
else
|
|
error('unrecognized file ending')
|
|
end
|
|
end
|
|
|
|
-- link
|
|
if outputs.object_files != nil and args.type != 'objects' then
|
|
tup.append_table(args.linker_objects, outputs.object_files)
|
|
toolchain.link(args.linker_objects, args.name)
|
|
end
|
|
|
|
outputs.includes = {}
|
|
for _,inc in pairs(args.includes) do
|
|
table.insert(outputs.includes, tup.nodevariable(inc))
|
|
end
|
|
if args.name != nil then
|
|
all_packages[args.name] = outputs
|
|
end
|
|
end
|
|
|
|
--for k,v in pairs(all_packages) do
|
|
-- print('have package '..k)
|
|
--end
|
|
end
|
|
|