summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIndrajith K L2025-11-10 01:58:00 +0530
committerIndrajith K L2025-11-10 01:58:25 +0530
commitd9d1a8a51ea7cd7e7076724918008b6adb1302ca (patch)
tree59a8f258c9bb4db4edafc2c70993319e3c3c859c
parent8c9367f3689aee05d33fc1cae8a5d1aa6d2b5fb8 (diff)
downloadreilua-enhanced-d9d1a8a51ea7cd7e7076724918008b6adb1302ca.tar.gz
reilua-enhanced-d9d1a8a51ea7cd7e7076724918008b6adb1302ca.tar.bz2
reilua-enhanced-d9d1a8a51ea7cd7e7076724918008b6adb1302ca.zip
Add flexible module loading and complete file embedding
- Support any folder structure (no hard-coded folders) - Embed all file types recursively from any folder - Fix require() dot-to-slash conversion for embedded modules - Clean build folder for fresh builds every time - Generate empty headers for Lua-only projects Backward compatible with existing projects.
-rw-r--r--CMakeLists.txt55
-rw-r--r--scripts/build_dev.bat54
-rwxr-xr-xscripts/build_dev.sh46
-rw-r--r--scripts/build_release.bat69
-rwxr-xr-xscripts/build_release.sh96
-rw-r--r--scripts/create_empty_assets.py24
-rw-r--r--scripts/embed_assets.py40
-rw-r--r--scripts/embed_lua.py40
-rw-r--r--src/lua_core.c65
9 files changed, 283 insertions, 206 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index aef831d..603c8f6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -97,15 +97,15 @@ if( WIN32 )
list( APPEND SOURCES ${CMAKE_SOURCE_DIR}/resources.rc )
endif()
-# Embed Lua files if EMBED_MAIN is ON
+# Embed Lua files if EMBED_MAIN is ON (recursively from all subdirectories)
if( EMBED_MAIN )
- file( GLOB LUA_FILES "${CMAKE_CURRENT_BINARY_DIR}/*.lua" )
+ file( GLOB_RECURSE LUA_FILES "${CMAKE_CURRENT_BINARY_DIR}/*.lua" )
if( LUA_FILES )
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/embedded_main.h
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/embed_lua.py ${CMAKE_CURRENT_BINARY_DIR}/embedded_main.h ${LUA_FILES}
DEPENDS ${LUA_FILES}
- COMMENT "Embedding Lua files into executable..."
+ COMMENT "Embedding Lua files from all subdirectories into executable..."
)
list( APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/embedded_main.h )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DEMBED_MAIN" )
@@ -114,21 +114,60 @@ if( EMBED_MAIN )
endif()
endif()
-# Embed asset files if EMBED_ASSETS is ON
+# Embed all non-Lua data files if EMBED_ASSETS is ON (from all subdirectories except CMake dirs)
+# Always create embedded_assets.h to prevent compilation errors
if( EMBED_ASSETS )
- file( GLOB_RECURSE ASSET_FILES "${CMAKE_CURRENT_BINARY_DIR}/assets/*" )
+ # Find all non-Lua files recursively, excluding build system files
+ file( GLOB_RECURSE ALL_DATA_FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/*"
+ )
+ # Filter out unwanted files
+ set( ASSET_FILES "" )
+ foreach( FILE_PATH ${ALL_DATA_FILES} )
+ # Exclude: .lua files (handled separately), build artifacts, and CMake files
+ if( NOT FILE_PATH MATCHES "\\.lua$"
+ AND NOT FILE_PATH MATCHES "CMakeFiles"
+ AND NOT FILE_PATH MATCHES "\\.cmake$"
+ AND NOT FILE_PATH MATCHES "CMakeCache"
+ AND NOT FILE_PATH MATCHES "Makefile$"
+ AND NOT FILE_PATH MATCHES "\\.a$"
+ AND NOT FILE_PATH MATCHES "\\.o$"
+ AND NOT FILE_PATH MATCHES "embedded_.*\\.h$"
+ AND NOT FILE_PATH MATCHES "\\.exe$"
+ AND NOT FILE_PATH MATCHES "ReiLua$" )
+ list( APPEND ASSET_FILES ${FILE_PATH} )
+ endif()
+ endforeach()
+
if( ASSET_FILES )
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/embedded_assets.h
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/embed_assets.py ${CMAKE_CURRENT_BINARY_DIR}/embedded_assets.h ${ASSET_FILES}
DEPENDS ${ASSET_FILES}
- COMMENT "Embedding asset files into executable..."
+ COMMENT "Embedding data files from all subdirectories into executable..."
)
- list( APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/embedded_assets.h )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DEMBED_ASSETS" )
+ message( STATUS "Embedding ${CMAKE_CURRENT_BINARY_DIR}/embedded_assets.h with asset files" )
else()
- message( WARNING "EMBED_ASSETS is ON but no files found in build/assets/ directory!" )
+ # Create empty embedded_assets.h to prevent compilation errors
+ message( STATUS "EMBED_ASSETS is ON but no data files found, creating empty embedded_assets.h" )
+ add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/embedded_assets.h
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/create_empty_assets.py ${CMAKE_CURRENT_BINARY_DIR}/embedded_assets.h
+ COMMENT "Creating empty embedded_assets.h (no data files to embed)"
+ )
+ set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DEMBED_ASSETS" )
endif()
+ list( APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/embedded_assets.h )
+else()
+ # EMBED_ASSETS is OFF - create empty header for compatibility
+ message( STATUS "EMBED_ASSETS is OFF, creating empty embedded_assets.h" )
+ add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/embedded_assets.h
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/create_empty_assets.py ${CMAKE_CURRENT_BINARY_DIR}/embedded_assets.h
+ COMMENT "Creating empty embedded_assets.h (EMBED_ASSETS is OFF)"
+ )
+ list( APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/embedded_assets.h )
endif()
add_executable( ${PROJECT_NAME} ${SOURCES} )
diff --git a/scripts/build_dev.bat b/scripts/build_dev.bat
index 40f394e..a1995d6 100644
--- a/scripts/build_dev.bat
+++ b/scripts/build_dev.bat
@@ -18,60 +18,25 @@ if errorlevel 1 (
exit /b 1
)
-REM Clean old embedded files (important for dev builds!)
-echo Cleaning old embedded files...
-del /Q embedded_main.h embedded_assets.h 2>nul
-
-REM Warn about Lua files in build directory
-dir /b *.lua >nul 2>&1
-if not errorlevel 1 (
- echo.
- echo WARNING: Found Lua files in build directory!
- echo Development builds should load from file system, not embed.
- echo.
- dir /b *.lua
- echo.
- set /p REMOVE="Remove these files from build directory? (Y/n): "
- if /i not "%REMOVE%"=="n" (
- del /Q *.lua
- echo Lua files removed.
- )
- echo.
-)
-
-REM Warn about assets folder in build directory
-if exist "assets" (
- echo.
- echo WARNING: Found assets folder in build directory!
- echo Development builds should load from file system, not embed.
- echo.
- set /p REMOVE="Remove assets folder from build directory? (Y/n): "
- if /i not "%REMOVE%"=="n" (
- rmdir /S /Q assets
- echo Assets folder removed.
- )
- echo.
-)
-
-REM Clean old configuration if requested
-if "%1"=="clean" (
- echo Cleaning build directory...
- del /Q CMakeCache.txt *.o *.a 2>nul
- rmdir /S /Q CMakeFiles 2>nul
- echo Clean complete!
- echo.
-)
+REM ALWAYS clean build folder for fresh build
+echo Cleaning build directory for fresh build...
+del /Q /S * >nul 2>&1
+for /d %%p in (*) do rmdir "%%p" /s /q >nul 2>&1
+echo * Build directory cleaned
+echo.
-REM Configure with MinGW
+REM Configure
echo Configuring CMake for development...
cmake -G "MinGW Makefiles" ..
if errorlevel 1 (
echo.
echo ERROR: CMake configuration failed!
+ pause
exit /b 1
)
+REM Build
echo.
echo Building ReiLua...
mingw32-make
@@ -79,6 +44,7 @@ mingw32-make
if errorlevel 1 (
echo.
echo ERROR: Build failed!
+ pause
exit /b 1
)
diff --git a/scripts/build_dev.sh b/scripts/build_dev.sh
index 5912bb0..914df21 100755
--- a/scripts/build_dev.sh
+++ b/scripts/build_dev.sh
@@ -62,49 +62,15 @@ fi
mkdir -p build
cd build || exit 1
-# Clean old embedded files (important for dev builds!)
-echo "Cleaning old embedded files..."
-rm -f embedded_main.h embedded_assets.h
-
-# Warn about Lua files in build directory
-LUA_COUNT=$(ls *.lua 2>/dev/null | wc -l)
-if [ "$LUA_COUNT" -gt 0 ]; then
- echo ""
- echo "WARNING: Found Lua files in build directory!"
- echo "Development builds should load from file system, not embed."
- echo ""
- ls -1 *.lua
- echo ""
- read -p "Remove these files from build directory? (Y/n): " -n 1 -r
- echo ""
- if [[ ! $REPLY =~ ^[Nn]$ ]]; then
- rm -f *.lua
- echo "Lua files removed."
- fi
- echo ""
-fi
-
-# Warn about assets folder in build directory
-if [ -d "assets" ]; then
- echo ""
- echo "WARNING: Found assets folder in build directory!"
- echo "Development builds should load from file system, not embed."
- echo ""
- read -p "Remove assets folder from build directory? (Y/n): " -n 1 -r
- echo ""
- if [[ ! $REPLY =~ ^[Nn]$ ]]; then
- rm -rf assets
- echo "Assets folder removed."
- fi
- echo ""
-fi
+# ALWAYS clean build folder for fresh build
+echo "Cleaning build directory for fresh build..."
+rm -rf ./* 2>/dev/null
+echo "✓ Build directory cleaned"
+echo ""
# Clean old configuration if requested
if [ "$1" == "clean" ]; then
- echo "Cleaning build directory..."
- rm -rf CMakeCache.txt CMakeFiles/ *.o *.a
- echo "Clean complete!"
- echo ""
+ echo "Extra clean flag detected (already cleaned)"
fi
# Detect platform and set appropriate generator
diff --git a/scripts/build_release.bat b/scripts/build_release.bat
index a1a08c0..4f9ce43 100644
--- a/scripts/build_release.bat
+++ b/scripts/build_release.bat
@@ -24,21 +24,48 @@ if errorlevel 1 (
exit /b 1
)
+REM ALWAYS clean build folder for fresh build
+echo Cleaning build directory for fresh build...
+del /Q /S * >nul 2>&1
+for /d %%p in (*) do rmdir "%%p" /s /q >nul 2>&1
+echo * Build directory cleaned
+echo.
+
REM Clean old embedded files
-echo Cleaning old embedded files...
+echo Ready for fresh build...
del /Q embedded_main.h embedded_assets.h 2>nul
-REM Check for Lua files
+REM Auto-copy from game folder if it exists
echo.
+if exist "..\game" (
+ echo Found game/ folder - auto-copying ALL contents to build...
+
+ REM Copy all files from game folder recursively, excluding LSP files
+ xcopy /E /I /Y /EXCLUDE:..\game\ReiLua_API.lua+..\game\.luarc.json "..\game\*" . >nul 2>&1
+ if exist "..\game\ReiLua_API.lua" del /Q "ReiLua_API.lua" 2>nul
+ if exist "..\game\.luarc.json" del /Q ".luarc.json" 2>nul
+
+ echo * Copied ALL game files and folders
+ echo * All folder structures preserved ^(user-created folders included^)
+ echo.
+)
+
+REM Check for Lua files
echo Checking for Lua files...
dir /b *.lua >nul 2>&1
if errorlevel 1 (
echo.
echo WARNING: No Lua files found in build directory!
echo.
- echo Please copy your Lua files:
- echo cd build
- echo copy ..\your_game\*.lua .
+ if exist "..\game" (
+ echo No Lua files found in game/ folder.
+ echo Add your main.lua to game/ folder and try again.
+ ) else (
+ echo Tip: Create a game/ folder in project root and add main.lua there.
+ echo Or manually copy files:
+ echo cd build
+ echo copy ..\your_game\*.lua .
+ )
echo.
set /p CONTINUE="Do you want to continue anyway? (y/N): "
if /i not "%CONTINUE%"=="y" exit /b 1
@@ -47,24 +74,22 @@ if errorlevel 1 (
dir /b *.lua
)
-REM Check for assets folder
+REM Check for non-Lua data files (any folder, any file type)
echo.
-echo Checking for assets...
-if not exist "assets" (
- echo.
- echo WARNING: No assets folder found!
- echo.
- echo To embed assets, create the folder and copy files:
- echo cd build
- echo mkdir assets
- echo copy ..\your_game\assets\* assets\
- echo.
- set /p CONTINUE="Do you want to continue without assets? (y/N): "
- if /i not "%CONTINUE%"=="y" exit /b 1
- set EMBED_ASSETS=OFF
-) else (
- echo Found assets folder
+echo Checking for data files to embed...
+set DATA_COUNT=0
+for /r %%f in (*) do (
+ echo %%~nxf | findstr /i /v ".lua .exe .o .a CMake Makefile" >nul
+ if not errorlevel 1 set /a DATA_COUNT+=1
+)
+
+if %DATA_COUNT% GTR 0 (
+ echo Found data files to embed
+ echo ^(includes: images, sounds, config, data, and any other files^)
set EMBED_ASSETS=ON
+) else (
+ echo No non-Lua files found ^(only Lua code will be embedded^)
+ set EMBED_ASSETS=OFF
)
echo.
@@ -72,7 +97,7 @@ echo ================================
echo Build Configuration
echo ================================
echo Lua Embedding: ON
-echo Asset Embedding: %EMBED_ASSETS%
+echo Data Embedding: %EMBED_ASSETS%
echo Build Type: Release
echo ================================
echo.
diff --git a/scripts/build_release.sh b/scripts/build_release.sh
index 5c0e6ab..6f2c0f7 100755
--- a/scripts/build_release.sh
+++ b/scripts/build_release.sh
@@ -68,38 +68,50 @@ fi
mkdir -p build
cd build || exit 1
+# ALWAYS clean build folder for fresh build
+echo "Cleaning build directory for fresh build..."
+rm -rf ./* 2>/dev/null
+echo "✓ Build directory cleaned"
+echo ""
+
# Clean old embedded files
-echo "Cleaning old embedded files..."
-rm -f embedded_main.h embedded_assets.h
+echo "Ready for fresh build..."
+rm -f embedded_main.h embedded_assets.h 2>/dev/null
# Auto-copy from game folder if it exists
echo ""
if [ -d "../game" ]; then
- echo "Found game/ folder - auto-copying contents to build..."
+ echo "Found game/ folder - auto-copying ALL contents to build..."
- # Copy all Lua files from game folder EXCEPT ReiLua_API.lua
- if ls ../game/*.lua 1> /dev/null 2>&1; then
- for lua_file in ../game/*.lua; do
- filename=$(basename "$lua_file")
- if [ "$filename" != "ReiLua_API.lua" ]; then
- cp "$lua_file" .
- fi
- done
- LUA_COUNT=$(ls *.lua 2>/dev/null | wc -l)
- echo " ✓ Copied $LUA_COUNT Lua file(s)"
- else
- echo " ⚠ No Lua files found in game/"
- fi
+ # Copy everything from game folder recursively, excluding:
+ # - ReiLua_API.lua (LSP only)
+ # - .luarc.json (LSP config)
+ # - .DS_Store (macOS)
+ # - Hidden files starting with . (except .gitkeep if present)
- # Copy assets folder if it exists
- if [ -d "../game/assets" ]; then
- rm -rf assets
- cp -r ../game/assets .
- ASSET_COUNT=$(find assets -type f 2>/dev/null | wc -l)
- echo " ✓ Copied assets/ ($ASSET_COUNT files)"
+ # Use rsync if available for better copying, otherwise use cp
+ if command -v rsync &> /dev/null; then
+ rsync -av --exclude='ReiLua_API.lua' --exclude='.luarc.json' --exclude='.DS_Store' --exclude='.*' --include='.gitkeep' ../game/ . 2>/dev/null
else
- echo " ℹ No assets folder in game/"
+ # Fallback to find + cp - Copy ALL files and directories
+ (cd ../game && find . -type f \
+ ! -name 'ReiLua_API.lua' \
+ ! -name '.luarc.json' \
+ ! -name '.DS_Store' \
+ ! -path '*/\.*' -o -name '.gitkeep' \
+ -exec sh -c 'mkdir -p "../build/$(dirname "{}")" && cp -p "{}" "../build/{}"' \; 2>/dev/null)
fi
+
+ # Count what was copied
+ LUA_COUNT=$(find . -maxdepth 10 -name "*.lua" -type f 2>/dev/null | wc -l)
+ ASSET_COUNT=$(find assets -type f 2>/dev/null | wc -l || echo "0")
+ TOTAL_FILES=$(find . -type f ! -path './CMakeFiles/*' ! -path './.cmake/*' ! -name 'CMake*' ! -name '*.a' ! -name '*.o' 2>/dev/null | wc -l)
+
+ echo " ✓ Copied ALL game files and folders:"
+ echo " - $LUA_COUNT Lua file(s) (including all subdirectories)"
+ echo " - $ASSET_COUNT Asset file(s) (if assets folder exists)"
+ echo " - $TOTAL_FILES total file(s)"
+ echo " - All folder structures preserved (user-created folders included)"
echo ""
fi
@@ -131,34 +143,18 @@ else
ls -1 *.lua
fi
-# Check for assets folder
+# Check for non-Lua data files (any folder, any file type)
echo ""
-echo "Checking for assets..."
-if [ ! -d "assets" ]; then
- echo ""
- echo "WARNING: No assets folder found!"
- echo ""
- if [ -d "../game" ]; then
- echo "No assets found in game/assets/ folder."
- echo "Add assets to game/assets/ if you need them embedded."
- else
- echo "Tip: Create game/assets/ in project root for auto-copy."
- echo "Or manually:"
- echo " cd build"
- echo " mkdir assets"
- echo " cp ../your_game/assets/* assets/"
- fi
- echo ""
- read -p "Do you want to continue without assets? (y/N): " -n 1 -r
- echo ""
- if [[ ! $REPLY =~ ^[Yy]$ ]]; then
- exit 1
- fi
- EMBED_ASSETS="OFF"
-else
- ASSET_FILES=$(find assets -type f 2>/dev/null | wc -l)
- echo "Found $ASSET_FILES asset file(s) in assets folder"
+echo "Checking for data files to embed..."
+NON_LUA_FILES=$(find . -type f ! -name "*.lua" ! -path "./CMakeFiles/*" ! -path "./.cmake/*" ! -name "CMake*" ! -name "Makefile*" ! -name "*.o" ! -name "*.a" 2>/dev/null | wc -l)
+
+if [ "$NON_LUA_FILES" -gt 0 ]; then
+ echo "Found $NON_LUA_FILES non-Lua file(s) to embed"
+ echo " (includes: images, sounds, config, data, and any other files)"
EMBED_ASSETS="ON"
+else
+ echo "No non-Lua files found (only Lua code will be embedded)"
+ EMBED_ASSETS="OFF"
fi
echo ""
@@ -166,7 +162,7 @@ echo "================================"
echo "Build Configuration"
echo "================================"
echo "Lua Embedding: ON"
-echo "Asset Embedding: $EMBED_ASSETS"
+echo "Data Embedding: $EMBED_ASSETS"
echo "Build Type: Release"
echo "================================"
echo ""
diff --git a/scripts/create_empty_assets.py b/scripts/create_empty_assets.py
new file mode 100644
index 0000000..fbc2d11
--- /dev/null
+++ b/scripts/create_empty_assets.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+"""
+Create an empty embedded_assets.h file for compatibility.
+Usage: python create_empty_assets.py <output.h>
+"""
+import sys
+
+if __name__ == '__main__':
+ if len(sys.argv) < 2:
+ print('Usage: python create_empty_assets.py <output.h>')
+ sys.exit(1)
+
+ output_file = sys.argv[1]
+
+ with open(output_file, 'w') as f:
+ f.write('#ifndef EMBEDDED_ASSETS_H\n')
+ f.write('#define EMBEDDED_ASSETS_H\n')
+ f.write('/* No assets to embed */\n')
+ f.write('typedef struct { const char* name; const unsigned char* data; unsigned int size; } EmbeddedAsset;\n')
+ f.write('static const EmbeddedAsset embedded_assets[] = {};\n')
+ f.write('static const int embedded_asset_count = 0;\n')
+ f.write('#endif\n')
+
+ print(f'Created empty {output_file}')
diff --git a/scripts/embed_assets.py b/scripts/embed_assets.py
index 52309ef..df4489a 100644
--- a/scripts/embed_assets.py
+++ b/scripts/embed_assets.py
@@ -40,17 +40,18 @@ def embed_files(output_file, input_files):
data = inf.read()
var_name = sanitize_name(input_file)
- # Extract relative path from 'assets/' onwards if present
- if 'assets' in input_file.replace('\\', '/'):
- parts = input_file.replace('\\', '/').split('assets/')
- if len(parts) > 1:
- relative_name = 'assets/' + parts[-1]
- else:
- relative_name = os.path.basename(input_file)
- else:
- relative_name = os.path.basename(input_file)
+ # Extract relative path from build directory
+ relative_name = input_file
+ for prefix in ['build/', 'build\\']:
+ if prefix in input_file:
+ parts = input_file.split(prefix, 1)
+ if len(parts) > 1:
+ relative_name = parts[1]
+ break
+ # Normalize path separators
+ relative_name = relative_name.replace('\\', '/')
- f.write(f'/* Embedded asset: {input_file} ({len(data)} bytes) */\n')
+ f.write(f'/* Embedded file: {relative_name} ({len(data)} bytes) */\n')
f.write(f'static const unsigned char embedded_asset_{idx}_{var_name}[] = {{\n')
for i, byte in enumerate(data):
@@ -78,15 +79,16 @@ def embed_files(output_file, input_files):
f.write('static const EmbeddedAsset embedded_assets[] = {\n')
for idx, input_file in enumerate(input_files):
var_name = sanitize_name(input_file)
- # Extract relative path from 'assets/' onwards if present
- if 'assets' in input_file.replace('\\', '/'):
- parts = input_file.replace('\\', '/').split('assets/')
- if len(parts) > 1:
- relative_name = 'assets/' + parts[-1]
- else:
- relative_name = os.path.basename(input_file)
- else:
- relative_name = os.path.basename(input_file)
+ # Extract relative path from build directory
+ relative_name = input_file
+ for prefix in ['build/', 'build\\']:
+ if prefix in input_file:
+ parts = input_file.split(prefix, 1)
+ if len(parts) > 1:
+ relative_name = parts[1]
+ break
+ # Normalize path separators
+ relative_name = relative_name.replace('\\', '/')
f.write(f' {{ "{relative_name}", embedded_asset_{idx}_{var_name}, embedded_asset_{idx}_{var_name}_len }},\n')
f.write('};\n\n')
diff --git a/scripts/embed_lua.py b/scripts/embed_lua.py
index 9562354..0d20921 100644
--- a/scripts/embed_lua.py
+++ b/scripts/embed_lua.py
@@ -27,7 +27,17 @@ def embed_files(output_file, input_files):
data = inf.read()
var_name = sanitize_name(input_file)
- f.write(f'/* Embedded file: {input_file} */\n')
+ # Get relative path for better module loading
+ # Try to extract path relative to common directories
+ relative_name = input_file
+ for prefix in ['build/', 'build\\']:
+ if prefix in input_file:
+ parts = input_file.split(prefix, 1)
+ if len(parts) > 1:
+ relative_name = parts[1]
+ break
+
+ f.write(f'/* Embedded file: {relative_name} */\n')
f.write(f'static const unsigned char embedded_lua_{idx}_{var_name}[] = {{\n')
for i, byte in enumerate(data):
@@ -55,18 +65,32 @@ def embed_files(output_file, input_files):
f.write('static const EmbeddedLuaFile embedded_lua_files[] = {\n')
for idx, input_file in enumerate(input_files):
var_name = sanitize_name(input_file)
- # Store both original filename and basename for require compatibility
- basename = os.path.basename(input_file)
- f.write(f' {{ "{basename}", embedded_lua_{idx}_{var_name}, embedded_lua_{idx}_{var_name}_len }},\n')
+ # Store relative path for proper require() support
+ relative_name = input_file
+ for prefix in ['build/', 'build\\']:
+ if prefix in input_file:
+ parts = input_file.split(prefix, 1)
+ if len(parts) > 1:
+ relative_name = parts[1]
+ break
+ # Normalize path separators
+ relative_name = relative_name.replace('\\', '/')
+ f.write(f' {{ "{relative_name}", embedded_lua_{idx}_{var_name}, embedded_lua_{idx}_{var_name}_len }},\n')
f.write('};\n\n')
f.write(f'static const int embedded_lua_file_count = {len(input_files)};\n\n')
- # Main entry point (first file)
- var_name = sanitize_name(input_files[0])
+ # Main entry point (first file with 'main.lua' in name, or first file)
+ main_idx = 0
+ for idx, input_file in enumerate(input_files):
+ if 'main.lua' in input_file.lower():
+ main_idx = idx
+ break
+
+ var_name = sanitize_name(input_files[main_idx])
f.write('/* Main entry point */\n')
- f.write(f'#define embedded_main_lua embedded_lua_0_{var_name}\n')
- f.write(f'#define embedded_main_lua_len embedded_lua_0_{var_name}_len\n\n')
+ f.write(f'#define embedded_main_lua embedded_lua_{main_idx}_{var_name}\n')
+ f.write(f'#define embedded_main_lua_len embedded_lua_{main_idx}_{var_name}_len\n\n')
f.write('#endif /* EMBEDDED_MAIN_H */\n')
diff --git a/src/lua_core.c b/src/lua_core.c
index 8d4bf52..6f0a6f6 100644
--- a/src/lua_core.c
+++ b/src/lua_core.c
@@ -124,23 +124,39 @@ static int embedded_lua_loader( lua_State* L ) {
const char* name = lua_tostring( L, 1 );
if ( name == NULL ) return 0;
- for ( int i = 0; i < embedded_lua_file_count; i++ ) {
- const EmbeddedLuaFile* file = &embedded_lua_files[i];
-
- const char* basename = file->name;
- size_t name_len = strlen( name );
- size_t base_len = strlen( basename );
+ /* Convert module name dots to slashes (e.g., "lib.gamestate" -> "lib/gamestate") */
+ char converted_name[512];
+ strncpy( converted_name, name, sizeof(converted_name) - 1 );
+ converted_name[sizeof(converted_name) - 1] = '\0';
+ for ( char* p = converted_name; *p; p++ ) {
+ if ( *p == '.' ) *p = '/';
+ }
+
+ /* Try both converted name and original name */
+ const char* names_to_try[] = { converted_name, name };
+
+ for ( int n = 0; n < 2; n++ ) {
+ const char* try_name = names_to_try[n];
- if ( strcmp( basename, name ) == 0 ||
- ( base_len > 4 && strcmp( basename + base_len - 4, ".lua" ) == 0 &&
- strncmp( basename, name, base_len - 4 ) == 0 && name_len == base_len - 4 ) ) {
+ for ( int i = 0; i < embedded_lua_file_count; i++ ) {
+ const EmbeddedLuaFile* file = &embedded_lua_files[i];
- if ( luaL_loadbuffer( L, (const char*)file->data, file->size, file->name ) == 0 ) {
- return 1;
- }
- else {
- lua_pushfstring( L, "\n\tembedded loader error: %s", lua_tostring( L, -1 ) );
- return 1;
+ const char* basename = file->name;
+ size_t name_len = strlen( try_name );
+ size_t base_len = strlen( basename );
+
+ /* Match exactly, or match without .lua extension */
+ if ( strcmp( basename, try_name ) == 0 ||
+ ( base_len > 4 && strcmp( basename + base_len - 4, ".lua" ) == 0 &&
+ strncmp( basename, try_name, base_len - 4 ) == 0 && name_len == base_len - 4 ) ) {
+
+ if ( luaL_loadbuffer( L, (const char*)file->data, file->size, file->name ) == 0 ) {
+ return 1;
+ }
+ else {
+ lua_pushfstring( L, "\n\tembedded loader error: %s", lua_tostring( L, -1 ) );
+ return 1;
+ }
}
}
}
@@ -1530,6 +1546,25 @@ bool luaInit( int argn, const char** argc ) {
TraceLog( LOG_WARNING, "%s", "Failed to init Lua" );
return false;
}
+
+ /* Configure package.path to include basePath and all subdirectories */
+ if ( state->basePath != NULL && strlen( state->basePath ) > 0 ) {
+ lua_getglobal( L, "package" );
+ lua_getfield( L, -1, "path" );
+ const char* currentPath = lua_tostring( L, -1 );
+ lua_pop( L, 1 );
+
+ /* Add basePath and recursive subdirectory patterns for flexible module loading */
+ char newPath[STRING_LEN * 4];
+ snprintf( newPath, sizeof(newPath),
+ "%s?.lua;%s?/init.lua;%s?/?.lua;%s?/?/init.lua;%s",
+ state->basePath, state->basePath, state->basePath, state->basePath, currentPath );
+
+ lua_pushstring( L, newPath );
+ lua_setfield( L, -2, "path" );
+ lua_pop( L, 1 );
+ }
+
/* Define object types. */
defineBuffer();
defineImage();