Linker errors with gcc 3.4.6 and NDK 3.2
Hi all
This has been bugging me for years but I decided to have another look at it this week.
I'm trying to build NetSurf with the NDK 3.2r4 instead of NDK 3.9. I can build other software with the same toolchain (it builds Curl for example, which has some Amiga-specific bits in it), however when I build NetSurf I just get linker errors like so:
[...]
build/Linux-amigaos3/frontends_amiga_theme.o(.text+0x804):build/Linux-amigaos3/frontends_amiga_theme.o: undefined reference to `_InitRastPort'
build/Linux-amigaos3/frontends_amiga_theme.o(.text+0x84c):build/Linux-amigaos3/frontends_amiga_theme.o: undefined reference to `_FreeRaster'
build/Linux-amigaos3/frontends_amiga_theme.o(.text+0x8a8):build/Linux-amigaos3/frontends_amiga_theme.o: undefined reference to `_FreeRaster'
build/Linux-amigaos3/frontends_amiga_theme.o(.text+0xa0e):build/Linux-amigaos3/frontends_amiga_theme.o: undefined reference to `_BltBitMapRastPort'
build/Linux-amigaos3/frontends_amiga_theme.o(.text+0xb1a):build/Linux-amigaos3/frontends_amiga_theme.o: undefined reference to `_BltBitMapRastPort'
build/Linux-amigaos3/frontends_amiga_utf8.o(.text+0x5e):build/Linux-amigaos3/frontends_amiga_utf8.o: undefined reference to `_CodesetsConvertStr'
build/Linux-amigaos3/frontends_amiga_utf8.o(.text+0xa2):build/Linux-amigaos3/frontends_amiga_utf8.o: undefined reference to `_CodesetsFind'
build/Linux-amigaos3/frontends_amiga_utf8.o(.text+0xbc):build/Linux-amigaos3/frontends_amiga_utf8.o: undefined reference to `_CodesetsFind'
build/Linux-amigaos3/frontends_amiga_utf8.o(.text+0x18a):build/Linux-amigaos3/frontends_amiga_utf8.o: undefined reference to `_FreeVec'
/opt/netsurf/m68k-unknown-amigaos/env/lib/libnsutils.a(src_time.o)(.text+0x12):src_time.o: undefined reference to `_ReadEClock'
/opt/netsurf/m68k-unknown-amigaos/cross/lib/gcc/m68k-unknown-amigaos/3.4.6/../../../../m68k-unknown-amigaos/bin/ld: link errors found, deleting executable `NetSurf'
The actual compilation seems fine. The linker line is as follows:
/opt/netsurf/m68k-unknown-amigaos/cross/bin/m68k-unknown-amigaos-gcc -o NetSurf build/Linux-amigaos3/build_Linux-amigaos3_duktape_application_cache.o build/Linux-amigaos3/build_Linux-amigaos3_duktape_attr.o [...] build/Linux-amigaos3/utils_utf8.o build/Linux-amigaos3/utils_utils.o -ljpeg -liconv -L/opt/netsurf/m68k-unknown-amigaos/env/lib -lcss -lparserutils -lwapcaplet -L/opt/netsurf/m68k-unknown-amigaos/env/lib -ldom -lexpat -lwapcaplet -lhubbub -lparserutils -L/opt/netsurf/m68k-unknown-amigaos/env/lib -lnsutils -lz -L/opt/netsurf/m68k-unknown-amigaos/env/lib -lcurl -lamisslstubs -lamisslauto -lz -lm -lz -L/opt/netsurf/m68k-unknown-amigaos/env/lib -lutf8proc -L/opt/netsurf/m68k-unknown-amigaos/env/lib -lpng16 -L/opt/netsurf/m68k-unknown-amigaos/env/lib -lnsbmp -L/opt/netsurf/m68k-unknown-amigaos/env/lib -lnsgif -L/opt/netsurf/m68k-unknown-amigaos/env/lib -lsvgtiny -ldom -lexpat -lwapcaplet -lhubbub -lparserutils -L/opt/netsurf/m68k-unknown-amigaos/env/lib -lnspsl -L/opt/netsurf/m68k-unknown-amigaos/env/lib -lnslog -Wl,--trace -lamisslauto -L/opt/netsurf/m68k-unknown-amigaos/env/lib -lcurl -lamisslstubs -lamisslauto -lz -lm -lamisslstubs -lamisslauto -lz -lm -lz -L/opt/netsurf/m68k-unknown-amigaos/env/lib -ltre -L/opt/netsurf/m68k-unknown-amigaos/env/lib -lpbl -liconv -lamiga -lm
As it builds other things I guess I'm missing some magic incantation which needs to be added here OR there's something missing in the compile lines. This is an example compile line which I know complains about missing symbols later:
/opt/netsurf/m68k-unknown-amigaos/cross/bin/m68k-unknown-amigaos-gcc -W -Wall -Wundef -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-declarations -Wuninitialized -Wno-unused-parameter -Wredundant-decls -Wno-cast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -I. -Iinclude -Ibuild/Linux-amigaos3 -Ifrontends -Icontent/handlers -fomit-frame-pointer -DWITH_JPEG -UWITH_PDF_EXPORT -ULIBICONV_PLUG -I/opt/netsurf/m68k-unknown-amigaos/env/include -I/opt/netsurf/m68k-unknown-amigaos/env/include -I/opt/netsurf/m68k-unknown-amigaos/env/include -DCURL_STATICLIB -I/opt/netsurf/m68k-unknown-amigaos/env/include -DWITH_CURL -DUTF8PROC_EXPORTS -I/opt/netsurf/m68k-unknown-amigaos/env/include -DWITH_UTF8PROC -I/opt/netsurf/m68k-unknown-amigaos/env/include/libpng16 -I/opt/netsurf/m68k-unknown-amigaos/env/include -DWITH_PNG -I/opt/netsurf/m68k-unknown-amigaos/env/include/ -DWITH_BMP -I/opt/netsurf/m68k-unknown-amigaos/env/include -DWITH_GIF -I/opt/netsurf/m68k-unknown-amigaos/env/include -DWITH_NS_SVG -I/opt/netsurf/m68k-unknown-amigaos/env/include -DWITH_NSPSL -I/opt/netsurf/m68k-unknown-amigaos/env/include -DWITH_NSLOG -DNETSURF_UA_FORMAT_STRING=\""Mozilla/5.0 (%s) NetSurf/%d.%d"\" -DNETSURF_HOMEPAGE=\""about:welcome"\" -DNETSURF_LOG_LEVEL=VERBOSE -DNETSURF_BUILTIN_LOG_FILTER=\""(level:WARNING || cat:jserrors)"\" -DNETSURF_BUILTIN_VERBOSE_FILTER=\""(level:VERBOSE || cat:jserrors)"\" -DSTMTEXPR=1 -std=c99 -Dnsamiga -O2 -DPATH_MAX=1024 -D__m68k__ -DNO_INLINE_STDARG -fomit-frame-pointer -m68020-60 -msoft-float -DWITH_AMIGA_ICON -DWITH_AMIGA_DATATYPES -DWITH_AMISSL -DWITH_OPENSSL -D__NO_NET_API -D__NO_NETINCLUDE_ERRNO -I/opt/netsurf/m68k-unknown-amigaos/env/netinclude -I/opt/netsurf/m68k-unknown-amigaos/env/include -I/opt/netsurf/m68k-unknown-amigaos/env/include -DDUK_OPT_HAVE_CUSTOM_H -MMD -MP -MT 'build/Linux-amigaos3/deps/frontends_amiga_theme.d build/Linux-amigaos3/frontends_amiga_theme.o' -MF build/Linux-amigaos3/deps/frontends_amiga_theme.d -o build/Linux-amigaos3/frontends_amiga_theme.o -c frontends/amiga/theme.c
Any ideas?
Oh If "3.4.6" if the thing optionally installed by "cube dunnowhat but was golded before" , I never could compile anything with it neither.
I always include the proto/#?.h includes, so it isn't that.
Standard NDK3.2r4 includes, so relevant bit:
#ifndef PROTO_GRAPHICS_H
#define PROTO_GRAPHICS_H
#ifdef _NO_INLINE
#include <clib/graphics_protos.h>
#else
/****************************************************************************/
#ifndef __NOLIBBASE__
#ifndef GRAPHICS_GFXBASE_H
#include <graphics/gfxbase.h>
#endif /* GRAPHICS_GFXBASE_H */
extern struct GfxBase * GfxBase;
#endif /* __NOLIBBASE__ */
#elif defined(__GNUC__)
#if defined(mc68000)
#ifndef _INLINE_GRAPHICS_H
#include <inline/graphics.h>
#endif /* _INLINE_GRAPHICS_H */
#else
#include <clib/graphics_protos.h>
#endif /* mc68000 */
/****************************************************************************/
/* Any other compiler */
#else
#include <clib/graphics_protos.h>
/****************************************************************************/
#endif /* __GNUC__ */
/****************************************************************************/
#endif /* _NO_INLINE */
/****************************************************************************/
#endif /* PROTO_GRAPHICS_H */
Default defines:
#define __DBL_MIN_EXP__ (-1021)
#define __FLT_MIN__ 1.17549435e-38F
#define __CHAR_BIT__ 8
#define __WCHAR_MAX__ 4294967295U
#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
#define __FLT_EVAL_METHOD__ 0
#define __chip __attribute__((__chip__))
#define __DBL_MIN_10_EXP__ (-307)
#define __FINITE_MATH_ONLY__ 0
#define __GNUC_PATCHLEVEL__ 6
#define __ixemul__ 1
#define __SHRT_MAX__ 32767
#define __LDBL_MAX__ 1.7976931348623157e+308L
#define __saveds __attribute__((__saveds__))
#define __LDBL_MAX_EXP__ 1024
#define __SCHAR_MAX__ 127
#define __USER_LABEL_PREFIX__ _
#define __STDC_HOSTED__ 1
#define __LDBL_HAS_INFINITY__ 1
#define __DBL_DIG__ 15
#define __FLT_EPSILON__ 1.19209290e-7F
#define __amiga__ 1
#define __LDBL_MIN__ 2.2250738585072014e-308L
#define __DECIMAL_DIG__ 17
#define __stackext __attribute__((__stackext__))
#define __LDBL_HAS_QUIET_NAN__ 1
#define __GNUC__ 3
#define __amigaos 1
#define MCH_AMIGA 1
#define __DBL_MAX__ 1.7976931348623157e+308
#define __DBL_HAS_INFINITY__ 1
#define __mc68000__ 1
#define ixemul 1
#define __USING_SJLJ_EXCEPTIONS__ 1
#define __DBL_MAX_EXP__ 1024
#define __amigaos__ 1
#define __LONG_LONG_MAX__ 9223372036854775807LL
#define amigaos 1
#define __GXX_ABI_VERSION 1002
#define __FLT_MIN_EXP__ (-125)
#define __DBL_MIN__ 2.2250738585072014e-308
#define __DBL_HAS_QUIET_NAN__ 1
#define __mc68000 1
#define __REGISTER_PREFIX__
#define __regargs __attribute__((__regparm__))
#define __NO_INLINE__ 1
#define __FLT_MANT_DIG__ 24
#define __VERSION__ "3.4.6"
#define amiga 1
#define AMIGA 1
#define mc68000 1
#define __MCH_AMIGA__ 1
#define __SIZE_TYPE__ long unsigned int
#define __AMIGA__ 1
#define __FLT_RADIX__ 2
#define __LDBL_EPSILON__ 2.2204460492503131e-16L
#define __stdargs __attribute__((__stkparm__))
#define __FLT_HAS_QUIET_NAN__ 1
#define __FLT_MAX_10_EXP__ 38
#define __LONG_MAX__ 2147483647L
#define __FLT_HAS_INFINITY__ 1
#define __LDBL_MANT_DIG__ 53
#define __WCHAR_TYPE__ unsigned int
#define __FLT_DIG__ 6
#define __INT_MAX__ 2147483647
#define __FLT_MAX_EXP__ 128
#define __DBL_MANT_DIG__ 53
#define __interrupt __attribute__((__interrupt__))
#define __WINT_TYPE__ unsigned int
#define __LDBL_MIN_EXP__ (-1021)
#define __LDBL_MAX_10_EXP__ 308
#define __DBL_EPSILON__ 2.2204460492503131e-16
#define __MCH_AMIGA 1
#define __ixemul 1
#define __FLT_DENORM_MIN__ 1.40129846e-45F
#define __FLT_MAX__ 3.40282347e+38F
#define __FLT_MIN_10_EXP__ (-37)
#define __GNUC_MINOR__ 4
#define __DBL_MAX_10_EXP__ 308
#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
#define __aligned __attribute__((__aligned__(4)))
#define __PTRDIFF_TYPE__ long int
#define __amiga 1
#define __AMIGA 1
#define __LDBL_MIN_10_EXP__ (-307)
#define __LDBL_DIG__ 15
I don't remember where the patches came from but, yeah, 3.4 is a thing(as a cross compiler). I would like to update it but haven't found any other working version. I could try 12 if I can get it working easily. Are there a set of patches for it? I need to patch the base archive, due to how the toolchain works.
(edit: corrected defines as I tink I ran the native compiler by accident, oops)
It looks like to get the inlines I need to define mc68000, but I did try that and it doesn't appear to help.
If you correctly "overcopied" correctly the NDK3.2 INCLUDES_H over the "gcc amiga os include"... this should work with the other gcc version I know.
Maybe you copied it in the wrong include dir ?
With my gcc2.95 ADE from aminet (a very rationalized version of the old GeekGadget GCC, but short and easy to install), I copyed INCLUDES_H in ADE:os-include
It also worked with the sasc I have.
"gcc 3.4.6 for OS3" ... frankly, I don't know what it is, where it comes from, who did it, and if it ever really worked.
last idea: try changing the orders of the includes, active all warning and read them all, most of all "no permissive option"
having permissive options to port libs is a very very bad idea. You have to face all legit compile error and find solutions for each. (I've just done that during 8 monthes to port a MAME.)
Amiga options I use with gcc2.95 and gcc6.5 that could help:
-DAMIGA -D__AMIGA__ -v
-funsigned-char
old amiga standard compiler have char as unsigned, C modern standard is signed by default. Will make problems.
-ansi
modern gcc may consider your string encodage is UTF-8 or whatever linux encodage. -ansi makes it use amiga like encodage.
-noixemul
this is the old stack of gcc2.9 to have linux api functions. -ixemul Would use a compltely different runtime. Became a source of problem because was forked with differents API by different people. gcc6.5bebbo completely removed that for static links.
....oooh and try options
-std=c90
or any C version your compiler support.... it is meant to change the whole includes dirs, it could perfectly be that. gcc6.5 needs -std=c11
... and tips!: if the erreor is defines collisions between includes,
1. avoid including things that are not directly related to what happens in your current source. seriously. Only microsoft sucks enough to have a unique <Windows.h>
2. you may use:
# include <ireallyneedthis>
#ifdef MACROTHATCOLLIDEINTHIS
#undef MACROTHATCOLLIDEINTHIS
#endif
#include <somethingelse>
've just read all that again, and so:
#if defined(mc68000)
#ifndef _INLINE_GRAPHICS_H
#include <inline/graphics.h>
#endif /* _INLINE_GRAPHICS_H */
#else
#include <clib/graphics_protos.h>
#endif /* mc68000 */
.... this mc68000 def is missing from your define lists.
, your gcc doesn't set this, so you may just compile with option:
-Dmc68000=1
... like amigaos includes are meant to work with all specific motorola cpu version -m68000 -m68020 , ... -m68060 , it makes no sense it would set 'mc68000'
mc68000 should be present whatever version is on.
I don't know why you're so sceptical of gcc 3.4. I've been using it for years with the 3.9 NDK with no issues whatsoever!
I already tried -Dmc68000 and it made no difference, which surprised me as it looked like the missing piece to me too :(
I'm currently attempting to get gcc 6.5 working on the NetSurf toolchain but having issues due to autoconf version mismatches (so close to getting it to build). Going to try gcc 15.2 next and see if I have more joy with that.
After a couple of weeks of solid building and rebuilding of newer gcc I've got bored with that.
However, I think I've maybe worked out the cause (albeit not necessarily how to solve).
I was using -DNO_INLINE_STDARG due to an error I was getting.
I think, however, this is expecting the missing functions to be in a static library (maybe amiga.lib), but I don't have one to link in (at least, not one suitable for gcc, I do have a libamiga but it mustn't have those functions in).
Solution? Remove that define?
Great, but then I get errors `unterminated argument list invoking macro "NewObject"`, which I think is why I tried that define in the first place.
Not sure how to proceed from here. Maybe there's a better libamiga I can build?
Do you use macro like ?:
#define ButtonObject NewObject( NULL, "button.gadget"
... They just can't work with gcc, and macro containing non-closed "(" inside, are completely incompatible with modern compiler in general.
Not mentionning, if you cross compîle, it will also impeach modern IDE like QtCreator or VSCode to parse the code (and so: no completion, etc etc).
First thing I did starting with BOOPSI (note MUI has exact same problem.), is replacing those macros by the real calls in examples, to be able to compile with GCC.
That way you can trace problems with closing brace, which might be your problem according to the error you give.
... if someone is interested, the old reaction big demo , modified to be compatible with GCC is here: https://github.com/krabobmkd/amigatests/tree/main/reactiondemo_gcc
Eek. OK, maybe I'll give that a try next.
Right, I've got it working!
I ended up converting the full amiga.lib to a gcc-compatible version, and using -DNO_INLINE_STDARG.
That means my macros still work without completely rewriting some extremely large nested GUI definitions.
Is there any chance of an amiga.lib built for gcc to be included in the next NDK update?
... If that can help ... here are just some inlines for DoMethod/DoSuperMethod/SetSuperAttrs/CoerceMethod . All this uses utility.library CallHookPkt() ... I actually adapted all these from the AROS version of amiga.lib source. Works with GCCx and SASC6.5.
https://github.com/krabobmkd/amigatests/blob/krb/dev/templateGadget/min…
Online Status
I know GCC 2.95, the cross compiler GCC6.5, I know there 's also a very modern GCC12 around tergeting Amiga on linux/windows, but never heard of "3.4.6".
Solution could be specific.
The link error you have is that in your installation, OS functions are declared as "linkable" functions, like regular functions.
Usually, in the GCC setups I used, OS functions are very specically decalred as "inlined", which means they are just replaced by a direct library call the old assembler way like
move.l letsSayIntuitionBase,a6
move.l myparam,d0
jsr.l myintuitionFunctionOffset(a6)
; d0 resturn result
... and that way , no further link is needed. Note: Some GCCs (2.9 and 6.5) even have in thir startup a a way so the OpenLibrary() and CloseLibrary() happens automatically if one of the function of a lib is used, but you can also do it explicitly if you declare the lib base explicitely, which wis all compiler compatible.
So how the "inline" call happens ?
in the NDK include, you're meant to include
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
... not directly <clib/....> ... the correct include are the "proto"
in proto/graphics you have things like:
#ifndef _NO_INLINE
# if defined(__GNUC__)
# ifdef __AROS__
# include <defines/graphics.h>
# else
# include <inline/graphics.h>
# endif
# else
# include <pragmas/graphics_pragmas.h>
# endif
#endif /* _NO_INLINE */
... what you want with your gcc is to have inline/graphics called by #include <proto/graphics.h> , and your compiler should manage the rest "if ity's done the same way as other amiga capable gcc"