I'm trying to debug claws-mail notification plugin, I have code like this:
#include "notification_indicator.h"
#include "notification_prefs.h"
#include "notification_core.h"
#include "folder.h"
#include "common/utils.h"
#include <messaging-menu.h>
#include <unity.h>
#define CLAWS_DESKTOP_FILE "claws-mail.desktop"
#include <stdio.h>
void main(void)
{
GList *cur_mb;
gint total_message_count;
total_message_count = 0;
/* check accounts for new/unread counts */
for(cur_mb = folder_get_list(); cur_mb; cur_mb = cur_mb->next) {
Folder *folder = cur_mb->data;
NotificationMsgCount count;
if(!folder->name) {
printf("Notification plugin: Warning: Ignoring unnamed mailbox in indicator applet\n");
continue;
}
gchar *id = folder->name;
notification_core_get_msg_count_of_foldername(folder->name, &count);
printf("%s: %d\n", folder->name, count.unread_msgs);
}
}
and I'm compiling it with this command:
gcc -I/home/kuba/Pobrane/claws-mail-3.13.2/src/
-I/usr/include/gtk-2.0/
-I/usr/include/cairo/
-I/usr/include/pango-1.0
-I/usr/lib/i386-linux-gnu/gtk-2.0/include/
-I/usr/include/gdk-pixbuf-2.0/
-I/usr/include/atk-1.0/
-I/home/kuba/Pobrane/claws-mail-3.13.2/src/common
-I/home/kuba/Pobrane/claws-mail-3.13.2/src/gtk
-I/usr/include/messaging-menu/
-I/usr/include/unity/unity/
-I/usr/include/dee-1.0/
-I/usr/include/libdbusmenu-glib-0.4/
-c `pkg-config --cflags glib-2.0` test.c
but gcc create object file test.o instead of a.out how can I create executable file? I'm running this on Xubuntu.
Remove the -c option from the commandline (which generates the object file instead of executable).
From man gcc:
-c
Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form
of an object file for each source file.
Examples:
To generate an object file (`.o' file):
gcc -c test.c
To generate an executable:
gcc test.c -o test
(if you omit the -o test, it'd generate a.out as executable by convention).
Related
I am forced to link two version of the same third party dynamic library (Linux .so, C language) into the same executable to support old and new functionality in the same process. Having two executables or remote services are undesirable.
I made the assumption that this must be a doable task. I tried to experiment with the naive approach of creating 2 proxy dynamic libraries each linked against one of the real libraries and have function renamed.
Unfortunately, this attempt failed – both new functions call the same target function.
I still want to believe that the problem is in the lack of my knowledge as there are plenty of compiler and linker ( gcc and ld) options.
I will appreciate any help. I also look forward to using dlopen/dlsym, but first want to check if the original approach can work.
Here is the sample code
/* ./old/b.c */
#include <stdio.h>
int b (int i)
{
printf("module OLD %d\n",i);
return 0;
}
/* ./old/Makefile */
libold.so: b.c
gcc -c -g b.c
gcc -shared b.o -o $#
/* ./new/b.c */
#include <stdio.h>
int b (int i)
{
printf("module new %d\n",i);
return 0;
}
/* ./new/Makefile */
libnew.so: b.c
gcc -c -g b.c
gcc -shared b.o -o $#
/* ./a1.c */
#include <stdio.h>
int b(int);
void call_new(void)
{
printf("will call new 1\n");
b(1);
printf("called new 1\n");
}
/* ./a2.c */
#include <stdio.h>
int b(int);
void call_old(void)
{
printf("will call old 2\n");
b(2);
printf("called old 2\n");
}
/* ./main.c */
#include <stdio.h>
int call_new(void);
int call_old(void);
int main()
{
call_new();
call_old();
return 0;
}
/* ./Makefile */
.PHONY: DEPSNEW DEPSOLD clean
main: liba1.so liba2.so main.c
gcc -c main.c
gcc -o main main.o -rdynamic -Wl,-rpath=new -Wl,-rpath=old -L . -la1 -la2
DEPSNEW:
make -C new
DEPSOLD:
make -C old
liba1.so: DEPSNEW a1.c
gcc -c -fpic a1.c
gcc -shared a1.o -L new -lnew -o liba1.so
liba2.so: DEPSOLD a2.c
gcc -c -fpic a2.c
gcc -shared a2.o -L old -lold -o liba2.so
clean:
find -name "*.so" -o -name "*.o" -o -name main | xargs -r rm
/* ./run.sh */
#/bin/sh
LD_LIBRARY_PATH=new:old:. main
The result is not that I want - function from "new" library is called twice
will call new 1
module new 1
called new 1
will call old 2
module new 2
called old 2
In this case, you can not control the automatic loading of the dynamic library in order to assure which library will be loaded for the depending libraries. What you can do, is to use one of the libraries (the new one) for the dynamic linker and to link the second library manually as follows:
Add function to dynamically load and link the function from the library.
a2.c
#include <stdio.h>
#include <dlfcn.h>
static int (*old_b)(int);
void init_old(void) {
void* lib=dlopen("./old/libold.so", RTLD_LOCAL | RTLD_LAZY);
old_b=dlsym(lib,"b");
}
void call_old(void)
{
printf("will call old 2\n");
old_b(2);
printf("called old 2\n");
}
call the initialization function
main.c
#include <stdio.h>
void init_old(void);
int call_new(void);
int call_old(void);
int main()
{
init_old();
call_new();
call_old();
return 0;
}
Modify the linker options to add the dynamic loading library -ldl
liba2.so: DEPSOLD a2.c
gcc -c -fpic a2.c
gcc -shared a2.o -L old -lold -ldl -o liba2.so
After this modification
~$ ./run.sh
will call new 1
module new 1
called new 1
will call old 2
module OLD 2
called old 2
I have source files written in C programming using notepad++ and I am running them from command lines and later i need to link them inorder to generate the .exe file.
Here are the following commands I want to use while generating .exe file
gcc logc.c -o logc
gcc mainc.c -o mainc
gcc -o output logc.o mainc.o
But when i run the following command my compiler is returning with the following error status.
gcc logc.c -o logc
(x86)/mingw-w64/i686-8.1.0-win32-dwarf-rt_v6-rev0/mingw32/bin/../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/lib/../lib/libmingw32.a(lib32_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x39): undefined reference to `WinMain#16'
when i run the following command to compile my mainc file
C:\Users\user\AppData\Local\Temp\ccskY3nf.o:mainc.c:(.text+0x31): undefined reference to `Log'
collect2.exe: error: ld returned 1 exit status
And here are my mainc.c and logc.c and logc.h files for your reference
logc.c file is here
#include <stdio.h>
#include "logc.h"
void InitLog()
{
Log("Initializing Log");
}
void Log(const char* message)
{
printf(" %s",message);
}
mainc.c file is here
#include <stdio.h>
#include <conio.h>
#include <stdbool.h>
#include "logc.h"
int main()
{
int x = 5;
bool comparisonResult = x == 5;
if(comparisonResult == 1)
Log("Hello World");
return 0;
}
and logc.h file is here
#ifndef _LOG_H
#define _LOG_H
void InitLog();
void Log(const char* message);
#endif
How can i compile individual source files and then link them and generate an executable file.
Thanks in advance.
You don't create object files, for that you need the -c argument:
gcc logc.c -c
gcc mainc.c -c
gcc -o output logc.o mainc.o
By default gcc will generate an executable file, not an object file. So when you compile logc.c, it tries to make an executable but it can't find the main function so it fails. Similarly with main.c, it tries to make an executable but can't find Log
You need to add the -c option to create object files:
gcc logc.c -c -o logc.o
gcc mainc.c -c -o mainc.o
Is there any way I can compile a poorly designed header file to a object file without changing file extension or content using gcc, or do I have to copy the file/edit it? (This because I am using a public SDK, i.e. I do not have permission to edit the header file, and because using cp in my Makefile seems like a major hack, and time consuming too)
Example
main.c
#include <print.h>
#include <app.h>
int main(void) {
print("Starting app . . . ");
run();
}
app.h
#ifndef APP_H
#define APP_H
int runApp(void);
#endif
app.c
#include <print.h>
#include <app.h>
int runApp(void) {
print("This is my app!");
return 0
}
print.h
#ifndef PRINT_H
#define PRINT_H
int print(char* str) {
printf(str);
return 0;
}
#endif
Which is compiled using:
$ gcc -o main.o main.c
$ gcc -o app.o app.c
$ gcc -o main main.o app.o
The SDK example programs use a single object file (gcc -o main.o main.c & gcc -o main main.o), but that would just get really messy in my case.
Create
_print.h
int print(char* str);
print.cpp
#include <print.h>
and change your includes to "_print.h"
I was looking here how to do static libraries using GCC, and the explanation is pretty clear (despise the fact I had to rewrite the factorial function): I have a function (fact.c), the header of the function (fact.h), and the main function (main.c), all of them in my home directory.
fact.h
int fact (int);
fact.c
int
fact (int f) {
if ( f == 0 )
return 1;
else
return (f * fact ( f - 1 ));
}
main.c
#include <stdio.h>
#include "fact.h"
int main(int argc, char *argv[])
{
printf("%d\n", fact(3));
return 0;
}
So I had first to generate the object file (phase 1)...
$ gcc -c fact.c -o fact.o
...then to generate the static library (phase 2)...
$ ar rcs libfact.a fact.o
...later to do the static library linking process (phase 3)...
$ gcc -static main.c -L. -lfact -o fact
...and finally run the program (phase 4 and final)
$ ./fact
My question is the following. Let's suppose my program will be so big that I had no alternative than put the headers in a header directory (/include/fact.h) and the static libraries will also be in another directory (/lib/libfact.a). In that case, how the compilation and/or the code of this program will change?
Edit/Problem Solved: First, the main.c was corrected in order to include a header in another directory called include. Remember that, in this case, both of the .c files are in the main directory.
main.c
#include <stdio.h>
#include "include/fact.h"
int main(int argc, char *argv[])
{
printf("%d\n", fact(3));
return 0;
}
Second, to generate the static library in another directory (phase 2), this is what I had done:
$ ar rcs lib/libfact.a fact.o
Here is your answer,
$ gcc -static main.c -L. -lfact -o fact
-L Add directory to the list of directories to be searched for -l
Its in the link that you gave. If you put the seach direction correctly and low search range, it will not be a problem. Otherwise it is not going to compile the code. Because code did not know where is the header.
You can add -I to specify include path(s).
gcc -I/include fact.c
gcc -I/include -static main.c -L/lib -lfact -o fact_main
How can I include foo() function of foo.c in this small program (sorry for my noob question):
In my foo.h file:
/* foo.h */
#include <stdio.h>
#include <stdlib.h>
int foo(double largeur);
In foo.c:
/* foo.c */
#include <stdio.h>
#include <stdlib.h>
#include "foo.h"
int foo(double largeur)
{
printf("foo");
return 0;
}
And in main.c:
/* main.c */
#include <stdio.h>
#include <stdlib.h>
#include "foo.h"
int main(int argc, char *argv[])
{
printf("Avant...");
foo(2);
printf("Apres...");
return 0;
}
After compiling:
$ gcc -Wall -o main main.c
I get this error:
Undefined symbols: "_foo",
referenced from:
_main in ccerSyBF.o ld: symbol(s) not found collect2: ld
returned 1 exit status
Thanks for any help.
$ gcc -Wall -o main main.c foo.c
GCC doesn't know to look for foo.c if you don't tell it to :)
Creating a program in C requires two steps, compiling and linking. To just run the compiling part, use the -c option to gcc:
gcc -c main.c
This creates an object file, main.o (or main.obj on Windows). Similarly for gcc -c foo.c. You won't get the error message above at this stage. Then you link these two object files together. At this stage, the symbol foo is resolved. The reason you got the error message was because the linker couldn't find the symbol, because it was only looking at main.o and not foo.o. The linker is usually run from gcc, so to link your object files and create the final executable file main, use
gcc -o main main.o foo.o
You have to compile foo.c also because it is another module. Let me see how they do it in gcc:
$ gcc -Wall main.c foo.c -o main
You could also do this in your MakeFiles, like this:
APP_NAME = Foo
Foo_HEADERS = foo.h
Foo_FILES = main.c foo.c
If you're not so much familiar with MakeFiles i suggest you to take a look at Make Docs, but this is a simple example, APP_NAME sets the name of the compiled executable(in this case is Foo), Foo_HEADERS will set the headers used by your application, Foo_FILES you will set the source files of your applications, remember to put the APP_NAME(in this case Foo) at the beginning of _HEADERS and _FILES. I suggest you to use MakeFiles because they will organize you application build process and will be better for the end-user.