How can I use libc_nano with Clang? - c

I'm exploring using clang as the compiler for ARM embedded development. As clang doesn't have an equivalent of .spec files, I'm having trouble convincing clang to link against libc_nano. How could I either tell clang to not link against any libraries by default so I can specify the correct library, or rewrite the -lc command to -lc_nano?
The command I'm trying to run is:
clang -target arm-none-eabi -mcpu=cortex-a5 -mfpu=neon-vfpv4 -mfloat-abi=hard -march=armv7-a main.c
Currently I get this error message:
/usr/lib/llvm-6.0/bin/ld.lld: error: unable to find library -lc
EDIT: I've noticed that clang has a -fno-autolink which according to the help text: Disable generation of linker directives for automatic library linking. However it doesn't seem to do anything?
EDIT2: I'm aware I could abuse symlinks to achieve this. I would like to avoid symlinks in this case as it can make the build system brittle.

Upon further google-fu and grep-fu, it turns out the answer was staring at me the entire time. Clang has a -nodefaultlibs that does the trick and prevents default linker directives. Although strangely it wasn't documented in --help.

You can build fake libc.a without any functions inside and use it together with libc_nano.

Related

gcc linker not automatically including dependency libraries

I am in the process of updating an arm cross compiler from 4.3.3 to 4.9.4. One issue I am seeing is that the new compiler no longer automatically includes dependent libraries. For example:
gcc ... -L -l -lssl -lrt
works fine with the previous compiler. If libssl needed to reference something in libcrypto, then the linker would automatically find and link with libcrypto (no -lcrypto needed).
With the new compiler, this still works, but only if libssl does not reference anything in libcrypto. If it does, then the -lcyrpto is required. The same issue applies to -lpthread, -ldl, etc.
Is this a change in the behavior of gcc or is something not configured properly when building gcc?
Are you using static or dynamic libraries? For dynamic libraries, if libssl depends on libcrypto, you don't need to explicitly link -lcrypto as long as libssl itself was correctly linked, but if you want to make direct use in your program of symbols from libcrypto, then you have to explicitly link it. This is a change/intentional-regression in newer versions of binutils.

difference of compiler between macOS and linux?

I am now learning c language, and my school put all assignments on myth, every time we have to log in by ssh and execute command remotely.
Thus I want to download the files and execute them on my own macbook. However when I use make command to compile the files, I got errors and warnings such as :
gcc -g -O0 -std=gnu99 -Wall $warnflags -m32 -c -I. vectest.c -o vectest.o
warning: unknown warning option '-Wlogical-op'; did you mean '-Wlong-long'?
vectest.c:10:10: fatal error: 'error.h' file not found
#include <error.h>”
I googled these problems but could not find a satisfactory answer. can anyone help me solve this ? or I have to use a linux machine instead?
Indeed; compilers for various platforms (even if it's the "same" compiler, such as GCC) may have different flags and behaviors. You may be able to get it to work - you could remove the -Wlogical-op flag from $warnflags in your Makefile, but if the error.h file is a system-supplied header file, you're probably in trouble. Therefore, I suggest that you download e.g. VirtualBox and run Linux on it.
See error(3) for what this header provides. It's not specific to linux but to the GNU C library. What you COULD do is provide your own minimal implementation of these functions and write your own error.h.
You could even `#define' them to do nothing at all, but then you will probably lose some error reporting in the existing code. Maybe you could try to find a teacher understanding the problem and discuss the issue ... it's probably better to learn standard C not using any platform-specific extensions.

Custom compile of binutils/ld doesn't find symbols in archives

I'm currently trying to compile Clang/LLVM for a bare metal aarch64 target. Compiling Clang was straightforward - in fact I have compiled to target multiple architectures including arm and aarch64. For the backend I'm using binutils. Since binutils can only target one architecture I've built both aarch64 and arm versions of this. Again building seemed to be straightforward. I built binutils for aarch64 using:
mkdir build
cd build
../configure --target=aarch64-none-elf
make
from an unpacked source package of binutils 2.24.
The problem I'm having is that I can't get my custom build of ld to handle archive files properly. It seems to find and open archive files without a problem but fails to search it for undefined symbols when compiling the final binary. Here's some more concrete details via an example:
Create a simple main.s file by compiling:
int foo();
int main() { return foo(); }
with Clang and using --target=aarch64 -S, i.e. to emit an architecture specific assembly file.
Do the same to create foo.s by compiling:
int foo() { return 0; }
Assemble both .s files to .o files using custom gas build from binutils.
Create an archive libfoo.a by running custom ar and ranlib builds from binutils using ar cr foo.a foo.s and ranlib libfoo.a.
Try to link the two files together using ld -L. -lfoo -o main.elf main.o.
The output shows an undefined reference to foo.
bar.cpp:(.text+0x14): undefined reference to `foo()'
I can run readelf on foo.a and it seems perfectly well formed. In particular I can see the public symbol for foo. If I run ld with --verbose then I see
attempt to open ./libfoo.a succeeded
but no indication that it's found any symbols.
If I link directly with the object files, i.e. using ld -o main.elf foo.o main.o then I get a well formed elf file. Furthermore, if I extract foo.o back out of libfoo.a then I can also link succesfully with the extracted foo.o.
Does anyone have any ideas why this might be happening? I'm pretty sure my clang build is okay as the emitted assembly files effectively decouple the problem from clang. I'd guess also that the assembled .o files are fine. So this only leaves ar/ranlib or ld as the culprit.
To try to eliminate ar/ranlib as the culprits I rebuilt binutils for arm (same steps but using --target=arm-none-eabi). If I integrate the built ar/ranlib binaries into a known good arm-eabi-none GCC toolchain then they seem to work correctly. My suspicions thus point to ld at the moment. Note that I get the same problem with the main/foo example as above if I use my Clang build with the arm build of binutils.
I also tried integrating the arm version of ld into the existing known good GCC toolchain, but got:
this linker was not configured to use sysroots
Need to figure that out. That's still a bit cryptic for me right now. It prevents me from sanity checking the arm ld build.
It might well be that I'm doing something obviously wrong, but right now I don't see it.
Notes:
I had to hack the make script for binutils to add a couple of -Wno-xxx flags. I need to do this the "correct" way, but I don't think this hack should affect the output.
I'm building/hosting all tools on OSX 10.9.4 64-bit.
UPDATE:
The error about sysroots is simple. The pre-existing toolchain was configured with flags:
--with-prefix $SOME_INSTALL_DIR
--with-sysroot $SOME_INSTALL_DIR/arm-none-eabi
If I rebuild with these then I can slot in my ld version without a problem and it works. I got excited thinking that this might have been my mistake. Previously I wasn't running make install as I didn't really care about installing at this stage. I thought perhaps my new build of ld was referencing OSX system libs/exes somehow (although I'm not sure exactly what it could reference, other than perhaps ar, i.e. if it runs ar to handle archives). However I still have the same problem with both the arm and arrach64 versions of binutils even when configured like this.
Looks like I was dramatically overthinking the problem and also missing something I'd never quite realised about ld. The issue was with the line:
ld -L. -lfoo -o main.elf main.o
I hadn't realise that ld is sensitive to object file/library ordering. The undefined reference to foo() was in main.o. I specified the library libfoo.a as input before main.o is parsed. This means that the linker doesn't bother searching libfoo.a for the symbol as it's already processed this library. main.o must be specified before, e.g.
ld -L. main.o -lfoo -o main.elf
Even wrapping -lfoo with --start-group ... --end-group doesn't fix this.
I'm still feeling somewhat surprised by this. And I've yet to convince myself it's a good feature of ld. Seems like the only use case I can think of right now is to sneakily allow duplicate symbols.
Time for a cup of tea!

How to configure a non-standard linker for an autotooled build?

I wanted to configure an autotooled project to invoke a non-standard
linker (the gold linker),
using the stock autotools of Linux Mint 16/Ubuntu 13.10
I believed I would achieve this by:
libtoolize-ing the project
Running ./configure LD=/path/to/my/linker ... etc.
However this has been ineffective. libtoolize has been successful. After
a standard ./configure; make I now see that libtool is doing the
linking:
/bin/bash ./libtool --tag=CXX --mode=link g++ -g -O2 -o helloworld helloworld.o
But passing LD=/path/to/my/linker to configure makes no difference. Experimentally,
I even ran:
./configure LD=/does/not/exist
expecting to provoke an error, but I didn't. The output contains:
checking if the linker (/does/not/exist -m elf_x86_64) is GNU ld... no
checking whether the g++ linker (/does/not/exist -m elf_x86_64) supports shared libraries... yes
And thereafter a make continues to link, successfully, invoking g++ exactly as before.
What is the right way to configure a non-standard linker?
But passing LD=/path/to/my/linker to configure makes no difference
This is because LD is almost never and should almost never be used to link any user-space program. Correct links are performed by using the appropriate compiler driver (gcc, g++, etc) instead.
What is the right way to configure a non-standard linker?
If you have /some/path/ld and you want gcc to use that ld, pass -B/some/path flag to gcc.
It then follows that you likely want:
./configure CC='gcc -B/some/path' CXX='g++ -B/some/path' ...
I landed on this via a Google search, though my scenario is a bit different from yours; there was no libtool involved. An old open source program's Makefile was hard-coding ld to create an object file with a symbol from binary data.
This is what I ended up doing to work around the lack of $(LD) being recognized when passed to configure:
https://github.com/turboencabulator/tuxnes/commit/bab2747b175ee7f2fc3d9afb28d69d82db054b5e
Basically I added to configure.ac:
AC_CHECK_TOOL([LD], [ld])
Leaving this answer here for if someone else lands via a google search.

GNU Autotools with TCC

I recently discovered the Tiny C Compiler. For the project that I'm currently working on, performance is not a real issue, but file size is, making TCC ideal. I'm using Autotools as a build manager, and I figured that using TCC would be as simple as ./configure CC=tcc.
However, this returns checking whether the C compiler works... no. In config.log, it says configure: exit 77.
Despite all of this, setting CC=clang works fine. Is there any way to get Autotools to use TCC?
The issue appears to have been the fault of my CFLAGS. While TCC was normally able to compile programs with them, Autotools seems to have thought otherwise. Setting CFLAGS="" resolved the issue.
For future reference, my CFLAGS are -march=native -mtune=native -O2 -pipe -fstack-protector --param=ssp-buffer-size=4.
iirc tcc does not produce tiny executables - it is tcc itself that is tiny. Perhaps you're looking for gcc -Os?

Resources