2016-11-26 9 views
0

Я пытаюсь сделать a repository сбор всех примеров, руководств и инструкций, которые я смог найти в Интернете для библиотек математики и алгебры C (BLAS, CBLAS, LAPACK, CLAPACK, LAPACKE , ATLAS, openblas, GSL ...). но мне кажется, что я просто не могу получить скомпилированного Блас .а файлов, работающих на Mac OS X.Невозможно использовать скомпилированный netlib BLAS на Mac OS X

До сих пор я был в состоянии собрать BLAS и использовать его на убунту:

  1. BLAS исходного кода с веб-сайта Netlib загружены и скомпилированы (переименовать blas_LINUX.a в libblas.a)
  2. Тогда я могу скомпилировать файл C на Ubuntu, используя следующую команду:

    gcc foo.c path/to/libblas.a

В моей ОС Mac OS X (EL Capitan) я могу скомпилировать BLAS (меняя LINUX в ​​make.inc на DARWIN), но когда я пытаюсь скомпилировать код C с помощью вышеприведенной команды, я получаю такие ошибки, как показано ниже:

Undefined symbols for architecture x86_64: 
    "_ddot_", referenced from: 
     _main in foo-3a35db.o 
ld: symbol(s) not found for architecture x86_64 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

ddot» часть отличается для различных функций)

возможности:

  1. Может быть, я не компиляции библиотеки правильно на макинтош и есть некоторые различия я не ав имеют
  2. Встроенная команда Ускорить рамках Mac OS X Мессинг с процессом компиляции

P.S. Ребята, я знаю, что BLAS/LAPACK уже встроен в среду Mac OS X Accelerate, и я могу легко скомпилировать ее с помощью команды gcc foo.c -lblas или gcc foo.c -framework Accelerate, но я хочу использовать скомпилированный .a из netlib. Я хочу знать, почему он работает правильно на ubuntu, но не Mac OS X?

P.S.2. Обратите внимание, что я могу скомпилировать исходный код без ошибок в Mac OS X. Я просто могу использовать его!

Пример кода: source

#include <stdio.h> 
#include <stdlib.h> 

double ddot_(const int *N, const double *a, const int *inca, const double *b, const int *incb); 

int main(int argc, char **argv) { 
    double *a = (double *)malloc(3 * sizeof(double)); 
    a[0] = 1.0; 
    a[1] = 2.0; 
    a[2] = 3.0; 
    // on the stack 
    double b[3] = {4.0, 5.0, 6.0}; 

    int N = 3, one = 1; // one really doesn't look good in C 

    double dot_product = ddot_(&N, a, &one, b, &one); 
    printf(" The dot product is: %f \n", dot_product); 

    return 0; 
} 

(edit1) Раствор:

  1. открыт make.inc
  2. изменить линию OPTS = -O3 к OPTS = -O3 -pipe -c и сделать.

(edit2): лучшее решение: , так как я задал этот вопрос, я понял, что делаю все неправильно. Netlib BLAS на самом деле представляет собой набор fortran подпрограмм/подпрограмм/функций. и Makefile в исходном коде просто дает нам статическую библиотеку libblas.a, которая представляет собой коллекцию всех объектных файлов .o, скомпилированных с помощью gfortran. когда мы хотим скомпилировать код C, который хочет вызвать одну из этих подпрограмм, нам также нужно связать с библиотекой gfortran libgfortran. * поэтому, если у вас установлена ​​gcc (brew install gcc). найдите libgfrotran * (sudo find/-name "libgfortrn.*"), а затем свяжите свой gcc с этой папкой.чтобы сделать его легко я положил Makefile здесь:

all: 
    gcc -c foo.c 
    gcc -o bar.out foo.o -L path/to/libgfortran.*/ -lgfortran -L path/to/libblas.a -lblas 

или в качестве альтернативы компиляции кода непосредственно gfortran:

all: 
    gcc -c foo.c 
    gfortran -o bar.out foo.o -L path/to/libblas.a -lblas 

или просто компилировать с:

gcc foo.c bar.out -L path/to/libblas.a -lblas -L path/to/libgfortran.*/ -lgfortran 

чудо как/почему первое решение действительно сработало и почему на ubuntu вам не нужно ссылаться на -lgfortran!

ответ

0

Кажется, вы скомпилировали библиотеку BLAS из Netlib с параметрами компилятора, которые изменили схему переключения подпрограмм Fortran.

По умолчанию Netlib-х make.inc использует gfortran для компиляции BLAS:

$ grep FORTRAN make.inc 
# Modify the FORTRAN and OPTS definitions to refer to the 
FORTRAN = gfortran 

Он компилируется без каких-либо флагов:

gfortran -O3 -pipe -c ddot.f -o ddot.o 

и вы получите рутина ddot():

$ grep -i ddot ddot.o libblas.a 
Binary file ddot.o matches 
Binary file libblas.a matches 

И вы можете найти его с помощью средств командной строки:

$ nm ddot.o libblas.a | grep -i ddot 
ddot.o: 
0000000000000000 T _ddot_ 
libblas.a(ddot.o): 
0000000000000000 T _ddot_ 

Ваш пример компилируется с библиотекой:

cc ex.c libblas.a 

или с файлом ddot.o:

cc -pipe ex.c ddot.o 

Я не могу воспроизвести вашу проблему. Вы должны использовать команды nm и grep, чтобы узнать, что произошло с именем подпрограммы ddot().

PS. У вашего кода есть дополнительная точка с запятой ; после окончания определения main().

+0

Думаю, мне удалось решить проблему, используя флаги, которые вы только что дали. Похоже, что добавив флаги '-pipe -c' в файл' make.inc', теперь библиотека BLAS скомпилирована правильно, и я могу использовать ее для компиляции другого C-кода. Я попробую еще раз. Я сообщу об этом здесь – Foad

+0

Не беспокойтесь о '-pipe' (это означает: не создавайте временные файлы в'/tmp', а используйте каналы UNIX для связи между цепочкой инструментов компилятора и линкера). Флаг '-c 'просто означает _compile-only_ (не связывайтесь и не пытайтесь создать исполняемый двоичный файл). – Piotr

+0

да на самом деле я был совершенно неправ. Я добавил дополнительные сведения к сообщению. не могли бы вы проверить его и сообщить, правильно ли это или нет? – Foad