From 42a901b7f51b9283974a3e0a9fb3bd63ddb9d193 Mon Sep 17 00:00:00 2001 From: Jordan Bancino Date: Wed, 1 Nov 2023 20:35:48 -0400 Subject: [PATCH 1/3] Update docs/dev/rationale.md --- docs/dev/rationale.md | 65 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/docs/dev/rationale.md b/docs/dev/rationale.md index 5358bc2..5c2cc1d 100644 --- a/docs/dev/rationale.md +++ b/docs/dev/rationale.md @@ -39,12 +39,71 @@ Telodendria that Conduit lacks. ### Small Dependency Chain -**TODO:** See #30. +Conduit's dependency chain is quite large. What this means is that +Conduit depends on a lot of code that it does not control, making it +vulnerable to supply chain attacks. A problem with Rust Crates +is that they are developer-published, so they don't go through any sort +of auditing process like a Debian package would, for example. + If any one of the dependencies is +hijacked or otherwise compromised, then Conduit itself is compromised +and it is likely that this would go unnoticed for quite a while. While +one could argue that this is extremely unlikely to happen, sometimes you +just don't want to take that risk, especially not if you're deploying a +Matrix homeserver, likely for the purpose of secure, private chat. + +Telodendria doesn't pull in any packages from developer repositories, so +the risk of supply chain attacks is much lower. It +only uses its own code and code provided by the operating system it is running +on, which has been vetted by a large number of developers and can be trusted +due to the sheer scope of an operating system. A supply chain attack against +Telodendria would be a supply chain attack against the entire operating system; +at that point, end users have much bigger problems. + +Minimal dependencies doesn't only mitigate supply chain attacks. It also makes +maintenance much easier. Telodendria can spend more time writing code than +Conduit because Conduit developers have to ensure dependencies stay up to date and +when they inevitably break things, Conduit must pause development to fix those. +Telodendria doesn't suffer from this problem: because most of the code is developed +along side of Telodendria, it can remain as stable or become as volatile as the +developers choose. Additionally, because Telodendria is so low-level, the code on +which it depends is extremely unlikely to be changed in any significant way, +since so many other programs depend on that code. ### Standardized -**TODO:** See #30. +Conduit is written in Rust, which has no formal standard. This makes it less than +ideal for long-lived software projects, because it changes frequently and often +breaks existing code. Telodendria is written in C, a stable, mature, and standardized +language that will always compile the same code the same way, making it more +portable and sustainable for the future because we don't ever have to worry about +upgrading our toolchain—using standard tools built into most operating systems +will suffice. + +Because the language in which Telodendria is written never changes, Telodendria can +continually optimize and improve the code, instead of having to fix breaking changes. +This ensures that Telodendria's code will last. Rust code becomes obsolete with in a +few years at best—programs written in Rust last year probably won't compile or run +properly on the latest Rust toolchain. Telodendria, on the other hand, is written in C89, +which compiled and ran the same way in 1989 as it does today and will continue to for the +foreseeable future. + +### Fast Compile Times + +Rust is well-known for taking an extremely long time to compile moderately-sized +programs. Since a Matrix homeserver is such a large project, the compile times would +be prohibitively large for rapid development. By writing Telodendria in C, we can take +advantage of decades worth of compiler optimizations and speed improvements, resulting +in extremely fast builds. ### Portable -**TODO:** See #30. +One does not typically think of C as more portable than something like Rust, but +Telodendria is written in such a way that it is. Rust relies on LLVM, which doesn't +support some strange or exotic architectures in the same way that a specialized C +compiler for those architectures will. This allows users to run Telodendria on the +hardware of their choice, even if that hardware is so strange that the modern world +has totally left it behind. + +Telodendria doesn't just aim at being lightweight and portable, it aims to empower +people to use common hardware that they already have, even if it is typically thought +of as underpowered. From 582c79b6089227de421ca56031f19050aa02b24f Mon Sep 17 00:00:00 2001 From: Jordan Bancino Date: Sat, 4 Nov 2023 15:28:20 -0400 Subject: [PATCH 2/3] Schema are now generated out-of-tree. Closes #40. --- configure | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/configure b/configure index 2dc0aec..c7887e0 100755 --- a/configure +++ b/configure @@ -14,7 +14,7 @@ INCLUDE="src/include" TOOLS="tools/src" SCHEMA="Schema" -CFLAGS="-Wall -Wextra -pedantic -std=c89 -O3 -pipe -D_DEFAULT_SOURCE -I${INCLUDE}" +CFLAGS="-Wall -Wextra -pedantic -std=c89 -O3 -pipe -D_DEFAULT_SOURCE -I${INCLUDE} -I${BUILD}" LIBS="-lm -pthread -lCytoplasm" @@ -112,8 +112,10 @@ compile_obj() { src="$1" obj="$2" - pref=$(cc -I${INCLUDE} -MM -MT "${obj}" "${src}") - echo "$pref $(collect ${SCHEMA}/ .json .h ${INCLUDE}/Schema/ print_obj)" + # TODO: Add a --cc flag to set the C compiler to use for + # Makefile generation. + pref=$(cc -I${INCLUDE} -I${BUILD} -MM -MT "${obj}" "${src}") + echo "$pref $(collect ${SCHEMA}/ .json .h ${BUILD}/Schema/ print_obj)" echo "${TAB}@mkdir -p $(dirname ${obj})" echo "${TAB}\$(CC) \$(CFLAGS) -fPIC -c -o \"${obj}\" \"${src}\"" } @@ -153,13 +155,19 @@ compile_schema() { src="$1" out="$2" - echo "${INCLUDE}/Schema/${out}.h:" - echo "${TAB}@mkdir -p ${INCLUDE}/Schema ${SRC}/Schema" - echo "${TAB}j2s -s \"${src}\" -h \"${INCLUDE}/Schema/${out}.h\" -c \"${SRC}/Schema/${out}.c\"" + obj="${BUILD}/Schema/${out}.o" - echo "${SRC}/Schema/${out}.c:" - echo "${TAB}@mkdir -p ${INCLUDE}/Schema ${SRC}/Schema" - echo "${TAB}j2s -s \"${src}\" -h \"${INCLUDE}/Schema/${out}.h\" -c \"${SRC}/Schema/${out}.c\"" + echo "${BUILD}/Schema/${out}.h:" + echo "${TAB}@mkdir -p ${BUILD}/Schema" + echo "${TAB}j2s -s \"${src}\" -h \"${BUILD}/Schema/${out}.h\" -c \"${BUILD}/Schema/${out}.c\"" + + echo "${BUILD}/Schema/${out}.c:" + echo "${TAB}@mkdir -p ${BUILD}/Schema" + echo "${TAB}j2s -s \"${src}\" -h \"${BUILD}/Schema/${out}.h\" -c \"${BUILD}/Schema/${out}.c\"" + + echo "${obj}: ${src} ${BUILD}/Schema/${out}.c" + echo "${TAB}@mkdir -p ${BUILD}/Schema" + echo "${TAB}\$(CC) \$(CFLAGS) -fPIC -c -o \"${obj}\" \"${BUILD}/Schema/${out}.c\"" } install_out() { @@ -185,15 +193,9 @@ uninstall_out() { echo "Generating Makefile..." -OBJS=$(collect ${SRC}/ .c .o ${BUILD}/ print_obj) +OBJS="$(collect ${SRC}/ .c .o ${BUILD}/ print_obj) $(collect ${SCHEMA}/ .json .o ${BUILD}/Schema/ print_obj)" TAB=$(printf '\t') -# If objects don't include the schema (this is the first configure), -# then include them manually. -if ! echo "${OBJS}" | grep "Schema" > /dev/null; then - OBJS="${OBJS} $(collect ${SCHEMA}/ .json .o ${BUILD}/Schema/ print_obj)" -fi - cat << EOF > Makefile .POSIX: From 1f02f3c2a290992d951ae9d83081cab9bc333c13 Mon Sep 17 00:00:00 2001 From: Jordan Bancino Date: Sat, 4 Nov 2023 15:56:57 -0400 Subject: [PATCH 3/3] Allow customization of compiler in configure. --- configure | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/configure b/configure index c7887e0..966eaf9 100755 --- a/configure +++ b/configure @@ -19,7 +19,7 @@ LIBS="-lm -pthread -lCytoplasm" # Set default args for all platforms -SCRIPT_ARGS="--prefix=/usr/local --enable-ld-extra --bin-name=telodendria --version=0.4.0 --static $@" +SCRIPT_ARGS="--cc=cc --prefix=/usr/local --enable-ld-extra --bin-name=telodendria --version=0.4.0 --static $@" echo "Processing options..." echo "Ran with arguments: $SCRIPT_ARGS" @@ -27,6 +27,9 @@ echo "Ran with arguments: $SCRIPT_ARGS" # Process all arguments for arg in $SCRIPT_ARGS; do case "$arg" in + --cc=*) + CC=$(echo "$arg" | cut -d '=' -f 2-) + ;; --prefix=*) PREFIX=$(echo "$arg" | cut -d '=' -f 2-) ;; @@ -60,7 +63,7 @@ for arg in $SCRIPT_ARGS; do STATIC="" ;; *) - echo "Invalid argument: $1" + echo "Invalid argument: $arg" exit 1 ;; esac @@ -112,9 +115,7 @@ compile_obj() { src="$1" obj="$2" - # TODO: Add a --cc flag to set the C compiler to use for - # Makefile generation. - pref=$(cc -I${INCLUDE} -I${BUILD} -MM -MT "${obj}" "${src}") + pref=$(${CC} -I${INCLUDE} -I${BUILD} -MM -MT "${obj}" "${src}") echo "$pref $(collect ${SCHEMA}/ .json .h ${BUILD}/Schema/ print_obj)" echo "${TAB}@mkdir -p $(dirname ${obj})" echo "${TAB}\$(CC) \$(CFLAGS) -fPIC -c -o \"${obj}\" \"${src}\"" @@ -202,7 +203,7 @@ cat << EOF > Makefile # Generated by '$0' on $(date). # This file should generally not be manually edited. -CC = cc +CC = ${CC} PREFIX = ${PREFIX} CFLAGS = ${CFLAGS} LDFLAGS = ${LDFLAGS}