Skip to content

Make cross-compilation easier#56

Open
MysteryBlokHed wants to merge 3 commits intoCordyJ:mainfrom
MysteryBlokHed:easier-cross-compiling
Open

Make cross-compilation easier#56
MysteryBlokHed wants to merge 3 commits intoCordyJ:mainfrom
MysteryBlokHed:easier-cross-compiling

Conversation

@MysteryBlokHed
Copy link
Copy Markdown
Contributor

@MysteryBlokHed MysteryBlokHed commented Mar 19, 2026

This PR makes a handful of small changes to help make cross-compilation easier. Specifically:

  1. It allows CC and LD in the csrc Makefile to be overridden by environment variables. This is useful because it allows build systems to define cross-compiler binary tool paths in $CC and $LD without needing to manually pass them to make (previously would require make CC=$CC LD=$CC). (Undone since make's own defaults would actually render these statements useless)
    Flags that were previously part of the CC variable were moved to the start of CFLAGS, so that setting a custom compiler does not make compilation fail due to the lack of -Wno-error=int-conversion.
    It also defines a STRIP option, so that the strip binary can be similarly overridden.

    These changes make it easier to cross-compile OpenTxl itself to other platforms. For example:

    $ make csrc
    $ cd csrc
    $ make CC=aarch64-linux-gnu-gcc LD=aarch64-linux-gnu-gcc STRIP=aarch64-linux-gnu-strip
  2. It allows using a custom C compiler for txlc, as well as passing different TXLLIB directories to use for the build system vs. the target system. The build system's BUILD_TXLLIB is used for any files that need to be executed at build time (in particular txlcvt.x), while the target system's TARGET_TXLLIB is used to provide Txl .o files for the target architecture. The default is to use the standard cc compiler, and to use the same TXLLIB for both build and target.

    These changes make it easier to cross-compile Txl programs to other platforms. For example, one could compile a Txl program on an x86-64 build system to run on an AArch64 (ARM) target system like so:

    $ CC=aarch64-linux-gnu-gcc BUILD_TXLLIB=/path/to/host/txl/lib TARGET_TXLLIB=/path/to/aarch64/txl/lib txlc program.txl

    Where the AArch64 lib files could themselves come from cross-compiling OpenTxl to AArch64.

@MysteryBlokHed MysteryBlokHed force-pushed the easier-cross-compiling branch from a337577 to e14a69f Compare March 19, 2026 14:29
@CordyJ
Copy link
Copy Markdown
Owner

CordyJ commented Mar 26, 2026

Hi, have these changes been tested on all of the currently supported distribution platforms? In particular, do they work for MacOS, LInux, Windows 10/11, Cygwin, Msys64, and the 32-bit versions?

@MysteryBlokHed
Copy link
Copy Markdown
Contributor Author

From an x86-64 Linux host, I've tested compiling for 32-bit Linux, AArch64 Linux, Cygwin, and MinGW. I couldn't test cross-compiling to Darwin because compiling to Darwin on a Linux build system isn't supported (little to no distro support + technically violates the terms of Xcode).

The only issue I had is needing to manually define -DWIN for MinGW. So that might be worth adding to CFLAGS here (which I could do if desired):

else ifeq ($(OS), MSYS)
MESSAGE = "Making TXL on Msys / MinGW using gcc and BSD signal handling"
LDFLAGS := $(LDFLAGS) -Wl,--stack,0x2000000
EXE = .exe
SIGTYPE = BSD
else ifeq ($(OS), MINGW64)
MESSAGE = "Making TXL on Msys / MinGW using gcc and BSD signal handling"
LDFLAGS := $(LDFLAGS) -Wl,--stack,0x2000000
EXE = .exe
SIGTYPE = BSD

Tested using this script to verify that builds succeed for each platform:

See script
#!/usr/bin/env bash
set -euo pipefail

declare -A sys_native=(
    [CC]="cc -std=gnu89"
    [LD]="cc"
    [STRIP]="strip"
    [OS]="$(uname -s)"
)

declare -A sys_linux32=(
    [CC]="i686-unknown-linux-gnu-cc -std=gnu89"
    [LD]="i686-unknown-linux-gnu-cc"
    [STRIP]="i686-unknown-linux-gnu-strip"
    [OS]="Linux"
)

declare -A sys_aarch64=(
    [CC]="aarch64-unknown-linux-gnu-cc -std=gnu89"
    [LD]="aarch64-unknown-linux-gnu-cc"
    [STRIP]="aarch64-unknown-linux-gnu-strip"
    [OS]="Linux"
)

declare -A sys_cygwin=(
    [CC]="x86_64-pc-cygwin-cc -std=gnu89"
    [LD]="x86_64-pc-cygwin-cc"
    [STRIP]="x86_64-pc-cygwin-strip"
    [OS]="CYGWIN"
)

declare -A sys_mingw=(
    [CC]="x86_64-w64-mingw32-cc -std=gnu89 -DWIN"
    [LD]="x86_64-w64-mingw32-cc -DWIN"
    [STRIP]="x86_64-w64-mingw32-strip"
    [OS]="MSYS"
)

systems=("sys_native" "sys_linux32" "sys_aarch64" "sys_cygwin" "sys_mingw")

make -f Makefile-C clean
make csrc
cd csrc
echo ""

for sys_name in "${systems[@]}"; do
    declare -n current_sys="$sys_name"
    
    echo "========================="
    echo "Building target: $sys_name"
    echo "========================="
    
    make clean
    
    make \
        CC="${current_sys[CC]}" \
        LD="${current_sys[LD]}" \
        STRIP="${current_sys[STRIP]}" \
        OS="${current_sys[OS]}"
        
    unset -n current_sys
    
    echo "Finished $sys_name."
    echo ""
done

I also ran the regression tests with the AArch64 binary via QEMU (by modifying the test file as below), and everything passed:

diff --git a/test/regression/TestAll.sh b/test/regression/TestAll.sh
index 35df870..c1a9dc5 100755
--- a/test/regression/TestAll.sh
+++ b/test/regression/TestAll.sh
@@ -1,11 +1,11 @@
-#!/bin/bash
+#!/usr/bin/env bash
 
 # OpenTxl Regression Test script
 # J.R. Cordy, October 2022
 
 # The TXLs to compare
-OLDTXL=/usr/local/bin/txl
-NEWTXL=../../bin/txl
+OLDTXL=$(which txl)
+NEWTXL="qemu-aarch64 ../../bin/txl"
 
 if [ ! -x $OLDTXL ]; then
     echo "ERROR: No installed TXL to compare to ($OLDTXL)"
@@ -22,32 +22,32 @@ ulimit -s hard
 echo "42" > /tmp/42
 
 # Clean up old results
-/bin/rm -f */*-oldoutput */*-newoutput
+rm -f */*-oldoutput */*-newoutput
 
 # Keep track of success
 echo "==== TESTING ===="
 success=true
 
 # For all of the tests in the regression set
-dirs=`/bin/ls`
+dirs=`ls`
 
 for dir in $dirs; do
     if [ -d $dir ]; then
         cd $dir
 
         # For each example input
-        egs=`/bin/ls eg*.*`
+        egs=`ls eg*.*`
 
         for eg in $egs; do
             # Run old TXL
             : > /tmp/tta-old$$
-            (/usr/bin/time $OLDTXL -v -s 400 -w 200 $eg -o /tmp/tta-old$$ < /tmp/42 2>&1 ) >> $eg-oldoutput
+            (time $OLDTXL -v -s 400 -w 200 $eg -o /tmp/tta-old$$ < /tmp/42 2>&1 ) >> $eg-oldoutput
             cat /tmp/tta-old$$ >> $eg-oldoutput
             grep "TXL0" $eg-oldoutput >> /tmp/tta-old$$
 
             # Run new TXL
             : > /tmp/tta-new$$
-            (/usr/bin/time ../$NEWTXL -v -s 400 -w 200 $eg -o /tmp/tta-new$$ < /tmp/42 2>&1 ) >> $eg-newoutput
+            (time $NEWTXL -v -s 400 -w 200 $eg -o /tmp/tta-new$$ < /tmp/42 2>&1 ) >> $eg-newoutput
             cat /tmp/tta-new$$ >> $eg-newoutput
             grep "TXL0" $eg-newoutput >> /tmp/tta-new$$

Allows overriding CC and LD with environment variables, and adds an
option to override the STRIP binary. This is useful when
cross-compiling, since the binary tool names are usually different.
When using a cross-compiling C compiler, this allows `txlc` to be used
to cross-compile to another platform by using the build system's library
for `BUILD_TXLLIB` and the target system's library for `TARGET_TXLLIB`.
@MysteryBlokHed MysteryBlokHed force-pushed the easier-cross-compiling branch from 1040f07 to 424fe53 Compare March 28, 2026 03:17
@MysteryBlokHed
Copy link
Copy Markdown
Contributor Author

The only issue I had is needing to manually define -DWIN for MinGW. So that might be worth adding to CFLAGS here (which I could do if desired):

else ifeq ($(OS), MSYS)
MESSAGE = "Making TXL on Msys / MinGW using gcc and BSD signal handling"
LDFLAGS := $(LDFLAGS) -Wl,--stack,0x2000000
EXE = .exe
SIGTYPE = BSD
else ifeq ($(OS), MINGW64)
MESSAGE = "Making TXL on Msys / MinGW using gcc and BSD signal handling"
LDFLAGS := $(LDFLAGS) -Wl,--stack,0x2000000
EXE = .exe
SIGTYPE = BSD

Implemented in 1040f07..424fe53

@CordyJ
Copy link
Copy Markdown
Owner

CordyJ commented Mar 30, 2026

Thanks - my question was not about whether cross-compiling works, it was whether compiling works on each platform itself, directly. The different C compilers require different CFLAGS for each platform, and I'm worried that your changes may have inadvertently invalidated the make chain on one of them. When I get time I'll check them mysefl if you like, I have all ten or twelve of the most common ones available.

@MysteryBlokHed
Copy link
Copy Markdown
Contributor Author

my question was not about whether cross-compiling works, it was whether compiling works on each platform itself, directly.

Ah, I misunderstood. I've tested building natively on x86-64 Linux and on an M-series MacBook and it seems to work as before, but if you could check the other platforms that would be great.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants