共有ライブラリの作成方法@vscode in Linux
Linux + vscodeの環境での共有ライブラリ(実行時ライブラリ、ランタイムライブラリ)の作成方法について調べた。
結論
簡単に結論から
1. 共有ライブラリの作成
clang++(g++) -fPIC -shared -o <libshared.so.1.0.0> xxx.cpp yyy.cpp ...
2. シンボリックリンクをはる
ln -nfs libshared.so.1.0.0 libshared.so
3. main.cppのビルドにshared libを利用
clang++ -o main.exe main.cpp -lshared ...
4. launch.jsonのLD_LIBRARY_PATH修正
"LD_LIBRARY_PATH" : "/usr/lib/x86_64-linux-gnu:/home/Sources/myprojectpath"
1. 共有ライブラリの作成
静的ライブラリ(x.a)と共有ライブラリ(x.so)の違いや作成コマンドは次のリンク先に書かれているが、簡単に言えばコンパイルするプログラムのサイズに違いが出てくる。
技術レポート「Linuxのライブラリ開発」|ソフテックだより|株式会社ソフテック
実際に比べてみた結果がこちら
・共有ライブラリなし
-rwxrwxr-x 1 user user 9.4M 10月 15 22:29 main.exe
=> 9.4MB
・共有ライブラリあり
lrwxrwxrwx 1 user user 20 10月 15 22:18 libshared.so -> libshared.so.1.0.0 -rwxrwxr-x 1 user user 9.3M 10月 15 22:18 libshared.so.1.0.0 -rwxrwxr-x 1 user user 1.9M 10月 15 22:18 main.exe
=> 合計11.2MB
単純に合計値を比べた場合、main.exe + 共有ライブラリに分けた方が容量は大きくなるようだが、共有ライブラリは他のプログラムでも流用できることを考えると、こちらの方が便利かも。
もちろん、ライブラリ部分を切り出せばmain.exeの容量は小さくなる。
vscodeに記述する場合、tasks.jsonにライブラリ作成コマンドを記述する。
{ // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format "version": "2.0.0", "tasks": [ { "label": "shared_lib", "type": "shell", "command": "clang++", "args": [ "-std=c++17", "-fPIC", "-shared", "-g", "-o", "libshared.so.1.0.0", "a.cpp", "b.cpp", "-lvulkan", "-lvulkan_radeon", "-lvulkan_intel", "-march=native", ], "group": { "kind": "build", "isDefault": true }, "problemMatcher": [ "$eslint-compact" ] }, { "label": "link", "type": "shell", "command": "ln", "args": [ "-nfs", "libshared.so.1.0.0", "libshared.so", ], "dependsOn" : [ "shared_lib" ] }, { "label": "echo", "type": "shell", "command": "clang++", "args": [ "-std=c++17", "-g", "-o", "${fileBasenameNoExtension}.exe", "${file}", "-L/home/Sources/myprojectpath", "-lshared", "-lvulkan", "-lvulkan_radeon", "-lvulkan_intel", "-march=native", ], "group": { "kind": "build", "isDefault": true }, "dependsOn" : [ "link" ], "problemMatcher": [ "$eslint-compact" ] } ] }
vscodeのtasks.jsonには複数のtaskを記述することが可能で、順序はdependsOnで制御することができる。
VSCodeでタスク実行時に複数コマンド実行 - Qiita
2. シンボリックリンクをはる
前述のリンク先でもあったように、共有ライブラリには命名規則があり、soファイルはシンボリックリンクで作成しておき、実態は別のところにあるという記述の仕方を行う。
メリットとしては単純にリンク先を変えることで古いバージョンを指すようにできたり、また最新版を指すようにしてプログラムを再コンパイルすることなくアップデートすることができる。
http://archive.linux.or.jp/JF/JFdocs/Program-Library-HOWTO/shared-libraries.html
アーカイブリナックの記事にはldconfigコマンドでシステム全体に共有ライブラリを認識させる方法も書かれているが、ここでは開発用にローカルに認識できれば良いとしてこの作業は行っていない。
ldconfigについては次の記事など、探せば色々見つかるよう。
https://wa3.i-3-i.info/word13812.html
3 main.cppのビルドにshared libを利用
単純に-lオプションでリンクする。
4 launch.jsonのLD_LIBRARY_PATH修正
プログラム実行時にライブラリを探せる必要があるので、launch.jsonにLD_LIBRARY_PATHに作成した共有ライブラリのパスを検索できるように追加する。
以下の記事に
"Multiple directories can be listed, separated by a colon (:)"
と書かれているので、:で分けて記述する。
LD_LIBRARY_PATH – or: How to get yourself into trouble!
私はCodeLLDBというextensionを入れているので、以下のような書き方になっている。
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "Launch", "type" : "lldb", "request": "launch", "program": "${workspaceFolder}/${fileBasenameNoExtension}.exe", "args": [], "stopOnEntry": false, "cwd": "${workspaceFolder}", "env": { "LD_LIBRARY_PATH" : "/usr/lib/x86_64-linux-gnu:/home/Sources/myprojectpath", "VK_LAYER_PATH" : "/usr/share/vulkan/explicit_layer.d" }, "terminal": "console", } ] }
未確認だが、通常のenvironmentには以下のように記述すると思われる。
"environment": [ { "name" : "LD_LIBRARY_PATH", "value" : "/usr/lib/x86_64-linux-gnu:/home/Sources/myprojectpath" }, { "name" : "VK_LAYER_PATH", "value" : "/usr/share/vulkan/explicit_layer.d" } ],