アプリケーション開発ポータルサイト
ServerNote.NET
Amazon.co.jpでPC関連商品タイムセール開催中!
カテゴリー【CORESERVERC/C++
レンタルサーバーCORESERVERにgcc/g++8.3をソースからインストールして使う
POSTED BY
2023-10-01
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.cppGitHub 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
※本記事は当サイト管理人の個人的な備忘録です。本記事の参照又は付随ソースコード利用後にいかなる損害が発生しても当サイト及び管理人は一切責任を負いません。
※本記事内容の無断転載を禁じます。
【WEBMASTER/管理人】
自営業プログラマーです。お仕事ください!
ご連絡は以下アドレスまでお願いします★

☆ServerNote.NETショッピング↓
ShoppingNote / Amazon.co.jp
☆お仲間ブログ↓
一人社長の不動産業務日誌
【キーワード検索】