Skip to content

Commit d1ae0d6

Browse files
authored
New contrib port: lua (#23682)
1 parent 582267f commit d1ae0d6

File tree

6 files changed

+133
-23
lines changed

6 files changed

+133
-23
lines changed

ChangeLog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ See docs/process.md for more on how version tagging works.
2525
- The `--output_eol` command line flag was renamed `--output-eol` for
2626
consistency with other flags. The old name continues to work as an alias.
2727
(#20735)
28+
- Added Lua contrib port (`--use-port=contrib.lua`) to easily embed the Lua
29+
scripting language in any C/C++ Emscripten project (#23682)
2830

2931
4.0.3 - 02/07/25
3032
----------------

site/source/docs/compiling/Contrib-Ports.rst

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,53 @@ available in emscripten. In order to use a contrib port you use the
1717
contrib.glfw3
1818
=============
1919

20-
This project is an emscripten port of GLFW written in C++ for the
20+
This project is an Emscripten port of GLFW written in C++ for the
2121
web/webassembly platform.
2222

2323
.. note::
24-
emscripten includes support for both GLFW 2 and 3 written in Javascript.
24+
Emscripten includes support for both GLFW 2 and 3 written in Javascript.
2525
These can be activated with the :ref:`settings <use_glfw>` ``-sUSE_GLFW=2``
2626
and ``-sUSE_GLFW=3``. This non-official contribution, written in C++,
2727
provides a more extensive and up-to-date implementation of the GLFW 3 API
2828
than the built-in port. It is enabled with the option
2929
``--use-port=contrib.glfw3``.
3030

31-
`Project information <https://github.com/pongasoft/emscripten-glfw>`_
31+
`Project information <https://github.com/pongasoft/emscripten-glfw>`__
3232

33-
License: Apache 2.0 license
33+
License: Apache 2.0 license
34+
35+
.. _contrib.lua:
36+
37+
contrib.lua
38+
===========
39+
40+
Lua is a powerful, efficient, lightweight, embeddable scripting language.
41+
42+
Example usage:
43+
44+
.. code-block:: text
45+
46+
// main.c
47+
#include <lua.h>
48+
#include <lualib.h>
49+
#include <lauxlib.h>
50+
#include <stdio.h>
51+
52+
int main() {
53+
lua_State *L = luaL_newstate();
54+
luaL_openlibs(L);
55+
if (luaL_dostring(L, "print('hello world')") != LUA_OK) {
56+
printf("Error running Lua code %s\n", lua_tostring(L, -1));
57+
lua_pop(L, 1);
58+
}
59+
lua_close(L);
60+
return 0;
61+
}
62+
63+
// compile with
64+
emcc --use-port=contrib.lua main.c -o /tmp/index.html
65+
66+
67+
`Project information <https://www.lua.org/>`__
68+
69+
License: MIT License

test/other/test_port_contrib_lua.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2025 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
#include <lua.h>
9+
#include <lualib.h>
10+
#include <lauxlib.h>
11+
#include <stdio.h>
12+
13+
int main() {
14+
// Create a new Lua state
15+
lua_State *L = luaL_newstate();
16+
17+
// Load standard Lua libraries
18+
luaL_openlibs(L);
19+
20+
char const *chunks[3] = {
21+
"print('hello world')", // test Basic Library
22+
"print(string.upper('hello world'))", // test string library
23+
"print('sqrt(16)=' .. math.tointeger(math.sqrt(16)))", // test math library
24+
};
25+
26+
// Iterate over each chunk of Lua code and execute it
27+
for (size_t i = 0; i <= 3; i++) {
28+
if (luaL_dostring(L, chunks[i]) != LUA_OK) {
29+
printf("Error running Lua code: %s\n", lua_tostring(L, -1));
30+
lua_pop(L, 1); // Remove the error message from the stack
31+
lua_close(L);
32+
return 1; // returning error so the test can fail
33+
}
34+
}
35+
36+
// Close the Lua state
37+
lua_close(L);
38+
39+
return 0;
40+
}

test/test_core.py

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6598,25 +6598,6 @@ def test_gcc_unmangler(self):
65986598

65996599
self.do_runf('third_party/libiberty/cp-demangle.c', '*d_demangle(char const*, int, unsigned int*)*', args=['_ZL10d_demanglePKciPj'])
66006600

6601-
@needs_make('make')
6602-
@crossplatform
6603-
def test_lua(self):
6604-
self.emcc_args.remove('-Werror')
6605-
env_init = {
6606-
'SYSCFLAGS': ' '.join(self.get_emcc_args(compile_only=True)),
6607-
'SYSLDFLAGS': ' '.join(self.get_emcc_args())
6608-
}
6609-
libs = self.get_library('third_party/lua',
6610-
['src/lua.o', 'src/liblua.a'],
6611-
make=['make', 'echo', 'generic'],
6612-
env_init=env_init,
6613-
configure=None)
6614-
self.do_run('',
6615-
'hello lua world!\n17\n1\n2\n3\n4\n7',
6616-
args=['-e', '''print("hello lua world!");print(17);for x = 1,4 do print(x) end;print(10-3)'''],
6617-
libraries=libs,
6618-
includes=[test_file('lua')])
6619-
66206601
@no_asan('issues with freetype itself')
66216602
@needs_make('configure script')
66226603
@is_slow_test

test/test_other.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2624,6 +2624,10 @@ def test_external_ports(self):
26242624
More info: https://emscripten.org
26252625
''', stdout)
26262626

2627+
@requires_network
2628+
def test_port_contrib_lua(self):
2629+
self.do_runf('other/test_port_contrib_lua.c', 'hello world\nHELLO WORLD\nsqrt(16)=4\n', emcc_args=['--use-port=contrib.lua'])
2630+
26272631
def test_link_memcpy(self):
26282632
# memcpy can show up *after* optimizations, so after our opportunity to link in libc, so it must be special-cased
26292633
create_file('main.c', r'''

tools/ports/contrib/lua.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Copyright 2025 The Emscripten Authors. All rights reserved.
2+
# Emscripten is available under two separate licenses, the MIT license and the
3+
# University of Illinois/NCSA Open Source License. Both these licenses can be
4+
# found in the LICENSE file.
5+
6+
import os
7+
8+
TAG = '5.4.7'
9+
HASH = '98c5c8978dfdf867e37e9eb3b3ec83dee92d199243b5119505da83895e33f10d43c841be6a7d3b106daba8a0b2bd25fe099ebff8f87831dcc55c79c78b97d8b8'
10+
11+
# contrib port information (required)
12+
URL = 'https://www.lua.org/'
13+
DESCRIPTION = 'Lua is a powerful, efficient, lightweight, embeddable scripting language'
14+
LICENSE = 'MIT License'
15+
16+
port_name = 'contrib.lua'
17+
lib_name = 'liblua.a'
18+
19+
20+
def get(ports, settings, shared):
21+
# get the port
22+
ports.fetch_project(port_name, f'https://www.lua.org/ftp/lua-{TAG}.tar.gz', sha512hash=HASH)
23+
24+
def create(final):
25+
root_path = os.path.join(ports.get_dir(), port_name, f'lua-{TAG}')
26+
source_path = os.path.join(root_path, 'src')
27+
28+
# install headers
29+
includes = ['lua.h', 'lua.hpp', 'luaconf.h', 'lauxlib.h', 'lualib.h']
30+
for f in includes:
31+
ports.install_headers(source_path, pattern=f)
32+
33+
srcs = '''
34+
lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c
35+
lparser.c lstate.c lstring.c ltable.c ltm.c lundump.c lvm.c lzio.c lauxlib.c lbaselib.c lcorolib.c
36+
ldblib.c liolib.c lmathlib.c loadlib.c loslib.c lstrlib.c ltablib.c lutf8lib.c linit.c
37+
'''.split()
38+
39+
flags = ['-DLUA_COMPAT_5_3']
40+
41+
ports.build_port(source_path, final, port_name, srcs=srcs, flags=flags)
42+
43+
return [shared.cache.get_lib(lib_name, create, what='port')]
44+
45+
46+
def clear(ports, settings, shared):
47+
shared.cache.erase_lib(lib_name)

0 commit comments

Comments
 (0)