From d7338b3935a54aa90d2e4867115db88198b5cd06 Mon Sep 17 00:00:00 2001 From: agorangetek Date: Fri, 18 Sep 2026 23:48:47 +0300 Subject: [PATCH 1/9] darwin: define DISABLE_OPENGL when X11/XQuartz is unavailable FB's OpenGL support is implemented in the X11 gfx driver. Without ENABLE_XQUARTZ that driver is compiled out, but gfx_opengl.c is still built and calls fb_hGL_GetProcAddress(), which only the driver defines. libfbgfx.a therefore ends up with an undefined symbol and every link fails: Undefined symbols for architecture arm64: "_fb_hGL_GetProcAddress", referenced from: _fb_GfxGetGLProcAddress in libfbgfxmt.a[31](gfx_opengl.o) gfx_opengl.c already provides a stub for exactly this situation; define DISABLE_OPENGL alongside DISABLE_X11 so it is used. --- makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/makefile b/makefile index 5e5b22ff4..cbe1cbbb1 100644 --- a/makefile +++ b/makefile @@ -585,6 +585,10 @@ ifeq ($(TARGET_OS),darwin) ALLFBCFLAGS += -d ENABLE_XQUARTZ else ALLCFLAGS += -DDISABLE_X11 + # FB's OpenGL support lives in the X11 driver, so without XQuartz there is + # no GL driver at all. gfx_opengl.c otherwise still calls the driver hook + # fb_hGL_GetProcAddress(), leaving libfbgfx with an undefined symbol. + ALLCFLAGS += -DDISABLE_OPENGL endif endif From 981d6bd06352615b0f70f25b07c09512291189db Mon Sep 17 00:00:00 2001 From: agorangetek Date: Fri, 18 Sep 2026 23:48:47 +0300 Subject: [PATCH 2/9] rtl-error: don't emit an indirect jump when RESUME support is off rtlErrorCheck() and rtlErrorThrow() only have a resume label to hand to the error throw when -ex/-exx enabled RESUME support. Without it the label arguments are NULL, fb_ErrorThrowAt() can never return a usable jump target, and `fb_ErrorThrow(); goto *result;` is equivalent to a plain call. Emitting the call also keeps the generated C compilable by clang, which rejects `goto *ptr;` in a function that contains no address-of-label expression ("indirect goto in function with no address-of-label expressions"). Code built with -ex/-exx is unaffected: there the label addresses are taken anyway (&&label), so the indirect jump is still emitted. --- src/compiler/rtl-error.bas | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/compiler/rtl-error.bas b/src/compiler/rtl-error.bas index 17096f555..8931daf95 100644 --- a/src/compiler/rtl-error.bas +++ b/src/compiler/rtl-error.bas @@ -293,7 +293,16 @@ function rtlErrorCheck( byval expr as ASTNODE ptr ) as ASTNODE ptr t = astNewLINK( t, astNewBOP( AST_OP_EQ, expr, astNewCONSTi( 0 ), nxtlabel, AST_OPOPT_NONE ), AST_LINK_RETURN_NONE ) '' fb_ErrorThrow() - t = astNewLINK( t, astNewBRANCH( AST_OP_JUMPPTR, NULL, hErrorThrow( reslabel, nxtlabel ) ), AST_LINK_RETURN_NONE ) + '' Only -ex (-exx) enables RESUME support, and only then is a resume + '' label handed to the throw. Without one the throw can never return + '' a usable jump target, so a plain call is equivalent -- and it keeps + '' the generated C acceptable to clang, which rejects `goto *ptr` in + '' functions that take no label address. + if( env.clopt.resumeerr ) then + t = astNewLINK( t, astNewBRANCH( AST_OP_JUMPPTR, NULL, hErrorThrow( reslabel, nxtlabel ) ), AST_LINK_RETURN_NONE ) + else + t = astNewLINK( t, hErrorThrow( reslabel, nxtlabel ), AST_LINK_RETURN_NONE ) + end if '' end if t = astNewLINK( t, astNewLABEL( nxtlabel ), AST_LINK_RETURN_NONE ) @@ -361,7 +370,13 @@ sub rtlErrorThrow _ end if '' dst - astAdd( astNewBRANCH( AST_OP_JUMPPTR, NULL, proc ) ) + '' As in rtlErrorCheck(): an indirect jump is only meaningful when RESUME + '' support (-ex) is enabled and a resume label was passed along. + if( env.clopt.resumeerr ) then + astAdd( astNewBRANCH( AST_OP_JUMPPTR, NULL, proc ) ) + else + astAdd( proc ) + end if astAdd( astNewLABEL( nxtlabel ) ) end sub From 27c623cae0c07bd2537fc35e50e65a97cf3be179 Mon Sep 17 00:00:00 2001 From: agorangetek Date: Fri, 18 Sep 2026 23:48:48 +0300 Subject: [PATCH 3/9] darwin: align DATA descriptors to the pointer size DATA items are emitted as a packed { short, void* } table, 10 bytes per entry, so the embedded string/link pointers sit at 2-byte offsets. ELF linkers accept that, but Mach-O's ld64 refuses to relocate a pointer that is not pointer-aligned and fails the link: ld: pointer not aligned in '_label$N'+0x16 Give the descriptor the natural pointer alignment when targeting Darwin, and make fb_data.h use the matching, non-packed layout. Other targets keep the packed 10-byte layout so their ABI is unchanged. --- src/compiler/ast-node-data.bas | 15 +++++++++++++-- src/rtlib/fb_data.h | 13 ++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/compiler/ast-node-data.bas b/src/compiler/ast-node-data.bas index 9d3803e57..bd5bfc8c0 100644 --- a/src/compiler/ast-node-data.bas +++ b/src/compiler/ast-node-data.bas @@ -266,9 +266,20 @@ end function private sub hCreateDataDesc( ) static as FBARRAYDIM dTB(0) + dim as integer byalign + + '' Using FIELD = 1, to pack it as done by the rtlib -- except on Darwin, + '' where the linker requires pointer-sized relocations to be aligned to + '' the pointer size. A packed { short, void* } puts the DATA entries' + '' pointers at offset 2 (and every 10 bytes after that), which ld64 + '' rejects ("pointer not aligned ...", fatal on arm64). There the layout + '' must use the natural pointer alignment, matching src/rtlib/fb_data.h. + byalign = 1 + if( fbGetOption( FB_COMPOPT_TARGET ) = FB_COMPTARGET_DARWIN ) then + byalign = env.pointersize + end if - '' Using FIELD = 1, to pack it as done by the rtlib - ast.data.desc = symbStructBegin( NULL, NULL, NULL, "__FB_DATADESC$", NULL, FALSE, 1, FALSE, 0, 0 ) + ast.data.desc = symbStructBegin( NULL, NULL, NULL, "__FB_DATADESC$", NULL, FALSE, byalign, FALSE, 0, 0 ) '' type as short symbAddField( ast.data.desc, "type", 0, dTB(), _ diff --git a/src/rtlib/fb_data.h b/src/rtlib/fb_data.h index 2b976807d..22de295a6 100644 --- a/src/rtlib/fb_data.h +++ b/src/rtlib/fb_data.h @@ -1,3 +1,14 @@ +/* Mach-O (Darwin) requires pointer-sized relocations to be aligned; the packed + layout would place the embedded pointers at 2-byte offsets, which ld64 + rejects ("pointer not aligned ...", a hard error on arm64). The compiler + emits the matching naturally-aligned layout for Darwin targets, see + hCreateDataDesc() in src/compiler/ast-node-data.bas. */ +#if defined(__APPLE__) + #define FB_DATADESC_PACKED +#else + #define FB_DATADESC_PACKED FBPACKED +#endif + struct _FB_DATADESC { short len; union { @@ -6,7 +17,7 @@ struct _FB_DATADESC { void *ofs; struct _FB_DATADESC *next; }; -} FBPACKED; +} FB_DATADESC_PACKED; typedef struct _FB_DATADESC FB_DATADESC; From 97a1a54b6ad565bb6241825d05b3293e22abfb3f Mon Sep 17 00:00:00 2001 From: agorangetek Date: Fri, 18 Sep 2026 23:48:48 +0300 Subject: [PATCH 4/9] darwin: use the correct arm64 va_list ABI AArch64 Darwin uses a plain pointer-like va_list (sizeof(va_list) == 8), not the AAPCS64 __va_list_tag struct used by Linux/BSD aarch64. The compiler assumed the struct, so cva_start()/cva_arg() walked the wrong memory and any program using cva_list crashed immediately. --- src/compiler/fb.bas | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/compiler/fb.bas b/src/compiler/fb.bas index c050c49c1..23fd1b4a6 100644 --- a/src/compiler/fb.bas +++ b/src/compiler/fb.bas @@ -1768,7 +1768,15 @@ function fbGetBackendValistType _ typedef = FB_CVA_LIST_BUILTIN_ARM case FB_CPUFAMILY_AARCH64 - typedef = FB_CVA_LIST_BUILTIN_AARCH64 + select case env.clopt.target + case FB_COMPTARGET_DARWIN + '' Apple's arm64 ABI uses a plain pointer-like va_list (8 bytes, + '' sizeof(va_list) == sizeof(char*)), not the AAPCS64 + '' __va_list_tag struct that Linux/BSD aarch64 use. + typedef = FB_CVA_LIST_BUILTIN_POINTER + case else + typedef = FB_CVA_LIST_BUILTIN_AARCH64 + end select case FB_CPUFAMILY_PPC typedef = FB_CVA_LIST_BUILTIN_POINTER From 974cf174945d3eb8c9250c8ee8238a072b6c6fb3 Mon Sep 17 00:00:00 2001 From: agorangetek Date: Fri, 18 Sep 2026 23:48:48 +0300 Subject: [PATCH 5/9] profile_cycles: handle Mach-O sections Mach-O has no __start_/__stop_ section boundary symbols and limits section names to 16 characters, so the ELF-style section scan cannot work there. Guard it for Darwin and fall back to the single version record (the report is then simply empty) instead of emitting an invalid section attribute and failing to build. --- src/rtlib/profile_cycles.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/rtlib/profile_cycles.c b/src/rtlib/profile_cycles.c index c6e2a7327..00f4718fc 100644 --- a/src/rtlib/profile_cycles.c +++ b/src/rtlib/profile_cycles.c @@ -99,10 +99,20 @@ typedef struct _FB_PROFILER_CYCLES */ #if !defined(HOST_DOS) +/* Mach-O section names are limited to 16 characters and, unlike ELF, the + linker does not synthesise __start_/__stop_ boundary symbols, so the + profiler's section scan cannot work the ELF way there; keep the record as a + plain used object instead. */ +#if defined(HOST_DARWIN) + #define FB_PROFILE_SECTION_ATTR __attribute__((used)) +#else + #define FB_PROFILE_SECTION_ATTR __attribute__((section("fb_profilecycledata"), used)) +#endif + /* make sure there is at least one record in the profile data section */ static FB_PROFILE_RECORD_VERSION __attribute__ ((aligned (16))) prof_data_version -__attribute__((section("fb_profilecycledata"), used)) = +FB_PROFILE_SECTION_ATTR = { sizeof( FB_PROFILE_RECORD_VERSION ), FB_PROFILE_RECORD_VERSION_ID, @@ -301,8 +311,15 @@ static void hProfilerWriteReport( FB_PROFILER_CYCLES *prof ) fprintf( f, "Total program execution time: %5.4g seconds\n", fb_Timer() - prof->start_time ); } +#if defined(HOST_DARWIN) + /* No __start_/__stop_ section symbols on Mach-O; fall back to the single + version record so the report is simply empty. */ + data = (unsigned char *)&prof_data_version; + length = sizeof( prof_data_version ); +#else data = (unsigned char *)&__start_fb_profilecycledata[0]; length = (ssize_t)&__stop_fb_profilecycledata - (ssize_t)&__start_fb_profilecycledata[0]; +#endif count = hProfilerCountProcs( data, length ); if( count ) { From ede5480d0119257c1cfba52d9c10f371cfbed785 Mon Sep 17 00:00:00 2001 From: agorangetek Date: Fri, 18 Sep 2026 23:48:48 +0300 Subject: [PATCH 6/9] darwin: link through the C compiler driver instead of driving ld64 The Darwin link command was built for a GNU ld: it adds crt1.o/crti.o/ crtbegin.o/crtend.o/crtn.o, `-macosx_version_min 10.4`, `--eh-frame-hdr`, `--export-dynamic` and `-lgcc`, and uses `-shared -h` for shared libraries. Modern ld64 rejects --eh-frame-hdr outright, the crt objects cannot be linked that way on macOS, and libgcc does not exist unless a GCC toolchain happens to be installed. Invoke the C compiler driver (clang) for linking Darwin targets instead: it supplies the startup object and libSystem itself. Drop the options it does not accept, use -dynamiclib/-install_name for -dylib, and add -arch arm64 so the architecture is explicit. Executables and dynamic libraries now link with the system toolchain alone. --- src/compiler/fbc.bas | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/src/compiler/fbc.bas b/src/compiler/fbc.bas index 61b77df3f..79a2a3ec8 100644 --- a/src/compiler/fbc.bas +++ b/src/compiler/fbc.bas @@ -840,6 +840,8 @@ private function hLinkFiles( ) as integer case FB_CPUFAMILY_ARM '' fixme: this is clearly too specific ldcline += "-arch armv6 " + case FB_CPUFAMILY_AARCH64 + ldcline += "-arch arm64 " end select end select @@ -945,7 +947,13 @@ private function hLinkFiles( ) as integer if( fbGetOption( FB_COMPOPT_OUTTYPE ) = FB_OUTTYPE_DYNAMICLIB ) then dllname = hStripPath( hStripExt( fbc.outname ) ) - ldcline += " -shared -h" + hStripPath( fbc.outname ) + if( fbGetOption( FB_COMPOPT_TARGET ) = FB_COMPTARGET_DARWIN ) then + '' Darwin's linker (ld64) has no -shared/-h; it uses -dynamiclib + '' and records the install name via -install_name. + ldcline += " -dynamiclib -install_name " + QUOTE + dllname + QUOTE + else + ldcline += " -shared -h" + hStripPath( fbc.outname ) + end if '' Turn libfoo into foo, so it can be checked against -l foo below if( left( dllname, 3 ) = "lib" ) then @@ -986,7 +994,8 @@ private function hLinkFiles( ) as integer '' But able to have shared library generated successfully afterward if( (fbGetOption( FB_COMPOPT_OUTTYPE ) = FB_OUTTYPE_DYNAMICLIB) or _ fbGetOption( FB_COMPOPT_EXPORT ) ) and _ - (fbGetOption( FB_COMPOPT_TARGET ) <> FB_COMPTARGET_SOLARIS) then + (fbGetOption( FB_COMPOPT_TARGET ) <> FB_COMPTARGET_SOLARIS) and _ + (fbGetOption( FB_COMPOPT_TARGET ) <> FB_COMPTARGET_DARWIN) then ldcline += " --export-dynamic" end if @@ -1166,7 +1175,10 @@ private function hLinkFiles( ) as integer FB_COMPTARGET_FREEBSD, FB_COMPTARGET_OPENBSD, _ FB_COMPTARGET_NETBSD, FB_COMPTARGET_DRAGONFLY, FB_COMPTARGET_SOLARIS - if( fbGetOption( FB_COMPOPT_OUTTYPE ) = FB_OUTTYPE_EXECUTABLE) then + '' Darwin's linker takes no explicit crt1.o; the C compiler driver + '' supplies the startup object (it lives inside libSystem). + if( (fbGetOption( FB_COMPOPT_OUTTYPE ) = FB_OUTTYPE_EXECUTABLE) and _ + (fbGetOption( FB_COMPOPT_TARGET ) <> FB_COMPTARGET_DARWIN) ) then if( fbGetOption( FB_COMPOPT_PROFILE ) ) then select case as const fbGetOption( FB_COMPOPT_TARGET ) case FB_COMPTARGET_OPENBSD, FB_COMPTARGET_NETBSD @@ -1322,18 +1334,17 @@ private function hLinkFiles( ) as integer end select - if( fbGetOption( FB_COMPOPT_TARGET ) = FB_COMPTARGET_DARWIN ) then - ldcline += " -macosx_version_min 10.4" - end if + '' Note: on Darwin the deployment target (-mmacosx-version-min) is supplied + '' by the C compiler driver used for linking, not hard-coded here. '' This is required for 64-bit modules on *nix-y platforms '' for the unwind tables to have any effect '' Windows doesn't need this option + '' (ld64 rejects --eh-frame-hdr; Darwin is handled by clang instead) select case as const fbGetOption( FB_COMPOPT_TARGET ) case FB_COMPTARGET_LINUX, FB_COMPTARGET_FREEBSD, _ FB_COMPTARGET_OPENBSD, FB_COMPTARGET_NETBSD, _ - FB_COMPTARGET_DRAGONFLY, FB_COMPTARGET_SOLARIS, _ - FB_COMPTARGET_DARWIN + FB_COMPTARGET_DRAGONFLY, FB_COMPTARGET_SOLARIS dim as long outtype = fbGetOption( FB_COMPOPT_OUTTYPE ) if outtype = FB_OUTTYPE_EXECUTABLE OrElse outtype = FB_OUTTYPE_DYNAMICLIB Then dim as long cpufamily = fbGetCpuFamily( ) @@ -1408,6 +1419,10 @@ private function hLinkFiles( ) as integer var ld = FBCTOOL_LD if( fbGetOption( FB_COMPOPT_TARGET ) = FB_COMPTARGET_JS ) then ld = FBCTOOL_EMLD + elseif( fbGetOption( FB_COMPOPT_TARGET ) = FB_COMPTARGET_DARWIN ) then + '' ld64 can't be driven like GNU ld (different crt handling, and it + '' rejects several GNU options), so use the C compiler driver to link. + ld = FBCTOOL_CLANG end if if( fbcRunBin( "linking", ld, ldcline ) = FALSE ) then @@ -4308,9 +4323,9 @@ private sub hAddDefaultLibs( ) end if case FB_COMPTARGET_DARWIN - fbcAddDefLib( "gcc" ) - fbcAddDefLib( "System" ) - fbcAddDefLib( "pthread" ) + '' There is no libgcc on macOS unless a GCC toolchain is installed; + '' the clang driver pulls in libSystem (and thus libc/libm/pthread) + '' by itself. libncurses is still needed by the FB runtime. fbcAddDefLib( "ncurses" ) case FB_COMPTARGET_DOS From d6c7528f236c3b2d54d5a4fb24b8ed1cb8422d38 Mon Sep 17 00:00:00 2001 From: agorangetek Date: Sat, 19 Sep 2026 00:10:32 +0300 Subject: [PATCH 7/9] X11: fix XGetKeyboardMapping prototype for NeedWidePrototypes Xfuncproto.h defines NeedWidePrototypes to 1 unless the application defines NARROWPROTO, which makes Xlib declare XGetKeyboardMapping()'s first_keycode parameter as unsigned int instead of KeyCode (unsigned char). FB's XGETKEYBOARDMAPPING typedef hard-codes KeyCode, so passing XGetKeyboardMapping to fb_hInitX11KeycodeToScancodeTb() no longer matches the parameter type: gfx_x11.c:588:68: error: incompatible function pointer types passing 'KeySym *(Display *, unsigned int, int, int *)' to parameter of type 'XGETKEYBOARDMAPPING' (aka 'unsigned long *(*)(struct _XDisplay *, unsigned char, int, int *)') GCC only warns about the mismatch, which is why this went unnoticed, but clang (and GCC 14+, where it is an error too) rejects it -- so the X11 rtlib/gfxlib2 code cannot be built by clang at all. That makes the XQuartz/X11 graphics path unbuildable on Darwin, where clang is the system compiler. Mirror Xlib's own conditional in the typedef so it matches either way. --- src/rtlib/unix/fb_private_scancodes_x11.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/rtlib/unix/fb_private_scancodes_x11.h b/src/rtlib/unix/fb_private_scancodes_x11.h index e76da67d4..bee31cd27 100644 --- a/src/rtlib/unix/fb_private_scancodes_x11.h +++ b/src/rtlib/unix/fb_private_scancodes_x11.h @@ -7,7 +7,16 @@ typedef Display *(*XOPENDISPLAY)(char *); typedef int (*XCLOSEDISPLAY)(Display *); typedef void (*XQUERYKEYMAP)(Display *, unsigned char *); typedef int (*XDISPLAYKEYCODES)(Display *, int *, int *); +/* XGetKeyboardMapping()'s first_keycode parameter is declared as KeyCode + (unsigned char) or as unsigned int depending on NeedWidePrototypes, which + Xfuncproto.h defaults to 1 unless NARROWPROTO is defined. Mirror Xlib's own + declaration, otherwise the function pointers do not match and clang (unlike + GCC, which merely warns) rejects the call. */ +#if defined(NeedWidePrototypes) && NeedWidePrototypes +typedef KeySym* (*XGETKEYBOARDMAPPING)(Display *, unsigned int, int, int *); +#else typedef KeySym* (*XGETKEYBOARDMAPPING)(Display *, KeyCode, int, int *); +#endif typedef int (*XFREE)(void *); extern unsigned char fb_x11keycode_to_scancode[256]; From 39438183289c2116bb61cc3762bf882e375df5c4 Mon Sep 17 00:00:00 2001 From: agorangetek Date: Sat, 19 Sep 2026 00:16:43 +0300 Subject: [PATCH 8/9] makefile: normalize arm64 to aarch64 uname -m reports "arm64" on Apple Silicon, which matched the arm% pattern and was normalized to "arm" -- the 32-bit family. A plain "make" on macOS therefore resolved FBTARGET to darwin-arm instead of darwin-aarch64, so objects and libraries landed in directories that do not match the ones fbc looks for at run time (lib/freebasic/darwin-aarch64). Normalize aarch64/arm64 first, then let the remaining 32-bit spellings match armv%/arm. Verified that arm-linux-gnueabihf and armv7-linux-gnueabihf still resolve to linux-arm, and that arm64-apple-darwin resolves to darwin-aarch64. Based on the corresponding change in #470 by @metaneutrons. --- makefile | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index cbe1cbbb1..50145e321 100644 --- a/makefile +++ b/makefile @@ -342,8 +342,13 @@ ifneq ($(filter 386 486 586 686 i386 i486 i586 i686,$(TARGET_ARCH)),) TARGET_ARCH := x86 endif -# Normalize TARGET_ARCH to arm -ifneq ($(filter arm%,$(TARGET_ARCH)),) +# Normalize TARGET_ARCH to aarch64 (macOS reports arm64) +ifneq ($(filter aarch64 arm64,$(TARGET_ARCH)),) + TARGET_ARCH := aarch64 +endif + +# Normalize TARGET_ARCH to arm (32-bit only, after aarch64 is handled) +ifneq ($(filter armv% arm,$(TARGET_ARCH)),) TARGET_ARCH := arm endif From 13794ed59d8562070dc5c5a417276e57b9355d02 Mon Sep 17 00:00:00 2001 From: agorangetek Date: Sat, 19 Sep 2026 12:04:36 +0300 Subject: [PATCH 9/9] darwin: name shared libraries .dylib, and export their symbols Two defects on the -dylib path, both found while cross-checking metaneutrons' freebasic-ng#160, which reviewed this branch against their fork: - Shared libraries were named .so on every unix target, including Darwin. Mach-O uses .dylib -- .so is the loadable bundle extension. fb_DylibLoad() looks for the .dylib name first on Darwin, so it worked, but only by falling through to the .so entry in its candidate list, and the file was named wrongly for every other tool on the platform. Darwin now has its own case in the output naming, leaving the ELF targets on .so. - The link line skipped --export-dynamic on Darwin entirely rather than translating it. The clang driver wants it spelled -Wl,-export_dynamic. Symbols resolved without it -- Mach-O exports global symbols by default -- but leaving it out was a silent difference from every other unix target, and -export therefore did nothing on Darwin. Verified by building a library and loading it back: fbc -dylib foo.bas -> libfoo.dylib, install name "libfoo" linking: clang ... -dynamiclib -install_name "libfoo" -Wl,-export_dynamic DyLibLoad("foo") -> handle, DyLibSymbol(handle, "FOO_ADD") -> 5 --- src/compiler/fbc.bas | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/compiler/fbc.bas b/src/compiler/fbc.bas index 79a2a3ec8..b469e0474 100644 --- a/src/compiler/fbc.bas +++ b/src/compiler/fbc.bas @@ -258,7 +258,13 @@ private sub hSetOutName( ) select case( fbGetOption( FB_COMPOPT_TARGET ) ) case FB_COMPTARGET_CYGWIN, FB_COMPTARGET_WIN32 fbc.outname += ".dll" - case FB_COMPTARGET_LINUX, FB_COMPTARGET_DARWIN, _ + case FB_COMPTARGET_DARWIN + '' Mach-O shared libraries are .dylib; .so is the loadable + '' bundle extension, and fb_DylibLoad() looks for the .dylib + '' name first on Darwin. + fbc.outname = hStripFilename( fbc.outname ) + _ + "lib" + hStripPath( fbc.outname ) + ".dylib" + case FB_COMPTARGET_LINUX, _ FB_COMPTARGET_FREEBSD, FB_COMPTARGET_OPENBSD, _ FB_COMPTARGET_NETBSD, FB_COMPTARGET_DRAGONFLY, _ FB_COMPTARGET_SOLARIS, FB_COMPTARGET_ANDROID @@ -994,9 +1000,14 @@ private function hLinkFiles( ) as integer '' But able to have shared library generated successfully afterward if( (fbGetOption( FB_COMPOPT_OUTTYPE ) = FB_OUTTYPE_DYNAMICLIB) or _ fbGetOption( FB_COMPOPT_EXPORT ) ) and _ - (fbGetOption( FB_COMPOPT_TARGET ) <> FB_COMPTARGET_SOLARIS) and _ - (fbGetOption( FB_COMPOPT_TARGET ) <> FB_COMPTARGET_DARWIN) then - ldcline += " --export-dynamic" + (fbGetOption( FB_COMPOPT_TARGET ) <> FB_COMPTARGET_SOLARIS) then + '' Darwin links through the clang driver, which wants the option + '' spelled with -Wl, rather than passed through as --export-dynamic + if( fbGetOption( FB_COMPOPT_TARGET ) = FB_COMPTARGET_DARWIN ) then + ldcline += " -Wl,-export_dynamic" + else + ldcline += " --export-dynamic" + end if end if case FB_COMPTARGET_XBOX