2010-04-01 3 views
2

Я пытаюсь скомпилировать код fortran, и я сталкиваюсь с некоторыми запутанными ошибками связывания. У меня есть некоторый код, который я скомпилировать и поместить в статическую библиотеку:Неопределенные ссылки

>gfortran -c -I../../inc -o bdout.o bdout.F 
>ar rv libgeo.a bdout.o 

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

>gfortran -o mytest -L -lgeo mytest.F 
/tmp/cc4uvcsj.o: In function `MAIN__': 
mytest.F:(.text+0xb0): undefined reference to `ncwrite1_' 
collect2: ld returned 1 exit status 

Это не в объект присвоения имен, потому что все выглядит отлично:

>nm -u libgeo.a 

bdout.o: 
    U _gfortran_exit_i4 
    U _gfortran_st_write 
    U _gfortran_st_write_done 
    U _gfortran_transfer_character 
    U _gfortran_transfer_integer 
    U ncobjcl_ 
    U ncobjwrp_ 
    U ncopencr_ 
    U ncopenshcr_ 
    U ncopenwr_ 
    U ncwrite1_ 
    U ncwrite2_ 
    U ncwrite3_ 
    U ncwrite4_ 
    U ncwritev_ 

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

>nm -u bdout.o 

    U _gfortran_exit_i4 
    U _gfortran_st_write 
    U _gfortran_st_write_done 
    U _gfortran_transfer_character 
    U _gfortran_transfer_integer 
    U ncobjcl_ 
    U ncobjwrp_ 
    U ncopencr_ 
    U ncopenshcr_ 
    U ncopenwr_ 
    U ncwrite1_ 
    U ncwrite2_ 
    U ncwrite3_ 
    U ncwrite4_ 
    U ncwritev_ 

тест код просто содержит один вызов функции, определенной в bdout.o:

program hello 
     print *,"Hello World!" 
     call ncwrite1(istat, f, ix2, ix3, ix4, ix5, ih) 
end program hello 

Я не могу понять, в чем проблема. У кого-нибудь есть предложения? Может быть, даже просто способ отследить проблему?

Cheers.

ответ

0

Во-первых, спасибо всем, кто ответил. Я отправляю сообщение, чтобы положить конец этой теме. Оказывается, человек, который написал библиотеку (libgeo.a), разместил несколько операторов #ifdef в коде, который был включен с использованием макросов макросов -D (макросов) компилятора. Эти # ifdef затем будут использоваться для расширения имен функций с определенными параметрами. Без предоставления соответствующих макросов компилятору имена функций остались нерасширенными, и символы, таким образом, не были определены. Grrrr ...

1

Не знаю, помогает ли эта конкретная проблема, но в общем случае всегда ставьте команды компоновщика ПОСЛЕ объектных файлов. Во-вторых, если libgeo.a находится в текущем каталоге, вам нужно добавить это явно, пустой -L AFAIK ничего не делает. То есть

gfortran -o mytest mytest.F -L. -lgeo 

EDIT: Также обратите внимание, что «U» в выходе nm означает, что символ не определен. То есть что файл .o ссылается на указанный символ, но символ фактически находится в каком-то другом файле. То есть вам может потребоваться явная ссылка в библиотеке, которая определяет символ ncwrite1_.

+0

Да, я просто попытался добавить команду компоновщика последним, но проблема не исчезла. -L. означает -L в. (Текущий каталог. – Brandon

+0

Я имел в виду, что в вашем вопросе у вас есть пустой -L, без "." – janneb

+0

Ах, извините, этого не заметили. Это было потеряно при вводе вопроса. Очевидно, это тоже не проблема. – Brandon

0

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

1

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

  1. Функция ncwrite1 не определена в библиотеках, к которым вы связываетесь. Используйте nm, чтобы убедиться, что это (или нет) случай.
  2. Библиотеки размещаются перед файлами объекта/исходного кода в командной строке (!). Линкеры - это самые глупые вещи, и не пытайтесь разрешать все против всего остального (и это иногда полезно для передовых методов) но это означает, что вам нужно положить библиотеки после всего остального. Если у вас много библиотек, вам нужно использовать топологическую сортировку для зависимостей между ними, чтобы определить правильный порядок, чтобы перечислить их в компоновщик.

Если мы предположим, что у гео-библиотеки есть функция, которую вы выполняете (проверьте это!), то вы должны построить и связать вот так:

gfortran -o mytest -L. mytest.F -lgeo 
Смежные вопросы