2016-11-26 103 views
0

我試圖讓a repository收集所有可在Internet上找到的關於C數學和代數庫(BLAS,CBLAS,LAPACK,CLAPACK,LAPACKE)的示例,教程和說明,ATLAS,openblas,GSL ...)。但似乎我只是不能編譯BLAS .a文件在Mac OS X工作無法在Mac OS X上使用已編譯的netlib BLAS

到目前爲止,我已經能夠編譯BLAS,並用它在Ubuntu:

  1. BLAS源代碼從NETLIB網站下載並編譯(重命名blas_LINUX.a到libblas.a)
  2. 然後,我可以使用下面的命令編譯ubuntu上的C文件:

    gcc foo.c path/to/libblas.a

在我的Mac OS X(EL Capitan)上,我可以編譯BLAS(將make.inc中的LINUX更改爲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. 也許我沒有正確編譯mac上的圖書館也有一些差別,我不AW是
  2. 的Mac OS X的內置加速框架是搞亂與編譯過程

P.S.我知道BLAS/LAPACK已經內置在mac OS X Accelerate框架中,我可以使用命令gcc foo.c -lblasgcc foo.c -framework Accelerate輕鬆編譯,但我想使用netlib編譯的.a。我想知道爲什麼它可以在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 = -O3OPTS = -O3 -pipe -c並作出。

(編輯2):更好的解決方案: 因爲我問了這個問題,我意識到我一直在做一切錯誤。 Netlib BLAS實際上是fortran例程/子例程/函數的集合。而源代碼中的Makefile只是給我們一個靜態庫libblas.a,它是用gfortran編譯的所有.o目標文件的集合。當我們想編譯一個想要調用其中一個例程的C代碼時,我們還需要鏈接到gfortran庫libgfortran。*,因此如果你安裝了gcc(brew安裝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

看起來你已經從Netlib編譯了BLAS庫,編譯器選項改變了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 

我無法重現你的問題。您應該使用nmgrep命令來了解ddot()例程的名稱發生了什麼。

PS。您的代碼在main()的定義結束後有額外的分號;

+0

我想我設法解決了問題,使用你剛纔給的標誌。看起來,現在通過向'make.inc'文件添加標誌'-pipe -c',BLAS庫被正確編譯,我可以使用它來編譯其他C代碼。我會嘗試更多。我將在此處報告 – Foad

+0

不要擔心'-pipe'(這意味着:不要在'/ tmp'中創建臨時文件,而是使用UNIX管道在編譯器和鏈接器工具鏈之間進行通信)。 '-c'標誌僅僅表示_compile-only_(不要鏈接或嘗試創建可執行的二進制文件)。 – Piotr

+0

是的,其實我完全錯了。我在帖子中增加了更多細節。你會介意檢查它並讓我知道它是否正確? – Foad