GHC ::链接agains sqlite3在Windows上失败

我创build了一个简单的应用程序,它使用sqlite3作为数据存储的后端。 在Linux上构build和运行时,我没有遇到任何问题,但在尝试在Windows上构build它之后,我发现了一个奇怪的链接错误:

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文件,以支持这一点?)。

Solutions Collecting From Web of "GHC ::链接agains sqlite3在Windows上失败"

不知道这是否是一个错误,但错误来自SQLite包的sqlite3.h包括。

文件中的外观显示了这一点

 /* ** 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 (aka 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; 

所以它被宣布为extern。 如此简单的测试:

 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,然后在编译haskell源文件时传递了一个c文件

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

然后运行它也返回预期的结果

 $ ./test done 

所以看起来你只需要为sqlite3_temp_directory赋值,如果你设置为NULL指针,将会使用SQLLITE手册中定义的TMP / TEMP等变量。

编辑,跟进为什么它在Linux上工作,而不是在Windows上

在sqlite包中,文件夹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() ){ 

所以对于windows sqlite3_temp_directory实际上是使用的。 这就是为什么它不能编译,如果它找不到它。