Не удается выполнить "make" в Ubuntu GCC - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть несколько файлов, которые я пытаюсь скомпилировать с помощью gcc в Ubuntu.У меня есть vmware машина 16.04 Ubuntu, которая 64-битный компьютер.Я добавил флаги для 32-битной компиляции в make-файл.(-m32 flag).

Это make-файл:

    all: clean binsem.a ut.a ph
FLAGS = -Wall  -L./ -m32


ph: ph.c
    gcc ${FLAGS} ph.c  -lbinsem -lut -o ph 


binsem.a:
    gcc $(FLAGS)  -c binsem.c
    ar rcu libbinsem.a binsem.o
    ranlib libbinsem.a 


ut.a:
    gcc $(FLAGS)  -c ut.c
    ar rcu libut.a ut.o
    ranlib libut.a 

clean:
    rm -f *.o 
    rm -f a.out
    rm -f *~
    rm -f ph
    rm -f *a 

Мои попытки скомпилировать код не увенчались успехом, так как я получил следующую ошибку:

ph.c:126:12: warning: ‘main’ defined but not used [-Wunused-function]
/usr/lib/gcc/i686-linux-gnu/5/../../../i386-linux-gnu/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: error: ld returned 1 exit status
Makefile:6: recipe for target 'ph' failed
make: *** [ph] Error 1

** Я пробовал - **

  1. Добавление флагов -c в файл ph.c в файле make.Однако это не имеет особого смысла, поскольку у него есть основная функция.Нет успеха
  2. Добавление флагов sum -m32 в make-файл в дополнение к уже написанному.Безуспешно.

Файл "ph.c" является следующим файлом -

#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <stdint.h>
#include <sys/time.h>
#include <inttypes.h>

#include "binsem.h"
#include "ut.h"



#define LEFT  (i+N-1)%N
#define RIGHT (i+1)%N
#define THINKING 0
#define HUNGRY   1
#define EATING   2

int N;

volatile int *phil_state;
sem_t *s;
sem_t mutex;
int *tid;

uint64_t get_wall_time() {
 struct timeval time;

 gettimeofday(&time, NULL); 
 uint64_t millis = (time.tv_sec * (uint64_t)1000) + (time.tv_usec / 1000);


 return millis;
}

void think(int p) {
  int i, factor;
  volatile int j;

  printf("Philosopher (%d) - time %" PRId64 " - is thinking\n",p, get_wall_time()); fflush (stdout);

  factor = 1 + random()%5;

  for (i = 0; i < 100000000*factor; i++){
    j += (int) i*i;
  }

  printf("Philosopher (%d) - time %" PRId64 " - is hungry\n", p, get_wall_time()); fflush (stdout);
}

void eat(int p){
  int i, factor;
  volatile int j;

   printf("Philosopher (%d) - time %" PRId64 " - is eating\n",p, get_wall_time()); fflush (stdout);

   factor = 1 + random()%5;
   for (i = 0; i < 100000000*factor; i++){
      j += (int) i*i;
   }
   //printf("Philosopher (%d) - time %" PRId64 " - is thinking\n",p, get_wall_time()); fflush (stdout);
}

void test(int i){
  if (phil_state[i] == HUNGRY &&
      phil_state[LEFT] != EATING &&
      phil_state[RIGHT] != EATING){
    phil_state[i] = EATING;

    binsem_up(&(s[i]));
  }
}

void take_forks(int i){
  binsem_down(&mutex);

  phil_state[i] = HUNGRY;

  test(i);

  binsem_up(&mutex);

  binsem_down(&(s[i]));
}


void put_forks(int i){
  binsem_down(&mutex);

  phil_state[i] = THINKING;

  test(LEFT);
  test(RIGHT);

  binsem_up(&mutex);
}

void int_handler(int signo) {
  long int duration;
  int i;

  for (i = 0; i < N; i++) {
    duration = ut_get_vtime(tid[i]);
    printf("Philosopher (%d) used the CPU %ld.%ld sec.\n",
       i+1,duration/1000,duration%1000);
  }
  exit(0);
}

void philosopher(int i){
  while (1){
    think(i);
    take_forks(i);
    eat(i);
    put_forks(i);
  }
}

static int main(int argc, char *argv[])
{
  int c;
  if (argc != 2){
    printf("Usage: %s N\n", argv[0]);
    exit(1);
  }

  N = atoi(argv[1]);

  if (N < 2){
    printf("Usage: %s N (N >=2)\n", argv[0]);
    exit(1);
  }

  ut_init(N);
  s = (sem_t *)malloc (N * sizeof(sem_t));
  phil_state = (int *) malloc (N * sizeof(int));
  tid = (int *) malloc (N * sizeof(int));

  for (c = 0; c < N ; c++){
    phil_state[c] = THINKING;
    binsem_init(&(s[c]), 0);
  }

  for (c = 0; c < N ; c++){
    tid[c] = ut_spawn_thread(philosopher,c);
    printf("Spawned thread #%d\n", tid[c]);
  }

  binsem_init(&mutex, 1);

  signal(SIGINT,int_handler);
  ut_start();

  return 0; // avoid warnings

}

Makefile также пытается скомпилировать эти файлы - ut.c, binsem.c

#include <stdlib.h>
#ifndef _UT_H
#define _UT_H
#include "ut.h"
#include <sys/time.h> // for itimerval
#include <unistd.h> // for alarm
#include <stdlib.h> // for malloc
#include <stdio.h> // for perror
#include <ucontext.h>
# include "ut.h"
#define MAX_TAB_SIZE 128 // the maximal threads table size.
#define MIN_TAB_SIZE 2   // the minimal threads table size.
#define SYS_ERR -1       // system-related failure code
#define TAB_FULL -2      // full threads table failure code
/*This type defines a single slot (entry) in the threads table. Each slot describes a single
thread. Note that we don't need to keep the thread state since every thread is always ready
or running. We also don't have to support adding/stopping thread dynamically, so we also don't
have to manage free slots.*/
typedef struct ut_slot {
    ucontext_t uc;
    unsigned long vtime;  /* the CPU time (in milliseconds) consumed by this thread.*/
    void (*func)(int);    /* the function executed by the thread.*/
    int arg;              /* the function argument.*/
} ut_slot_t, *ut_slot;

static ut_slot threads; // pointer to thread table
static volatile int numThreads = 0; // number of threads in the table
static volatile int currentThread = 0; // current thread
static ucontext_t mainThread;


#define STACKSIZE 8192   // the thread stack size.

/* The TID (thread ID) type. TID of a thread is actually the index of the thread in the
   threads table. */
typedef short int tid_t;



void handler(int signal){
    alarm(1); //the alarm every second as demanded in the assignment
    currentThread = (currentThread +1 ) % numThreads;
    printf("in signal handler: switching from %d to %d\n", currentThread, currentThread - 1);
    swapcontext(&threads[currentThread].uc, &threads[currentThread].uc); /*save current thread,
*                                                                              load next thread*/
    if (signal == SIGVTALRM){ // increment the time stats
        threads[currentThread].vtime+=100;

    } else if(signal==SIGALRM) {
        if (swapcontext(&threads[currentThread - 1].uc, &threads[currentThread].uc) == -1) {
            perror("could not do swapping");
            exit(1);
        }
    }
}

int ut_init(int tab_size){

    /// (###)

    if(tab_size < MAX_TAB_SIZE) {
        threads = (ut_slot) malloc(tab_size * sizeof(int(ut_slot_t)));
    }
    else{
        threads = (ut_slot) malloc(MAX_TAB_SIZE * sizeof(int(ut_slot_t)));
    }
    if (!threads) {
        return SYS_ERR;
    }
    return 0;

}

tid_t ut_spawn_thread(void (*func)(int), int arg){
    /*uc[1].uc_link = &uc[0];
    uc[1].uc_stack.ss_sp = st1; //stack fro thread 1
    uc[1].uc_stack.ss_size = sizeof st1; //size of stack for therad
    makecontext(&uc[1], (void(*)(void)) f, 1, 1); */
    int thread_stack_size = STACKSIZE/8; //no need for 8K in size
    if (numThreads>=TAB_FULL){ //(*)
        return TAB_FULL;
    }
    if (getcontext(&threads[numThreads].uc)==-1){
        return SYS_ERR;
    }
    ut_slot_t newThread;
    threads[numThreads] = newThread;
    threads[numThreads].uc.uc_link = &mainThread;
    threads[numThreads].uc.uc_stack.ss_sp = (void* *)malloc(thread_stack_size);

    if(threads[numThreads].uc.uc_stack.ss_sp==NULL){
        return SYS_ERR;
    }
    makecontext(&threads[numThreads].uc,(void(*)(void))func,1,arg);
    numThreads++;

    return numThreads - 1;


}


int ut_start(void){
    struct sigaction sigaction1;
    int firstThread = 0; /*represents the current thread*/
    struct itimerval itv;
    /* set up vtimer for accounting */
    itv.it_interval.tv_sec = 0;
    itv.it_interval.tv_usec = 10000;
    itv.it_value = itv.it_interval;


    /* Initialize the data structures for SIGALRM handling. */
    sigaction1.sa_flags = SA_RESTART; //restart instead of throwing exception
    sigfillset(&sigaction1.sa_mask); // don't throw exception for additional signals
    sigaction1.sa_handler = handler; // specify handler for the sigaction declared

    if (sigaction(SIGVTALRM, &sigaction1, NULL) < 0)
        return SYS_ERR;
    /*START THE TIMER */
    if (setitimer(ITIMER_VIRTUAL, &itv, NULL) < 0)
        return SYS_ERR;

    if (sigaction(SIGINT, &sigaction1, NULL) < 0)
        return SYS_ERR;

    /* Start running. */

    alarm(1); //alarm every second
    if(swapcontext(&threads[firstThread].uc,&threads[firstThread+1].uc)==-1){ //swap first time
        return SYS_ERR;
    }

    return -1;
}


unsigned long ut_get_vtime(tid_t tid){
    return threads[tid].vtime;
}


#endif

binsem.c

#ifndef _BIN_SEM_H
#define _BIN_SEM_H

#include "binsem.h"
#include <signal.h>
#include "atomic.h"

typedef unsigned long sem_t;

void binsem_init(sem_t *s, int init_val){
    if(init_val == 1){
        *s = 1;
    }
    else{
        *s = 0;
    }
}

void binsem_up(sem_t *s){
    xchg(s,1); /*send the pointer of s, and the new value 1*/
}


int binsem_down(sem_t *s){
    int flag = 0;
    while (flag == 0){
        xchg(s,0); /*try changing the value - down*/
        if (*s != 0){  /*no success in changing*/
            if (raise(SIGALRM)!=0){ /*raise returns 0 on success*/
                return -1;
            }
        } else{
            flag = 1;
            return 0;
        }
    }

}

#endif

Есть идеи?

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Сообщение об ошибке довольно ясно:

(.text+0x18): undefined reference to `main'

В ph.c у вас (вероятно, привыкли к Java ?):

static int main(int argc, char *argv[])

In C :

  1. статический ( [CPPReference]: C ключевые слова: статический) означает внутренняя связь (действует только в текущем единица перевода (* в нашем случае ph.o )), поэтому static символ не будет «виден» компоновщиком ( загрузчик )

  2. Код, связанный с приложением (не )динамическая библиотека или общий объект ( .so : связана с -shared)), должна явно определять main , и это должно быть видно компоновщик

Сочетание вышеуказанного 2 приведет к тому, что вы испытываете.

Снимите статический и все будет в порядке.

Примечание : могут быть другие ошибки в make-файле .

0 голосов
/ 20 ноября 2018

Вы объявляете функцию main равной static.Это означает, что он будет иметь внутреннюю связь и не будет экспортироваться.Поэтому компоновщик не сможет его найти.

Удалите модификатор static, и это должно сработать.


Однако в вашем Makefile есть и много других проблем, которыескорее всего приведет к проблемам:

Цель ph только зависит от ph.c, а не от библиотек, с которыми вы хотите связать.Вам также необходимо добавить библиотеки как зависимости (их полные имена файлов).

Вы также должны сделать библиотеки зависимыми от объектных файлов, используемых для их создания, и полагаться на неявные правила для создания объектных файлов.из исходных файлов.

Также обратите внимание, что для библиотеки с именем A имя файла должно быть libA.a, иначе компоновщик не сможет найти его с помощью -l (нижнийвариант L) вариант.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...