I have some code which relies on a library, namely the University of Tsukuba Elliptic Pairing Library. This library itself relies on GMP. I'd like to run this program baremetal on an ARM core, specifically on a beaglebone black.
GMP is a massive library, so I'd prefer to cross-compile if possible. I'd also prefer something other than the ``brute force" solution of simply dumping the entire GMP source code into the same file as my program and pushing it into arm-none-eabi-gcc.
What is the standard method for linking nontrivial libraries into baremetal code?
In this specific case, mini-gmp is sufficient, providing a bunch of functionality is removed from TEPLA. This is sufficient for my purposes, but hardly a satisfying answer -- my solution to linking a nontrivial library is to instead link a trivial library. Though my exact problem is solved, I'll be leaving this question open in case someone has any cleverer ideas.
Related
If I compile a self-contained project with gcc and statically link the C run-time library, will this work on any Linux distro? I don't care about any static link disadvantages (such as big file size) so long as it works. It is a closed-source project and this is beyond my control. The architecture of the PCs is the same.
If you can guarantee that all of the code it will execute is self-contained in the binary you ship, then theoretically (emphasis on theoretically) it should work on any linux distribution. In this process there are an enormous number of pitfalls. My personal opinion is that it is pretty much impossible to make this work due to changing interfaces across versions. Interfacing with other libraries is a fragile nightmare.
Most companies that I'm familiar with (including my own) produce builds made for different distributions. There are some complications that result from having to make a build for SLES, Redhat, etc., but I'm confident that providing a few different builds ultimately is simpler and causes less problems than attempting to statically link everything.
So I have a minimal OS that doesn't do much. There's a bootloader, that loads a basic C kernel in 32-bit protected mode. How do I port in a C library so I can use things like printf? I'm looking to use the GNU C Library. Are there any tutorials anywhere?
Ok, porting in a C library isn't that hard, i'm using Newlib in my kernel. Here is a tutorial to start: http://wiki.osdev.org/Porting_Newlib.
You basically need to:
Compile the library (for example Newlib) using your cross compiler
Provide stub-implementations for a list of system functions (like fork, fstat, etc.) in your kernel
Link the library and your kernel together
If you want to use functions like malloc or printf (which uses malloc internally), you need some kind of memory management and simplest working implementation of sbrk.
I strongly recommend against glibc. It is a beast.
Try newlib instead. Porting it to a new kernel is easy. You just need to write a few support functions, as explained here.
Another new kid on the block is musl which specifically aims to improve the situation in embedded space.
It's probably not the best choice for a beginner, though, since it's still pretty much work in progress.
Better look for a small libc, like uClibc. The GNU C library is huge. And as the comments tell, the first step is to get a C compiler going.
What are you trying to do? Building a full operating system is a job for a group of people lasting a few years... better start with something that already works, and hack on the parts that most interest you.
I have implemented semaphores in Linux last year. But for that I have to use -lpthread.
Now while implementing log10() function in C, I surfed the INTERNET and I saw that I have to use -lm.
I want to know why these kind of command line arguments are necessary in Linux.And Does this rule is compiler oriented?
(In windows Turboc compiler, I never used these kind of arguments.)
You are instructing the compiler to look for certain libraries and use them to try and produce a final object file.
When you were doing your threading code, you used threading primitives. These threading primitives are implemented in a library called pthread, -lpthread tells the linker to use the library pthread, without providing this switch the compiler will not be able to produce a valid object file as it is missing threading code implementation.
On the file system the libraries can be found in /usr/lib and lib (among others) when you look in these directories you will see files start with the lib prefix. for example libpthreadxxxxxx. You will have to do your own research to figure out what the xxxx means.
The development cycle using unix style tools is very granular on the surface, when you use heavyweight IDE's (read: visual studiio for C++), the IDE implicetly links against loads of standard libraries, so often you do not need to supply the name of the libraries you will commonly use. However, when you start doing more advanced programming you will probably have to install and configure your IDE to use external code libraries. If you were to use threading primitives in visual studio, you most likely will not have to provide the compiler with information on where to look for threading primitives, Microsoft considers this a common library and every new project will implicitly link against it.
A little discussion on GCC
GCC is a very diverse compiler producing code for various different usage scenarios. As such they try to be neutral and do not make assumptions. For example pthread is a particular threading primitives implementation. However, even through now on Linux at least it is the defacto standard, it is not the only one. Other Unix implementation have had different implementation. When such choices exist it is not fair for the compiler developers to implicitly link against libraries. They do however implicitly link against standard libraries; for example G++ is just a wrapper command to the internal compiler code, it is a C++ front-end so it implicitly links against an implementation of the C++ standard library. Similarly the C front end links against a the standard C library.
People often do not want to use certain standard library implementation, and instead they might want to use another implementation, in such cases you have to explicetly inform the compiler to use an implementation that you provide. Such use cases are very granular and are surface level issues with G++. In visual studio, you would have to tinker a lot to make such changes generally, since it is not an anticipated use-case anymore.
wikipedia will provide you with more information.
Edit: I'll fix the spelling and Grammatical issues later :D
The option -l indicates to gcc what libraries must be used for linking. -lpthread stands for "use the pthread library", and -lm stands for "use the m library" which is the math library. These commands are relative to gcc, not linux.
Because by default, gcc only links the C library (libc), which contains the well-known functions printf, scanf, and many more.
log10 exists in a different library called libm, and thus you need to explictly tell gcc to link that library, with -lm. The same logic applies for -lpthread.
This is purely a backwards, harmful practice. Separating parts of the standard library into separate .so files does nothing but increase load time and memory usage. Good luck getting anyone to change it though... Just accept that you have to do it (and that POSIX specifically allows, but does not require, that an implementation require -lm for using the math functions and -lpthread for using threads, etc.) and move on to more important things.
Or, go pester Drepper about it on the glibc bug tracker/mailing list. He won't change his mind, but if you enjoy flamewars you can get some kicks...
I am a beginner in C, and i would like to read how various libraries are implemented. I looked under /usr/src/include and all i found was .h files. For example , i was looking at malloc.h and all that it does is , declare extern functions.
So i am trying to find the source for those functions. I downloaded gcc source rpm, but looking at the gcc source, it looks more like compiler code,rather than code for libraries such as stdlib.
Can you please help me by pointing me to the right direction.
Thank you.
You need to get the source code of the associated C library, probably glibc or eglibc in your case.
In the /usr/include/ folder, only the headers of the libc are present, along with some linux kernel headers in the linux/ subfolder.
You're looking for glibc, rather than gcc.
.h files never contains code (well, at least they should. Macros are exceptions)
the basic C functions are either in glibc or linux kernel
gcc, linux and glibc code are huge beasts, if you are a beginning beginner, you should go for simpler things
you probably should take a simple library, one that offer a few tools, on a narrow subject.
then go for linux and glibc (or uclibc)
I personnaly learnt many interesting stuff by reading microcontroller system libraries such as http://www.nongnu.org/avr-libc/, but this depends on what you need to do, and it requires a microcontroller to run it.
An idea: depending of what you're looking for, you could go for busybox: it is a reimplementation of many usefull system commands, you can learn a lot from it and running it do not require a dedicated computer.
Update: i asked a question related to glibc functions that got a few very interesting answers from my not-guru p.o.v:
where to find select() source code in glibc source?
I'm compiling newlib for a bespoke PowerPC platform with no OS. Reading information on the net I realise I need to implement stub functions in a <newplatform> subdirectory of libgloss.
My confusion is to how this is going to be picked up when I compile newlib. Is it the last part of the --target argument to configure e.g. powerpc-ibm-<newplatform> ?
If this is the case, then I guess I should use the same --target when compiling binutils and gcc?
Thank you
I ported newlib and GCC myself too. And i remember i didn't have to do much stuff to make newlib work (porting GCC, gas and libbfd was most of the work).
Just had to tweak some files about floating point numbers, turn off some POSIX/SomeOtherStandard flags that made it not use some more sophisticated functions and write support code for longjmp / setjmp that load and store register state into the jump buffers. But you certainly have to tell it the target using --target so it uses the right machine sub-directory and whatnot. I remember i had to add small code to configure.sub to make it know about my target and print out the complete configuration trible (cpu-manufacturer-os or similar). Just found i had to edit a file called configure.host too, which sets some options for your target (for example, whether an operation systems handles signals risen by raise, or whether newlib itself should simulate handling).
I used this blog of Anthony Green as a guideline, where he describes porting of GCC, newlib and binutils. I think it's a great source when you have to do it yourself. A fun read anyway. It took a total of 2 months to compile and run some fun C programs that only need free-standing C (with dummy read/write functions that wrote into the simulator's terminal).
So i think the amount of work is certainly manageable. The one that made me nearly crazy was libgloss's build scripts. I certainly was lost in those autoconf magics :) Anyway, i wish you good luck! :)
Check out Porting Newlib.
Quote:
I decided that after an incredibly difficult week of trying to get newlib ported to my own OS that I would write a tutorial that outlines the requirements for porting newlib and how to actually do it. I'm assuming you can already load binaries from somewhere and that these binaries are compiled C code. I also assume you have a syscall interface setup already. Why wait? Let's get cracking!