Compile all necessary files with gcc - c

I’m quite new to C and the gcc compiler. I have a project where I include some other .h files. In that files there are include from more own .h files. And so on. Its a decent amount of includes.
My problem is, when I try to compile the main file with:
gcc -o test tests_main.c
I get the following error:
Undefined symbols for architecture x86_64:
"_waves_secure_hash_test", referenced from:
_crypto_tests in tests_main-d1ae56.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Thats because the compiler cant find the method "waves_secure_hash_test", but its in the included file:
#include "crypto_tests.h"
So, I searched a little bit and found a solution, just compile it with:
gcc -o test tests_main.c crypto_tests.c
Okay, that work for me with that two test file, where the functions are only some test prints.
For my complete project with a decent amount of includes, I can’t write down all that c files to compile... Is there a way to tell the compiler that he has to compile all needed and included files?

You're mixing up included files (.h files, header files) and source files (.c files). You don't have to do anything about header files, the compiler will process them automatically(1).
You do have to list all source files which you want to compile.They are what defines your project. Based on your source tree organisation, you might get away with using shell pattern expansion (e.g. *.c) to get them, though.
For larger projects, you normally don't type the compilation command by hand, but use some project management tool, such as an IDE, a Makefile, or a buildsystem generator such as CMake.
Also note that the error you're actually getting is not a compiler error, it's a linker error. Linking is a separate step that comes after compiling. The compilation reads source files and produces object files. Linking then reads object files and produces a binary (executable or shared library) out of them.
You should also note that there is not always a 1:1 correspondence between header and source files. The classic example are libraries: you can include one or more header files which are shipped with an external library; these will provide declarations for functions implemented inside that library. This allows you to call the functions in your code. To then make these functions available to the linker (so that they can become part of your program), instruct the linker to link the library into your binary (normally via the -l command-line option).
(1) You may still need to point your compiler at directories where these header files reside, which is usually done using the -I command-line option.

Related

Why does (host) GCC need to be built against the target's standard library?

I've been looking into building cross-toolchains and have a general question about the compilation and workings of gcc.
The question is about this excerpt from the official gcc documentation:
In order to build GCC, the C standard library and headers must be present for all target variants for which target libraries will be built (and not only the variant of the host C++ compiler).
Why is the target's standard library required to build the (cross) compiler itself? Shouldn't the (cross) compiler running on the host only require the host's standard library to be built and then be able to compile the target's standard library?
I also found this on crosstool-NG's how a toolchain is constructed:
the final compiler needs the C library, to know how to use it, but: building the C library requires a compiler
This is consistent with what's stated above but I don't get why the final compiler needs to be built against a prebuilt target C library just to know how to use it later on. What is there to know for the host compiler about the target C library? Isn't it the linker's job to link target programs against the target's standard library at compile time?
Because that's the only way to ensure a working compiler for the target platform is created. There's no point in creating a non-working compiler, distributing it to the target platform, and finding out then that it's useless.
In general, a non-shared-object executable file is only successfully created if there are no unresolved symbols.
Per the GCC 11.2 "Overall Options" documentation
Compilation can involve up to four stages: preprocessing, compilation proper, assembly and linking, always in that order. GCC is capable of preprocessing and compiling several files either into several assembler input files, or into one assembler input file; then each assembler input file produces an object file, and linking combines all the object files (those newly compiled, and those specified as input) into an executable file.
So the final step is linking. The GNU linker 'ld' man page states:
Normally the linker will generate an error message for each
reported unresolved symbol but the option
--warn-unresolved-symbols can change this to a warning.
and
--error-unresolved-symbols
This restores the linker's default behaviour of generating
errors when it is reporting unresolved symbols.
So, by default linking fails when there are unresolved symbols.
Why?
Because if there are unresolved symbols, the resulting executable file won't work when it's run.
And the only way to ensure there are no unresolved symbols is to have all the necessary libraries from the target platform available when cross-compiling so all symbols can be resolved when the new compiler executables are being linked.

Multible definitions including open source library (with seemingly correct linker settings?)

Im working on a program for my studies, that uses an open source library. It is meant to run on Raspberry Pi (Raspbian Kernel). Because of my intention to be also able to load it on a PLC i used mostly pure C. The Library itself comes with suitable header and .c files.
When i use the pre installed GCC compiler on the Raspberry my program compiles without any errors and works fine. Now here comes my problem:
I tried to get this projekt to work on windows using code::blocks IDE with MinGW installed. I revisited the library and downloaded the zip for windows (apperently same header and .c file, but also .lib and .dll included).
I set the search directories and linker settings within the project and included the header as usual with #include "header.h" for the relative path. It doesn't compile and gives alot multible definition and first defined here which usually indicate wrong linking and inclusion.
As i tried to identify some of this definitions i noticed that the functions which cause errors are defined one time in the library.c file. At the beginning of this .c file it also includes the header one time.
Short summary:
This works with raspbian GCC:
$ gcc -sdt=c99 main.c library.c -o executable
but gives errors with Windows IDE + MinGW
Am i missing something serious? The dynamic link lib should only be used by the executable afterwards. I thought maybe the libraby.c gets replaced by the library.lib but if i remove one of them the project doesn't know the functions. I also searched for wrong inclusions. I'm really at the end of my knowledge here, and also searched for posts that would help me, but those were mostly "where is the linker path" or "inclusion of .c files". It seems so an simple problem which i overlooked.
Any help Would be appriciated. I will supply more details if needed.
Thanks!
Edit (2):
obj\Debug\open62541.o:open62541.c:(.text+0x3152a): undefined reference to `__imp_shutdown'
obj\Debug\open62541.o:open62541.c:(.text+0x3153f): undefined reference to `__imp_closesocket'
obj\Debug\open62541.o:open62541.c:(.text+0x315a7): undefined reference to `__imp_send'
obj\Debug\open62541.o:open62541.c:(.text+0x315b9): undefined reference to `__imp_WSAGetLastError'
.....
Edit (3)
Answer 1!
Compiled good now, thanks everyone.
It looks like your library is open62541.
There are two ways to include the library in your source:
Build a shared/static lib and link it to your code
Enable Amalgamation which generates a single .c and .h file which you can directly compile with your code
You are combining both methods on mingw which adds the whole library two times.
Probably you only want to link the .c file without the .lib, thus your compile command should look something like this:
gcc -sdt=c99 main.c open62541.c -o test
Additionally, since open62541 needs the ws2_32 library on windows, the compiler should be called with:
gcc -std=c99 main.c open62541.c -o test -lws2_32

How to Include external C library on windows

I am fairly new to C and I am trying to include a external library without using any IDE, only text-editor and the minGW compiler on windows cmd. The library is libPNG in this case, I would really like to understand how the process work not only for this library.
If there is a better way (and easier) to do this, I would also like to know.
You have two parts to take care of:
compilation,
linking.
Compilation
In compilation, when you transform source files in object files, your compiler must know what are the functions provided by the external library.
You could declare each function you use or you can include the library header file(s) in your code:
#incude <library_file.h>
It's not enough, you will have to tell your compiler where it can find this file:
-I<path_to_lib_folder> with gcc
/I<path_to_lib_folder> with cl (the visual studio compiler)
Linking
In linking process, you put the object and library files together to construct an executable file.
You need to tell the linker
what files it must use and
where it can find the library file
You tell the linker what files to use with the -l options, for instance, -lfoo will tell it to search for the libfoo.so lib
Note: with cl you can tell specify which library to use directly in your source code with #pragma comment (lib, "libfoo.lib")
Add you specify where with:
-L<path_to_lib_folder> with gcc
/LIBPATH:<path_to_lib_folder> with link (the visual studio linker)
You can also use dynamic linking, but let's start with the first step.

Creating static libraries

I'm trying to create a static library to use inside my PHP extension. To do that, I'm compiling my .c files using gcc -c file.c -o file.o and obtaining .o files. I then use ar rcs lib.a *.o to archive all the compiled objects into an .a file.
After doing this, I'm referring to this .a file when compiling my PHP extension, but I get the following error:
*** Warning: Linking the shared library <extension>.la against the
*** static library lib.a is not portable!
If I use the .o files instead of the .a file, I get:
*** Warning: Linking the shared library <extension>.la against the non-libtool
*** objects file1.o file2.o is not portable!
What am I doing wrong and what's the correct way of doing this?
The short answer: shared libraries (of which a PHP extension is a special case) cannot depend on static libraries.
Actually that's not quite entirely true. As long as your static library is built as position-independent code (PIC), using it from a shared library will work; whatever .o files from the archive are needed to satisfy the undefined symbols in the .o files you explicitly linked to make the .so will get pulled in and become part of the shared library file.
Linking non-PIC .o files into a shared library will also work on some archs (like i386) but it's not portable (and won't work on x86_64).
As for what you should do, if it's possible, I would just forget about the intermediate .a file and link all your .o files explicitly into the .so file for the extension. This is clean and simple. Or you could keep doing it the way you're doing as long as you're sure all your files got built as PIC (i.e. with the -fPIC option).
What I would not do is make and install an extra .so file that the main .so file for the extension will then depend on. All this does is create bloat, increase load time, and make lots of trouble with deployment/integration.
Linking shared libraries to static libraries is not possible (unless you really know very well what you are doing). Don't do it.
The first warning is from libtool. It tells you, that the operation you asked for will do different things on different systems and some of those things are probably not what you want. Often it's just going to fail in various spectacular ways, because code that goes in shared and static libraries needs to be compiled with different compiler flags.
i have faced same problem once but i have solved it by corrcting some linking flag in make file you can see
What is the meaning of “Warning: Linking the shared library against static library is not portable”?

How do you actually use a C library?

I'm sure this question has been asked many times, but I can't figure this out. Bear with me.
So when you download a library, you get a bunch of .c and .h files, plus a lot of other stuff. Now say you want to write a program using this library.
I copy all the .h files into my project directory. It just doesn't compile.
Great, so then I get the library as a bunch of .dll's, and i copy the dlls into my project directory. Still doesn't compile.
How does this work?
What do you do, like right after creating the folder for your project? What parts of the library package do you copy/paste into the folder? How do you make it so that it can compile? Go through the steps with me please.
Where to put the .h files?
Where to put the .dll files?
How to compile?
Thanks.
(the library I'm trying to get working is libpng, I'm in windows with MinGW, and i'm looking to compile from command-line like usual.)
(from what i gather, you put the .h files in directory A and the .dll files in directory B and you can use -l and -L compiler options to tell the compiler where to find them, is this correct?)
Here's a brief guide to what happens when you compile and build a basic C project:
The first stage compiles all your source files - this takes the source files you've written and translates them into what are called object files. At this stage the compiler needs to know the declaration of all functions you use in your code, even in external libraries, so you need to use #include to include the header files of whatever libraries you use. This also means that you need to tell the compiler the location of those header files. With GCC you can use the -I command line to feed in directories to be searched for header files.
The next stage is to link all the object files together into one executable. At this stage the linker needs to resolve the calls to external libraries. This means you need the library in object form. Most libraries will give you instructions on how to generate this or might supply it ready built. Under Linux the library file is often a .a or .so file, though it might just be a .o. Again you can feed the location of the library's object file to GCC with the -L option.
Thus your command line would look like this:
gcc myProg.c -I/path/to/libpng/include -L/path/to/libpng/lib -lpng -o myProg.exe
(Note that when using the -l command line GCC automatically adds lib to the start of the library, so -lpng causes libpng.a to be linked in.)
Hope that helps.
Doing it under windows (supposing you user Visual Studio)
After unpacking add the library include directories to your projects' settings (Project -> Properties -> C/C++ -> Additional Include Directories)
Do the same thing for the Libraries Directory (Project -> Properties -> Linker -> Additional Library Directories)
Specify the name of the library in your Linker Input: Project -> Properties -> Linker -> Input -> Additional Dependencies
After this hopefully should compile.
I don't recommend adding the directories above to the Global settings in Visual Studio (Tools -> Options -> Project and Solutions) since it will create and environment where something compiles on your computer and does NOT compile on another one.
Now, the hard way, doing it for a Makefile based build system:
Unpack your stuff
Specify the include directory under the -I g++ flag
Specify the Library directory under the -L g++ flag
Specify the libraries to use like: -llibrary name (for example: -lxml2 for libxml2.so)
Specify the static libraries like: library name.a
at the end you should have a command which is ugly and looks like:
g++ -I/work/my_library/include -L/work/my_library/lib -lmylib my_static.a -o appname_exe MYFILE.CPP
(the line above is not really tested just a general idea)
I recommend go, grab a template makefile from somewhere and add in all your stuff.
You must link against a .lib or something equivalent i.e. add the ".lib" to the libraries read by the linker. At least that's how it works under Linux... haven't done Windows so a long while.
The ".lib" contains symbols to data/functions inside the .dll shared library.
It depends on the library. For examples, some libraries contain precompiled binaries (e.g. dlls) and others you need to compile them yourself. You'd better see the library's documentation.
Basically, to compile you should:
(1) have the library's include (.h) file location in the compiler's include path,
(2) have the library stubs (.lib) location in the linker's library path, and have the linker reference the relevant library file.
In order to run the program you need to have the shared libraries (dlls) where the loader can see them, for example in your system32 directory.
There are two kinds of libraries: static and dynamic (or shared.)
Static libraries come in an object format and you link them directly into your application.
Shared or dynamic libraries reside in a seperate file (.dll or .so) which must be present at the time your application is run. They also come with object files you must link against your application, but in this case they contain nothing more than stubs that find and call the runtime binary (the .dll or the .so).
In either case, you must have some header files containing the signatures (declarations) of the library functions, else your code won't compile.
Some 'libraries' are header-only and you need do nothing more than include them. Some consist of header and source files. In that case you should compile and link the sources against your application just as you would do with a source file you wrote.
When you compile, assuming you have the libs and the headers in the same folder as the sources you are compiling, you need to add to your compile line -L . -I . -lpng. -L tells the linker where to look for the library, -I tells the compiler where to look for the headers and -lpng tells the linker to link with the png library.
[Edit]
Normal projects would have some sort of hierarchy where the headers are in an /include folder and the 3rd party libs are in a /libs folder. In this case, you'd put -I ./include and -L ./libs instead of -I . and -L.
[Edit2] Most projects make use of makefile in order to compile from the command line. You can only compile manually for a small number of files, it gets quite hectic after that
Also,
you may want to look over Dynamic Loading support in various languages and on various
platforms.
This support is very handy in cases when you want to use a library optionally and you don't want your program to fail in case that library is not available.

Resources