1

sendfdsock.c and recvfdsock.cmakeファイルを使用して2つの独立したプロセスをコンパイルする必要があります。どちらのファイルにも独自のmain機能があります。これは、それらが独立していることを意味し、2つの異なるバイナリとしてコンパイルする必要があります。これは私の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。GNUMakeDocで述べたように-単純な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 なぜですか?

4

2 に答える 2

3

両方のリンク ターゲットで accessories.o を見逃しました。このようなもの:

accessories.o: accessories.c

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

また、組み込みルールの使用を検討し、必要に応じてパラメーターを変更してください。完全なリストについては、を参照make -pしてください (および情報ページを作成します)

于 2012-07-16T06:01:20.950 に答える
1

ソース ファイル、ヘッダー ファイル、オブジェクト ファイルの関係を誤解しています。

次の 4 つのファイルがあるとします。

//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->bar.oおよびbaz.c-> baz.ofoo.hヘッダーとからオブジェクト ファイルを作成する必要はありません。これらは、それらを必要とするソース ファイルによってbar.h単純に作成されます。#include次に、オブジェクト ファイルをリンクして実行可能ファイルを作成します。

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の場所に到達し、リンカーがそこに何を配置すればよいかわからないときにリンカー エラーが発生します ( inの定義がないため)。bazfunc()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 が機能するようになったら、より簡潔にする方法を紹介します。)

于 2012-07-16T12:04:14.680 に答える