Currently only Window provided in this initial release
TLDR;
All you need is gcc.pb and polink.pb to get started, compile them as gcc and polink in the source folder then rename gcc and polink in the pb compilers folder and copy in the gcc and polink you just made.
Also I recommend installing mingw64, all sorts of cool stuff can be done with that and a bit of creativity
Full download with examples for Raylib4, PortAudio, MiniAudio
https://github.com/idle-PB/pbcex
OR
Gcc
Code: Select all
;fake gcc to facitlate working with inline c
;compile this to the source folder as gcc and then rename gcc in the pb compliers folder to gcc_real and copy in this version of gcc
;useage
;you can specify additional compiler flags on the command line as below use an inline c comment !// and keyword followed by parameters and end the line in ;
; !//gccflags -fno-schedule-insns -fno-schedule-insns2 ;
;if you need to add a header use !//#include followed by file path.h and end in ;
; !//#include /usr/include/portaudio.h ;
;this will ensure that the macros and constants are availableto for use from the header in c
;if you want to compile with clang rather than gcc
; !//useclang;
;and if you want to make a static lib use !//makestatic
; !//makestatic e:\idle\pbstuff\portaudio\libringbuffer.a;
;but make sure it's the last compilerflag
; mingw64-clang13 build can be downloaded here
; https://github.com/mstorsjo/llvm-mingw/releases/download/20211002/llvm-mingw-20211002-msvcrt-x86_64.zip
; Edit your environment PATH variable to include llvm-mingw-20211002-msvcrt-x86_64;llvm-mingw-20211002-msvcrt-x86_64\bin;llvm-mingw-20211002-msvcrt-x86_64\include
; windows 10, windows xp
; 1.02
EnableExplicit
#DisplayMessages = 1
#CopyMessages=0
Macro _SetClipboardText(message)
SetClipboardText("Cd /D " + GetCurrentDirectory() +#CRLF$+ "PATH=%PATH%;" + GetPathPart(ProgramFilename()) + ";" + GetCurrentDirectory() +#CRLF$+ message +#CRLF$+ "")
EndMacro
OpenConsole()
Global Flags.s,Fn,a,Command.s,Param.s,ParamCount,Find.s,CompilerHome.s,Pos,Precomp,len,*data,fn1,fn2
Global Output.s,Gcc,Len,tCommand.s,error.s,usellvm,clangpath.s,libname.s,objname.s,err
clangpath="C:\llvm\bin\clang.exe"
If ExamineEnvironmentVariables()
CompilerHome = #PB_Compiler_Home
If CompilerHome <> ""
ParamCount = CountProgramParameters()
If ParamCount
For a = 0 To ParamCount-1
Param = ProgramParameter(a)
Command + Param + " "
Next
Command + ProgramParameter(a)
If FileSize("purebasic.c")
Fn = OpenFile(#PB_Any,"purebasic.c")
If Fn
Repeat
Flags.s = ReadString(Fn,#PB_UTF8)
If Not precomp
If FindString(Flags,"//useclang",1)
usellvm = 1
command = RemoveString(command,"-fno-tree-vrp")
command = RemoveString(command,"-fno-schedule-insns2")
command = RemoveString(command,"-fno-schedule-insns")
command = RemoveString(command,"-freorder-blocks-algorithm=simple")
EndIf
If FindString(Flags,"//gccflags",1)
tCommand.s = " " + Right(flags,Len(flags)-10)
pos = FindString(tCommand,";")
If pos
Command.s + " " + Trim(Left(tCommand,pos-1))
EndIf
EndIf
If FindString(Flags,"//#include",1)
tCommand = "-include " + Right(flags,Len(flags)-10)
pos = FindString(tCommand,";")
If pos
Command.s + " " + Trim(Left(tCommand,pos-1))
EndIf
EndIf
If (FindString(Flags,"//makestatic",1) Or FindString(Flags,"//precompile",1))
precomp=1
libname = Right(flags,Len(flags)-12)
pos = FindString(libname,";")
If pos
libname = Trim(Left(libname,pos-1))
fn2 = CreateFile(#PB_Any,"makestatic.txt")
If fn2
WriteStringN(fn2,libname)
EndIf
EndIf
pos = FindString(libname,".")
libname = Left(libname,pos) + "o"
objname = GetFilePart(libname)
FileSeek(fn,1)
Continue
EndIf
EndIf
If Precomp
If FindString(flags,"int PB_Compiler_Thread=1;",1)
WriteStringN(fn2,"threaded")
ElseIf FindString(flags,"int PB_ExecutableType=",1)
len = Loc(fn)
*Data = AllocateMemory(len)
FileSeek(fn,0)
ReadData(fn,*data,len)
fn1 = CreateFile(#PB_Any,"purebasic1.c")
If fn1
WriteData(fn1,*data,len)
CloseFile(fn1)
CompilerIf #DisplayMessages
RunProgram("notepad.exe",GetCurrentDirectory()+"purebasic1.c","")
CompilerEndIf
pos = FindString(command,"-c -o PureBasic.obj")
tCommand = Left(command,pos-1)
tcommand + " -o " + objname + " " + "purebasic1.c -c"
CompilerIf #CopyMessages
_SetClipboardText(tcommand)
CompilerEndIf
CompilerIf #DisplayMessages
MessageRequester("gcc 1 do not Link Before", "gcc_real.exe " + tcommand)
CompilerEndIf
If usellvm
Gcc = RunProgram(clangpath,tcommand,GetCurrentDirectory(),#PB_Program_Open);
Else
Gcc = RunProgram(CompilerHome + "Compilers\gcc_real.exe",tcommand,GetCurrentDirectory(),#PB_Program_Open);
EndIf
If WaitProgram(Gcc)
err = ProgramExitCode(Gcc)
If Err
MessageRequester("error",Str(err))
EndIf
EndIf
EndIf
FreeMemory(*data)
Break
EndIf
EndIf
Until Eof(Fn)
CloseFile(Fn)
EndIf
EndIf
If IsFile(fn2)
CloseFile(fn2)
EndIf
CompilerIf #CopyMessages
_SetClipboardText(command)
CompilerEndIf
CompilerIf #DisplayMessages
Select MessageRequester("gcc 3 Before real", "gcc_real.exe " + command, #PB_MessageRequester_YesNoCancel|#MB_DEFBUTTON2)
Case #PB_MessageRequester_Yes
RunProgram("notepad.exe", #DQUOTE$+GetCurrentDirectory()+"purebasic.c"+#DQUOTE$, "", #PB_Program_Wait)
Case #PB_MessageRequester_Cancel
DeleteDirectory(GetCurrentDirectory(), "", #PB_FileSystem_Force)
End
EndSelect
CompilerEndIf
If usellvm
Gcc = RunProgram(clangpath,command,GetCurrentDirectory(),#PB_Program_Open);
Else
Gcc = RunProgram(CompilerHome + "Compilers\gcc\gcc_real.exe",command,GetCurrentDirectory(),#PB_Program_Open);
EndIf
If WaitProgram(Gcc)
End ProgramExitCode(Gcc)
EndIf
EndIf
EndIf
EndIf
Code: Select all
@echo off
cd /d %~dp0
set "compiler32=c:\program files (x86)\purebasic\compilers\gcc"
set "compiler64=c:\program files\purebasic\compilers\gcc"
REM x64
if not exist "%compiler64%\gcc_real.exe" (
move "%compiler64%\gcc.exe" "%compiler64%\gcc_real.exe"
if %ERRORLEVEL% NEQ 0 goto err
)
copy /B "gcc.exe" "%compiler64%\gcc.exe"
if %ERRORLEVEL% NEQ 0 goto err
REM x86
if not exist "%compiler32%\gcc_real.exe" (
move "%compiler32%\gcc.exe" "%compiler32%\gcc_real.exe"
if %ERRORLEVEL% NEQ 0 goto err
)
copy /B "gcc.exe" "%compiler32%\gcc.exe"
if %ERRORLEVEL% NEQ 0 goto err
goto done
:err
echo An error happened.
goto afterdone
:done
echo done!
:afterdone
pause
Polink
Code: Select all
EnableExplicit
#DispalyMessages = 1
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
#Cdir = "\"
CompilerElse
#Cdir = "/"
CompilerEndIf
Structure folderContents
type.b
value.s
EndStructure
Procedure GetFileList(StartDir.s,List Lfiles.folderContents(),pattern.s="*.*",Recursive=1,bset=0)
Protected mDir,Directory.s,Filename.s,FullFileName.s, tdir.s,ct,a,depth,bmatch
Static NewList Lpattern.s()
Static FileCount
If Not bset
StartDir = RTrim(StartDir, #Cdir)
pattern = RemoveString(pattern,"*.")
ct = CountString(pattern,"|") + 1
ClearList(lpattern())
For a = 1 To ct
AddElement(Lpattern())
Lpattern() = UCase(StringField(pattern,a,"|"))
Next
filecount=0
bset=1
EndIf
mDir = ExamineDirectory(#PB_Any, StartDir, "*.*")
If mDir
While NextDirectoryEntry(mDir)
If DirectoryEntryType(mDir) = #PB_DirectoryEntry_File
Directory = startdir
FileName.s = DirectoryEntryName(mDir)
ForEach Lpattern()
If Lpattern() = GetExtensionPart(UCase(Filename))
bmatch=1
ElseIf Lpattern() = "*"
bmatch =1
EndIf
If bmatch
FullFileName.s = StartDir + #Cdir + FileName
AddElement(LFiles())
Lfiles()\value = FullFileName
Lfiles()\type = #PB_DirectoryEntry_File
FileCount+1
bmatch =0
EndIf
Next
Else
tdir = DirectoryEntryName(mDir)
If tdir <> "." And tdir <> ".."
If Recursive = 1
depth + 1
GetFileList(startDir + #Cdir + tdir,LFiles(),Pattern,Recursive,bset)
EndIf
EndIf
EndIf
Wend
FinishDirectory(mDir)
EndIf
ProcedureReturn FileCount
EndProcedure
Macro _SetClipboardText(message,prog)
SetClipboardText("Cd /D " + GetCurrentDirectory() +#CRLF$+ "PATH=%PATH%; " + GetPathPart(ProgramFilename()) + ";" + GetCurrentDirectory() +#CRLF$+ prog + message +#CRLF$+ "")
EndMacro
Global NewList myfiles.folderContents()
Global tmp.s,cmd.s,libname.s,prog,name.s,pos
If FileSize("makestatic.txt")
If ReadFile(0,"makestatic.txt")
libname = ReadString(0)
cmd = GetFilePart(libname,#PB_FileSystem_NoExtension) + ".o "
tmp = ReadString(0) ;might need to inlude some system libs based on setting like threadsafe
If FindString(tmp,"threaded")
CopyFile(#PB_Compiler_Home + "Compilers\" + "StringManagerCThread.lib",GetCurrentDirectory()+"ObjectManagerThread.lib")
CopyFile(#PB_Compiler_Home + "Compilers\" + "StringManagerCThread.lib",GetCurrentDirectory()+"StringManagerCThread.lib")
CopyFile(#PB_Compiler_Home + "Compilers\" + "libgcc.a",GetCurrentDirectory()+"libgcc.a")
EndIf
If GetFileList(GetCurrentDirectory(),myfiles(),"*.lib|*.a",0)
ForEach myfiles()
cmd + myfiles()\value + " "
Next
EndIf
cmd + " /OUT:" + libname
CloseFile(0)
CompilerIf #DispalyMessages
_SetClipboardText(cmd,"polib.exe")
MessageRequester("polib Before", "polib.exe " + cmd)
CompilerEndIf
RunProgram(#PB_Compiler_Home + "Compilers\polib.exe",cmd,GetCurrentDirectory(),#PB_Program_Wait)
MessageRequester("polib",cmd)
EndIf
EndIf
cmd = ""
cmd = PeekS( GetCommandLine_())
cmd = RemoveString(cmd, #DOUBLEQUOTE$ + ProgramFilename() + #DOUBLEQUOTE$, #PB_String_NoCase, 1, 1)
cmd = Mid(cmd,2)
CompilerIf #DispalyMessages
_SetClipboardText(cmd,"polink.exe")
MessageRequester("polink",cmd)
CompilerEndIf
prog = RunProgram(#PB_Compiler_Home + "Compilers\polink_real.exe", cmd, GetCurrentDirectory(), #PB_Program_Open)
While IsProgram(prog)
If ProgramRunning(prog)
Delay(100)
Else
CloseProgram(prog)
EndIf
Wend
End ProgramExitCode(prog)
PBCEX tools to facilitate using inline c and to make precompiled static libs
Author idle 2022
Version 1.0 for windows purebasic 6.00 c backend
Linux and Raspberry PI version will be on their way
It's my hope that Fred will eventually add this to the c backend.
Set up:
Compile gcc and polink to the source folder.
navigate to your purebasic compilers directory and rename Gcc and polink to gcc_real and polink_real
copy your compiled gcc and polink to the purebasic compilers directory.
Use:
The tool facilitates you to control gcc compiler flags and utilize c libs directly in PB and also make precompiled libs to save compile times
flags are entered as inline c comments !// followed by command and arguments that end in ;
!//gccflags -O3; optimize to O3
!//useclang; if you've installed mingw64 and added the enviroment path to the compiler you can use that in place of the supplied gcc
!//#include path\to\some\clibheader.h; ;this will include the entire c lib so it's available to use with inline c
!//makestatic path\to\your\lib.a; ;this will generate a static lib all function marked as procedureCDll will be exported
Some examples make use of llvm mingw64 you can download it here and install c:\ or where ever
https://github.com/mstorsjo/llvm-mingw/ ... x86_64.zip
;Edit your environment PATH variable to include the paths
Tool filesc:\llvm-mingw-20211002-msvcrt-x86_64
c:\llvm-mingw-20211002-msvcrt-x86_64\bin
c:\llvm-mingw-20211002-msvcrt-x86_64\include
gcc.pb tool source instructions to install mingw64 in readme
polink.pb source to facilitate making static libs
Examples
*Note you will need to modify the inline c paths used on all examples and use c backend for compile
librb - ringbuffer static lib.
portaudio - ffttest and dueltest requires librb.a
raylib4 - screen and julia set.
librb a static lib example librb.a allows you to create a static lib and compile as a dll
the file pattern used allows you to easily work on and precompile a lib and use it in a project easily.
Set compiler to c backend, set to the compile type to shared dll, turn off debugger and hit F5 to compile to static lib
files:
librb.a the generated static lib compiled with optional !//useclang;
librb.dll the compiled dll from using create executable
librb.lib the import lib to the dll
testlibrb.pb test for librb compile as thread safe for debug messages
ringbuffer.pbi lockfree ring buffer to produce librb.a
Notes the filepattern used in ringbuffer.pbi facilitates you to easily create test and use precompiled libs in a project to save compile times
while the static libary generated is usable with pb it may not be usable from another language as it misses out the intialization functions
also note that while the generated static libs are large, the resultant executable won't be anywhere near as large.
Example PortAudio
Portaudio x64 build only uses gcc as compiler
Dueltest ;example of bridging streams via a ring buffer from two threads (note you need to build the ring buffer librb first)
FFTtest ;uses a single callback on the input output streams and runs an FFT iFFT
Example Raylib4
Raylib4 x64, requires Mingw64 to be installed
Screen basic hello world example
juliaset creates an animate fullscreen juilia set fractal with glsl shader