The libui source tree has a simple layout:
common/
common sources and headers, .c and .h
darwin/
darwin-specific sources and headers, .m and .h
examples/
controlgallery/
main.c
cpp-multithread/
main.cpp
histogram/
main.cpp
a .rc and .manifest for Windows
test/
test sources and headers, .c, .h, .rc, and .manifest
unix/
unix-specific sources and headers, .c and .h
windows/
windows-specific sources and headers, .cpp, .hpp, .rc, and .manifest
ui.h
ui_darwin.h (the public Darwin-specific API)
ui_unix.h
ui_windows.h
There are 2*(3+n) targets (where n is the number of examples). The 2* comes because for each target, there is both a shared and a static mode, that affect linking.
The 3 fixed targets are libui, the test program, and the special target examples
that builds all the examples in one fell swoop.
In addition, each example can be built individually.
A build of libui itself combines four items:
- ui.h
- ui_system.h
- common/
- system/
A build of the test program combines
- ui.h
- test/
A build of an example combines
- ui.h
- the specific main.c or main.cpp for that example
Ideally, a build
program would be invoked as so:
$ build # builds only libui
$ build test # builds libui and test
$ build example EXAMPLE=name # builds libui and given example
$ build examples # builds libui and all examples
In addition, the following additional arguments may be provided:
STATIC=1
use static linking instead of shared linking
RELEASE=1
make a release instead of a debug
VERBOSE=1
show build steps (default is to show human-friendly progress)
So
build examples STATIC=1
builds libui as a static library and links all the examples statically to that static library.
Additionally, the standard CC
, CXX
, CFLAGS
, CXXFLAGS
, LD
, LDFLAGS
, RC
, and RCFLAGS
variables can be used to adjust build parameters.
By default, we build for the host OS. THis can be overridden with the OS
variable. The OS
name maps to the system folders above, so either darwin
, unix
(any other Unix system), or windows
.
If the OS is Windows, the default toolchain is MSVC. To use a gcc/clang-based toolchain like MinGW-w64 instead, set the TOOLCHAIN
variable, and (at present, due to internal limitations) static linking must be used (explicitly). The exact value isn't important. If the OS is not windows, only a gcc/clang-based toolchain will be available.
The actual build system does not need to use this exact syntax. This is just an explanation of how libui will be built through examples.
- -Wall -Wextra -pedantic (and MSVC equivalent)
- -Wno-unused-parameter -Wno-switch (and MSVC equivalent)
- -fPIC (for non-Windows shared builds only)
libui itself also has
- -fvisibility=hidden (for non-Windows builds only; this is important, see below)
- -D_UI_EXTERN=something
- -mmacosx-version-min=10.8 (on OS X)
- MSVC safety options, maybe
- Ideally for MSVC, .c files are built /TC
And finally, system libraries are linked only in:
- libui shared build
- test and example static build
Shared libraries are fine as they are.
Static libraries, on the other hand, need additional steps to ensure the -fvisibility=hidden setting required above actually works.
A normal static build would do
ar rcs library.a objects
However, this exposes hidden symbols to the caller, which will lead to name clashes which I don't want.
On non-OS X, if we instead do
ld -r objects -o hugeobject.o
objcopy --localize-hidden hugeobject.o
ar rcs library.a hugeobject.o
then we wind up with a library.a with the hidden symbols truly hidden, thanks to how ld -r and objcopy work: ld -r combines multiple .o files into one big .o file and objcopy rewrites that .o file to scramble the hidden symbols.
The equivalent on OS X is
nm -m objects | sed -E -n 's/^[0-9a-f]* \([A-Z_]+,[a-z_]+\) external //p' > symbols
ld -exported_symbols_list symbols -r objects -o hugeobject.o
ar rcs library.a hugeobject.o
A build system that allows me to specify custom rules for this will require me to also say that hugeobject.o
should not be treated as a build product to be included along with libui and the executables.
- The ability to stuff all object files and per-source debugging symbol files in a separate directory such as
.obj/
- The ability to stuff all actual build output (libui and executables and final debugging symbols) in a separate directory such as
out/
- The ability to set rpath settings for both libui and executables
- The ability to set a version number on libui's filename