NOTE: Binaries for supported platforms are already included, so rebuilding them is not necesssary unless you want to.
C sources are included as git submodules so you need to clone them first:
git submodule update --init --recursive
Building is based on bash scripts most of which invoke gcc directly. To (re)build a library, type:
sh <lib>/build
To (re)build all libraries, type:
sh build-all
-
Download and install MSYS2.
-
Add to PATH (in this order):
<msys2-path>\mingw64\bin <msys2-path>\usr\bin
-
Install the toolchain:
pacman -S mingw-w64-x86_64-gcc pacman -S mingw-w64-x86_64-cmake pacman -S make nasm
The current stack is built on a Debian 10 x64 Server and it's the only supported way to build it. To install the toolchain, type:
sudo apt-get install gcc cmake nasm
sudo apt-get install libssl-dev
Note that Linux binaries are not very backwards compatible because of glibc's "versioned symbols", and because of OpenSSL. If you need backwards-compatible binaries you'll have to build them on the oldest Linux that you care to support, but using the newest GCC that you can install on that system. Good luck!
- both dynamic libraries (stripped) and static libraries are created.
- static libraries can be bundled into your app executable.
- libgcc is statically linked.
- libstdc++ is statically linked.
- binaries on Windows are linked to msvcrt.dll.
- the luajit exe on Linux sets
rpath
to$ORIGIN
- Lua/C modules on Windows are linked to lua51.dll.
Note that the same gcc/g++ frontend is used on every platform, which greatly reduces what you need to know for writing build scripts.
The best way to create a new build script is to use an existing one as a starting point so that you retain some desirable properties of the script:
- make it independent of the current directory.
- make it detect the current platform and build for it.
The build script must generate binaries as follows:
bin/windows/foo.dll C library, Windows
bin/windows/foo.a C library, Windows, static version
bin/windows/clib/foo.dll Lua/C library, Windows
bin/windows/foo.a Lua/C library, Windows, static version
bin/linux/libfoo.so C library, Linux
bin/linux/libfoo.a C library, Linux, static version
bin/linux/clib/foo.so Lua/C library, Linux
bin/linux/libfoo.a Lua/C library, Linux, static version
So prefix everything with lib
except for Windows and except for dynamic
Lua/C libs; put dynamic Lua/C libs in the clib
subdirectory but put static
Lua/C libs in the platform directory along with the normal C libs.
Building with gcc is a 2-step process, compilation and linking, because we want to build both static and dynamic versions the libraries.
gcc -c options... files...
g++ -c options... files...
-c
: compile only (don't link; produce .o files)-O2
: enable code optimizations-I<dir>
: search path for headers (eg.-I../lua
)-I../lua-headers
: necessary include path for Lua/C modules.-D<name>
: set a#define
-D<name>=<value>
: set a#define
with a value-U<name>
: unset#define
-fpic
or-fPIC
: generate position-independent code (required for linux64)-D_WIN32_WINNT=0x601
: Windows: set API level to Windows 7 (set WINVER too)-DWINVER=0x601
: Windows: set API level to Windows 7-D_POSIX_SOURCE
: Linux and MinGW: enable POSIX 1003.1-1990 APIs-D_XOPEN_SOURCE=700
: Linux: enable POSIX.1 + POSIX.2 + X/Open 7 (SUSv4) APIs-U_FORTIFY_SOURCE=1
: gcc: enable some runtime checks-std=c++11
: for C++11 libraries
gcc -shared options... files...
g++ -shared options... files...
-shared
: create a shared library-s
: strip debug and private symbols-o <output-file>
: output file path (eg.-o ../../bin/windows/z.dll
)-L<dir>
: search path for library dependencies (eg.-L../../bin/windows
)-l<libname>
: library dependency (eg.-lz
looks forz.dll
/libz.so
/libz.dylib
orlibz.a
)-Wl,--no-undefined
: do not allow unresolved symbols in the output library.-static-libstdc++
: link libstdc++ statically (for C++ libraries)-static-libgcc
: link the GCC runtime library statically (for C and C++ libraries)-pthread
: enable pthread support (not for Windows)-Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic
: statically link the winpthread library (for C++ libraries on Windows)-fno-exceptions
: avoid linking to libstdc++ if the code doesn't use exceptions-fno-rtti
: make the binary smaller if the code doesn't use dynamic_cast or typeid-fvisibility=hidden
: make the symbol table smaller if the code is explicit about exports
IMPORTANT: The order in which -l
options appear is significant!
Always place all object files and all dependent libraries before
all dependency libraries.
rm -f ../../bin/<platform>/static/<libname>.a
ar rcs ../../bin/<platform>/static/<libname>.a *.o
IMPORTANT: Always remove the old .a
file first before invoking ar
.
gcc -c -O2 lpeg.c -fPIC -I. -I../lua-headers
gcc -shared -s -static-libgcc -o ../../bin/linux/clib/lpeg.so
rm -f ../../bin/linux/liblpeg.a
ar rcs ../../bin/linux/liblpeg.a
In some cases it's going to be more complicated than that.
- sometimes you won't get away with specifying
*.c
-- some libraries rely on the makefile to choose which .c files need to be compiled for a specific platform or set of options as opposed to using platform defines. - some libraries actually do use one or two of the myriad of defines
generated by the
configure
script -- you might have to grep for those and add appropriate-D
switches to the command line. - some libraries have parts written in assembler or other language. At that point, maybe a simple makefile is a better alternative, YMMV (if the package has a clean and simple makefile that doesn't add more dependencies to the toolchain, use that instead)
After compilation, check that your builds work on your oldest platforms.