1
QB64 Discussion / Changes To Auto Install/Run QB64 on Raspberry PI ARM Processors
« on: February 03, 2022, 06:56:17 pm »
I've have updates ready to QB64 that will automatically install it on a Raspberry PI and works properly, including DATA statements.
With Apple's new computers running the M1 ARM processor, and Intel (announced in June of 2021), along with AMD and Microsoft working together (announced in October of 2021) to develop ARM processors, QB64 needs to be able to run on these chips as well.
I have tested my changes, but I would like some others to check it out as well before I push the change on Gitub.
In my tests, I have even run compiled QB64 programs that use MariaDB and Zenity on the PI without issues. Pipecom runs without issues as well as $DEBUG. However, my testing has only been done on the 32bit Raspian OS. I do plan to test it with other Linux systems that run on the PI.
There were a number of changes needed, which most are automated in the setup_lnx.sh script. The other change was made directly to common.h.
The two files that changed are below, but here is what I needed to change.
common.h
Two of the issues I ran into had to do with mis-aligned addresses (int32 and int16 for example). To correct this, I either needed to add "-fsanitize=address" to the gcc statement, or add code to the common.h file for ARM processors. I was given the code by a C++ programmer who explained that, while not an issue with x86_64 or i386 processors, it is an issue with ARM processors. The code (see below) corrects this issue. She also gave me the corresponding code for the x86_64/i386, just in case. I've regression tested this on my x86_64 system, but others should also run it as well.
setup_lnx.sh
The setup script has a number of issues on ARM processors. The first is it doesn't download the libraries needed, and the other it created invalid link modules. To correct the first issue, the setup script now checks whether or not the processor is an ARM. If so, it sets DISTRO to "raspbian". The issue about the link/binary executables has to do with how the ARM processes bits. ARM processors are little endian (See note below). So the script replaces both the makedat_lnx32.txt and makedat_lnx64.txt files with the correct parameters for the OBJCOPY. ("-Oelf32-littlearm -Barm" replaced the original "-Oelf32-i386 -Bi386" in the 32bit file and the "-Oelf64-littlearm -Barm" replaced the "-Oelf64-x86-64 -Bi386:x86-64" in the 64bit file)
NOTE: Yes, Intel, AMD and the PI ARM chips are all little endian. However, from what I've read, the Intel and AMD chips convert the little endian to big endian. It has something to do with floating point. However, this does not seem to be the case with ARM processors, at least for the PI. From what I read, the Apple M1 is designed the same as that the PI's ARM. This change to the OBJCOPY allows DATA statements, among other things, to work. the -Barm tells OBJCOPY how to format the binary executable file. This is my understanding, which is of course, subject to interpretation, but the changes makes QB64 run and compile, and compiled programs also run on the PI.
To implement these changes, after extracting the QB64 compiler, you need to replace the common.h file in the qb64/internal/c directory, and the setup_lnx.sh file in the main qb64 directory. Then all you have to do is run the setup_lnx.sh file to install library dependencies and compile qb64.bas.
These changes should also work on the Apple M1 ARM processor, but I do not have one to test this on. If someone has a M1 ARM processor, I can provide the changes to the setup_osx.command script. You'll have to do the testing as I will not have a M1 processor until July.
Also, besides the M1 processor, I haven't been able to test is a 64bit OS on the Raspberry PI. Raspberry no longer offers the 64bit version of their Raspbian OS. So while I am looking for non-raspbian OS's to test on, if someone here is running, say Kali on a PI or an earlier version of the 64bit Raspbian OS, please test this. I will do so as well, but the more who tests this, the better. (This was suggested by Fellippe).
Some Issues:
When testing this on my PI, I was unable to get InForm to run. It compiles, but I get a series of errors from "Bus signal errors" to misaligned addresses. I am still looking into this, but I may need to defer to Fellippe or Luke on this, as I am not a C++ programmer, and in my C coding, I've never encountered these errors. I have run tests in gdb and ddd utilites to try and isolate the issue, but I am at a loss. If someone wants to tackle this on their PI, I'd appreciate it.
Here is the common.h file:
Here is the setup_lnx.sh file:
Thanks,
With Apple's new computers running the M1 ARM processor, and Intel (announced in June of 2021), along with AMD and Microsoft working together (announced in October of 2021) to develop ARM processors, QB64 needs to be able to run on these chips as well.
I have tested my changes, but I would like some others to check it out as well before I push the change on Gitub.
In my tests, I have even run compiled QB64 programs that use MariaDB and Zenity on the PI without issues. Pipecom runs without issues as well as $DEBUG. However, my testing has only been done on the 32bit Raspian OS. I do plan to test it with other Linux systems that run on the PI.
There were a number of changes needed, which most are automated in the setup_lnx.sh script. The other change was made directly to common.h.
The two files that changed are below, but here is what I needed to change.
common.h
Two of the issues I ran into had to do with mis-aligned addresses (int32 and int16 for example). To correct this, I either needed to add "-fsanitize=address" to the gcc statement, or add code to the common.h file for ARM processors. I was given the code by a C++ programmer who explained that, while not an issue with x86_64 or i386 processors, it is an issue with ARM processors. The code (see below) corrects this issue. She also gave me the corresponding code for the x86_64/i386, just in case. I've regression tested this on my x86_64 system, but others should also run it as well.
setup_lnx.sh
The setup script has a number of issues on ARM processors. The first is it doesn't download the libraries needed, and the other it created invalid link modules. To correct the first issue, the setup script now checks whether or not the processor is an ARM. If so, it sets DISTRO to "raspbian". The issue about the link/binary executables has to do with how the ARM processes bits. ARM processors are little endian (See note below). So the script replaces both the makedat_lnx32.txt and makedat_lnx64.txt files with the correct parameters for the OBJCOPY. ("-Oelf32-littlearm -Barm" replaced the original "-Oelf32-i386 -Bi386" in the 32bit file and the "-Oelf64-littlearm -Barm" replaced the "-Oelf64-x86-64 -Bi386:x86-64" in the 64bit file)
NOTE: Yes, Intel, AMD and the PI ARM chips are all little endian. However, from what I've read, the Intel and AMD chips convert the little endian to big endian. It has something to do with floating point. However, this does not seem to be the case with ARM processors, at least for the PI. From what I read, the Apple M1 is designed the same as that the PI's ARM. This change to the OBJCOPY allows DATA statements, among other things, to work. the -Barm tells OBJCOPY how to format the binary executable file. This is my understanding, which is of course, subject to interpretation, but the changes makes QB64 run and compile, and compiled programs also run on the PI.
To implement these changes, after extracting the QB64 compiler, you need to replace the common.h file in the qb64/internal/c directory, and the setup_lnx.sh file in the main qb64 directory. Then all you have to do is run the setup_lnx.sh file to install library dependencies and compile qb64.bas.
These changes should also work on the Apple M1 ARM processor, but I do not have one to test this on. If someone has a M1 ARM processor, I can provide the changes to the setup_osx.command script. You'll have to do the testing as I will not have a M1 processor until July.
Also, besides the M1 processor, I haven't been able to test is a 64bit OS on the Raspberry PI. Raspberry no longer offers the 64bit version of their Raspbian OS. So while I am looking for non-raspbian OS's to test on, if someone here is running, say Kali on a PI or an earlier version of the 64bit Raspbian OS, please test this. I will do so as well, but the more who tests this, the better. (This was suggested by Fellippe).
Some Issues:
When testing this on my PI, I was unable to get InForm to run. It compiles, but I get a series of errors from "Bus signal errors" to misaligned addresses. I am still looking into this, but I may need to defer to Fellippe or Luke on this, as I am not a C++ programmer, and in my C coding, I've never encountered these errors. I have run tests in gdb and ddd utilites to try and isolate the issue, but I am at a loss. If someone wants to tackle this on their PI, I'd appreciate it.
Here is the common.h file:
Code: C: [Select]
- //Setup for ARM Processor (Similar to -fsanitize=address GCC compiler flag)
- #ifdef __arm__
- #define POST_PACKED_STRUCTURE
- #else
- #define POST_PACKED_STRUCTURE __attribute__((__packed__))
- #endif /* ARM */
- //Fill out dependency macros
- #ifndef DEPENDENCY_NO_SOCKETS
- #define DEPENDENCY_SOCKETS
- #endif
- #ifndef DEPENDENCY_NO_PRINTER
- #define DEPENDENCY_PRINTER
- #endif
- #ifndef DEPENDENCY_NO_ICON
- #define DEPENDENCY_ICON
- #endif
- #ifndef DEPENDENCY_NO_SCREENIMAGE
- #define DEPENDENCY_SCREENIMAGE
- #endif
- #ifndef INC_COMMON_CPP
- #define INC_COMMON_CPP
- #include "os.h"
- #define QB64_GL1
- #define QB64_GLUT
- #ifdef DEPENDENCY_CONSOLE_ONLY
- #undef QB64_GLUT
- #else
- #define QB64_GUI
- #endif
- //core
- #ifdef QB64_GUI
- #ifdef QB64_GLUT
- //This file only contains header stuff
- #include "parts/core/src.c"
- #endif
- #endif
- #ifdef QB64_WINDOWS
- #ifndef QB64_GUI
- #undef int64 //definition of int64 from os.h conflicts with a definition within windows.h, temporarily undefine then redefine
- #include <windows.h>
- #define int64 __int64
- #endif
- #include <shfolder.h>
- #include <float.h>
- #include <winbase.h>
- #endif
- //common includes
- #include <stdio.h>
- #ifdef QB64_MACOSX
- #include <cmath>
- #else
- //#include <math.h> //<-causes overloading abs conflicts in Windows
- #include <cmath>
- #endif
- #include <time.h>
- #include <iostream>
- #include <fstream>
- #include <time.h>
- #include <string.h>
- #include <errno.h>
- #include <fcntl.h>
- //OS/compiler specific includes
- #ifdef QB64_WINDOWS
- #include <direct.h>
- #ifdef DEPENDENCY_PRINTER
- #include <winspool.h>
- #endif
- #include <csignal>
- #include <process.h> //required for multi-threading
- #if defined DEPENDENCY_AUDIO_OUT || defined QB64_GUI
- #include <mmsystem.h>
- #endif
- #else
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #include <stdint.h>
- #include <pthread.h>
- #ifndef QB64_MACOSX
- #include <dlfcn.h>
- #endif
- #endif
- #ifdef QB64_GUI
- #ifdef QB64_GLUT
- #include "parts/core/gl_headers/opengl_org_registery/glext.h"
- #endif
- #endif
- //QB64 string descriptor structure
- struct qbs_field{
- int32 fileno;
- int64 fileid;
- int64 size;
- int64 offset;
- };
- struct qbs{
- uint8 *chr;//a 32 bit pointer to the string's data
- int32 len;//must be signed for comparisons against signed int32s
- uint8 in_cmem;//set to 1 if in the conventional memory DBLOCK
- uint16 *cmem_descriptor;
- uint16 cmem_descriptor_offset;
- uint32 listi;//the index in the list of strings that references it
- uint8 tmp;//set to 1 if the string can be deleted immediately after being processed
- uint32 tmplisti;//the index in the list of strings that references it
- uint8 fixed;//fixed length string
- uint8 readonly;//set to 1 if string is read only
- qbs_field *field;
- };
- struct img_struct{
- void *lock_offset;
- int64 lock_id;
- uint8 valid;//0,1 0=invalid
- uint8 text;//if set, surface is a text surface
- uint8 console;//dummy surface to absorb unimplemented console functionality
- uint16 width,height;
- uint8 bytes_per_pixel;//1,2,4
- uint8 bits_per_pixel;//1,2,4,8,16(text),32
- uint32 mask;//1,3,0xF,0xFF,0xFFFF,0xFFFFFFFF
- uint16 compatible_mode;//0,1,2,7,8,9,10,11,12,13,32,256
- uint32 color,background_color,draw_color;
- uint32 font;//8,14,16,?
- int16 top_row,bottom_row;//VIEW PRINT settings, unique (as in QB) to each "page"
- int16 cursor_x,cursor_y;//unique (as in QB) to each "page"
- uint8 cursor_show, cursor_firstvalue, cursor_lastvalue;
- union{
- uint8 *offset;
- uint32 *offset32;
- };
- uint32 flags;
- uint32 *pal;
- int32 transparent_color;//-1 means no color is transparent
- uint8 alpha_disabled;
- uint8 holding_cursor;
- uint8 print_mode;
- //BEGIN apm ('active page migration')
- //everything between apm points is migrated during active page changes
- //note: apm data is only relevent to graphics modes
- uint8 apm_p1;
- int32 view_x1,view_y1,view_x2,view_y2;
- int32 view_offset_x,view_offset_y;
- float x,y;
- uint8 clipping_or_scaling;
- float scaling_x,scaling_y,scaling_offset_x,scaling_offset_y;
- float window_x1,window_y1,window_x2,window_y2;
- double draw_ta;
- double draw_scale;
- uint8 apm_p2;
- //END apm
- };
- //img_struct flags
- #define IMG_FREEPAL 1 //free palette data before freeing image
- #define IMG_SCREEN 2 //img is linked to other screen pages
- #define IMG_FREEMEM 4 //if set, it means memory must be freed
- //QB64 internal variable type flags (internally referenced by some C functions)
- #define ISSTRING 1073741824
- #define ISFLOAT 536870912
- #define ISUNSIGNED 268435456
- #define ISPOINTER 134217728
- #define ISFIXEDLENGTH 67108864 //only set for strings with pointer flag
- #define ISINCONVENTIONALMEMORY 33554432
- #define ISOFFSETINBITS 16777216
- struct ontimer_struct{
- uint8 allocated;
- uint32 id;//the event ID to trigger (0=no event)
- int64 pass;//the value to pass to the triggered event (only applicable to ON ... CALL ...(x)
- uint8 active;//0=OFF, 1=ON, 2=STOP
- uint8 state;//0=untriggered,1=triggered
- double seconds;//how many seconds between events
- double last_time;//the last time this event was triggered
- };
- struct onkey_struct{
- uint32 id;//the event ID to trigger (0=no event)
- int64 pass;//the value to pass to the triggered event (only applicable to ON ... CALL ...(x)
- uint8 active;//0=OFF, 1=ON, 2=STOP
- uint8 state;//0=untriggered,1=triggered,2=in progress(TIMER only),2+=multiple events queued(KEY only)
- uint32 keycode;//32-bit code, same as what _KEYHIT returns
- uint32 keycode_alternate;//an alternate keycode which may also trigger event
- uint8 key_scancode;
- uint8 key_flags;
- //flags:
- //0 No keyboard flag, 1-3 Either Shift key, 4 Ctrl key, 8 Alt key,32 NumLock key,64 Caps Lock key, 128 Extended keys on a 101-key keyboard
- //To specify multiple shift states, add the values together. For example, a value of 12 specifies that the user-defined key is used in combination with the Ctrl and Alt keys.
- qbs *text;
- };
- struct onstrig_struct{
- uint32 id;//the event ID to trigger (0=no event)
- int64 pass;//the value to pass to the triggered event (only applicable to ON ... CALL ...(x)
- uint8 active;//0=OFF, 1=ON, 2=STOP
- uint8 state;//0=untriggered,1=triggered,2=in progress(TIMER only),2+=multiple events queued(KEY only)
- };
- struct byte_element_struct
- {
- uint64 offset;
- int32 length;
- };
- struct device_struct{
- int32 used;
- int32 type;
- //0=Unallocated
- //1=Joystick/Gamepad
- //2=Keybaord
- //3=Mouse
- char *name;
- int32 connected;
- int32 lastbutton;
- int32 lastaxis;
- int32 lastwheel;
- //--------------
- int32 max_events;
- int32 queued_events;
- uint8 *events;//the structure and size of the events depends greatly on the device and its capabilities
- int32 event_size;
- //--------------
- uint8 STRIG_button_pressed[256];//checked and cleared by the STRIG function
- //--------------
- void *handle_pointer;//handle as pointer
- int64 handle_int;//handle as integer
- char *description;//description provided by manufacturer
- int64 product_id;
- int64 vendor_id;
- int32 buttons;
- int32 axes;
- int32 balls;
- int32 hats;
- };
- //device_struct constants
- #define QUEUED_EVENTS_LIMIT 1024
- #define DEVICETYPE_CONTROLLER 1
- #define DEVICETYPE_KEYBOARD 2
- #define DEVICETYPE_MOUSE 3
- struct mem_block{
- ptrszint offset;
- ptrszint size;
- int64 lock_id;//64-bit key, must be present at lock's offset or memory region is invalid
- ptrszint lock_offset;//pointer to lock
- ptrszint type;
- /*
- memorytype (4 bytes, but only the first used, for flags):
- 1 integer values
- 2 unsigned (set in conjunction with integer)
- 4 floating point values
- 8 char string(s) 'element-size is the memory size of 1 string
- */
- ptrszint elementsize;
- int32 image;
- int32 sound;
- };
- struct mem_lock{
- uint64 id;
- int32 type;//required to know what action to take (if any) when a request is made to free the block
- //0=no security (eg. user defined block from _OFFSET)
- //1=C-malloc'ed block
- //2=image
- //3=sub/function scope block
- //4=array
- //5=sound
- //---- type specific variables follow ----
- void *offset;//used by malloc'ed blocks to free them
- };
- #endif //INC_COMMON_CPP
Here is the setup_lnx.sh file:
Code: Bash: [Select]
- #!/bin/bash
- #QB64 Installer -- Shell Script -- Matt Kilgore 2013
- #Version 5 -- January 2020
- #This version includes the updates to sucessfully install QB64 on the PI
- #or any ARM processor (Current version only tested on the Raspberry PI and
- #sets the DISTRO to "raspbian".) -- George McGinn (2/1/2022)
- #This checks the currently installed packages for the one's QB64 needs
- #And runs the package manager to install them if that is the case
- pkg_install() {
- #Search
- packages_to_install=
- for pkg in $pkg_list; do
- if [ -z "$(echo "$installed_packages" | grep $pkg)" ]; then
- packages_to_install="$packages_to_install $pkg"
- fi
- done
- if [ -n "$packages_to_install" ]; then
- echo "Installing required packages. If prompted to, please enter your password."
- $installer_command $packages_to_install
- fi
- }
- #Make sure we're not running as root
- if [ $EUID == "0" ]; then
- echo "You are trying to run this script as root. This is highly unrecommended."
- echo "This script will prompt you for your sudo password if needed to install packages."
- exit 1
- fi
- GET_WGET=
- #Path to Icon
- #Relative Path to icon -- Don't include beginning or trailing '/'
- QB64_ICON_PATH="internal/source"
- #Name of the Icon picture
- QB64_ICON_NAME="qb64icon32.png"
- DISTRO=
- lsb_command=`which lsb_release 2> /dev/null`
- if [ -z "$lsb_command" ]; then
- lsb_command=`which lsb_release 2> /dev/null`
- fi
- #Outputs from lsb_command:
- #Arch Linux = arch
- #Debian = debian
- #Fedora = Fedora
- #KUbuntu = ubuntu
- #LUbuntu = ubuntu
- #Linux Mint = linuxmint
- #Ubuntu = ubuntu
- #Raspbian = raspbian
- #Slackware = slackware
- #VoidLinux = voidlinux
- #XUbuntu = ubuntu
- #Zorin = Zorin
- if [ -n "$lsb_command" ]; then
- DISTRO=`$lsb_command -si | tr '[:upper:]' '[:lower:]'`
- elif [ -e /etc/arch-release ]; then
- DISTRO=arch
- elif [ -e /etc/debian_version ] || [ -e /etc/debian_release ]; then
- DISTRO=debian
- elif [ -e /etc/fedora-release ]; then
- DISTRO=fedora
- elif [ -e /etc/redhat-release ]; then
- DISTRO=redhat
- elif [ -e /etc/centos-release ]; then
- DISTRO=centos
- elif $(arch | grep arm > /dev/null); then
- DISTRO=raspbian
- fi
- echo "DISTRO detected = $DISTRO"
- #Find and install packages
- if [ "$DISTRO" == "arch" ]; then
- echo "ArchLinux detected."
- pkg_list="gcc zlib xorg-xmessage $GET_WGET"
- installed_packages=`pacman -Q`
- installer_command="sudo pacman -S "
- pkg_install
- elif [ "$DISTRO" == "linuxmint" ] || [ "$DISTRO" == "ubuntu" ] || [ "$DISTRO" == "debian" ] || [ "$DISTRO" == "zorin" ] || [ "$DISTRO" == "raspbian" ]; then
- echo "Debian/Raspian based distro detected."
- pkg_list="g++ x11-utils mesa-common-dev libglu1-mesa-dev libasound2-dev zlib1g-dev $GET_WGET"
- installed_packages=`dpkg -l`
- installer_command="sudo apt-get -y install "
- pkg_install
- elif [ "$DISTRO" == "fedora" ] || [ "$DISTRO" == "redhat" ] || [ "$DISTRO" == "centos" ]; then
- echo "Fedora/Redhat based distro detected."
- pkg_list="gcc-c++ xmessage mesa-libGLU-devel alsa-lib-devel zlib-devel $GET_WGET"
- installed_packages=`yum list installed`
- installer_command="sudo yum install "
- pkg_install
- elif [ "$DISTRO" == "voidlinux" ]; then
- echo "VoidLinux detected."
- pkg_list="gcc xmessage glu-devel zlib-devel alsa-lib-devel $GET_WGET"
- installed_packages=`xbps-query -l |grep -v libgcc`
- installer_command="sudo xbps-install -Sy "
- pkg_install
- elif [ -z "$DISTRO" ]; then
- echo "Unable to detect distro, skipping package installation"
- echo "Please be aware that for QB64 to compile, you will need the following installed:"
- echo " OpenGL developement libraries"
- echo " ALSA development libraries"
- echo " GNU C++ Compiler (g++)"
- echo " xmessage (x11-utils)"
- echo " zlib"
- fi
- echo "Compiling and installing QB64..."
- ### Build process
- find . -name "*.sh" -exec chmod +x {} \;
- find internal/c/parts -type f -iname "*.a" -exec rm -f {} \;
- find internal/c/parts -type f -iname "*.o" -exec rm -f {} \;
- find internal/c/libqb -type f -iname "*.o" -exec rm -f {} \;
- rm ./internal/temp/*
- #if [ "$DISTRO" == "raspbian" ]; then
- if $(arch | grep arm > /dev/null); then
- echo "Updating files for the ARM processor..."
- echo "updating makedat_lnx32.txt file..."
- pushd internal/c >/dev/null
- cat > makedat_lnx32.txt <<EOF
- objcopy -Ibinary -Oelf32-littlearm -Barm
- EOF
- echo "updating makedat_lnx64.txt file..."
- cat > makedat_lnx64.txt <<EOF
- objcopy -Ibinary -Oelf64-littlearm -Barm
- EOF
- popd >/dev/null
- fi
- echo "Building library 'LibQB'"
- pushd internal/c/libqb/os/lnx >/dev/null
- rm -f libqb_setup.o
- ./setup_build.sh
- popd >/dev/null
- echo "Building library 'FreeType'"
- pushd internal/c/parts/video/font/ttf/os/lnx >/dev/null
- rm -f src.o
- ./setup_build.sh
- popd >/dev/null
- echo "Building library 'Core:FreeGLUT'"
- pushd internal/c/parts/core/os/lnx >/dev/null
- rm -f src.a
- ./setup_build.sh
- popd >/dev/null
- echo "Building 'QB64'"
- cp -r ./internal/source/* ./internal/temp/
- pushd internal/c >/dev/null
- g++ -no-pie -w qbx.cpp libqb/os/lnx/libqb_setup.o parts/video/font/ttf/os/lnx/src.o parts/core/os/lnx/src.a -lGL -lGLU -lX11 -lpthread -ldl -lrt -D FREEGLUT_STATIC -o ../../qb64
- popd
- if [ -e "./qb64" ]; then
- echo "Done compiling!!"
- echo "Creating ./run_qb64.sh script..."
- _pwd=`pwd`
- echo "#!/bin/sh" > ./run_qb64.sh
- echo "cd $_pwd" >> ./run_qb64.sh
- echo "./qb64 &" >> ./run_qb64.sh
- chmod +x ./run_qb64.sh
- #chmod -R 777 ./
- echo "Adding QB64 menu entry..."
- cat > ~/.local/share/applications/qb64.desktop <<EOF
- [Desktop Entry]
- Name=QB64 Programming IDE
- GenericName=QB64 Programming IDE
- Exec=$_pwd/run_qb64.sh
- Icon=$_pwd/$QB64_ICON_PATH/$QB64_ICON_NAME
- Terminal=false
- Type=Application
- Categories=Development;IDE;
- Path=$_pwd
- StartupNotify=false
- EOF
- echo "Running QB64..."
- ./qb64 &
- echo "QB64 is located in this folder:"
- echo "`pwd`"
- echo "There is a ./run_qb64.sh script in this folder that should let you run qb64 if using the executable directly isn't working."
- echo
- echo "You should also find a QB64 option in the Programming/Development section of your menu you can use."
- else
- ### QB64 didn't compile
- echo "It appears that the qb64 executable file was not created, this is usually an indication of a compile failure (You probably saw lots of error messages pop up on the screen)"
- echo "Usually these are due to missing packages needed for compilation. If you're not running a distro supported by this compiler, please note you will need to install the packages listed above."
- echo "If you need help, please feel free to post on the QB64 Forums detailing what happened and what distro you are using."
- echo "Also, please tell them the exact contents of this next line:"
- echo "DISTRO: $DISTRO"
- fi
- echo
- echo "Thank you for using the QB64 installer."
Thanks,