简体   繁体   English

使用make包含头文件时出错

[英]Error while including header file using make

I have to compile two independent processes- sendfdsock.c and recvfdsock.c using make file. 我必须使用make文件编译两个独立的进程 - sendfdsock.c and recvfdsock.c Both the files have there own main function. 这两个文件都有自己的main功能。 This means they are independent and I have to compile them as two different binaries. 这意味着它们是独立的,我必须将它们编译为两个不同的二进制文件。 This is my make file: 这是我的make文件:

compileAll:sendfdsock recvfdsock


sendfdsock:sendfdsock.o 
    gcc -o sendfdsock sendfdsock.o

sendfdsock.o:sendfdsock.c accessories.h
    gcc -c sendfdsock.c


recvfdsock.o:recvfdsock.c accessories.h
    gcc -c recvfdsock.c

recvfdsock:recvfdsock.o 
    gcc -o recvfdsock recvfdsock.o

Here I have made a compileAll target which compiles both the files. 在这里,我创建了一个compileAll目标,用于编译这两个文件。
Both files need to use accessories.h . 这两个文件都需要使用accessories.h As mention in GNU Make Doc - A simple Make file. 正如在GNU Make Doc中提到的 - 一个简单的Make文件。 I wrote this make file. 我写了这个make文件。

accessories.h : accessories.h

#include <malloc.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <error.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/un.h>
#include <stropts.h>

#define PORT "4444" //port we are listening on

int sendall(int fd, char *buf, int *len);
int recvall(int fd, char *buf, int *len);
void logp(int typ, char* msg);
void errorp(char *where, int boolean, int errn,char *what);

accessories.c : 配件。

#include "accessories.h"

void logp(int typ, char* msg) // typ --> type(category) of message [1-Normal Log, 2-Warning(any unexpected thing happened), 3-Error, 4-Debugging Log ]
{
    int fd;
    time_t now;
    ssize_t wlength=0;
    char * dat;
    char * str;
    int size = 45+strlen(msg);//14+24+5+sizeof msg+1

    str= (char *) malloc(size);

    time(&now);//system time in seconds
    dat = ctime(&now); // converting seconds to date-time format
    dat = strtok(dat,"\n");

    //Appending type of log
    switch(typ)
    {
    case 1:
        strcpy(str,"__LOG__    |  ");
        strcat(str,dat);
        break;
    case 2:
        strcpy(str,"__WARN__   |  ");
        strcat(str,dat);
        break;
    case 3:
        strcpy(str,"__ERR__    |  ");
        strcat(str,dat);
        break;
    case 4:
        strcpy(str,"__DEBUG__  |  ");
        strcat(str,dat);
        break;
    default:
        strcpy(str,"__UNDEF__  |  ");
        strcat(str,dat);
        break;
    }


    strcat(str,"  |  ");
    strcat(str,msg);//appending message
    strcat(str,"\n");

    fd = open("log", O_WRONLY | O_CREAT | O_APPEND, 0644); // should be opened somewhere else
    if (fd == -1)
        printf("Could not open log - %s\n",strerror(errno));
    else
    {//need to add lock to the file and printing error message
        while ( wlength < strlen(str) )
        {
            wlength = write(fd, str,strlen(str));
            if (wlength == -1)
            {
                printf("Error : writing log\n");
                break;
            }
        }


    }
}

int sendall(int fd, char *buf, int *len)
{
    int total = 0;        // how many bytes we've sent
    int bytesleft = *len; // how many we have left to send
    int n;

    while(total < *len) {
        n = send(fd, buf+total, bytesleft, 0);
        if (n == -1) { break; }
        total += n;
        bytesleft -= n;
    }

    *len = total; // return number actually sent here

    return n==-1?-1:0; // return -1 on failure, 0 on success
}

int recvall(int fd, char *buf, int *len)
{
    int total = 0;        // how many bytes we've sent
    int bytesleft = *len; // how many we have left to send
    int n;

    while(total < *len) {
        n = recv(fd, buf+total, bytesleft, 0);
        if (n == -1) { break; }
        total += n;
        bytesleft -= n;
    }

    *len = total; // return number actually sent here

    return n==-1?-1:0; // return -1 on failure, 0 on success
} 

void errorp(char *where, int boolean, int errn,char *what)
{
    char errmsg[21+strlen(where)];
    strcpy(errmsg,"Where - ");
    strcat(errmsg,where);
    strcat(errmsg,"  |  Error - ");

    if(boolean == 1)//we got error number
    {
        strcat(errmsg,strerror(errn));
        //fprintf(stderr,"ERROR - In %s and error is %s\n",where ,strerror(errn));
        logp(3,errmsg);
    }
    else if(boolean == 0)//we got a message
    {
        strcat(errmsg,what);
        //fprintf(stderr,"ERROR - In %s and error is %s\n",where ,what);
        logp(3,errmsg);
    }
    else//we got nothing
    {
        strcat(errmsg,"No Message");
        //fprintf(stderr,"ERROR - In %s\n",where);
        logp(3,errmsg); 
    }
}

Initially everything work fine but when I trid to use any function which is defined in accessories.c compilation give me error. 最初一切正常,但是当我试图使用在accessories.c定义的任何函数编译时给我错误。
For example I use the log function in sendfdsock.c : 例如,我在sendfdsock.c使用log函数:

#include "accessories.h"


#define CONTROLLEN  CMSG_LEN(sizeof(int))


static struct cmsghdr   *cmptr = NULL;  /* malloc'ed first time */ 
int send_err(int fd, int errcode, const char *msg);
int send_fd(int fd, int fd_to_send);

int main(int argc, char const *argv[])
{   
    logp(1,"started"); //This function is defined in accessories.c

    int fd_to_send;
    if((fd_to_send = open("vi",O_RDONLY)) < 0)
        printf("vi open failed");

    struct sockaddr_un address;
    int  socket_fd, nbytes;
    char buffer[256];
........

Output of the compilation is: 编译的输出是:

abhi@abhi-me:~/bridge/server$ make compileAll 
gcc -c sendfdsock.c
sendfdsock.c: In function ‘send_fd’:
sendfdsock.c:111:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘ssize_t’ [-Wformat]
sendfdsock.c:114:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘ssize_t’ [-Wformat]
gcc -o sendfdsock sendfdsock.o
sendfdsock.o: In function `main':
sendfdsock.c:(.text+0x32): undefined reference to `logp'
collect2: ld returned 1 exit status
make: *** [sendfdsock] Error 1
abhi@abhi-me:~/bridge/server$ 

Why undefined reference to logp error? 为什么未定义引用logp错误?

Why I don't write accessories.o in final linking: 为什么我不写配件.o在最后的链接:

But as this example is given in GNU Make Doc: 但是这个例子在GNU Make Doc中给出:

In this example, all the C files include ‘defs.h’, but 
only those defining editing comminclude ‘command.h’, and only
low level files that change the editor buffer include 'buffer.h':


edit : main.o kbd.o command.o display.o \
    insert.o search.o files.o utils.o
    cc -o edit main.o kbd.o command.o display.o \
    insert.o search.o files.o utils.o
main.o : main.c defs.h
    cc -c main.c
kbd.o : kbd.c defs.h command.h
    cc -c kbd.c
command.o : command.c defs.h command.h
    cc -c command.c
display.o : display.c defs.h buffer.h
    cc -c display.c
insert.o : insert.c defs.h buffer.h
    cc -c insert.c
search.o : search.c defs.h buffer.h
    cc -c search.c
files.o : files.c defs.h buffer.h command.h
    cc -c files.c
utils.o : utils.c defs.h
    cc -c utils.c
clean :
    rm edit main.o kbd.o command.o display.o \
    insert.o search.o files.o utils.o

Here while linking all the files in edit they don't write defs.o or buffer.o . 在链接edit所有文件时,它们不会写defs.o or buffer.o Means while linking they are not including object files of header files. 链接时意味着它们不包括头文件的目标文件。 Also they have not written any target like: defs.o or buffer.o Why ? 他们还没有写任何目标,如: defs.o or buffer.o 为什么

You just missed accessories.o in both linking targets. 你刚刚错过了两个链接目标中的accessories.o。 Something like this: 像这样的东西:

accessories.o: accessories.c

sendfdsock: sendfdsock.o accessories.o
    $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $+

Also, consider using the built-in rules, just modify their parameters, if needed. 另外,考虑使用内置规则,只需修改其参数(如果需要)。 See make -p for the full list (and makes infopage) 请参阅make -p获取完整列表(并制作infopage)

You misunderstand the relationship between source files, header files and object files. 您误解了源文件,头文件和目标文件之间的关系。

Suppose I have the following four files: 假设我有以下四个文件:

//foo.h
#define PI 3.1

//bar.h
void func();

//bar.c
#include "foo.h"
#include "bar.h"
void func()
{
  ...
}

//baz.c
#include "foo.h"
#include "bar.h"

int main()
{
  func();
}

(I left out the header guards, I presume you know about those.) I must use the compiler to produce an object file from each source file: bar.c -> bar.o and baz.c -> baz.o . (我离开了头警卫,我想你知道这些。)我必须使用编译器生成每个文件的目标文件: bar.c - > bar.obaz.c - > baz.o I don't have to make object files from the headers foo.h and bar.h , those will simply be #include d by any source file that needs them. 我不必从头文件foo.hbar.h创建目标文件,只需要#include d来任何需要它们的源文件。 Then I link the object files together to form an executable: 然后我将目标文件链接在一起形成一个可执行文件:

baz: bar.o baz.o
    gcc -o baz bar.o baz.o

bar.o: bar.c foo.h bar.h
    gcc -c bar.c

baz.o: baz.c foo.h bar.h
    gcc -c baz.c

If I neglect to link bar.o into the executable, I'll get a linker error when the linker gets to the place where baz calls func() and the linker doesn't know what to put there (because it lacks the definition of func() in bar.o ): 如果我忽略了将bar.o链接到可执行文件中,当链接器到达baz调用func()并且链接器不知道要放在那里的位置时,我会收到链接器错误(因为它缺少定义bar.o func() ):

baz.o: In function `main':
baz.c:(.text+0x32): undefined reference to `func()'

So the GNU Make doc is correct, and as Alex said, your rule should have: 所以GNU Make doc是正确的,正如Alex所说,你的规则应该有:

sendfdsock:sendfdsock.o accessories.o
    ...

accessories.o: accessories.c accessories.h
    ...

(Incidentally, once you get this makefile working, we can show you how to make it more concise.) (顺便说一句,一旦你使这个makefile工作,我们可以告诉你如何使它更简洁。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM