Skip to content

How to build libarchive on msvc

Claybird edited this page Oct 12, 2019 · 4 revisions

libarchiveをMSVC2017でコンパイルする方法

  • 方針1:DLLではなく、static linkとする
    • 理由:ユーザーにとってDLLが多いのは混乱を招くと考えるため
    • 安全にstatic linkするため、VS2017にコンパイラを統一する。Bash On Windowsでクロスコンパイルも可能だが、手間&ランタイムライブラリでややこしくなる。
  • 方針2:誰かがビルドしてくれたライブラリ(例えばezwinports)は使用しない
    • 理由:セキュリティパッチが出たとき、即座に自力で対応できるようにしたいため

手順1: ShiftMediaProjectが提供する依存ライブラリのビルド

ShiftMediaProjectが各種ライブラリをVCでビルドできるようにして公開してくれているのでありがたく使用する。

プロジェクトフォルダ\SMPにVisual Studio用のソリューションがあるので使用する。 ただし、プロジェクトフォルダ....\msvc*にinclude/lib/licensesをコピーするよう設定されているため、プロジェクトフォルダの場所には注意のこと。

用途 ライブラリ ShiftMediaProjectのURL ライセンス / 備考
圧縮解凍 bzip2 https://github.com/ShiftMediaProject/bzip2/releases BSD-style
文字コード変換 libiconv https://github.com/ShiftMediaProject/libiconv/releases LGPL
圧縮解凍 liblzma https://github.com/ShiftMediaProject/liblzma/releases public domain
圧縮解凍 zlib https://github.com/ShiftMediaProject/zlib/releases zlib license
xml(xar) libxml2 https://github.com/ShiftMediaProject/libxml2/releases MIT License / 先にlibiconvをビルドしておくこと
多倍長演算 GMP https://github.com/ShiftMediaProject/gmp/releases LGPL / Nettleが依存
暗号系 Nettle https://github.com/ShiftMediaProject/nettle/releases LGPL / readme.txtに従ってYASMのインストールが必要。先にGMPをビルドしておくこと。

手順2: 自前でライブラリのビルド

libcharset: LGPL

libiconv付属だが、ShiftMediaProjectのlibiconv付属のものはautogen.shで失敗した。以下の手順で自前ビルドする必要がある。 Bash on Windowsで

  1. ./autogen.sh
  2. ./configure そのあと、Visual Studioでソリューションを作成し、以下のファイルを追加。
  • localcharset.c
  • relocatable-stub.c 追加のインクルードディレクトリは$(ProjectDir);$(ProjectDir)\include LGPL

zstd: BSD License

公式で最新版のWindows Binaryが入手可能だが、念のため自前でビルドする。

  1. VS2017のコマンドプロンプトを開く
  2. build\VS_scripts\build.VS2017Community.cmdを実行

lz4: BSD 2-Clause license

公式で最新版のWindows Binaryが入手可能だが、念のため自前でビルドする。 visual/以下にVS用のソリューションファイルあり。

未使用のライブラリ

libarchiveのCMakeでリストに挙げられるが、おそらく使用しない物

手順3: libarchiveのconfig.hの修正

"#define HAVE_ICONV 1"を手動で追加しないと、iconvを使用してくれない

手順4: libarchive

最後に、libarchiveをcmakeにかけ、プロジェクトを作らせる

libb2をどうしてもVSでコンパイルするには

※これでできたライブラリが正常に動作するかどうかは未確認。コンパイルできるところまでしか確認していない。 手動でソリューションを作成しコンパイル。config.hだけはBash on Windowsで作成する。 Bash On Windowsにて

  1. Makefile.amに「pkgconfigdir = $(libdir)/pkgconfig」を追加
  2. ./autogen.sh
  3. ./configure --host=x86_64-w64-mingw32 --enable-static mingwでは改行コードが異なるため、テストスクリプトの結果判定に失敗する。そこでconfigureを編集: 12668行目
- edx=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 4`
+ edx=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | tr '\r' '\n' | cut -d ":" -f 4`

そのあと、MSVCにて、以下のファイルを含むソリューションを作成。

  • config.h
  • blake2sp.c
  • blake2bp.c
  • blake2s.c
  • blake2b.c
  • blake2-impl.h
  • blake2-config.h
  • blake2s-round.h
  • blake2b-round.h
  • blake2s-load-xop.h
  • blake2s-load-sse41.h
  • blake2s-load-sse2.h
  • blake2b-load-sse41.h
  • blake2b-load-sse2.h

なお、x86で_mm_set_epi64xが再定義される旨のエラーが出た場合は、そのままコメントアウト。

/*#if defined(_MSC_VER) && !defined(_M_X64)
static inline __m128i _mm_set_epi64x( const uint64_t u1, const uint64_t u0 )
{
  return _mm_set_epi32( u1 >> 32, u1, u0 >> 32, u0 );
}
#endif*/

動作確認

//https://github.com/libarchive/libarchive/wiki/Examples
#define LIBARCHIVE_STATIC
#include <stdio.h>
#include "archive.h"
#include "archive_entry.h"
#include <string>
#include <vector>
#include <assert.h>
#define ASSERT assert
#include <windows.h>
#include <locale.h>


#include <io.h>
#include <fcntl.h>
int main()
{
	setlocale(LC_ALL, "");
	_setmode(_fileno(stdout), _O_U8TEXT);
	struct archive *a;
	struct archive_entry *entry;
	int r;

	a = archive_read_new();
	archive_read_support_filter_all(a);
	archive_read_support_format_all(a);
	r = archive_read_open_filename(a, "z:/test/テスト.zip", 10240);
	if (r != ARCHIVE_OK) {
		printf("archive not found\n");
		return 1;
	}
	while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
		const wchar_t* p = archive_entry_pathname_w(entry);
		ASSERT(p);
		std::wstring name = p;
		wprintf(L"%s\n", name.c_str());
		archive_read_data_skip(a);
	}
	archive_read_close(a);
	r = archive_read_free(a);
	if (r != ARCHIVE_OK) {
		printf("Failed to close archive\n");
		return 2;
	}
	return 0;
}