Skip to content

Linux Port WIP #295

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 30 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
6f1e555
Fixed: Few old ends with out of date parts of the Linux code
Mallchad Jun 22, 2024
a90684f
Fixed: [linux] Some compile errors with hostname and attempted rewrit…
Mallchad Jun 22, 2024
2b82eae
[metagen_linux] Added: Various fixes and missing implimentations for …
Mallchad Jun 30, 2024
af52d98
[metagen_linux] Added: Various fixes and missing implimentations for …
Mallchad Jul 6, 2024
f2996ec
Added: Initial build.sh for Linux
Mallchad Jul 7, 2024
42f9765
[Build] Added: Linux build now compiles cleanly from new build.sh
Mallchad Jul 7, 2024
7fbafe1
Fixed: Mistakes with conversion function signatures
Mallchad Jul 9, 2024
e317fc9
[Metagen Linux] Added: Checkpoint - Yet more missing implimentations
Mallchad Jul 12, 2024
5f262da
[Metagen Linux] Added: Checkpoint - Yet more missing implimentations
Mallchad Jul 14, 2024
20b848e
[Metagen Linux] Added: Checkpoint - Yet more missing implimentations
Mallchad Jul 21, 2024
79b463d
[Metagen Linux] Added: More missing Linux implimentations, metagen co…
Mallchad Jul 25, 2024
cbe4d4f
Fixed: Various fixes for raddbg and transferred over work from metagen
Mallchad Jul 26, 2024
d208f2c
[Raddbg Linux] Fixed: 'tctx_release()' being removed possibly erroneo…
Mallchad Aug 1, 2024
1521008
[OS Core] Added: Atomic gcc intrinsics implimentations for Linux
Mallchad Aug 5, 2024
c40a4eb
[Tests] Added: A bunch of tests for the os_core platform layer
Mallchad Aug 12, 2024
63e3147
[Tests] Added: Some more transient tests for os_linux
Mallchad Aug 25, 2024
142cc24
Added: Basic rough out for freetype font provider and many random fix…
Mallchad Sep 2, 2024
76fe659
Bump: Save WIP freetype stuff
Mallchad Nov 19, 2024
06e6dc2
Bump: Saved some WIP work
Mallchad Nov 19, 2024
a671e79
Added: Main bulk out of freetype code, difficult to test so moving on…
Mallchad Dec 18, 2024
92a7f31
[OS Core] Fixed: Linux implementation for 'os_large_pages_enabled'
Mallchad Dec 20, 2024
66ce417
[Demon Core] Added: Some function block-out for demon control
Mallchad Dec 21, 2024
9158129
[OS Graphics] Added: Bulk out basics for X11 and EGL Windowing
Mallchad Dec 23, 2024
18806f2
[OS Graphics] Added: 'os_window_open' definition
Mallchad Dec 24, 2024
c06325e
[OS Graphics] Added: Bulked out majority of event handling code
Mallchad Dec 28, 2024
36a6537
[OS Graphics] Added: Bulked out 'os_push_monitors_array', 'os_primary…
Mallchad Jan 4, 2025
619a0dd
[OS Graphics] Added: Bulked out some more linux graphics server funct…
Mallchad Jan 7, 2025
a60248e
[OS Graphics] Added: Bulked out some more os_gfx functions.
Mallchad Jan 24, 2025
3a4b063
[OS Graphics] Added: icon display of window manager (and various othe…
Mallchad Feb 6, 2025
6b6fdf7
Checkpoint: Working on Linux/OpenGL graphical stuff
Mallchad Apr 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
245 changes: 245 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
#!/usr/bin/env bash

# TODO(mallchad): This code is really ugly especially with the stupid && branching tricks. Please fix.

# --- Usage Notes (2024/1/10) ------------------------------------------------
#
# This is a central build script for the RAD Debugger project. It takes a list
# of simple alphanumeric-only arguments which control (a) what is built, (b)
# which compiler & linker are used, and (c) extra high-level build options. By
# default, if no options are passed, then the main "raddbg" graphical debugger
# is built.
#
# Below is a non-exhaustive list of possible ways to use the script:
# `build raddbg`
# `build raddbg clang`
# `build raddbg release`
# `build raddbg asan telemetry`
# `build rdi_from_pdb`
# `build gcodeview`
#
# For a full list of possible build targets and their build command lines,
# search for @build_targets in this file.
#
# Below is a list of all possible non-target command line options:
#
# - `asan`: enable address sanitizer
# - `telemetry`: enable RAD telemetry profiling support
# - `gcodeview`: generate codeview symbols instead of DRWARF for clang
#
# Also you can set the environment variable RAD_DEBUG=1 to enable some extra debug output

# --- Random Init -----------------------------------------------------------
ansi_red="\x1b[31m"
ansi_cyanbold="\x1b[36;1m"
ansi_reset="\e[0m"
function rad_log ()
{
echo -e "$ansi_cyanbold[Rad Build]$ansi_reset ${@}"
}

function rad_debug_log ()
{
if [[ -n "${RAD_DEBUG}" ]] ; then
# -e enable escape sequences
rad_log "${@}"
fi
}

# cd to script directory
self_directory="$(dirname $(readlink -f $0))"
rad_log "cd to '${self_directory}'"
cd "${self_directory}"
RAD_BUILD_DEBUG="${RAD_DEBUG}"
if [[ -n ${RAD_BUILD_DEBUG} ]] ; then
shellcheck $0
fi
# RAD_META_COMPILE_ONLY=1

# --- Unpack Command Line Build Arguments ------------------------------------
# NOTE: With this setup you can use environment variables or arguments and
# they'll do roughly the same thing.
for x_arg in $@ ; do declare ${x_arg}=1 ; done
if [[ -z "${msvc}" && -z "${clang}" ]] ; then clang=1 ; fi
if [[ -z "${release}" ]] ; then debug=1 ; fi
if [[ -n "${debug}" ]] ; then release= && rad_log "[debug mode]" ; fi
if [[ -n "${release}" ]] ; then debug= && rad_log "[release mode]" ; fi
if [[ -n "${msvc}" ]] ; then clang= && rad_log "[msvc compile]" ; fi
if [[ -n "${clang}" ]] ; then msvc= && rad_log "[clang compile]" ; fi
if [[ -z "$1" ]] ; then echo "[default mode, assuming 'raddbg' build]" && raddbg=1 ; fi
if [[ "$1" == "release" && -z "$2" ]] ; then
rad_log "[default mode, assuming 'raddbg' build]" && raddbg=1 ;
fi
if [[ -n "${msvc}" ]] ; then
clang=0
rad_log "You're going to have to figure out something else if you want to use \
anything even remotely MSVC related on Linux. Bailing."
exit 1
fi

set auto_compile_flags=
[[ -n "${telemetry}" ]] && auto_compile_flags="${auto_compile_flags} -DPROFILE_TELEMETRY=1" &&
rad_log "[telemetry profiling enabled]"
[[ -n "${asan}" ]] && auto_compile_flags="${auto_compile_flags} -fsanitize=address" &&
rad_log "[asan enabled]"

# --- Compile/Link Line Definitions ------------------------------------------
cl_common="/I../src/ /I../local/ /nologo /FC /Z7"
clang_common="-I../src/ -I../local -I/usr/include/freetype2/ -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf -Wl,-z,notext -std=c11 -D_DEFAULT_SOURCE=1"
clang_dynamic="-lpthread -ldl -lrt -latomic -lm -lfreetype -lEGL -lX11 -lGL -lXrandr -luuid"
clang_errors="-Werror=atomic-memory-ordering -Wno-parentheses"
cl_debug="cl /Od /Ob1 /DBUILD_DEBUG=1 ${cl_common} ${auto_compile_flags}"
cl_release="cl /O2 /DBUILD_DEBUG=0 ${cl_common} ${auto_compile_flags}"
clang_debug="clang -g -O0 -DBUILD_DEBUG=1 ${clang_common} ${clang_dynamic} ${clang_errors} ${auto_compile_flags}"
clang_release="clang -g -O2 -DBUILD_DEBUG=0 ${clang_common} ${clang_dynamic} ${clang_errors} ${auto_compile_flags}"
cl_link="/link /MANIFEST:EMBED /INCREMENTAL:NO \
/natvis:'${self_directory}/src/natvis/base.natvis' logo.res"
clang_link="-fuse-ld=ld"
cl_out="/out:"
clang_out="-o"

# --- Per-Build Settings -----------------------------------------------------
link_dll="-DLL"
[[ -n "${msvc}" ]] && only_compile="/c"
[[ -n "${clang}" ]] && only_compile="-c"
[[ -n "${msvc}" ]] && EHsc="/EHsc"
[[ -n "${clang}" ]] && EHsc=""
[[ -n "${msvc}" ]] && no_aslr="/DYNAMICBASE:NO"
[[ -n "${clang}" ]] && no_aslr="-Wl,/DYNAMICBASE:NO"
[[ -n "${msvc}" ]] && rc="rc"
[[ -n "${clang}" ]] && rc="llvm-rc"
[[ -n "${gcodeview}" ]] && clang_common="${clang_common} -gcodeview"

# --- Choose Compile/Link Lines ----------------------------------------------
if [[ -n "${msvc}" ]] ; then compile_debug="${cl_debug}" ; fi
if [[ -n "${msvc}" ]] ; then compile_release="${cl_release}" ; fi
if [[ -n "${msvc}" ]] ; then compile_link="${cl_link}" ; fi
if [[ -n "${msvc}" ]] ; then out="${cl_out}" ; fi
if [[ -n "${clang}" ]] ; then compile_debug="${clang_debug}" ; fi
if [[ -n "${clang}" ]] ; then compile_release="${clang_release}" ; fi
if [[ -n "${clang}" ]] ; then compile_link="${clang_link}" ; fi
if [[ -n "${clang}" ]] ; then out="${clang_out}" ; fi
if [[ -n "${debug}" ]] ; then compile="${compile_debug}" ; fi
if [[ -n "${release}" ]] ; then compile="${compile_release}" ; fi

# --- Prep Directories -------------------------------------------------------
# Si
mkdir -p "build"
mkdir -p "local"

# --- Produce Logo Icon File -------------------------------------------------
cd build
# TODO(mallchad): "Linux cannot embed icons in exes :( build a .desktop file instead
cd "${self_directory}"

# --- Get Current Git Commit Id ----------------------------------------------
# for /f ${}i in ('call git describe --always --dirty') do set compile=${compile} -DBUILD_GIT_HASH=\"${}i\"
# NOTE(mallchad): I don't really understand why this written has a loop. Is it okay without?
compile="${compile} -DBUILD_GIT_HASH=\"$(git describe --always --dirty)\""

rad_debug_log "Compile Command: "
rad_debug_log "${compile}"

# --- Build & Run Metaprogram ------------------------------------------------
if [[ -n "${no_meta}" ]] ; then
rad_log "[skipping metagen]"
else
cd build
${compile_debug} "../src/metagen/metagen_main.c" ${compile_link} "${out}metagen.exe" || exit 1
# Skip if compile only
[[ -z "${RAD_META_COMPILE_ONLY}" ]] && (./metagen.exe || exit 1)
cd ${self_directory}
fi

# --- Build Everything (@build_targets) --------------------------------------

function finish()
{
rad_log "Some unexpected command failed unexpectedly. ${ansi_red}Line: $1 ${ansi_reset}"
exit 1
}

function get_epoch()
{
echo "$(date +%s)"
}

# @param $1 - name of file to compile
# @param $2 - name of executable to output as
# @param $@ - rest is any arguments provided
function build_single()
{
local binary=$2
rad_log "Building '${binary}'"
didbuild=1

build_start=$(get_epoch)
${compile} "$1" ${@:3:100} ${compile_link} "${out}$2"
status=$?
build_end=$(get_epoch)
time_elapsed=$((build_end - build_start))

rad_log "Compilation Time: $ansi_cyanbold \
$((time_elapsed / 60))min $((time_elapsed % 60))s $ansi_reset"
if [[ "${status}" != 0 ]] ; then
rad_log "A standalone build command didn't complete successfully. \
${ansi_red}Line: ${BASH_LINENO[$i]} ${ansi_reset}" ;
exit ${status} ;
fi
return ${status}
}

function build_dll()
{
local binary=$2
rad_log "Building '${binary}'"
didbuild=1
${compile} "$1" ${compile_link} ${@:3:100} ${link_dll} "${out}$2"
return $?
}

cd build
[[ -n "${raddbg}" ]] && build_single ../src/raddbg/raddbg_main.c raddbg.exe
[[ -n "${rdi_from_pdb}" ]] && build_single ../src/rdi_from_pdb/rdi_from_pdb_main.c rdi_from_pdb.exe
[[ -n "${rdi_from_dwarf}" ]] && build_single ../src/rdi_from_dwarf/rdi_from_dwarf.c rdi_from_dwarf.exe
[[ -n "${rdi_dump}" ]] && build_single ../src/rdi_dump/rdi_dump_main.c rdi_dump.exe
[[ -n "${rdi_breakpad_from_pdb}" ]] && build_single ../src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c rdi_breakpad_from_pdb.exe
[[ -n "${ryan_scratch}" ]] && build_single ../src/scratch/ryan_scratch.c ryan_scratch.exe
[[ -n "${cpp_tests}" ]] && build_single ../src/scratch/i_hate_c_plus_plus.cpp cpp_tests.exe
[[ -n "${look_at_raddbg}" ]] && build_single ../src/scratch/look_at_raddbg.c look_at_raddbg.exe
if [[ -n "${mule_main}" ]] ; then
didbuild=1
rm -v vc*.pdb mule*.pdb
${compile_release} ${only_compile} ../src/mule/mule_inline.cpp &&
${compile_release} ${only_compile} ../src/mule/mule_o2.cpp &&
${compile_debug} ${EHsc} ../src/mule/mule_main.cpp ../src/mule/mule_c.c \
"mule_inline.o" "mule_o2.o" ${compile_link} ${no_aslr} \
${out} mule_main.exe || exit 1
fi

# Continue building the rest line normal
[[ -n "${mule_module}" ]] && $(build_dll ../src/mule/mule_module.cpp mule_module.dll || finish ${LINENO} )
[[ -n "${mule_hotload}" ]] && $(build_single ../src/mule/mule_hotload_main.c mule_hotload.exe &&
build_dll ../src/mule/mule_hotload_module_main.c mule_hotload_module.dll || finish ${LINENO})

if [[ -n "${mule_peb_trample}" ]] ; then
didbuild=1
[[ -f "mule_peb_trample.exe" ]] && mv "mule_peb_trample.exe" "mule_peb_trample_old_${random}.exe"
[[ -f "mule_peb_trample_new.pdb" ]] && mv "mule_peb_trample_new.pdb" "mule_peb_trample_old_${random}.pdb"
[[ -f "mule_peb_trample_new.rdi" ]] && mv "mule_peb_trample_new.rdi" "mule_peb_trample_old_${random}.rdi"
build_single "../src/mule/mule_peb_trample.c" "mule_peb_trample_new.exe"
mv "mule_peb_trample_new.exe" "mule_peb_trample.exe"
fi
cd "${self_directory}"

# --- Unset ------------------------------------------------------------------
# NOTE: Shouldn't need to unset, bash variables are volatile, even environment variables

# --- Warn On No Builds ------------------------------------------------------
if [[ -z "${didbuild}" ]] ; then
rad_log "[WARNING] no valid build target specified; must use build target names as arguments to this script, like `build raddbg` or `build rdi_from_pdb`."
exit 1
else
rad_log "Build Finished!"
exit 0
fi
7 changes: 7 additions & 0 deletions documentation/bugs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# #1 - codegen bug with clang
For some reason I encountered a spurious bug where clang tries to use aligned
instructions like `movaps` on addresses that are unaligned, but only when you
are unfortunate enough to change the program entry point. As well as just
generally destroying the program stack. Adding the argument `-mrealignstack`
seems to alleviate it somehow, so this should be added if segfaults are seen in
a suspicious location again
42 changes: 42 additions & 0 deletions documentation/build_system.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Build System
Each of the `build.bat` and `build.sh ` files have a bit of extra documentation
in the header of the file. Please read that for more info.

# Linux Version
All of the Linux build.sh arguments have been set up in a way where you can
specify it as command line arguments or environment variables. This is by pure
coincidence, but it does work, and it is nice.

This version has as close to feature parity with the build.bat as possible, even
though a lot of the commands are semi-nonsense unless using something niche like
mingw, but its being left that way as to not make any assumptions for the time
being to allow any major changes to be left to somebody better informed in the
future. One notable change is the removal of the logo embed because
unfortunately Linux does not have an equivilent of that, however in the future
this can be turned into a `.desktop` file.

## TODO
- [ ] Make a `.desktop` file on build

## Compiler Flags
* -lpthread | POSIX threading library
* -ldl | dynamic linking library
* -lrt | realtime time library for clock functionality
* -lfreetype | freetype font provider library
* -latomic | GLIBC atomic intrinsics
* -m | Standard Math Library
* -Wno=parenthesis | Checks surprising gotchas with operator precedence, seems
mostly like basic noob trap mistakes, think we can ignore it here.
* -Werror=atomic-memory-ordering | This is probably an actual major bug if it appears.
* -std=c11 | pin version to some oldish C standard to try to increase version support
* -D_DEFAULT_SOURCE=1 provides missing definitions like 'futimes' that vanish when '-std=c11' is used
It's not entirely clear why this works this way but _GNU_SOURCE=1 was providing it previously

## Linker Flags
* `-Wl,-z,notext` this linker flag was given to allow metagen to relocate data in the read only segment, it gave the option between that and "-fPIC". This is the exact compiler output.
```
ld.lld: error: can't create dynamic relocation R_X86_64_64 against local symbol in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
>>> defined in /tmp/metagen_main-705025.o
>>> referenced by metagen_main.c
>>> /tmp/metagen_main-705025.o:(mg_str_expr_op_symbol_string_table)
```
63 changes: 63 additions & 0 deletions src/base/base_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -560,3 +560,66 @@ ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_s
}
return read_size;
}
////////////////////////////////
// Generic Array Functions

B32
_ArrayAllocate(GenericArray* target, Arena* arena, U32 size, U32 item_size)
{
Assert(arena != NULL); // The arena parameter is incorrect
target->arena = arena;
target->size = size;
target->item_size = item_size;
target->data = arena_push(arena, (size * item_size));

return 1;
}

B32 _ArrayZero(GenericArray* target, U64 item_size)
{
MemoryZero(target->data, (target->size * item_size));
return 1;
}

// Candidate for inline
U64
_ArrayGetTailIndex(GenericArray* target)
{
return (target->head + target->head_size - 1);
}

B32 _ArrayGetTail(GenericArray* target, void* out, U32 item_size)
{
if (target->fast_unbounded && target->head_size <= 0) { return 0; }
U8* tail = target->data;
tail += (target->head + ((target->head_size - 1) * item_size));
MemoryCopy(out, tail, item_size);
return 1;
}

void*
_ArrayPushTail(GenericArray* target, void* item, U32 item_size)
{
if (target->fast_unbounded && (target->head + target->head_size >= target->size) && item)
{ return 0; }
U8* new_tail = target->data;
new_tail += (target->head + (target->head_size * item_size));

// Return a new object
if (item != NULL)
{ MemoryCopy(new_tail, item, item_size); }
++(target->head_size);
return new_tail;
}

B32
_ArrayPopTail(GenericArray* target, void* out, U32 item_size)
{
if (target->fast_unbounded && (target->head_size <= 0))
{ return 0; }
U8* tail = target->data;
tail += (target->head + ((target->head_size -1) * item_size));
MemoryCopy(out, tail, item_size);
--(target->head_size);
return 1;
}
Loading