How to deal with function definitions in header files? - c

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"

Related

linking with wrap directive for unit testing can be used to redefine a subroutine?

I'm using Cmocka to write a unit testing suite for a shared object written in C, but I'm having some issue. Since I cannot share the source code, I have written a minimum "not-working" example to show what is the issue:
my program is composed 5 files: foo.c, foo.h bar.c bar.h main.c.
bar.* files define a bar() function, which simply returns the argument multiplied by 2
foo.* files declare a foo() function that uses the bar() function defined by bar.h
main.c contains a simple cmocka test and a __wrap_bar()
function, returning the argument multiplied by 3.
I compile the program by producing a libfootest.so object (foo+bar) and then I link this object with main.o passing the -Wl,--wrap=bar flag to the compiler. In this configuration libfootest is the module under test and main is the tester program. I expect the __wrap__bar to be called (failing the test), but the standard bar() is called(test is passed). How can I solve this problem? Below you find all the code I'm using.
bar.c:
#include "bar.h"
int bar(int val) {
return val*2;
}
bar.h:
int bar(int val);
foo.h:
#include <stdio.h>
int foo(int val);
foo.c:
#include "foo.h"
#include "bar.h"
int foo(int val) {
int ret;
ret = bar(val);
printf("RET: %d", ret);
return ret;
}
main.c:
#include <stdio.h>
//required include for CMOCKA
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <setjmp.h>
#include <cmocka.h>
//library under test
#include "foo.h"
int __wrap_bar(int val) {
return 3*val;
}
static void test_foo(void **state) {
int ret = foo(5);
assert_int_equal(ret, 10);
}
int main (int argc, char** argv) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_foo),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}
Makefile:
CMOCKA_LIB_DIR=../../cmocka-1.1.5/build/src
CXXFLAGS+=-g -Og -fPIC
CFLAGS+=-g -Og -std=c99 -fPIC
CC=gcc
CXX=g++
all: main.o ./libfootest.so
gcc -o linux-test -g -L. -L$(CMOCKA_LIB_DIR) $(filter %.o, $^) -lcmocka -lfootest -Wl,-rpath=. -Wall -Wl,--wrap=bar -Wl,-rpath=$(CMOCKA_LIB_DIR)
./libfootest.so: foo.o bar.o
$(CC) -shared -o $# -g $^ -pedantic -Wall
clean:
rm -f *.o
rm -f *.so
The problem is your build of the library. You don't create a link library as commonly done, with separated modules. Instead you link all given modules and place the resulting single module in the target library.
That's why the linker resolved the call to bar() already, and it is no longer unresolved when linking the test program.
The option --wrap works only for unresolved references between modules.
The solution is to build the library from separated modules. Use the tool ar for this:
ar r libfootest.a foo.o bar.o

Compiling header files in ubuntu. What do I type in terminal?

I'm pretty sure this is a simple question but I've searched online for about half an hour.
I have 3 files:
02_01.c
#include <stdio.h> // Notice the library included in the header of this file
#include <stdlib.h>
#include "myLibrary.h" // Notice that myLibrary.h uses different include syntax
#define MAX_LENGTH 21.8
#define WORK_WEEK 5
int main(void) {
function1();
return EXIT_SUCCESS;
}
myLibrary.c
void function1(void){
puts("It works :)");
}
void function2(void){
//This function does nothing as well
}
myLibrary.h
#ifndef MYLIBRARY_H_
#define MYLIBRARY_H_
void function1(void);
void function2(void);
#endif /* MYLIBRARY_H_ */
First, I navigate to my working directory.
Normally in a file with no local headers I would type:
gcc -o 02_01 02_01.c
./02_01
and it would work.
I've tried a variety of things like:
gcc -o 02_01 02_01.c myLibrary.c
which gives me an error "implicit declaration of function 'puts'
gcc -o myLibrary myLibrary.c which also gives the same error.
What should I be typing in the terminal in ubuntu?
So I'm assuming that the puts() function in myLibrary.c is not connected to 02_01.c which is where I include stdio.h.
You must include required headers in every file, where you using included functions. In your case, you must include #include <stdio.h> in beginning of your myLibrary.c file.
Also, you probably want to build .a library and link with it later.
So, finally:
Compile lib:
gcc -c -o mylib myLibrary.c
Make static lib:
ar rcs libMyLib.a mylib
Compile app and link together:
gcc -o 02_01 02_01.c -L. -lMyLib

gcc generate .o file instead of executable

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).

gcc compile multiple files

I have these five source
main.c src_print1.c src_print2.c header_print1.h header_print2.h
the contents are simple and are as following for respective files:
main.c
#include "header_print1.h"
#include "header_print2.h"
int main(int argc, char** argv) {
print1();
print2();
return 0;
}
header_print1.h
#ifndef PRINT_1
#define PRINT_1
#include <stdio.h>
#include <stdlib.h>
void print1();
#endif
header_print2.h
#ifndef PRINT_2
#define PRINT_2
#include <stdio.h>
#include <stdlib.h>
void print2();
#endif
src_print1.c
#include "header_print1.h"
void print1() {
printf("Hello 1\n");
}
src_print2.c
#include "header_print2.h"
void print2() {
printf("Hello 2\n");
}
Using gcc I have tried to compile using the following command line:
gcc -I ./ -o test -c main.c src_print1.c src_print2.c
Everything is in the same folder.
The error I get is:
gcc: cannot specify -o with -c or -S with multiple files
I looked up at gcc manual, but actually I don't understand what to do in this case, since usually I use IDE and not the command line.
IMHO, if you rewrite your compilation statement like
gcc -I./ -o test main.c src_print1.c src_print2.c
You'll be good to go. There is no need for -c flag [NOTE] when you're specifying the output binary using -o.
Also, as mentioned here, all the files are in same directory, you can even shorten the statement as
gcc -o test main.c src_print1.c src_print2.c
Suggestion: While the above change(s) will do the job, this is not considered an elegant way of doing so. Please consider creating a makefile which will make your life easier.
[Note]:
Regarding the -c option, as per the online gcc manual, (emphasis mine)
-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.
So, it should be clear by now, why you got the error.

Include a source file in a C program

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.

Resources