Compile software from source

This page documents how to Compile a software from source in Alpine Linux. The recommended way to install software in Alpine Linux is to create a APKBUILD file and install using apk.
The below example steps are based on the installation procedure as written by reddit user Beneficial_Bug_4892 in reddit for ImHex, a Hex Editor for Reverse Engineers and Programmers. Eventhough the package is available in Alpine Linux, it did not work for the author, hence the post. 
== Compiling ImHex on Alpine Linux ==
On Linux, ImHex is built through regular GCC (or optionally Clang).
* Clone the repo using git clone https://github.com/WerWolv/ImHex --recurse-submodules
* Install all the dependencies by hand according to Arch script dist/get_deps_archlinux.sh.
* Build ImHex itself using the following commands:
cd ImHex
mkdir -p build
cd build
CC=gcc-12 CXX=g++-12 \
cmake -G "Ninja" \
 -DCMAKE_BUILD_TYPE=Release \
 -DCMAKE_INSTALL_PREFIX="/usr" \
 ..
ninja install
All paths follow the XDG Base Directories standard, and can thus be modified with the environment variables XDG_CONFIG_HOME, XDG_CONFIG_DIRS, XDG_DATA_HOME and XDG_DATA_DIRS.
== Error due to lseek ==
The following command eventually failed.
Looking through compiler errors I figured out that for whatever reason lseek(2) is #define'd to lseek64 in the very beginning of one of the source files. I guess on other Linux distributions it ought to be 64-bit version of function, but Alpine's MUSL lseek(2) is already 64-bit, doesn't have any prefix. Removed it as follows and proceeded with build. 
--- a/plugins/builtin/source/content/providers/disk_provider.cpp
+++ b/plugins/builtin/source/content/providers/disk_provider.cpp
@@ -44,7 +44,8 @@
 #endif
 #if defined(OS_LINUX) && !defined(OS_FREEBSD)
- #define lseek lseek64
+ /* I use Alpine btw */
+// #define lseek lseek64
 #elif defined(OS_FREEBSD)
 #include <sys/disk.h>
 #define DEFAULT_SECTOR_SIZE 512
The next problem was pretty simple to fix: no magic.h header. A little bit of searching showed that it seems to be a part of library, which file(1) uses too determine the type of given file. Added and continued using the below command.
 
== Custom Compiler Flag == 
This one was really strange. It was linking issue (if you're an experienced C/C++ dev, you should probably know that linking is the most cursed and annoying area in which you can face problems). I got lots of undefined references to glfw* family of functions, which are all obviously come from glfw library. At first it didn't make any sense: I've already installed both glfw and glfw-dev packages. But some time after I noticed that there are no mentions of glfw stuff in ninja-providen compilation line (?)
I didn't know how to add custom LDFLAGS of some sort to ninja, so I decided to do a dirty workaround (I think the most dirtiest workaround in my entire life): call compiler from a shell wrapper, which translates arguments to the original compiler and in addition appends all the necessary glfw flags for linking...
# rm /usr/bin/clang++
# cat <<EOF >/usr/bin/clang++
> #!/bin/sh
> /usr/lib/llvm17/bin/clang++ $@ -L/usr/lib `pkg-config --libs glfw3`
> EOF
# chmod 755 /usr/bin/clang++
And after that it has successfully built and installed ImHex! 
== Troubleshooting with gdb == 
Unfortunately it still crashed after first run during startup. So I decided to run it through gdb to see what's wrong and where does it segfault:
$ gdb ./imhex
...
(gdb) r
...
Thread 1 "Main" received signal SIGSEGV, Segmentation fault.
get_meta (p=p@entry=0x7ffff63387b0 "e") at src/malloc/mallocng/meta.h:141
warning: 141 src/malloc/mallocng/meta.h: No such file or directory
(gdb)
It seemed like heap corruption issue, or something is just wrong with the heap. When I checked stack backtrace, it became much cleaner what's going on:
(gdb) bt
#0 get_meta (p=p@entry=0x7ffff63387b0 "e") at src/malloc/mallocng/meta.h:141
#1 0x00007ffff7f80db3 in __libc_free (p=0x7ffff63387b0) at src/malloc/mallocng/free.c:105
#2 0x00007ffff7f80422 in free (p=<optimized out>) at src/malloc/free.c:5
#3 0x00007ffff7fa4f6c in regfree (preg=<optimized out>) at src/regex/regcomp.c:2926
#4 0x00007ffff7314d99 in ?? () from /usr/lib/libglfw.so.3
#5 0x00007ffff730ec39 in ?? () from /usr/lib/libglfw.so.3
#6 0x00005555555bafdc in hex::init::WindowSplash::~WindowSplash() ()
#7 0x00005555555debc9 in hex::init::runImHex() ()
#8 0x0000555555576482 in main ()
(gdb)
The fact, that it crashes somewhere deep in the free(3) implementation doesn't indicate the bug with LibC itself, but rather that NULL pointer or some other invalid location was passed into it, so it didn't expect that and acts like it has received a valid page allocated by malloc(3).
If that was more important stuff, maybe it'd be worth to fix. But because it is just a memory freeing, we could just get rid of it. I mean, of course it's a memory leak, but it isn't critical: this code runs only during startup, not in loop or inside an interrupt of some sort. Linux will free all pages allocated for this process after it's termination, so who cares if we leak a couple of bytes here.
--- a/main/gui/source/init/splash_window.cpp
+++ b/main/gui/source/init/splash_window.cpp
@@ -65,8 +65,8 @@ namespace hex::init {
 }
 WindowSplash::~WindowSplash() {
- this->exitImGui();
- this->exitGLFW();
+ /* Who needs it, right?... */
+ ;
 }
After recompiling finally able to launch ImHex Editor. 
== See Also ==
* Original Reddit Post 
* Creating an Alpine package
Category:Package Manager