win64アプリケーションクロスビルドでアイコン・プロパティ・リソースを付ける

Gtk3/Cで書いたベクターグラフィック・エディタのvecterionを、Ubuntu16.04ホストでwin64ターゲットにクロスビルド中。でアイコン・プロパティ・リソースを付けた作業のメモです。


以下のようなコードで実現できます。

# .rcほか、リソースファイルを用意する 

実際に必要なのは```IDI_ICON ICON ~```行だけです。
そのICONこれも実は文字列"ICON"とファイルパス以外は大した意味はないとか、他にもオプションが付けられるとかあるようです。
Win32アプリケーションプログラミングをマスターしたいわけではないので.rcファイルの記述はスルー。
.icoファイルですが、GIMPでいい加減に縮小するだけならいい加減に作れます。PNG透過の正方形画像を、512px, 64px,32px,16pxの順にレイヤ複製->レイヤ縮小を繰り返して、最後に.icoで保存しようとすると、アイコン形式画像を保存するウィザードが出てきてGIMPが良いようにしてくれます。
(64pxは48pxのほうがいいかもしれないけれどしていません。512pxもMacOSX対応にしては中途半端。)


Ubuntu16.04環境ではnautilusもeogもこの.icoを正しく描画できませんでしたが、Windowsではとしてはきちんとアプリケーションアイコンとして表示されたので問題ありません。

```
diff --git a/deploy/win/vecterion.rc b/deploy/win/vecterion.rc
new file mode 100644
index 0000000..ed229c3
--- /dev/null
+++ b/deploy/win/vecterion.rc
@@ -0,0 +1,24 @@
+#include <windows.h>
+
+//ICON
+IDI_ICON1 ICON DISCARDABLE "deploy/win/vecterion_icon.ico"
+
+1 VERSIONINFO
+FILEVERSION     0,0,0,1
+PRODUCTVERSION  0,0,0,1
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "080904E4"
+        BEGIN
+            VALUE "InternalName",        "vecterion_vge"
+            VALUE "OriginalFilename",     "vecterion_vge.exe"
+            VALUE "ProductName",        "vecterion_vge"
+            VALUE "ProductVersion",        "0.0.0.1"
+            VALUE "FileVersion",        "0.0.0.1"
+            VALUE "CompanyName",        "project daisy bell"
+            VALUE "LegalCopyright",        "Michinari.Nukazawa"
+            VALUE "FileDescription", "Vecterion, the true vector graphics editor for linux (and other)."
+        END
+    END
+END
diff --git a/deploy/win/vecterion_icon.ico b/deploy/win/vecterion_icon.ico
new file mode 100644
index 0000000..bf8ade4
Binary files /dev/null and b/deploy/win/vecterion_icon.ico differ
diff --git a/deploy/win/vecterion_icon.xcf b/deploy/win/vecterion_icon.xcf
new file mode 100644
index 0000000..7ba9088
Binary files /dev/null and b/deploy/win/vecterion_icon.xcf differ

```

# Windowsリソースのオブジェクト作成します。

クロスビルドはbashスクリプトにしています。

ここでリソース(.rc テキストのソース)をwindresでオブジェクトに変換します。
Makefileに入れるより楽そうで、やってみると、ビルド時間にほぼ影響がなかったので。
```
+# make resource(icon and other)
+TARGET_ARCH_WIN_RESOURCE=${OBJECT_DIR}/vecterion.res
+x86_64-w64-mingw32-windres ${ROOT_DIR}/deploy/win/vecterion.rc -O coff -o ${TARGET_ARCH_WIN_RESOURCE}
+


 # build app source
 CFLAGS_APPEND=-Wno-missing-include-dirs

 [ -d ${GTK3LIBRARY_DIR}/lib/pkgconfig ]
 export PKG_CONFIG_PATH=${GTK3LIBRARY_DIR}/lib/pkgconfig
-make TARGET_ARCH=win CC=x86_64-w64-mingw32-gcc CFLAGS_APPEND=${CFLAGS_APPEND} INCLUDE_APPEND="-mwindows"
+make TARGET_ARCH=win CC=x86_64-w64-mingw32-gcc CFLAGS_APPEND=${CFLAGS_APPEND} INCLUDE_APPEND="-mwindows" TARGET_ARCH_WIN_RESOURCE=${TARGET_ARCH_WIN_RESOURCE}

```



# リソースのオブジェクトをリンクします。

Windowsクロスビルド以外ではリソースのオブジェクトのパスを空文字にします。```
diff --git a/Makefile b/Makefile
index 4f859f1..0aa22f9 100644
--- a/Makefile
+++ b/Makefile
@@ -71,6 +71,7 @@ $(APP_FILE) : $(OBJECTS)
     $(CC) \
         $^ \
         $(OBJECT_DIR)/version.c \
+        $(TARGET_ARCH_WIN_RESOURCE) \
         $(CFLAGS) \
         $(INCLUDE) \
         -o $(APP_FILE)


```



gtk3アプリケーションのクロスビルド(Windowsターゲット、Linuxホスト)した際のメモ

開発中のGtk3/Cによるベクターグラフィック・エディタであるvecterionの、Windowsx64ターゲット、Linuxホストでクロスビルド作業中。
とりあえず動作するところまでは行きました。



その時のトライアンドエラーというか問題と解決のざっとしたメモです。


Windowsターゲットビルドはvecterionにとってあくまでおまけなのだけれど、Linuxターゲットで開発していてコード中に甘かった箇所がいくつかあり(ex. フォーマット文字列中のsize_tの変換指定を%zuにしていなかったなど)、ついでに修正することができた。


原因を追い切ってはいません。Windows版の優先度はその程度です。

#### 解決方法をメモし忘れたエラー error: unknown type name ‘uid_t’


詳細を忘れてしまった。
確かMinGW64のWindowsターゲットクロスビルドであるにも関わらず、pkg-configがLinuxのライブラリをリンクして、起こっていたような気がする。
http://stackoverflow.com/questions/32282270/c99-error-unknown-type-name-pid-t


```
In file included from /usr/lib/x86_64-linux-gnu/glib-2.0/include/glibconfig.h:9:0,
                 from /usr/include/glib-2.0/glib/gtypes.h:32,
                 from /usr/include/glib-2.0/glib/galloca.h:32,
                 from /usr/include/glib-2.0/glib.h:30,
                 from /usr/include/gtk-3.0/gdk/gdkconfig.h:13,
                 from /usr/include/gtk-3.0/gdk/gdk.h:30,
                 from /usr/include/gtk-3.0/gtk/gtk.h:30,
                 from ./include/et_pointing_manager.h:4,
                 from source/et_pointing_manager.c:1:
/usr/include/glib-2.0/glib/gtypes.h: In function ‘_GLIB_CHECKED_ADD_U64’:
/usr/include/glib-2.0/glib/gmacros.h:232:53: error: size of array ‘_GStaticAssertCompileTimeAssertion_0’ is negative
 #define G_STATIC_ASSERT(expr) typedef char G_PASTE (_GStaticAssertCompileTimeAssertion_, __COUNTER__)[(expr) ? 1 : -1] G_GNUC_UNUSED
                                                     ^
/usr/include/glib-2.0/glib/gmacros.h:229:47: note: in definition of macro ‘G_PASTE_ARGS’
 #define G_PASTE_ARGS(identifier1,identifier2) identifier1 ## identifier2
                                               ^
/usr/include/glib-2.0/glib/gmacros.h:232:44: note: in expansion of macro ‘G_PASTE’
 #define G_STATIC_ASSERT(expr) typedef char G_PASTE (_GStaticAssertCompileTimeAssertion_, __COUNTER__)[(expr) ? 1 : -1] G_GNUC_UNUSED
                                            ^
/usr/include/glib-2.0/glib/gtypes.h:422:3: note: in expansion of macro ‘G_STATIC_ASSERT’
   G_STATIC_ASSERT(sizeof (unsigned long long) == sizeof (guint64));
   ^
In file included from /usr/include/glib-2.0/gio/gio.h:46:0,
                 from /usr/include/gtk-3.0/gdk/gdkapplaunchcontext.h:28,
                 from /usr/include/gtk-3.0/gdk/gdk.h:32,
                 from /usr/include/gtk-3.0/gtk/gtk.h:30,
                 from ./include/et_pointing_manager.h:4,
                 from source/et_pointing_manager.c:1:
/usr/include/glib-2.0/gio/gcredentials.h: At top level:
/usr/include/glib-2.0/gio/gcredentials.h:75:1: error: unknown type name ‘uid_t’
 uid_t            g_credentials_get_unix_user      (GCredentials    *credentials,
 ^
/usr/include/glib-2.0/gio/gcredentials.h:79:52: error: unknown type name ‘uid_t’
                                                    uid_t           uid,
                                                    ^
Makefile:60: ターゲット 'object/win/et_pointing_manager.o' のレシピで失敗しました


```

```
 58 export PKG_CONFIG_PATH=${GTK3LIBRARY_DIR}/lib/pkgconfig¬
 59 make TARGET_ARCH=win CC=x86_64-w64-mingw32-gcc CFLAGS_APPEND=${CFLAGS_APPEND} INCLUDE_APPEND="-m    windows"¬


```



#### pkg-configで生成したビルドオプションの[-Werror=missing-include-dirs]


一時的にチェックフラグを解除して回避
最終的にビルドスクリプトを変更し、pkg-config(*.pc設定ファイル)が正しいパスを指すよう修正して解決

```
cc1: error: /srv/win32builder/fixed_3104/build/win64/include/freetype2: そのようなファイルやディレクトリはありません [-Werror=missing-include-dirs]
cc1: error: /srv/win32builder/fixed_3104/build/win64/include/libxml2: そのようなファイルやディレクトリはありません [-Werror=missing-include-dirs]
cc1: error: /srv/win32builder/fixed_3104/build/win64/include/freetype2: そのようなファイルやディレクトリはありません [-Werror=missing-include-dirs]
cc1: all warnings being treated as errors
Makefile:60: ターゲット 'object/win/et_pointing_manager.o' のレシピで失敗しました


```

``` packaging_win64.sh
 42 >-------pushd ${GTK3LIBRARY_DIR}¬
 43 ¬
 44 >-------unzip ${CACHE_DIR}/gtk+-bundle_3.10.4-20131202_win64.zip > /dev/null¬
 45 >-------find -name '*.pc' | while read pc; do sed -e "s@^prefix=.*@prefix=$PWD@" -i "$pc"; done¬
 46 >-------find -name '*.pc' | while read pc; do sed -e "s@/srv/win32builder/fixed_3104/build/win64    @$PWD@g" -i "$pc"; done¬
 47 >-------sed -e "s@Z:/srv/win32builder/fixed_3104/build/win32/@@g" -i "lib/gdk-pixbuf-2.0/2.10.0/    loaders.cache"¬
 48 ¬
 49 >-------popd¬


```




#### mingwがswitch defaultに置いたassert(false)を解釈してくれない

「到達しないソース行」の検出あたりが、linuxのgccとMinGWで違うようで(バージョンの違いかもしれない)、リターンエラーのメッセージが出る。
assert()のラッパを、新規作成したabort()のラッパ関数に置き換えて解決。

```
source/pv_type.c: In function ‘pv_rect_get_edge_point’:
source/pv_type.c:202:1: error: control reaches end of non-void function [-Werror=return-type]
 }
 ^
cc1: all warnings being treated as errors

```

```
195 >------->-------case PvRectEdgeKind_DownLeft:¬
196 >------->------->-------return (PvPoint){rect.x, (rect.y + rect.h)};¬
197 >------->-------case PvRectEdgeKind_DownRight:¬
198 >------->------->-------return (PvPoint){(rect.x + rect.w), (rect.y + rect.h)};¬
199 >------->-------default:¬
200 >------->------->-------pv_assertf(false, "%d", edgeKind);¬
201 >-------}¬
202 }¬

```
```
200 >------->------->-------pv_abortf("%d", edgeKind);¬
```


#### size_t型のリテラル間違い

size_tを"%lu"のままにしてしまうミス。
修正後、正しい指定の"%zu"を受け付けない。
一時的には、出力を潰して対処した。
最終的に、`-posix` 追加で"%zu"が使えるようになり解決。

```
-               pv_debug("len:%lu '%s'", strlen(src), src);
+               pv_debug("len: '%s'", /*strlen(src),*/ src);

```




#### sscanfの非C11標準(posix標準)リテラルの使用

sscanf()にて、リテラル記述に"%m"が存在しないとされて使えない。
-D_GNU_SOURCE=1 は効果なし。
gcc(MinGW)のバージョンが原因でもないように見えた。
最終的に、`-posix` 追加で解決。


```
source/pv_io.c: In function ‘_new_css_str_maps_from_str’:
source/pv_io.c:450:24: error: unknown conversion type character ‘m’ in format [-Werror=format=]
   if(2 != sscanf(head, " %m[^:;] : %m[^;]", &skey, &svalue)){
                        ^
source/pv_io.c:450:24: error: unknown conversion type character ‘m’ in format [-Werror=format=]


```

http://linuxjm.osdn.jp/html/LDP_man-pages/man3/scanf.3.html


http://stackoverflow.com/questions/11926883/scanf-dynamic-allocation
`I don't see anything about m flag in my copy of C11 (which is, admittedly, a draft).`


http://grokbase.com/t/postgresql/pgsql-hackers/114vq5qrhn/unknown-conversion-m
`Hmm. The error disappears if I use -D__USE_MINGW_ANSI_STDIO=1 or -posix`


#### libxml2の引数型の間違い

関数の引数の型が合わないビルドエラー。
Web上のドキュメントではconst付きで記載されているが、実際にヘッダのソースコードを当たってみると、constなしになっている。
constを外して解決。

```
source/pv_io.c:450:24: error: too many arguments for format [-Werror=format-extra-args]
source/pv_io.c: In function ‘_overwrite_conf_read_svg_from_xmlnode’:
source/pv_io.c:534:32: error: passing argument 1 of ‘xmlGetProp’ discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
  xmlChar *xc_fill = xmlGetProp(xmlnode, BAD_CAST "fill");


```

http://xmlsoft.org/html/libxml-tree.html#xmlGetProp

#### libgtk3 for windowsの古いバージョンの未実装関数

gtk3-3.10.4がこの関数を未実装であるためエラー。
同名のラッパ関数を定義、またはターゲットにより関数呼び出しを取り除くマクロを定義して解決。

```
source/et_canvas_collection.c: In function ‘et_canvas_collection_delete_canvases_from_doc_id’:
source/et_canvas_collection.c:250:3: error: implicit declaration of function ‘gtk_notebook_detach_tab’ [-Werror=implicit-function-declaration]
   gtk_notebook_detach_tab(GTK_NOTEBOOK(self->widget_tab), canvas_frame);

```

https://mail.xfce.org/pipermail/xfce4-commits/2016-June/071144.html

```
source/et_layer_view.c:148:2: error: implicit declaration of function ‘gtk_text_view_set_monospace’ [-Werror=implicit-function-declaration]
  gtk_text_view_set_monospace (GTK_TEXT_VIEW(self->text), TRUE);


```

#### libgtkのsvgのローダ

svgが開かない
以前も見ていた不具合。
相対パスへの書き換えとライブラリの追加パッケージングで解決。

```
sed -e "s@Z:/srv/win32builder/fixed_3104/build/win32/@@g" -i "lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"

${GTK3LIBRARY_DIR}/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.dll
${GTK3LIBRARY_DIR}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache

```


#### Windows環境でのマウスポインタ変更

windowへのポインタを取ろうとして、Windows環境で取れないため、マウスカーソル周りの処理でエラー。
マウスカーソル周りをWindowsターゲットのビルドで無効にして一時的に解決。


 
その後、あらためて確認したらビルドが通りました。ヘッダなどが必要だったのかもしれない。

```
(vecterion_vge.exe:4292): Gdk-CRITICAL **: gdk_screen_get_root_window: assertion 'GDK_IS_SCREEN screen)' failed

(vecterion_vge.exe:4292): Gdk-CRITICAL **: gdk_window_new: assertion 'GDK_IS_WINDOW (parent)' failed

(vecterion_vge.exe:4292): Gdk-WARNING **: gdk_input_wintab_init: gdk_window_new failed

```



#### libgtkで一部のダイアログを出すのに必要なファイルの追加

Save操作時にエラーダイアログ。
パッケージにschemasファイルを追加して解決。

```
GLib-GIO-ERROR**: No GSettings schemas are installed on the system
```

```
 76 mkdir -p ${PACKAGE_DIR}/share/glib-2.0/¬
 77 cp -r ${GTK3LIBRARY_DIR}/share/glib-2.0/schemas ${PACKAGE_DIR}/share/glib-2.0/¬

```

http://stackoverflow.com/questions/28953925/glib-gio-error-no-gsettings-schemas-are-installed-on-the-system




Linuxコマンドライン上でSVGベクタ画像をJPG等へラスタライズ変換する

 Linuxコマンドライン上でSVGベクタ画像をJPG等へラスタライズ変換することができるが、上手く変換されない場合がある。   以前作った魔法陣イラスト素材をイラスト素材ストックサイトへ登録しようと思い立ち、改めて素材用にラスタライズ変換をかけようとした。   ラスタライズ変換...