windows - GHC::在 Windows 上再次链接 sqlite3 失败

标签 windows sqlite haskell linker ghc

我创建了简单的应用程序,它使用 sqlite3 作为数据存储后端。我在 Linux 上构建和运行它时没有遇到任何问题,但在尝试在 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 文件以支持这一点?)。

最佳答案

不确定这是否是一个错误,但该错误来自 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 (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,然后在编译 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。这就是为什么如果找不到它就无法编译的原因。

关于windows - GHC::在 Windows 上再次链接 sqlite3 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11390941/

相关文章:

python - 当变量值更改时,文本对象不会在屏幕上更新

windows - 标准窗口类名称列表

c++ - 打开 >2.5k TCP 端口和线程后进程退出

HTC Thunderbolt 上的 Android 数据库大小不会减少

haskell - Acid-state:更新的 MonadState 实例

haskell - Test.QuickCheck.Monadic : why is assert applied to Bool, 不可测试 a => a

c++ - 我在fwrite()和fread()上遇到了一些麻烦

Python3 - 有没有一种方法可以在一个非常大的 SQlite 表上逐行迭代,而无需将整个表加载到本地内存中?

sql - 愚蠢的sql错误

opengl - 如何将 Haskell 字符串转换为 Ptr (Ptr GLchar)?