• בלוג
  • היום למדתי: את המתג `-l` של gcc צריך לכתוב בסוף

היום למדתי: את המתג `-l` של gcc צריך לכתוב בסוף

11/05/2023

אתם מכירים את המתג -l של gcc, כי בעזרתו בקומפילציה אנחנו מוסיפים ספריה חיצונית. לדוגמה בשביל לקמפל תוכנית עם libmath משתמשים ב:

gcc -l m

אז היום גיליתי שהצלחתי להעביר חיים שלמים בלי לשים לב שיש חשיבות למקום של -l בתוך שורת הפקודה של הקומפילציה, או מתוך התיעוד:

It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded.

בעברית זה אומר שאם אנחנו מנסים לקמפל קובץ שמשתמש בספריה, יש לרשום את ה -l אחרי שם הקובץ. לדוגמה נתונה התוכנית הבאה:

#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
  CURL *curl;
  CURLcode res;
  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/");
    /* Perform the request, res will get the return code */
    res = curl_easy_perform(curl);
    /* Check for errors */
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));
    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  return 0;
}

ושם הקובץ getter.c, אז ניסיון לקמפל את הקובץ עם:

$ gcc -l curl getter.c

מחזיר:

/usr/bin/ld: /tmp/ccToWOcP.o: in function `main':
getter.c:(.text+0x84): undefined reference to `curl_easy_init'
/usr/bin/ld: getter.c:(.text+0xb0): undefined reference to `curl_easy_setopt'
/usr/bin/ld: getter.c:(.text+0xb8): undefined reference to `curl_easy_perform'
/usr/bin/ld: getter.c:(.text+0xdc): undefined reference to `curl_easy_strerror'
/usr/bin/ld: getter.c:(.text+0xf8): undefined reference to `curl_easy_cleanup'
collect2: error: ld returned 1 exit status

והדרך הנכונה לקמפל את הקובץ היא:

$ gcc getter.c -l curl