使用make包含头文件时出错

时间:2012-07-16 05:54:56

标签: c makefile header-files gnu-make

我必须使用make文件编译两个独立的进程 - sendfdsock.c and recvfdsock.c。这两个文件都有自己的main功能。这意味着它们是独立的,我必须将它们编译为两个不同的二进制文件。这是我的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

在这里,我制作了一个compileAll目标来编译这两个文件 这两个文件都需要使用accessories.h。正如在GNU Make Doc中提到的 - 一个简单的Make文件。我写了这个make文件。

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); 
    }
}

最初一切正常但是当我试图使用accessories.c汇编中定义的任何函数时,给我错误。
例如,我使用sendfdsock.c中的日志功能:

#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];
........

汇编的输出是:

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$ 

为什么未定义引用logp 错误?

为什么我不在最后的链接中编写accessories.o:

但是这个例子是在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

此处在链接edit中的所有文件时,他们不会写defs.o or buffer.o。链接时意味着它们不包括头文件的目标文件。他们也没有写任何目标,如:defs.o or buffer.o为什么

2 个答案:

答案 0 :(得分:3)

你刚刚错过了两个链接目标中的配件。像这样:

accessories.o: accessories.c

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

另外,考虑使用内置规则,只需修改其参数即可。有关完整列表,请参阅make -p(并填写信息)

答案 1 :(得分:1)

您误解了源文件,头文件和目标文件之间的关系。

假设我有以下四个文件:

//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();
}

(我省略了标题保护,我猜你知道那些。)我必须使用编译器从每个文件生成一个目标文件:bar.c - &gt; bar.obaz.c - &gt; baz.o。我不必从标题foo.hbar.h创建目标文件,只需要#include d来任何需要它们的源文件。然后我将目标文件链接在一起形成一个可执行文件:

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

如果我忽略了将bar.o链接到可执行文件中,当链接器到达baz调用func()且链接器不知道的地方时,我会收到链接器错误该怎么做(因为它缺少func()bar.o的定义):

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

所以GNU Make doc是正确的,正如Alex所说,你的规则应该有:

sendfdsock:sendfdsock.o accessories.o
    ...

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

(顺便说一句,一旦你使这个makefile工作,我们就可以告诉你如何使它更简洁。)