カテゴリー別アーカイブ: Build

Tcl SQLite build configuration

Prerequisites

Build tool = MinGW GCC v4.9.3
Tcl build path = /c/src/tcl8.6.6/win
Tcl install path = /c/bin/tcl8.6.6
SQLite3 build path = /c/src/sqlite-autoconf-3160200/tea
wxSQLite3 secure source path = /c/src/wxsqlite3-trunk/sqlite3/secure/src

Tcl

./configure --prefix=(Tcl install path)
make
make install

Tk

./configure --prefix=(Tcl install path) --with-tcl=(Tcl build path)
make
make install

TclSQLite

Copy the files in (wxSQLite3 secure source path) to (SQLite3 build path)/generic.
Open tclsqlite3.c and replace "sqlite3.c" by "sqlite3secure.c" in the line #4.
cd (SQLite3 build path)
./configure --enable-threads --prefix=(Tcl install path) --with-tcl=(Tcl build path) CFLAGS="-DSQLITE_HAS_CODEC -DSQLITE_ENABLE_FTS4_UNICODE61"
make
make install

This also works with ActiveTcl.

I could not make sqlite3 v3.8.2 independent from libgcc_s_dw2-1.dll with MinGW gcc v4.8.1.
I don't know the reason. But I could build it with nmake.
For example:
nmake -f makefile.vc TCLDIR=(Tcl install path) INSTALLDIR=(Tcl install path) OPTDEFINES="-DSQLITE_HAS_CODEC"

Ref. 暗号化APIを有効にしたSQLite3のTclバインディングをコンパイルする

kitgenをVisual Studio 2012でビルドする

kitgenが正式にサポートしているのはVC6からVC8(2005)までです。
VS2008~VS2013についても、いくつか変更を加えてやればビルドできます。

ただ、これはTclに限ったことではないのですが、VS2012で普通にビルドした実行ファイルはXPで動作しません。SDK 7.1Aにリンクすればビルドできますが、VS2010以前を持ってる人にとっては面倒なだけでメリットがないので古いVSを使った方がいいです。(参考ページ)。

あと、これはいいのかどうか分かりませんが、VC6でビルドするとOS標準添付のC++ランタイム(msvcrt.dll)をリンクするので、別途ランタイムをインストールすることなく動作します。MinGWでビルドした場合もそうなるのでまあ問題ないんじゃないでしょうか。

kitgen/Makefile.vc

70c70
< CFLAGS  = -W3 -D_WINDOWS -DWIN32 -DSTATIC_BUILD
---
> CFLAGS  = -W3 -D_WINDOWS -DWIN32 -DSTATIC_BUILD -D_CRT_SECURE_NO_WARNINGS
142c142,148
< !if $(VCVERSION) >= 1500
---
> !if $(VCVERSION) >= 1800
> VCVER=12
> !elseif $(VCVERSION) >= 1700
> VCVER=11
> !elseif $(VCVERSION) >= 1600
> VCVER=10
> !elseif $(VCVERSION) >= 1500

kitgen/8.x/mk/tcl/mk4tcl.cpp

2597c2597
< EXTERN int Mk4tcl_Init(Tcl_Interp *interp) {
---
> int Mk4tcl_Init(Tcl_Interp *interp) {
2601c2601
< EXTERN int Mk_Init(Tcl_Interp *interp) {
---
> int Mk_Init(Tcl_Interp *interp) {
2605c2605
< EXTERN int Mk4tcl_SafeInit(Tcl_Interp *interp) {
---
> int Mk4tcl_SafeInit(Tcl_Interp *interp) {
2609c2609
< EXTERN int Mk_SafeInit(Tcl_Interp *interp) {
---
> int Mk_SafeInit(Tcl_Interp *interp) {

kitgen/8.x/mk/tcl/mk4tcl.h

382a383,391
> 
> 
> EXTERN int Mk4tcl_Init(Tcl_Interp *interp);
> 
> EXTERN int Mk_Init(Tcl_Interp *interp);
> 
> EXTERN int Mk4tcl_SafeInit(Tcl_Interp *interp);
> 
> EXTERN int Mk_SafeInit(Tcl_Interp *interp);

kitgen/8.x/itcl/win/rules.vc

195c195,201
< !if $(VCVERSION) >= 1500
---
> !if $(VCVERSION) >= 1800
> VCVER=12
> !elseif $(VCVERSION) >= 1700
> VCVER=11
> !elseif $(VCVERSION) >= 1600
> VCVER=10
> !elseif $(VCVERSION) >= 1500

kitgen/8.x/mk/win/rules.vc

187c187,195
< !if $(VCVERSION) >= 1400
---
> !if $(VCVERSION) >= 1800
> VCVER=12
> !elseif $(VCVERSION) >= 1700
> VCVER=11
> !elseif $(VCVERSION) >= 1600
> VCVER=10
> !elseif $(VCVERSION) >= 1500
> VCVER=9
> !elseif $(VCVERSION) >= 1400
189,190d196
< _VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1
< _VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2
195a202,205
> !if $(VCVERSION) >= 1400
> _VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1
> _VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2
> !endif

kitgen/8.x/thread/win/rules.vc

195c195,201
< !if $(VCVERSION) >= 1500
---
> !if $(VCVERSION) >= 1800
> VCVER=12
> !elseif $(VCVERSION) >= 1700
> VCVER=11
> !elseif $(VCVERSION) >= 1600
> VCVER=10
> !elseif $(VCVERSION) >= 1500

kitgen/8.x/vqtcl/win/rules.vc

195c195,201
< !if $(VCVERSION) >= 1500
---
> !if $(VCVERSION) >= 1800
> VCVER=12
> !elseif $(VCVERSION) >= 1700
> VCVER=11
> !elseif $(VCVERSION) >= 1600
> VCVER=10
> !elseif $(VCVERSION) >= 1500

8.6.1をビルドするには、kitgen、Tcl、Tkのソースをダウンロードして、
以下にコピーします。

C:\src\kitgen
C:\src\kitgen\8.6.1\tcl
C:\src\kitgen\8.6.1\tk

Visual Studioのコマンドプロンプトを開き、

mkdir C:\src\kitgen\8.6.1\kit-msvc
cd C:\src\kitgen\8.6.1\kit-msvc
echo all: lite heavy > Makefile
echo !include ..\..\Makefile.vc >> Makefile
nmake -f Makefile.vc -nologo VERSION=86 KITOPTS=”-t -z”

ちなみに、tdbc関連のモジュールが大量にビルド失敗しますが、使わない限りは問題ありませんでした。

kitgen+VC6でtclkitを作るときの注意点

TclAppを使うと、Tcl/Tkのスクリプトと実行環境を単一のEXEファイルにラップすることができるのですが、このときprefixファイルといって、ベースとなる実行ファイルを指定する必要があります。これをtclkitとかbasekitとか呼び、標準ライブラリや最低限のエンコーディングファイルなどが含まれていて、自分で開発したアプリに必要な、スクリプト一式、ライブラリ、エンコーディングなどを、TclAppを使って追加することで単体のアプリとして動作するようになります。アイコンやバージョン情報なども、prefixに組み込まれているものを置き換えることもできます。

prefixとして使えるファイルは、実はActiveTclにbasekitという名前でついてきます(Tcl/binフォルダにある)。これがあれば別に自分でtclkitを入手する必要はないのですが、2点ほど問題があります。

  • 実行ファイルのサイズが比較的大きい
  • バイトコードコンパイルすると、スペースおよびマルチバイト文字を含むパスから起動できない

ということで、私にとっては不都合だったので、basekitをやめてtclkitを使うことにしました。tclkitのWindowsバイナリはTcl8.5.13まではhttp://www.patthoyts.tk/tclkitで配布していたのですが、8.5.14がなかなか出ないなあと思っていたら今日見たら落ちてました。また、配布しているものにはtzdataというタイムゾーンの定義ファイルがないので、時刻表示が狂う場合がありました。そういう理由があって、自分でコンパイルすることにしました。前置きが長くなりましたが、以下がその手順です。Windows7 Professional SP1 32bit上で試しました。

必要なものをそろえる

Visual Studio 6.0 (Visual Studio 2003でもいいと書いてあった。)
Microsoft Platform SDK Febuary 2003 (Last version with VC6 support)

kitgenのソースコードを取ってくる

C:\src\kitgenに展開。

Tcl/Tkのソースコードを取ってくる

C:\src\kitgen\8.5\tcl
C:\src\kitgen\8.5\tkに展開。

ビルド用のフォルダとMakefileを作る

VC6のコマンドプロンプトを開く
mkdir C:\src\kitgen\8.5\kit-msvc
cd C:\src\kitgen\8.5\kit-msvc
echo all: lite heavy > Makefile
echo !include ..\..\Makefile.vc >> Makefile

リソースファイルを編集する

これはお好みですが、kitgenに添付されているものを使うと、TclAppでバージョン情報を編集できなくなるので、変更することをお勧めします。
C:\src\kitgen\tclkit.rcをテキストエディタで開き、CommentとPaddingを削除する。

            VALUE "Comments", "Comments\0More Comments\0"
            VALUE "Padding",
               "                                                            "
               "                                                            "
               "                                                            "
               "                                                            \0"

ビルドする

Platform SDKを参照するようにします。また、KITOPTS=-zというオプションを与えることで、tzdataが含まれるようにします。他にもオプションがありますが、kitgenのREADMEファイルを読んでください。

set INCLUDE=C:\PROGRA~1\MIC1C5~1\include;%INCLUDE%
nmake -f Makefile.vc -nologo VERSION=85 KITOPTS="-z"

C:\src\kitgen\8.5\kit-msvcの中にできる、tclkit-cli.exe、tclkit-gui.exeをTclAppのprefixに指定できます。

XOTcl というか Next Scripting Framework 2.0b3のコンパイル

XOTclの最新安定版はteacupで配布してる1.6.7ですが、今のところTcl8.6b2で使うことができません。
私の場合、XOTclに依存しまくってるので、8.4から8.6に1つ飛ばしで移行しようと思ったところ、これだけが引っかかっていて、
仕方なく8.5に移行しました。

一方XOTcl開発チームの人々はNext Scripting Framework (NSF)という壮大なプロジェクトを立ち上げ、XOTclの次期バージョンである2.0はそのフレームワークの上で実装されているそうです。すでにNSF Beta2のソースコードが配布されているのでコンパイルしてみました。

MinGWで比較的簡単にコンパイルできました。
Tcl関連のソースコードでVC6で簡単にコンパイルできるものってあんまりないです。

必要なもの
C:/src/tcl8.6b2 --- Tclのソースコード。tcl86b2-src.zip
C:/src/nsf2.0b3 --- NSFのソースコード。nsf2.0b3.tar.gz

MinGW shellを起動し、

cd /c/src/nsf2.0b3
./configure --prefix=/c/bin/tcl8. 6b2/lib --exec-prefix=/c/tcl8.6b2 --enable-threads
make
make install

簡単なスクリプトは動くようです。

(bin) 1 % package require XOTcl
2.0b3
(bin) 2 % namespace import xotcl::*
(bin) 3 % Class Dog
::Dog
(bin) 4 % Dog instproc init {} {puts "created"}
::nsf::classes::Dog::init
(bin) 5 % Dog instproc hello {} {puts "Bow"}
::nsf::classes::Dog::hello
(bin) 6 % set dog [Dog new]
created
::nsf::__#0
(bin) 7 % $dog hello
Bow
(bin) 8 % info patchlevel
8.6b

が、いろんな機能を使ってる複雑なコードの場合はエラーが出ました。以下例。
Warning: Arguments 'component xdobry::sqlite' to constructor of object ::idemeta are most likely not processed
no current object; command called outside the context of a Next Scripting method

XOTcl 1と2の非互換性についてはドキュメントがありますが、
Incompatibilities between XOTcl 1 and XOTcl 2

これで全部網羅してるとは思えないし、
2で追加されたというcurrentというコマンドは存在しないと言われます。

せっかく作ったので丸ごと置いときます。
Tcl/Tk8.6b2 with nsf2.0b3

暗号化APIを有効にしたSQLite3のTclバインディングをコンパイルする

コンパイルに使用したもの
ActiveTcl 8.4.19.5 http://www.activestate.com/activetcl/downloads
wxSQLite3(wxsqlite3-2.1.2.zip) http://sourceforge.net/projects/wxcode/files/Components/wxSQLite3/
SQLite3ソースコード(sqlite-autoconf-3070701.tar.gz) http://www.sqlite.org/download.html
MinGW(mingw-get-inst-20110530.exe) http://sourceforge.net/projects/mingw/files/Automated%20MinGW%20Installer/mingw-get-inst/

作業フォルダはどこでもいいですが、今回はc:\srcとします。
そこにSQLite3ソースコードとwxSQLite3を展開します。
こんな感じ。

c:\src
├─sqlite-autoconf-3070701
│  └─tea
│      ├─doc
│      ├─generic
│      ├─tclconfig
│      └─win
└─wxsqlite3-2.1.2
    ├─build
    ├─build29
    ├─dbadmin
    │  └─images
    ├─docs
    │  └─html
    ├─include
    │  └─wx
    ├─lib
    ├─samples
    ├─sqlite3
    │  ├─include
    │  ├─lib
    │  └─secure
    │      ├─aes128
    │      ├─aes256
    │      └─src
    │          ├─codec
    │          └─codec-c
    ├─src
    └─website

以下のフォルダ内の全てのファイルを
C:\src\wxsqlite3-2.1.2\sqlite3\secure\src\codec-c

ここに上書きコピーします。
C:\src\sqlite-autoconf-3070701\tea\generic

そして、以下のソースコードをテキストエディタで開きます。
C:\src\sqlite-autoconf-3070701\tea\generic\tclsqlite3.c

4行目の"../../sqlite3.c"を

#ifdef USE_SYSTEM_SQLITE
# include 
#else
#include "../../sqlite3.c"
#endif

"sqlite3secure.c"に書き換える。

#ifdef USE_SYSTEM_SQLITE
# include 
#else
#include "sqlite3secure.c"
#endif

これで、コンパイルの準備はできました。

さて、MinGW shellを起動しましょう。

ディレクトリを移動してコンパイルします。

cd /c/src/sqlite-autoconf-3070701/tea
$ ./configure CFLAGS="-DSQLITE_HAS_CODEC"
$ make

デフォルトではAES128コーデックが使われます。
試してませんが、AES256にしたければ、以下のようにすればよいと思います。

$ ./configure CFLAGS="-DSQLITE_HAS_CODEC -DCODEC_TYPE=CODEC_TYPE_AES256"

wxSQLite3 AES128ならGUIツールのSQLite2009 Proが対応していますが、AES256に対応しているツールはなさそうなので、セキュリティの強化以外の理由でAES256を選択する理由はないと思います。

これで以下のファイルができました。これ単体でTclのパッケージです。

C:\src\sqlite-autoconf-3070701\tea\sqlite3771.dll

直接tclshからloadするか、pkgIndex.tclとともにTcl/libにインストールしてpackage requireすることもできます。

さて、テストしてみましょう。

load sqlite3771.dll Sqlite3

# create plain database file
sqlite3 pdb plain.db

# create encrypted database file
sqlite3 sdb secret.db -key password

# SQL test script
# 1. create table
# 2. populate test data
# 3. execute query
set sql {
	create table users (
		id integer primary key autoincrement not null,
		name text,
		age integer
	);
	insert into users (name, age) values ("山田太郎", 30);
	select * from users;
}
 
pdb eval $sql
#=>; 1 山田太郎 30
pdb close
 
sdb eval $sql
#=>; 1 山田太郎 30
sdb close

# Re-open plain.db
sqlite3 pdb plain.db
pdb eval {
	select * from users;
}
#=>; 1 山田太郎 30
pdb close

# Re-open secret.db without a key
sqlite3 sdb secret.db
sdb eval {
	select * from users;
}
#=>; file is encrypted or is not a database
sdb close

既存のデータベースファイルを暗号化するには、rekeyするか、dumpを取得して
暗号化した新規データベースでrestoreすればOKです。
この作業には、wxSQLite3に付属するコンパイル済みのshellを使用してください。
C:\src\wxsqlite3-2.1.2\sqlite3\secure\aes128\sqlite3shell.exe

追記:Tclからもできます。

load sqlite3771.dll Sqlite3
# Encrypt plain database
sqlite3 pdb plain.db
pdb rekey "password"
pdb close

# Reopen as plain database
sqlite3 pdb plain.db
pdb eval {
	select * from users;
}
#=>; file is encrypted or is not a database

# Decript secret database
sqlite3 sdb plain.db -key password
sdb rekey ""; # specify null string as encryption key
sdb close

# Re-open plain.db
sqlite3 pdb plain.db
pdb eval {
	select * from users;
}
#=>; 1 山田太郎 30
pdb close

最後はちょっとはしょった説明になりましたが、できてしまえば結構簡単です。
tclsqliteの暗号化APIについてのドキュメントはないのですが、ネイティブの関数と基本的に変わりはないと思います。
間違ったコマンドを与えてやるとエラーメッセージに関数リストが出てきたり、
関数に間違った引数を与えてやることで使い方が出てきたりするので、いろいろ試してみるとよいと思います。

(tea) 1 % load sqlite3771.dll Sqlite3
(tea) 2 % sqlite3 sdb secret.db -key password
(tea) 3 % sdb ?
bad option "?": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, profile, progress, rekey, restore, rollback_hook, status, timeout, total_changes, trace, transaction, unlock_notify, update_hook, version, or wal_hook

なお、.NET Frameworkから使えるADOプロバイダとしてSystem.Data.SQLite.dllが暗号化に対応していますが、これはRSA-MS Cryptだそうです。名前しか分かりませんがとりあえずAESとは別物です。SQLite Encryption Extension($2,000)は4つのコーデックがコンパイル時に選択できるようです。

Visual Studio 2010でOpenSSLをビルドする

ここに行けばWindows用のDLLを入手することはできるんですが、
http://www.slproweb.com/products/Win32OpenSSL.html

今回はスタティックライブラリが欲しかったので、自分でビルドしてみました。

ここを参考にしました。
http://shishi.syuriken.jp/openssl.html

使ったプログラム
Visual Studio 2010 Professional SP1
Microsoft Windows SDK v7.1 : http://goo.gl/2sFTo
StrawberryPerl 5.12.3.0 : http://strawberryperl.com/
NASM : http://www.nasm.us/

準備
perl.exeとnasm.exeにはパスを通しておく。

OpenSSL本家から最新ソースをダウンロード。現在1.0.0dが最新。
http://www.openssl.org/source/

どこでもいいですが、ここでは以下に展開するとします。
c:srcopenssl-1.0.0d

コマンドプロンプトで作業します。
cd c:srcopenssl-1.0.0d

perl Configure VC-WIN32 --prefix=c:/openssl
※--prefix=でインストールディレクトリを指定。

nasmで最適化する。
msdo_nasm

Microsoft Windows SDK v7.1をインストールすると環境設定用のバッチスクリプトがついてくるので、
スタートメニュー>全てのプログラムから以下を実行する。
Microsoft Windows SDK v7.1Windows SDK 7.1 Command Prompt

開いたプロンプトで以下を実行すると、ビルドが始まります。
数分かかります。
nmake -f msntdll.mak

検証する。
nmake -f msntdll.mak test

最後に以下が表示されれば検証OK。
passed all tests

以下を実行すると、c:/opensslに実行ファイルやヘッダファイルがコピーされる。
nmake -f msntdll.mak install

こんな感じ。

C:>tree openssl
フォルダー パスの一覧: ボリューム OS
ボリューム シリアル番号は 00000002 54BE:1C45 です
C:OPENSSL
├─bin (dll, exe)
├─include
│ └─openssl (ヘッダ群)
├─lib (スタティックライブラリ)
│ └─engines (dll)
└─ssl (openssl.cnf)