2012-07-09 96 views
2

我創建了一個簡單的應用程序,它使用sqlite3作爲它的數據存儲後端。構建和運行在Linux上,當我遇到任何問題,但在我試圖建立它在Windows上,我看到了奇怪的鏈接錯誤:GHC ::鏈接重複sqlite3在Windows上失敗

Linking dist\build\hnotes\hnotes.exe ... 
C:\Documents and Settings\Admin\Application Data\cabal\sqlite-0.5.2.2\ghc-7.0.4/libHSsqlite-0.5.2.2. 
a(sqlite3-local.o):sqlite3-local.c:(.text+0x21): undefined reference to `sqlite3_temp_directory' 
C:\Documents and Settings\Admin\Application Data\cabal\sqlite-0.5.2.2\ghc-7.0.4/libHSsqlite-0.5.2.2. 
a(sqlite3-local.o):sqlite3-local.c:(.text+0x40): undefined reference to `sqlite3_temp_directory' 
collect2: v ld  1 
cabal.EXE: Error: some packages failed to install: 
hnotes-0.1 failed during the building phase. The exception was: 
ExitFailure 1 

什麼可能是錯誤的呢?我懷疑,qalite3.dll必須添加到鏈接階段,但不知道如何做到這一點。添加--extra-lib-dirs = path-to-sqlite-dll也沒有幫助(也許是因爲我需要以某種方式更新我的cabal文件,以支持這一點?)。

+0

我重寫了我的應用程序以使用HDBC-sqlite3及其工作正確。也許sqlite hackage有些問題。 – jdevelop 2012-07-09 10:44:13

回答

2

不知道這是否是一個錯誤,但錯誤來自sqlite3.h包括sqlite包。

一看文件中顯示了這個

/* 
** CAPI3REF: Name Of The Folder Holding Temporary Files {H10310} <S20000> 
** 
** If this global variable is made to point to a string which is 
** the name of a folder (a.k.a. directory), then all temporary files 
** created by SQLite will be placed in that directory. If this variable 
** is a NULL pointer, then SQLite performs a search for an appropriate 
** temporary file directory. 
** 
** It is not safe to modify this variable once a [database connection] 
** has been opened. It is intended that this variable be set once 
** as part of process initialization and before any SQLite interface 
** routines have been call and remain unchanged thereafter. 
*/ 
SQLITE_EXTERN char *sqlite3_temp_directory; 

所以它聲明爲一個外部。如此簡單的測試:

module Main where 

import Database.SQLite 

main 
= do hwd <- openConnection "test" 
     closeConnection hwd 
     putStrLn "done" 

這會在鏈接期間崩潰,如您所預期的錯誤與上面的錯誤。 所以我創建了一個小型的C測試文件foo.c

#include "sqlite-0.5.2.2\\include\\sqlite3-local.h" 

char* sqlite3_temp_directory = "C:\\test2"; 

所以我定義temp_directory,然後我的哈斯克爾源

$ ghc test.hs foo.c 
[1 of 1] Compiling Main    (test.hs, test.o) 
Linking test.exe ... 

的編譯過程中通過C文件一起,然後運行它也返回預期結果

$ ./test 
done 

如此看來,你只需要給出的sqlite3_temp_directory,而如果將其設置爲A N的值ULL指針將使用SQLLITE手冊中定義的TMP/TEMP等變量。

編輯,跟進爲什麼它的工作在Linux上而不是在Windows

在源碼包,有個文件夾sqlite3.6下的文件sqlite3.c。這爲sqlite包提供了一堆默認值。

在linux上定義OS_UNIX時,在linux上使用OS_WIN下的定義。 我們感興趣的功能是設置臨時目錄的功能。對於unix,這將是unixGetTempname和windows winGetTempname

如果你看看這兩個功能的實現,對於UNIX一個有目錄列表,它會嘗試

static const char *azDirs[] = { 
    0, 
    "/var/tmp", 
    "/usr/tmp", 
    "/tmp", 
    ".", 
    }; 

它試圖訪問它們爲了和一個可以寫入它用來產生在一個臨時文件夾

對於windows然而,第一線中的一個是:

if(sqlite3_temp_directory){ 
    sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory); 
    }else if(isNT()){ 

所以對於窗戶sqlite3_temp_directory是ACTU盟友使用。這就是它無法找到它時不編譯的原因。

+0

它爲什麼在Linux上工作?該軟件包爲兩個操作系統使用相同的頭文件。而且,在構建HDBC-sqlite3時,我從sqlite3 hackage指定了頭文件(它位於sqlite-0.5.2.2/include文件夾中)。 – jdevelop 2012-07-09 15:52:33

+0

我目前無法檢查,但我相信在Linux上它可能不會調用sqlite3_temp_directory,或者它在某處定義了值。如果未被調用,則不會生成鏈接器錯誤。 HDBC也是如此。答案很可能在#ifdef中的某處。我回家看看 – Phyx 2012-07-09 16:16:36

+0

@jdevelop我有一段時間瞭解了爲什麼它在Windows上工作,而不是在Linux上工作。我編輯了包含它的答案。 – Phyx 2012-07-11 11:18:34