diff --git a/docs/pages/overview.md b/docs/pages/overview.md index c9e766e9..74cd11d2 100644 --- a/docs/pages/overview.md +++ b/docs/pages/overview.md @@ -843,16 +843,15 @@ All Lua operators are provided: {: .table.table-bordered.table-striped.table-sm} All the operators follows Lua semantics, i.e.: -* `%` and `//` rounds the quotient towards minus infinity. -* `///` rounds the quotient towards zero. * `/` and `^` promotes numbers to floats. +* `//` and `%` rounds the quotient towards minus infinity. +* `///` and `%%%` rounds the quotient towards zero. * Integer overflows wrap around. * Bitwise shifts are defined for negative and large shifts. * `and`, `or`, `not`, `==`, `~=` can be used on any variable type. The additional operators over Lua are `>>>`, `///`, `%%%`, `$` and `&`, used for low level programming. - {:.alert.alert-info} ## Functions diff --git a/nelua/ccompiler.lua b/nelua/ccompiler.lua index c0bba6fd..198b042b 100644 --- a/nelua/ccompiler.lua +++ b/nelua/ccompiler.lua @@ -27,6 +27,11 @@ local function get_compiler_cflags(compileopts) cflags:add(' ', config.cflags_debug) end end + if config.shared then + cflags:add(' -shared -fPIC') + elseif config.static then + cflags:add(' -c') + end --luacov:enable if #config.cflags > 0 then cflags:add(' ', config.cflags) @@ -126,19 +131,23 @@ function compiler.compile_code(ccode, outfile, compileopts) return cfile end -local function detect_binary_extension(ccinfo, cflags) +local function detect_binary_extension(ccinfo) --luacov:disable if ccinfo.is_emscripten then return '.html' elseif ccinfo.is_windows then - if cflags:find('-shared') then + if config.shared then return '.dll' + elseif config.static then + return '.a' else return '.exe', true end else - if cflags:find('-shared') then + if config.shared then return '.so' + elseif config.static then + return '.a' else return '', true end @@ -146,10 +155,25 @@ local function detect_binary_extension(ccinfo, cflags) --luacov:enable end +function compiler.compile_static_library(objfile, outfile) + local ar = config.cc:gsub('[a-z]+$', 'ar') + local arcmd = string.format('%s rcs %s %s', ar, outfile, objfile) + if not config.quiet then console.info(arcmd) end + + -- compile the file + local success, status, stdout, stderr = executor.execex(arcmd) + except.assertraisef(success and status == 0, + "static library compilation for '%s' failed:\n%s", outfile, stderr or '') + + if stderr then + io.stderr:write(stderr) + end +end + function compiler.compile_binary(cfile, outfile, compileopts) local cflags = get_compiler_cflags(compileopts) local ccinfo = compiler.get_cc_info() - local binext, isexe = detect_binary_extension(ccinfo, cflags) + local binext, isexe = detect_binary_extension(ccinfo) local binfile = outfile if not stringer.endswith(binfile, binext) then binfile = binfile .. binext end @@ -165,8 +189,12 @@ function compiler.compile_binary(cfile, outfile, compileopts) fs.eensurefilepath(binfile) + local midfile = binfile + if config.static then -- compile to an object first for static libraries + midfile = binfile:gsub('.[a-z]+$', '.o') + end -- generate compile command - local cccmd = get_compile_args(cfile, binfile, cflags) + local cccmd = get_compile_args(cfile, midfile, cflags) if not config.quiet then console.info(cccmd) end -- compile the file @@ -178,6 +206,10 @@ function compiler.compile_binary(cfile, outfile, compileopts) io.stderr:write(stderr) end + if config.static then + compiler.compile_static_library(midfile, binfile) + end + return binfile, isexe end diff --git a/nelua/configer.lua b/nelua/configer.lua index 2389dc92..02b1ee21 100644 --- a/nelua/configer.lua +++ b/nelua/configer.lua @@ -121,6 +121,8 @@ local function create_parser(args) -- argparser:option('--lua-version', "Target lua version for lua generator", defconfig.lua_version) -- argparser:option('--lua-options', "Lua options to use when running", defconfig.lua_options) argparser:flag('--script', "Run lua a script instead of compiling") + argparser:flag('--static', "Compile as a static library") + argparser:flag('--shared', "Compile as a shared library") 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') diff --git a/spec/08-runner_spec.lua b/spec/08-runner_spec.lua index 1f126739..3a41f55c 100644 --- a/spec/08-runner_spec.lua +++ b/spec/08-runner_spec.lua @@ -139,8 +139,8 @@ it("program arguments", function() ]], 'a', 'b', 'c'}) end) -it("C libraries", function() - assert.run({'-o', 'libmylib', 'tests/libmylib.nelua'}) +it("shared libraries", function() + assert.run({'--shared', '-o', 'libmylib', 'tests/libmylib.nelua'}) assert.run({'-o', 'mylib_test', 'tests/mylib_test.nelua'}, [[mylib - init mylib - in top scope mylib - sum @@ -151,4 +151,17 @@ mylib - terminate]]) os.remove('mylib_test') end) +it("static libraries", function() + assert.run({'--static', '-o', 'libmylib', 'tests/libmylib.nelua'}) + assert.run({'-o', 'mylib_test', 'tests/mylib_test.nelua'}, [[mylib - init +mylib - in top scope +mylib - sum +the sum is: +3 +mylib - terminate]]) + os.remove('libmylib.a') + os.remove('libmylib.o') + os.remove('mylib_test') +end) + end) diff --git a/tests/libmylib.nelua b/tests/libmylib.nelua index 13c69a28..28ede12f 100644 --- a/tests/libmylib.nelua +++ b/tests/libmylib.nelua @@ -5,8 +5,6 @@ -- Prefix used when declaring C symbols for this file. -- With this an exported function named 'sum' will be exported as 'mylib_sum' ## pragmas.unitname = 'mylib' --- Compilation flags needed for compiling C libraries. -## cflags '-shared -fPIC' print 'mylib - in top scope'