Skip to content

Commit

Permalink
Add suffix options to compiled binaries
Browse files Browse the repository at this point in the history
  • Loading branch information
edubart committed Sep 14, 2019
1 parent 6ecdf5c commit 5206020
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 46 deletions.
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ RUN sudo luarocks-5.1 install --only-deps nelua-dev-1.rockspec
# nelua lua dependencies (5.3)
RUN sudo luarocks-5.3 install --only-deps nelua-dev-1.rockspec

RUN echo "return { binary_suffix = '.out' }" >> .nelua.lua
RUN cp /.nelua.lua /root/.nelua.lua

WORKDIR /nelua
7 changes: 7 additions & 0 deletions nelua/cbuiltins.lua
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,13 @@ end
function functions.require(context, node, emitter)
local scope = context:push_scope('block')
local ast = node.attr.loadedast
if node.attr.runtime_require then
if node.attr.modulename then
node:raisef("compile time module '%s' not found", node.attr.modulename)
else
node:raisef('runtime require is not supported in C backend yet')
end
end
assert(ast)
scope.staticstorage = true
local bracepos = emitter:get_pos()
Expand Down
27 changes: 16 additions & 11 deletions nelua/ccompiler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ local cdefs = require 'nelua.cdefs'

local compiler = {}

local function get_compile_args(infile, outfile, compileopts)
local function get_compile_args(cfile, binfile, compileopts)
local compiler_flags = cdefs.compilers_flags[config.cc] or cdefs.compiler_base_flags
local cflags = sstream(compiler_flags.cflags_base)
cflags:add(' ')
Expand All @@ -32,8 +32,8 @@ local function get_compile_args(infile, outfile, compileopts)
cflags:add(' -l')
cflags:addlist(compileopts.linklibs, ' -l')
end
local env = { infile = infile, outfile = outfile, cflags = cflags:tostring(), cc = config.cc }
return pegger.substitute('$(cc) -o "$(outfile)" "$(infile)" $(cflags)', env)
local env = { cfile = cfile, binfile = binfile, cflags = cflags:tostring(), cc = config.cc }
return pegger.substitute('$(cc) -o "$(binfile)" "$(cfile)" $(cflags)', env)
end

local last_ccinfos = {}
Expand Down Expand Up @@ -77,34 +77,39 @@ function compiler.compile_code(ccode, outfile, compileopts)
end

function compiler.compile_binary(cfile, outfile, compileopts)
local binfile = outfile
if config.binary_suffix then
binfile = outfile .. config.binary_suffix
end

-- if the file with that hash already exists skip recompiling it
if not config.no_cache then
local cfile_mtime = fs.getfiletime(cfile)
local outfile_mtime = fs.getfiletime(outfile)
if cfile_mtime and outfile_mtime and cfile_mtime <= outfile_mtime then
local binfile_mtime = fs.getfiletime(binfile)
if cfile_mtime and binfile_mtime and cfile_mtime <= binfile_mtime then
if not config.quiet then
console.info("using cached binary " .. outfile)
console.info("using cached binary " .. binfile)
end
return outfile
return binfile
end
end

fs.ensurefilepath(outfile)
fs.ensurefilepath(binfile)

-- generate compile command
local cccmd = get_compile_args(cfile, outfile, compileopts)
local cccmd = get_compile_args(cfile, binfile, compileopts)
if not config.quiet then console.info(cccmd) end

-- compile the file
local success, status, stdout, stderr = executor.execex(cccmd)
except.assertraisef(success and status == 0,
"C compilation for '%s' failed:\n%s", outfile, stderr or '')
"C compilation for '%s' failed:\n%s", binfile, stderr or '')

if stderr then
io.stderr:write(stderr)
end

return outfile
return binfile
end

function compiler.get_run_command(binaryfile, runargs)
Expand Down
57 changes: 34 additions & 23 deletions nelua/configer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,45 @@ local configer = {}
local config = {}
local defconfig = {
cc = 'gcc',
generator = 'c',
cflags = '',
lua = 'lua',
lua_version = '5.3',
cache_dir = 'nelua_cache',
standard = 'default',
cpu_bits = 64
}

local function create_parser(argv)
local argparser = argparse("nelua", "Nelua 0.1")
local d = defconfig
argparser:flag('-c --compile', "Compile the generated code only")
argparser:flag('-b --compile-binary', "Compile the generated code and binaries only")
--argparser:option('-o --output', "Output file when compiling")
argparser:flag('-e --eval', 'Evaluate string code from input')
argparser:flag('-l --lint', 'Only check syntax errors')
argparser:flag('-q --quiet', "Don't print any information while compiling")
argparser:flag('--strict', "Compile in strict mode (more checks)")
argparser:flag('-a --analyze', 'Analyze the code only')
argparser:flag('-r --release', 'Release mode build')
argparser:flag('-t --timing', 'Debug compile timing information')
argparser:flag('--no-cache', "Don't use any cached compilation")
argparser:flag('-e --eval', 'Evaluate string code from input', d.eval)
argparser:flag('-l --lint', 'Only check syntax errors', d.lint)
argparser:flag('-q --quiet', "Don't print any information while compiling", d.quiet)
argparser:flag('-s --strict', "Compile in strict mode (more checks)", d.strict)
argparser:flag('-a --analyze', 'Analyze the code only', d.analyze)
argparser:flag('-r --release', 'Release mode build', d.release)
argparser:flag('-t --timing', 'Debug compile timing information', d.timing)
argparser:flag('--no-cache', "Don't use any cached compilation", d.no_cache)
argparser:flag('--print-ast', 'Print the AST only')
argparser:flag('--print-analyzed-ast', 'Print the analyzed AST only')
argparser:flag('--print-code', 'Print the generated code only')
argparser:flag('--no-compile-gc', 'Disable compiler GC (faster but uses more mem)'):action(
function() collectgarbage('stop') end)
argparser:option('-g --generator', "Code generator to use (lua/c)", "c")
argparser:option('-s --standard', "Source standard (default/luacompat)", "default")
argparser:option('--cc', "C compiler to use", defconfig.cc)
argparser:option('--cpu-bits', "Target CPU architecture bit size", defconfig.cpu_bits)
argparser:option('--cflags', "Additional C flags to use on compilation", defconfig.cflags)
argparser:option('--lua', "Lua interpreter to use when runnning", defconfig.lua)
argparser:option('--lua-version', "Target lua version for lua generator", defconfig.lua_version)
argparser:option('--lua-options', "Lua options to use when running")
argparser:option('--cache-dir', "Compilation cache directory", defconfig.cache_dir)
argparser:option('--path', "Nelua modules search path", defconfig.path)
function() collectgarbage('stop') end, d.no_compile_gc)
argparser:option('-g --generator', "Code generator to use (lua/c)", d.generator)
argparser:option('-d --standard', "Source standard (default/luacompat)", d.standard)
argparser:option('--cc', "C compiler to use", d.cc)
argparser:option('--cpu-bits', "Target CPU architecture bit size", d.cpu_bits)
argparser:option('--cflags', "Additional C flags to use on compilation", d.cflags)
argparser:option('--lua', "Lua interpreter to use when runnning", d.lua)
argparser:option('--lua-version', "Target lua version for lua generator", d.lua_version)
argparser:option('--lua-options', "Lua options to use when running", d.lua_options)
argparser:option('--cache-dir', "Compilation cache directory", d.cache_dir)
argparser:option('--path', "Nelua modules search path", d.path)
argparser:option('--binary-suffix', "Binary suffix for the C generator", d.binary_suffix)
argparser:argument("input", "Input source file"):action(function(options, _, v)
-- hacky way to stop handling options
local index = tabler.ifind(argv, v) + 1
Expand Down Expand Up @@ -84,15 +89,21 @@ function configer.get()
end

local function init_default_configs()
defconfig.path = get_path()
defconfig.runtime_path = get_runtime_path()
defconfig.path = os.getenv('NELUA_PATH') or get_path()
defconfig.cache_dir = os.getenv('NELUA_CACHE_DIR') or defconfig.cache_dir
defconfig.lua = os.getenv('LUA') or defconfig.lua
defconfig.cc = os.getenv('CC') or defconfig.cc
defconfig.cflags = os.getenv('CFLAGS')
defconfig.cflags = os.getenv('CFLAGS') or defconfig.cflags
metamagic.setmetaindex(config, defconfig)
end

local function load_home_configs()
local homeconfigfile = fs.join(fs.getuserconfpath(), '.nelua.lua')
if not fs.isfile(homeconfigfile) then return end
local homeconfig = dofile(homeconfigfile)
tabler.update(defconfig, homeconfig)
end

init_default_configs()
load_home_configs()

return configer
8 changes: 2 additions & 6 deletions nelua/typechecker.lua
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ local function builtin_call_require(context, node)
argnode.attr.type and argnode.attr.type:is_string() and
argnode.attr.compconst) then
-- not a compile time require
node:assertraisef(context.state.backend ~= 'c', 'runtime require is not supported in C backend yet')
node.attr.runtime_require = true
return
end

Expand All @@ -902,7 +902,7 @@ local function builtin_call_require(context, node)
local filepath = fs.findmodulefile(modulename, config.path)
if not filepath then
-- maybe it would succeed at runtime
node:assertraisef(context.state.backend ~= 'c', "compile time module '%s' not found", node.attr.modulename)
node.attr.runtime_require = true
return
end
local input = fs.readfile(filepath)
Expand Down Expand Up @@ -1603,10 +1603,6 @@ function typechecker.analyze(ast, parser, parentcontext)
context.parser = parser
context.astbuilder = parser.astbuilder

if not context.state.backend then
context.state.backend = config.generator
end

-- phase 1 traverse: infer and check types
context.phase = phases.type_inference
context:repeat_scope_until_resolution('function', function(scope)
Expand Down
5 changes: 5 additions & 0 deletions nelua/utils/fs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ fs.abspath = plpath.abspath
fs.getbasename = plpath.basename
fs.getpathdir = plpath.dirname
fs.getfiletime = plfile.modified_time
fs.isfile = plpath.isfile

function fs.ensurefilepath(file)
local outdir = plpath.dirname(file)
Expand Down Expand Up @@ -52,6 +53,10 @@ function fs.getdatapath(arg0)
return path
end

function fs.getuserconfpath()
return plpath.expanduser('~')
end

function fs.findmodulefile(name, path)
name = name:gsub('%.', plpath.sep)
local paths = stringer.split(path, ';')
Expand Down
5 changes: 3 additions & 2 deletions spec/06-preprocessor_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,10 @@ end)

it("print config", function()
assert.ast_type_equals([=[
local a = #[config.cc]
## config.test = 'test'
local a = #[config.test]
]=], [[
local a = 'gcc'
local a = 'test'
]])
end)

Expand Down
13 changes: 9 additions & 4 deletions tools/benchmarker.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local argparse = require 'argparse'
local nanotime = require 'chronos'.nanotime
local executor = require 'nelua.utils.executor'
local binary_suffix = '.out'

local benchmarks = {
'ackermann',
Expand Down Expand Up @@ -66,25 +67,29 @@ local function run_benchmark(name)
config.ntimes)
benchmark(
string.format('| %12s | %9s', name, 'nelua c'),
string.format('./nelua_cache/benchmarks/%s', name),
string.format('./nelua_cache/benchmarks/%s%s', name, binary_suffix),
config.ntimes)
benchmark(
string.format('| %12s | %9s', name, 'c'),
string.format('./nelua_cache/benchmarks/c%s', name),
string.format('./nelua_cache/benchmarks/c%s%s', name, binary_suffix),
config.ntimes)
end

local function nelua_compile(name, generator)
local file = 'benchmarks/' .. name .. '.nelua'
local flags = '-q -b -r --lua-version=5.1 --cache-dir nelua_cache --cflags="-march=native"'
local flags = '-q -b -r \
--binary-suffix='..binary_suffix..'\
--lua-version=5.1 \
--cache-dir nelua_cache \
--cflags="-march=native"'
local command = string.format('lua ./nelua.lua %s -g %s %s', flags, generator, file)
local success = executor.exec(command)
assert(success, 'failed to compile nelua benchmark ' .. name)
end

local function c_compile(name)
local cfile = 'benchmarks/c/' .. name .. '.c'
local ofile = 'nelua_cache/benchmarks/c' .. name
local ofile = 'nelua_cache/benchmarks/c' .. name .. binary_suffix
local cflags = "-pipe -Wall -Wextra -rdynamic " ..
"-O2 -fno-plt -flto -march=native -Wl,-O1,--sort-common,-z,relro,-z,now"
local command = string.format('gcc %s -o %s %s', cflags, ofile, cfile)
Expand Down

0 comments on commit 5206020

Please sign in to comment.