# How to build a Lua binary with MSYS2 that does not depend on MinGW-w64’s DLLs As an environment for building Windows binaries [MSYS2](https://msys2.github.io/) improves upon [MinGW](http://mingw.org/)/MSYS in [several important ways](http://stackoverflow.com/a/25023611). When you switch, however, you will notice that its builds of Lua, unlike those produced with plain old `mingw-base`, depend upon external DLLs by default. ![\"Lua.exe - System Error\" screenshot](/media/lua-msys2/lua-dll-missing.png){.center-block} When you build Lua 5.1.5 with MSYS2's 32-bit version of MinGW-w64 using the command `make mingw` you end up with a `lua51.dll` that requires `libgcc_s_dw2-1.dll` and `libwinpthread-1.dll`: ```sh $ wget https://www.lua.org/ftp/lua-5.1.5.tar.gz $ tar xvf lua-5.1.5.tar.gz $ cd lua-5.1.5/src/ $ make mingw $ ldd lua51.dll ntdll.dll => /c/WINDOWS/system32/ntdll.dll (0x7c900000) kernel32.dll => /c/WINDOWS/system32/kernel32.dll (0x7c800000) msvcrt.dll => /c/WINDOWS/system32/msvcrt.dll (0x77c10000) libgcc_s_dw2-1.dll => /mingw32/bin/libgcc_s_dw2-1.dll (0x6eb40000) libwinpthread-1.dll => /mingw32/bin/libwinpthread-1.dll (0x64b40000) ``` If you want fewer DLLs to manage, you have several options. For a quick fix you could build a Lua interpreter statically with `make all`—but then you would not be able to use binary modules, which expect a `lua51.dll`. A solution that keeps `lua51.dll` is explained below. The output of `ldd` and the message box in the screenshot mentions `libgcc_s_dw2-1.dll`, which means the library `lua51.dll` depends on a dynamically linked copy of [`libgcc`](https://gcc.gnu.org/onlinedocs/gccint/Libgcc.html). We should be able to use GCC's flag `-static-libgcc` to ensure `libgcc` is linked statically. The makefile for Lua has a section for user-supplied settings with the variables `MYCFLAGS` and `MYLDFLAGS` for the compiler and the linker flags respectively. However, convenience build targets like `mingw` actually ignore those. Let's look at the target `mingw` itself, then, with an eye for what to change there: ```make mingw: $(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \ "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe $(MAKE) "LUAC_T=luac.exe" luac.exe ``` The first command runs `make` recursively to build both `lua51.dll` (`LUA_A`) and `lua.exe` (`LUA_T`) with a predefined set of `MY*` flags. To keep the original target intact for reference, we'll make a copy of it named `mingw-w64` and modify that. If we put `-static-libgcc` in `MYLDFLAGS` or `MYCFLAGS` in the copy, though, it will not accomplish what we are trying to do. Why? If you search the makefile for the target `LUA_A` you will find the following: ```make $(LUA_A): $(CORE_O) $(LIB_O) $(AR) $@ $(CORE_O) $(LIB_O) # DLL needs all object files $(RANLIB) $@ ``` It turns out that it is the `$(AR)` command that creates `lua51.dll`. Looking at the target `mingw-w64` we can see that, despite its name, the variable `AR` is set to `$(CC) -shared -o`, i.e., the `$(AR) $@ ...` command runs GCC. So let's add `-static-libgcc` where we set `AR` and try to build again: ```make mingw-w64: $(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \ "AR=$(CC) -shared -static-libgcc -o" "RANLIB=strip --strip-unneeded" \ "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe $(MAKE) "LUAC_T=luac.exe" luac.exe ``` ```sh $ make clean $ make mingw-w64 $ ldd lua51.dll ntdll.dll => /c/WINDOWS/system32/ntdll.dll (0x7c900000) kernel32.dll => /c/WINDOWS/system32/kernel32.dll (0x7c800000) msvcrt.dll => /c/WINDOWS/system32/msvcrt.dll (0x77c10000) ``` There. We've built a `lua51.dll` (and a `lua.exe`) that does not expect an external `libgcc`. If you want to achieve the same effect without editing the makefile you can use an equivalent command: ```sh $ make clean $ make "LUA_A=lua51.dll" "LUA_T=lua.exe" "AR=cc -shared -static-libgcc -o" "RANLIB=strip --strip-unneeded" "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe $ make "LUAC_T=luac.exe" luac.exe ``` ## Page metadata URL: Published 2016-08-30, updated 2021-08-21. Tags: - how-to - Lua - MSYS2 - old blog - programming - Windows Index: [Old blog](/old-blog).