2024-09-30


CORESERVERはgcc/g++の利用が可能となっているが、確認してみるとバージョンが低すぎる。
g++ --version g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39) Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
これではC++14はおろか11のコードですら大量のコンパイルエラーが出たので、自分のホームディレクトリにソースから最新をインストールして以後そっちのg++を使うことにする。レンタルサーバーなので当然システムにはインストールできない。
ソースコードパッケージ取得、展開
wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-8.3.0/gcc-8.3.0.tar.gz tar xvfzp gcc-8.3.0.tar.gz
依存ライブラリのダウンロード実行
cd gcc-8.3.0 ./contrib/download_prerequisites
一旦gccディレクトリを出て、ビルドディレクトリを作成しそこからconfigure
インストール先は$HOME/.localとした。languagesはc,c++で充分。
cd .. mkdir build cd build/ ../gcc-8.3.0/configure --prefix=$HOME/.local --enable-languages=c,c++ --disable-multilib --disable-bootstrap
コンパイル・インストール
make -j4 make install
ビルドは非常に負荷のかかる作業で、CORESERVERはレンタルサーバーなのでそういうことをしていると途中で強制終了させられる。そうなってもめげずにひたすらmakeやmake -j4と打っていればいつかはビルドは完了する。
$HOME/.local/binにgcc/g++、
$HOME/.local/include/c++にC++ヘッダファイル、
$HOME/.local/lib64にlibstdc++.soがあるので、コンパイル、実行時はこれらを使用しなくてはいけない。
テストで以下C++14ベースのvectorサンプルコードをコンパイル・実行してみる。
C/C++ | vector.cpp | GitHub Source |
#include <iostream> #include <string> #include <memory> #include <vector> class A { std::string mName; public: A(void) { std::cout << "A constructor" << std::endl; mName = std::string("えーでふぉると"); } A(std::string name) { std::cout << "A constructor" << std::endl; mName = name; } virtual ~A(void) { std::cout << "A destructor" << std::endl; } void hello(void) { std::cout << "A said こんにちは my name is" << mName << std::endl; } }; void sample_1(void) { std::cout << "enter sample_1" << std::endl; std::vector<std::shared_ptr<A>> vec = std::vector<std::shared_ptr<A>>(); std::shared_ptr<A> a1 = std::make_shared<A>(std::string("えーいち")); std::shared_ptr<A> a2 = std::make_shared<A>(std::string("えーに")); std::shared_ptr<A> a3 = std::make_shared<A>(std::string("えーさん")); std::shared_ptr<A> a4 = std::make_shared<A>(std::string("えーよん")); vec.push_back(a1); vec.push_back(a2); vec.push_back(a3); vec.push_back(a4); std::cout << "vector count=" << vec.size() << std::endl; vec.at(0)->hello(); vec.back()->hello(); std::cout << "before vector clear" << std::endl; vec.clear(); std::cout << "after vector clear" << std::endl; std::cout << "leave sample_1" << std::endl; } void sample_2(void) { std::cout << "enter sample_2" << std::endl; std::vector<std::shared_ptr<A>> vec = std::vector<std::shared_ptr<A>>(); vec.push_back(std::make_shared<A>(std::string("えーいち"))); vec.push_back(std::make_shared<A>(std::string("えーに"))); vec.push_back(std::make_shared<A>(std::string("えーさん"))); vec.push_back(std::make_shared<A>(std::string("えーよん"))); std::cout << "vector count=" << vec.size() << std::endl; vec.at(0)->hello(); vec.back()->hello(); std::cout << "before vector clear" << std::endl; vec.clear(); std::cout << "after vector clear" << std::endl; std::cout << "leave sample_2" << std::endl; } int main(int argc, char **argv) { std::cout << "enter main" << std::endl; sample_1(); sample_2(); std::cout << "leave main" << std::endl; return 0; }
コンパイルは以下のようにローカルインストールしたg++、パスを指定する
$HOME/.local/bin/g++ -I$HOME/.local/include/c++ -L$HOME/.local/lib64 vector.cpp
出来上がった実行ファイルa.outをlddにかけてみても、ローカルのライブラリを見てくれてはいないのでNOT FOUNDがあるが、
ldd a.out ./a.out: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./a.out) ./a.out: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by ./a.out) ./a.out: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by ./a.out) linux-vdso.so.1 => (0x00007ffdc5f52000) libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f87a155e000) libm.so.6 => /lib64/libm.so.6 (0x00007f87a125c000) libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f87a1046000) libc.so.6 => /lib64/libc.so.6 (0x00007f87a0c78000) /lib64/ld-linux-x86-64.so.2 (0x00007f87a1865000)
これは何も指定せずそのまま以下のように実行してしまうとエラーになるが、
./a.out ./a.out: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./a.out) ./a.out: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by ./a.out) ./a.out: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by ./a.out)
実行時ライブラリの場所をソースインストールしたローカルlib64をLD_LIBRARY_PATHに指定すれば、そこのlibstdc++を読みにいってくれるので、無事実行できる。
export LD_LIBRARY_PATH=$HOME/.local/lib64 ./a.out enter main enter sample_1 A constructor A constructor A constructor A constructor vector count=4 A said こんにちは my name isえーいち A said こんにちは my name isえーよん before vector clear after vector clear leave sample_1 A destructor A destructor A destructor A destructor enter sample_2 A constructor A constructor A constructor A constructor vector count=4 A said こんにちは my name isえーいち A said こんにちは my name isえーよん before vector clear A destructor A destructor A destructor A destructor after vector clear leave sample_2 leave main
CGIとしてWEBから実行するなら通常.htaccessに
public_html/.htaccess SetEnv LD_LIBRARY_PATH "/virtual/hogeuser/.local/lib64"
と書いておけば上記のように無事実行されると期待したが、どうもCORESERVERは.htaccessでのSetEnvを許可していないようでInternal Serer Errorになってしまう。
ということは独自パスにあるダイナミックリンクライブラリはCGIでは使えないということになる。
このような場合は、以下のようにlibstdcをスタティックリンクする指令-static-libstdc++ -static-libgccを与えてコンパイルする。
$HOME/.local/bin/g++ -I$HOME/.local/include/c++ -L$HOME/.local/lib64 -static-libstdc++ -static-libgcc vector.cpp
これなら単体でもCGI経由でもLD_LIBRARY_PATHの指定は不要で実行可能となる。スタティックリンクなのでファイルサイズは相当になってしまうため、気になるならデバッグを捨てて以下のようにstripする。
strip a.out
※本記事内容の無断転載を禁じます。
ご連絡は以下アドレスまでお願いします★
オープンソースリップシンクエンジンSadTalkerをDebianで動かす
ファイアウォール内部のOpenAPI/FastAPIのdocsを外部からProxyPassで呼ぶ
Debian 12でsshからshutdown -h nowしても電源が切れない場合
【Windows&Mac】アプリのフルスクリーンを解除する方法
Debian 12でtsコマンドが見つからないcommand not found
Debian 12でsyslogやauth.logが出力されない場合
Debian 12で固定IPアドレスを使う設定をする
Debian 12 bookwormでNVIDIA RTX4060Ti-OC16GBを動かす
【Debian】apt updateでCD-ROMがどうのこうの言われエラーになる場合
【Windows10】リモートデスクトップ間のコピー&ペーストができなくなった場合の対処法
Windows11+WSL2でUbuntuを使う【2】ブリッジ接続+固定IPの設定
【Apache】サーバーに同時接続可能なクライアント数を調整する
GitLabにHTTPS経由でリポジトリをクローン&読み書きを行う
【C/C++】小数点以下の切り捨て・切り上げ・四捨五入
Intel Macbook2020にBootCampで入れたWindows11 Pro 23H2のBluetoothを復活させる
【PHP】Mail/mimeDecodeを使ってメールの中身を解析(準備編)
【ひかり電話+VoIPアダプタ】LANしか通ってない環境でアナログ電話とFAXを使う
Windows11のコマンドプロンプトでテキストをコピーする