How can I cross-compile for Solaris with cgo? - c

I am trying to compile some cgo code for Solaris. I get these errors when I try to build:
$ CGO_LDFLAGS="-L$(pwd)/solaris-11.4-amd64-libs" CGO_CFLAGS='-I/home/shane/src/ioctl-experimentation/solaris-11.4-headers -Wno-unknown-pragmas' CGO_ENABLED=1 GOOS=solaris GOARCH=amd64 go build
# runtime/cgo
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x16): undefined reference to `__libc_csu_fini'
/usr/bin/ld: (.text+0x1d): undefined reference to `__libc_csu_init'
/usr/bin/ld: (.text+0x2a): undefined reference to `__libc_start_main'
/usr/bin/ld: $WORK/b003/_x003.o: in function `_cgo_release_context':
gcc_context.c:(.text+0x5c): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x004.o: in function `x_cgo_sys_thread_create':
gcc_libinit.c:(.text+0x87): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x004.o: in function `_cgo_wait_runtime_init_done':
gcc_libinit.c:(.text+0x121): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x004.o: in function `_cgo_try_pthread_create':
gcc_libinit.c:(.text+0x291): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x006.o: in function `x_cgo_init':
gcc_solaris_amd64.c:(.text+0xb6): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x006.o:gcc_solaris_amd64.c:(.text+0x214): more undefined references to `__stack_chk_fail' follow
collect2: error: ld returned 1 exit status
I am cross-compiling on Linux. Here is my Go version:
$ go version
go version go1.18.3 linux/amd64
The solaris-11.4-amd64-libs directory contains a copy of all files under /lib/amd64 from a Solaris 11.4 AMD64 machine. The solaris-11.4-headers directory contains a copy of all files under /usr/include from a Solaris 11.4 AMD64 machine.
Here is my Go code in main.go:
//go:build solaris
// +build solaris
package main
import "C"
func main() {
}
I know cgo is fully supported for Solaris as of Go 1.5, and I am using Go 1.18.
I'm looking for help understanding why these linker errors are happening, even when I copied across all libs from the /lib/amd64 directory. Is it possible there are more libs I also need to copy over from somewhere else?
Edit
At the suggestion of Liam Kelly, I looked at this question about how to link against a different libc. I tried passing -Xlinker -rpath=$(pwd)/solaris-11.4-amd64-libs as part of CGO_LDFLAGS, but I got the same errors as before. I tried using -nodefaultlibs and -nostdlib both separately and together along with -Xlinker -rpath=$(pwd)/solaris-11.4-amd64-libs, but using either of these two flags either separately or together just increased the number of linker errors.

I am going to assume that libxnet is needed for Solaris and that is why is is being automatically added.
First confirm that the libxnet library is where is should be with sudo find /lib libxnet*. I expect you will see one line of the output show:
lib/64/libxnet.so
Assuming you see the above output, I believe you just need to tell the linker to look in that location with CGO_LDFLAGS="-L/lib/64" CGO_ENABLED=1 GOOS=solaris GOARCH=amd64 go build. If that works then you should be able to embedded that LDFlag in your main.go file with:
// #cgo LDFLAGS: -L/lib/64
import "C"
Once embedded you will not need to explicitly set CGO_LDFLAGS

Related

understanding compilation commands C and configuring CodeBlocks

I'm learning C in college. And I wanted to try new things, so I decided to use the allegro Game library to create some stuff. I followed the tutorial, and everything went fine. I wrote a piece of code in the text editor and executed the commands provided by the tutorial and it compiled and run. (I'm on linux btw).
These are the commands:
gcc hello.c -o hello $(pkg-config allegro-5 allegro_font-5 --libs --cflags)
./hello
So, I understand that gcc is calling the gcc compiler and hello.c is the name of the source code file and -o hello specifies the name of the compiled file. but the next part is ambiguous and beyond my knowledge:
$(pkg-config allegro-5 allegro_font-5 --libs --cflags)
So can anyone explain what it means (it has something to do with linking). and if I remove that part the compiler returns these error codes:
/usr/bin/ld: /tmp/ccIQsEis.o: in function `main':
hello.c:(.text+0x2f): undefined reference to `al_install_system'
/usr/bin/ld: hello.c:(.text+0x34): undefined reference to `al_install_keyboard'
/usr/bin/ld: hello.c:(.text+0x45): undefined reference to `al_create_timer'
/usr/bin/ld: hello.c:(.text+0x4e): undefined reference to `al_create_event_queue'
/usr/bin/ld: hello.c:(.text+0x61): undefined reference to `al_create_display'
/usr/bin/ld: hello.c:(.text+0x6a): undefined reference to `al_create_builtin_font'
/usr/bin/ld: hello.c:(.text+0x73): undefined reference to `al_get_keyboard_event_source'
/usr/bin/ld: hello.c:(.text+0x85): undefined reference to `al_register_event_source'
/usr/bin/ld: hello.c:(.text+0x91): undefined reference to `al_get_display_event_source'
/usr/bin/ld: hello.c:(.text+0xa3): undefined reference to `al_register_event_source'
/usr/bin/ld: hello.c:(.text+0xaf): undefined reference to `al_get_timer_event_source'
/usr/bin/ld: hello.c:(.text+0xc1): undefined reference to `al_register_event_source'
/usr/bin/ld: hello.c:(.text+0xd4): undefined reference to `al_start_timer'
/usr/bin/ld: hello.c:(.text+0xe7): undefined reference to `al_wait_for_event'
/usr/bin/ld: hello.c:(.text+0x125): undefined reference to `al_is_event_queue_empty'
/usr/bin/ld: hello.c:(.text+0x13d): undefined reference to `al_map_rgb'
/usr/bin/ld: hello.c:(.text+0x16a): undefined reference to `al_clear_to_color'
/usr/bin/ld: hello.c:(.text+0x17e): undefined reference to `al_map_rgb'
/usr/bin/ld: hello.c:(.text+0x1ca): undefined reference to `al_draw_text'
/usr/bin/ld: hello.c:(.text+0x1cf): undefined reference to `al_flip_display'
/usr/bin/ld: hello.c:(.text+0x1e7): undefined reference to `al_destroy_font'
/usr/bin/ld: hello.c:(.text+0x1f3): undefined reference to `al_destroy_display'
/usr/bin/ld: hello.c:(.text+0x1ff): undefined reference to `al_destroy_timer'
/usr/bin/ld: hello.c:(.text+0x20b): undefined reference to `al_destroy_event_queue'
collect2: error: ld returned 1 exit status
And for the second part of the question, I tried to compile this code in code:blocks but it returns the same errors given by the compiler without the term: $(pkg-config allegro-5 allegro_font-5 --libs --cflags)
So, what configuration should I change in codeblocks so that it compiles well code using allegro libraries.
PS. I didn't include the source code intentionally as it adds no useful information to the question, only clutters it.
This is a Bash command-syntax feature which executes another command and then provides its output as a string. This idiom is being used here to programmatically provide command-line parameters to the gcc command. The pkg-config command is being executed, and it returns a string which becomes part of – is textually included in – the command-string for invoking gcc. (Which of course neither knows nor cares where its command-line parameters "come from.")
(Clever, huh?)
For example, try this:
echo $(ls)
You will be rewarded with a list of all the files in the current directory, concatenated as a string.
To elaborate on the answer by #Mike Robinson,
$(pkg-config allegro-5 allegro_font-5 --libs --cflags) will execute the command pkg-config and substitute the result. pkg-config is build utility that helps when compiling C programs. It's not specific to allegro, it is used by many C libraries.
In this particular case, pkg-config is called with the parameters allegro-5 allegro_font-5 --libs --cflags, which asks pkg-config "what are the compiler options (--cflags) and libraries (--libs) I need when compiling and linking with allegro?" Allegro consists of several modules, in this case you chose the main module 'allegro' and the font module 'allegro_font'. In both cases you're referring to major version 5 of allegro.
On your system, the result of the command is -I/usr/include/x86_64-linux-gnu -lallegro_font -lallegro. The meaning of these options is as follows:
-I/usr/include/x86_64-linux-gnu tells the compiler to add the path /usr/include/x86_64-linux-gnu to the header search path (because the allegro headers are located there)
-lallegro_font and '-lallegro` tells the linker to add the allegro_font and allegro libraries respectively. That also explains why you get all those undefined reference errors when you remove this - you are no longer telling the linker to add the allegro library, so it can't find all those functions anymore.

Undefined reference to a function, linker error

This is a rookie question and I might be doing something stupid, but I wrote a C program that includes two non default libraries: curl and libxml2. I am trying to go through the compilation process in detail to learn the process and statically link the libraries. These are the steps I took:
Downloaded libxml2 and curl and compiled it with the included makefile and did the following:
ar rcs libcurl.a /home/${USER}/Desktop/Curl/curl-7.73.0/lib/*.o
ar rcs libxml2.a /home/${USER}/Desktop/xml2/libxml2-2.7.2/*.o
Even though I only use a few functions from those libraries I packed all together in case they needed each other, or at least I think that's how it works. I copied the generated arhive library to a separate location and lastly I did:
cp ~/Desktop/libxml2-2.7.2/libxml2.a ~/Desktop/libs/
cp ~/Desktop/Curl/curl-7.73.0/lib/libxml2.a ~/Desktop/libs/
gcc WolframParser.c -I/home/${USER}/Desktop/Curl/curl-7.73.0/include/ -I/home/${USER}/Desktop/libxml2-2.7.2/include/ -L/home/${USER}/Desktop/libs/ -lcurl -lxml2 -lm
The linker reports a bunch of errors of undefined references, the likes of:
/usr/bin/ld: /home/${USER}/Desktop/libs//libcurl.a(libcurl_la-multi.o): in function `multi_getsock':
multi.c:(.text+0x18e): undefined reference to `Curl_ssl_getsock'
/usr/bin/ld: /home/${USER}/Desktop/libs//libcurl.a(libcurl_la-easy.o): in function `curl_global_init':
easy.c:(.text+0x172): undefined reference to `Curl_ssl_init'
/usr/bin/ld: /home/${USER}/Desktop/libs//libcurl.a(libcurl_la-easy.o): in function `curl_global_init_mem':
easy.c:(.text+0x22e): undefined reference to `Curl_ssl_init'
/usr/bin/ld: /home/${USER}/Desktop/libs//libcurl.a(libcurl_la-easy.o): in function `curl_global_cleanup':
easy.c:(.text+0x295): undefined reference to `Curl_ssl_cleanup'
. . .
Can someone please point out what I did wrong, and can this be done like this at all?

Issue with linking libraries built with gnat

When trying to build some test cases (just programs written in Ada), I get the following error:
gcc -c -shared decimaltests.adb
gnatbind -x decimaltests.ali
gnatlink decimaltests.ali -lGenerics -lNumerics -lTesting
/usr/bin/ld: decimaltests: hidden symbol `_Unwind_Resume' in
/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/libgcc_eh.a(unwind-dw2.o) is referenced by DSO
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
gnatlink: error when calling /usr/bin/gcc
gnatmake: *** link failed.
I'm building them with gnatmake -shared *.ad{b,s} -largs -lGenerics -lNumerics -lTesting Clearly this isn't a problem with building the sources, but just to further confirm that, I copied the sources into this directory and built using gnatmake -shared *.ad{b,s} which built the tests just fine.
The dependent libraries are built and installed into a path gnat searches through. It doesn't seem to be an issue of not finding those. Not sure what's going on here.
All the libraries are built with gnatmake -O2 -fPIC -shared *.ad{b,s} as well as any relevant library dependencies. All libraries that depend on these can still be built. It's only even programs that depend on the libraries that throw this error, and always the same error.
Update: Building the libraries using gprbuild and then installing them with gprinstall seems to work similarly, except now the error is as follows:
decimaltests.o: In function `_ada_decimaltests':
decimaltests.adb:(.text+0x43): undefined reference to `testing__start'
decimaltests.adb:(.text+0x4a): undefined reference to
`generics__testing__default_tolerance'
decimaltests.adb:(.text+0x9e): undefined reference to
`generics__testing__default_tolerance'
decimaltests.adb:(.text+0x108): undefined reference to
`generics__testing__default_tolerance'
decimaltests.adb:(.text+0x172): undefined reference to
`generics__testing__default_tolerance'
decimaltests.adb:(.text+0x1dc): undefined reference to
`generics__testing__default_tolerance'
decimaltests.o:decimaltests.adb:(.text+0x23f): more undefined references to
`generics__testing__default_tolerance' follow
decimaltests.o: In function `_ada_decimaltests':
decimaltests.adb:(.text+0x14f5): undefined reference to `testing__stop'
/usr/lib/numerics//libNumerics.so: undefined reference to
`generics__testing__not_started#SYMS'
/usr/lib/numerics//libNumerics.so: undefined reference to
`generics__testing__pass#SYMS'
/usr/lib/numerics//libNumerics.so: undefined reference to
`generics__testing__fail#SYMS'
collect2: error: ld returned 1 exit status
gprbuild: link of decimaltests.adb failed
So I looked through the symbols table for both build methods and noticed, in both cases, the symbol most definitely exists, but the reference to it seems to be the wrong location. I'll try building on different platforms/compilers and update again if anything relevant comes up.
Both processes correctly build the libraries and test programs, and the test programs run properly, on different platforms. To further confirm that this is a bug, I've installed a different GCC toolchain and repeated the builds under the original platform, and this problem did not arise. I'll be filing a bug report.

Which library shall I add to get fcntl64, stat64, ... resolved?

I'm trying to build a project for ARM uClibc environment, but I've some functions missing. Can not find which library shall I include to resolve dependancies. nm do not help me to search, since it says on most of libs coming with toolchain:
nm: ./host/usr/arm-unknown-linux-uclibcgnueabi/sysroot/lib/libuClibc-0.9.32.1.so: no symbols
Here is the output from GCC:
./host/usr/bin/arm-unknown-linux-uclibcgnueabi-gcc
-Wl,-rpath,./host/usr/lib/
-Wl,-rpath,./host/usr/../lib/
-Wl,-rpath,./host/usr/arm-unknown-linux-uclibcgnueabi/sysroot/lib/
-Llibzway -o test_so main.o -lzway
-L./host/usr/lib/
-L./host/usr/../lib/
-L./host/usr/arm-unknown-linux-uclibcgnueabi/sysroot/lib/ -lpthread
-lxml2 -lz -lm
./host/usr/lib/libxml2.so: warning: gethostbyname is obsolescent, use getnameinfo() instead.
./host/usr/lib/libxml2.so: undefined reference to `fcntl64'
./host/usr/lib/libxml2.so: undefined reference to `fopen64'
./host/usr/../lib/libz.so: undefined reference to `lseek64'
./host/usr/lib/libxml2.so: undefined reference to `stat64'
./host/usr/lib/libiconv.so.2: undefined reference to `mbrtowc'
./host/usr/lib/libiconv.so.2: undefined reference to `_stdlib_mb_cur_max'
./host/usr/lib/libiconv.so.2: undefined reference to `wcrtomb'
./host/usr/lib/libxml2.so: undefined reference to `open64'
collect2: ld returned 1 exit status
make: *** [test_so] Error 1
UPD:
I've copied uClibc from the target host and explicitely defined asked to link with it:
./host/usr/bin/arm-unknown-linux-uclibcgnueabi-gcc
-Wl,-rpath,./host/usr/lib/
-Wl,-rpath,./host/usr/../lib/
-Wl,-rpath,./host/usr/arm-unknown-linux-uclibcgnueabi/sysroot/lib/
-Llibzway -o test_so main.o -lzway
-L./host/usr/lib/
-L./host/usr/../lib/
-L./host/usr/arm-unknown-linux-uclibcgnueabi/sysroot/lib/
-luClibc-0.9.31
-lpthread -lxml2 -lz -lm
./host/usr/bin/../lib/gcc/arm-unknown-linux-uclibcgnueabi/4.5.3/../../../../arm-unknown-linux-uclibcgnueabi/bin/ld:
errno: TLS reference in ./host/usr/bin/../arm-unknown-linux-uclibcgnueabi/sysroot/lib/libpthread.so.0 mismatches non-TLS definition in ./host/usr/lib/libuClibc-0.9.31.so section .bss
./host/usr/bin/../arm-unknown-linux-uclibcgnueabi/sysroot/lib/libpthread.so.0: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [test_so] Error 1
This is much bayond my knowledge of cross-compilation. Any idea?
It sounds like you have several issues going on:
You seem to be trying to use the host's copy of libxml2.so. This is not going to work. You need one built for your target system and its libc.
Your uClibc was compiled without large file support. Go back and fix the build options or uClibc. It's not strictly necessary (a correctly built libxml2.so linked against uClibc will work without doing this), but using the pre-large-file interfaces is really backwards and will unnecessarily limit your programs.

GCC -nostdlib fails with undefined reference to `__libc_csu_fini'

I provide the linker with my files: ld-2.7.so, libc-2.7.so and crt1.o but it fails to compile successfully. Is it possible to link to a different glibc from the default one ?
(Static compilation or installing a separate glibc is not an option.)
gcc -Wl,-dynamic-linker,ld-2.7.so,libc-2.7.so,crt1.o -nostdlib program.c
crt1.o: In function `_start':
(.text+0x12): undefined reference to `__libc_csu_fini'
crt1.o: In function `_start':
(.text+0x19): undefined reference to `__libc_csu_init'
/tmp/user/1000/ccauFlwt.o: In function `findsize':
program.c:(.text+0x21): undefined reference to `stat'
/tmp/user/1000/ccauFlwt.o: In function `findtime':
program.c:(.text+0x4c): undefined reference to `stat'
collect2: ld returned 1 exit status
I found out how to do it:
rpath specifies where the provided libraries are located. This folder should contain: libc.so.6, libdl.so.2, libgcc_s.so.1 and maybe more. Check with strace to find out which libraries your binary file uses.
ld.so is the provided linker
gcc -Xlinker -rpath=/default/path/to/libraries -Xlinker -I/default/path/to/libraries/ld.so program.c
As #onemasse said, you also need header files compatible with that version of libc. Between glibc versions things still work anyway though, but this can not relied upon.
Otherwise, I would suggest you use export LD_PRELOAD_PATH to wherever your other libc is before starting the new library.
But what you really is after, is to cross-compile in linux, for linux, but with another libc.
Have a look at crosstool.
If you want to link to another libc than the one provided by the system you also need to compile your program with header files compatible with that version of libc.
Also, I'm not familiar with the option "-dynamic-linker". It's not in the man page for gcc. I really can't work out what you're trying to do.
Maybe you should try this instead and work from there:
gcc -ldl program.c -o program
You normally don't have to explicitly link with "libc" or "crt1.o".

Resources