im new to writing makefile. Now im trying to use pjsip c-library, which i installed in my home-directory. I took a little snipped and tried to compile it. Had some errors and so i searched for an solution, so i found out i had to include this library's to the search path. Further there is a possibility to declare them in the makefile, so i tried the 2nd solution.
Here my makefile:
pjpath=home/pi/pjproject-2.4.5
LIB=-L/$(pjpath)/pjlib/lib -L/$(pjpath)/pjlib-util/lib -L/$(pjpath)/pjnath/lib -L/$(pjpath)/pjmedia/lib -L/$(pjpath)/pjsip/lib
INC=-I/$(pjpath)/pjlib/include -I/$(pjpath)/pjlib-util/include -I/$(pjpath)/pjnath/include -I/$(pjpath)/pjmedia/include -I/$(pjpath)/pjsip/include
all:
gcc -o test $(INC) simple_pjsua.c $(LIB) -lpj -lpjlib -lpjnath -lpjmedia -lpjmedia-audiodev -lpjmedia-codec -lpjmedia-videodev -lpjsdp -lpjsip -lpjsip-simple -lpjsip-ua -lpjsua -lpjsua2
clean:
rm simple_pjsua.o test
and here my c-file simple_pjsua.c:
#define PJ_IS_LITTLE_ENDIAN 1
#define PJ_IS_BIG_ENDIAN 0
#include <pjsua-lib/pjsua.h>
#define THIS_FILE "App"
#define SIP_USER "demo-user2"
#define SIP_DOMAIN "sip:192.168.2.59"
#define SIP_PASSWD "123456"
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata);
static void on_call_state(pjsua_call_id call_id, pjsip_event *e);
static void on_call_media_state(pjsua_call_id call_id);
static void error_exit(const char *title, pj_status_t status);
int main(int argc, char *argv[]){
printf("Hello World");
return 0;
}
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata){
pjsua_call_info ci;
PJ_UNUSED_ARG(acc_id);
PJ_UNUSED_ARG(rdata);
pjsua_call_get_info(call_id, &ci);
PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!", (int) ci.remote_info.slen, ci.remote_info.ptr));
/* Automatically answer incoming calls with 200/OK */
pjsua_call_answer(call_id, 200, NULL, NULL);
}
static void on_call_state(pjsua_call_id call_id, pjsip_event *e){
pjsua_call_info ci;
PJ_UNUSED_ARG(e);
pjsua_call_get_info(call_id, &ci);
PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s", call_id, (int) ci.state_text.slen, ci.state_text.ptr));
}
static void on_call_media_state(pjsua_call_id call_id){
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
pjsua_conf_connect(ci.conf_slot, 0);
pjsua_conf_connect(0, ci.conf_slot);
}
}
static void error_exit(const char *title, pj_status_t status){
pjsua_perror(THIS_FILE, title, status);
pjsua_destroy();
exit(1);
}
and this is my output of the makefile:
gcc -o test -I/home/pi/pjproject-2.4.5/pjlib/include -I/home/pi/pjproject-2.4.5/pjlib-util/include -I/home/pi/pjproject-2.4.5/pjnath/include -I/home/pi/pjproject-2.4.5/pjmedia/include -I/home/pi/pjproject-2.4.5/pjsip/include simple_pjsua.c -L/home/pi/pjproject-2.4.5/pjlib/lib -L/home/pi/pjproject-2.4.5/pjlib-util/lib -L/home/pi/pjproject-2.4.5/pjnath/lib -L/home/pi/pjproject-2.4.5/pjmedia/lib -L/home/pi/pjproject-2.4.5/pjsip/lib -lpj -lpjlib -lpjnath -lpjmedia -lpjmedia-audiodev -lpjmedia-codec -lpjmedia-videodev -lpjsdp -lpjsip -lpjsip-simple -lpjsip-ua -lpjsua -lpjsua2
In file included from /home/pi/pjproject-2.4.5/pjlib/include/pj/config.h:288:0,
from /home/pi/pjproject-2.4.5/pjlib/include/pj/types.h:33,
from /home/pi/pjproject-2.4.5/pjsip/include/pjsip/sip_config.h:27,
from /home/pi/pjproject-2.4.5/pjsip/include/pjsip/sip_types.h:34,
from /home/pi/pjproject-2.4.5/pjsip/include/pjsip.h:24,
from /home/pi/pjproject-2.4.5/pjsip/include/pjsua-lib/pjsua.h:30,
from simple_pjsua.c:3:
/home/pi/pjproject-2.4.5/pjlib/include/pj/config_site.h:3:35: warning: extra tokens at end of #include directive [enabled by default]
/usr/bin/ld: cannot find -lpj
/usr/bin/ld: cannot find -lpjlib
/usr/bin/ld: cannot find -lpjnath
/usr/bin/ld: cannot find -lpjmedia
/usr/bin/ld: cannot find -lpjmedia-audiodev
/usr/bin/ld: cannot find -lpjmedia-codec
/usr/bin/ld: cannot find -lpjmedia-videodev
/usr/bin/ld: cannot find -lpjsdp
/usr/bin/ld: cannot find -lpjsip
/usr/bin/ld: cannot find -lpjsip-simple
/usr/bin/ld: cannot find -lpjsip-ua
/usr/bin/ld: cannot find -lpjsua
/usr/bin/ld: cannot find -lpjsua2
collect2: ld returned 1 exit status
makefile:6: recipe for target 'all' failed
make: *** [all] Error 1
I also found a useful site which explains how it's done, although i couldn't yet figure it out.
First of all, the first warning is from the library code, your code isn't guilty.
Then, always specify link libraries after all of your source or object files. By default GNU linker doesn't remember the symbols from libraries which haven't been referenced yet, so it simply drops out all of your -lsomelib if that somelib hasn't been referenced by a previous object or library.
So, I bet, the line
gcc -o test $(INC) simple_pjsua.c $(LIB)
would help you (or at least this particular error would be resolved).
so i found the the simplest solution at this Site, in the section makefile with version 1.6 or later.
# If your application is in a file named myapp.cpp or myapp.c
# this is the line you will need to build the binary.
all: myapp
myapp: myapp.cpp
$(CC) -o $# $< `pkg-config --cflags --libs libpjproject`
clean:
rm -f myapp.o myop
Worked for me, but there was one clue which i stumble over.
This is important and is also described at the bottom of the page i linked. If you notice there are spaces towards the bottom of the file (before $(CC) and rm, these are a single tab, not spaces. This is important, or otherwise make command will fail with "missing separator" error.
Related
I am getting undefined reference error while trying to compile main that refers to two libraries. I have two files lib1/func1.c and lib2/func2.c in separate folders. Those files contain two functions print1() and print2(), function print1() is calling print2().
I am compiling those separately into two libraries libfunc1.a and libfunc2.a.
But when I am trying to compile main which is calling print1(), I get the following error:
/usr/bin/ld: /home/sv/ztest2/lib1/libfunc1.a(func1.o): in function print1:
/home/sv/ztest2/lib1/func1.c:7: undefined reference to print2
collect2: error: ld returned 1 exit status
make: *** [Makefile:21: DP] Error 1
Here is the code and Makefiles:
Makefile:
TARGET = DP
HOME = /home/slav/FORECAST/ztest2
INCDIRS = -I./ \
-I$(HOME)/lib1 \
-I$(HOME)/lib2
LIBDIRS = -L$(HOME)/lib1 \
-L$(HOME)/lib2
SRCFILES = DP.c
OBJFILES = DP.o
CFLAGS = -g -O3 $(INCDIRS)
all: $(TARGET)
$(TARGET): $(OBJFILES)
cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc2 -lfunc1
clean:
-rm *.o $(TARGET)
DP.c:
#include "func1.h"
int main()
{
print1();
return 0;
}
func1.h:
void print1();
func1.c:
#include <stdio.h>
void print1()
{
printf("print1 is called!\n");
print2();
}
func2.h:
extern void print2();
func2.c:
#include <stdio.h>
void print2()
{
printf("print2 is called!\n");
}
Libraries must be listed in the order their symbols are needed.
The command cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc2 -lfunc1 tells the linker to first use the func2 library to resolve any pending references in the executable it is building and then to use the func1 library.
Since the linker processes func2 first, and, at the time it does so, there is no pending reference to print2, the linker does not include the module with print2 in the executable.
Later, when the linker is processing func1, it includes the module with print1 in the executable because main uses it. That module print1 uses print2, so including that module adds a new reference to print2. Then, when the linker is done processing func1, it has an unresolved reference. The linker does not go back to func2 to check it again.
Since the func1 library depends on func2, change the link command to cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc1 -lfunc2.
(If the func2 library also depends on func1, that is a bad design and should be reconsidered. If it is not changed, asking the linker to reconsider the libraries multiple times, as with -lfunc1 -lfunc2 -lfunc1, might fix the immediate problem, but others can arise.)
I am starting out with coding for Wayland. I have been following many tutorials, but I am still stuck at compiling. I wrote this very simple code:
#include<stdio.h>
#include<wayland-client-core.h>
int main(int argc, char *argv[]) {
struct wl_display *display = wl_display_connect(NULL);
if(!display) {
fprintf(stderr, "Failed to connect to Wayland display\n");
return 1;
}
fprintf(stdout, "Connection established!\n");
getchar();
wl_display_disconnect(display);
return 0;
}
Then, I tried to compile it with gcc -o client -lwayland-client client.c
But, compilation fails with this error message:
/usr/bin/ld: /tmp/ccfXeOS8.o: in function `main':
client.c:(.text+0x19): undefined reference to `wl_display_connect'
/usr/bin/ld: client.c:(.text+0x7c): undefined reference to `wl_display_disconnect'
collect2: error: ld returned 1 exit status
This looks strange because there is a file /usr/include/wayland-client-core.h in the system, which has got these declarations:
struct wl_display *wl_display_connect(const char *name);
void wl_display_disconnect(struct wl_display *display);
What am I doing wrong here?
You need to change the command line to:
gcc client.c -o client -lwayland-client
or:
gcc client.c -lwayland-client -o client
or:
gcc -o client client.c -lwayland-client
Basically, the .c file (or .o file) needs to appear before the library linking options.
I am trying to compile an example program to use HDF-EOS. The example code is taken from the HDF-EOS website (I will therefore only post the top section):
/* This example shows how to read a data field in HDF-EOS2 grid data. */
#include <mfhdf.h>
#include <hdf.h>
#include <HdfEosDef.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int32 gridfile1;
int32 grid1;
int32 datafield1rank;
int32 datafield1dimsize[32];
int32 datafield1type;
char datafield1dimname[512];
float32 *datafield1data;
int32 i, j;
/* Open 'AMSR_E_L3_RainGrid_B05_200707.hdf' using grid API */
if ((gridfile1 = GDopen("AMSR_E_L3_RainGrid_B05_200707.hdf", DFACC_RDONLY)) == -1) {
fprintf(stderr, "error: cannot open grid 'AMSR_E_L3_RainGrid_B05_200707.hdf'\n");
return -1;
}
return 0;
The corresponding make file looks like this:
HDF4_DIR=<hdf4_path>
HDFEOS2_DIR=<hdfeos2_path>
CC=$(HDF4_DIR)/bin/h4cc
CFLAGS=-I$(HDFEOS2_DIR)/include
LDFLAGS=-L$(HDFEOS2_DIR)/lib
LIBS=-lhdfeos -lGctp
read_grid: read_grid.c
$(CC) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $#
In addition to the above mentioned paths I have also added links to the hdf5 library, so my make file looks like this:
HDF4_DIR=<hdf4_path>
HDFEOS2_DIR=<hdfeos2_path>
HDF5_DIR=<hdf5_path>
CC=$(HDF4_DIR)/bin/h4cc
CFLAGS=-I$(HDFEOS2_DIR)/include -I$(HDF4_DIR)/include -I$(HDF5_DIR)/include
LDFLAGS=-L$(HDFEOS2_DIR)/lib64 -L$(HDF4_DIR)/lib64 -L$(HDF5_DIR)/lib64
LIBS=-lhdfeos -lGctp
read_grid: read_grid.c
$(CC) read_hdf_eos.c $(CFLAGS) $(LDFLAGS) $(LIBS) -o $#
The problem now is that it does not compile, throwing linking errors such like this:
<hdfeos2_path>/lib64/libhdfeos.a(GDapi.o): In function `lamazDxDtheta':
<hdfeos2_path>/src/GDapi.c:9579: undefined reference to `sin'
<hdfeos2_path>/src/GDapi.c:9580: undefined reference to `sin'
...
collect2: error: ld returned 1 exit status
So for me this looks like a linking problem, however I have no idea why.
To add to the confusion I get another error:
read_grid.o: In function `main':
read_grid.c:(.text.startup+0x0): multiple definition of `main'
read_grid.o:read_grid.c:(.text.startup+0x0): first defined here
Of course I have not defined main more than once. In a second example program that throws the same linking errors I do not get this error.
So if some one would have an idea on the first problem, the linking, I would be very happy.
SOLUTION:
add -lm at the end of the compile statement in the, removes the linking problem
remove the read_hdf_eos.c in the compile statement, that caused the multiple main issue
Thanks for the comments and hints.
I made a shared library as the follow:
gcc -c output.c
gcc -shared -fPIC -o liboutput.so output.o
When output.c is the follow, it could work.
//#include "output.h"
#include <stdio.h>
int output(const char* st) {
return 1+2;
}
But, when output.c changed as the follow, a error occur.
//#include "output.h"
#include <stdio.h>
int output(const char* st) {
printf("%s\n", st);
return 1+2;
}
This is error message:
/usr/bin/ld: output.o: relocation R_X86_64_PC32 against undefined 符号 `puts##GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: 最后的链结失败: 错误的值
collect2: error: ld returned 1 exit status
I want to know why and how to deal it. Thanks in advance.
You need to compile output.c as position independent code.
gcc -c -fPIC output.c
In the first version you have not called any library function. But in second one printf is being called. In general, compile all sources with -fPIC if you intend to build a shared library later.
I am having slight problems with using makefile in C. Ive been following a tutorial in a textbook, but it doesnt seem to want to work. I have three files, message_hider.c, encrypt.h and encrypt.c. When I create a makefile for these files it returns an error, but when I run each command individually it works just fine. Here are my files.
encrypt.c
#include "encrypt.h"
void encrypt(char *message) {
char c;
while (*message) {
*message = *message ^ 31;
message++;
}
}
message_hider.c
#include <stdio.h>
#include "encrypt.h"
int main() {
char msg[80];
while (fgets(msg, 80, stdin)) {
encrypt(msg);
printf("%s", msg);
}
}
encrypt.h
void encrypt(char *message);
Makefile
message_hider: message_hider.o encrypt.o
gcc message_hider.o encrypt.o -o message_hider
message_hider.o: message_hider.c encrypt.h
gcc -c message_hider.c
encrypt.o: encrypt.c encrypt.h
gcc -c encrypt.c
Error message
$ make message_hider
cc message_hider.o -o message_hider
message_hider.o:message_hider.c:(.text+0x17): undefined reference to `encrypt'
message_hider.o:message_hider.c:(.text+0x17): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `encrypt'
/usr/lib/gcc/x86_64-pc-cygwin/4.8.2/../../../../x86_64-pc-cygwin/bin/ld: message_hider.o: bad reloc address 0x0 in section `.pdata'
/usr/lib/gcc/x86_64-pc-cygwin/4.8.2/../../../../x86_64-pc-cygwin/bin/ld: final link failed: Invalid operation
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'message_hider' failed
make: *** [message_hider] Error 1
$ make message_hider
cc message_hider.o -o message_hider
That is not the rule you've specified in your makefile. First off, it appears to be using cc rather than gcc. Second, there's no mention of encrypt.o in there which is why your link is failing.
Try to explicitly use the makefile, such as with:
make -f Makefile message_hider
It may be that it's picking up a different makefile, one that either has different rules or one that simply relies on the default rules like .c.o.
And, based on your update that:
make -f Makefile message_hider
gives you:
$ make -f Makefile message_hider
make: Makefile: No such file or directory
make: *** No rule to make target 'Makefile'. Stop.
that's the error you get when Makefile does not actually exist.
So you need to check that it's in the current directory, and named exactly as you expect.
That would explain the use of default rules as mentioned earlier, since your makefile isn't actually being picked up.
Another thing to check, though it's probably moot now that we've seen the error above, is that you're actually running the correct make program. Use which make to find out where it is (should be /usr/bin/make on CygWin) and make --version to check the version.