質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.01%

c++ make時のコンパイルエラー

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,521

MF_19

score 25

追加質問です

下記で質問させて頂いてましたが、新たなエラーが出てきたので
質問させて頂きます。

もともと3つの.aファイルをを共有ライブラリに静的に結びつけようとしていて
undifineのエラーが出ていました。(実行ファイルのmake時)

試しに別の.aファイルを試すとこちらは上手く静的に結びつき
undifineのエラーが出ませんでした。

同じ方法でもともとの.aファイルで実行するとエラーが出てくるので
ここの部分が問題かと思います。

新たなエラー

NPACK -shared obj/region_layer.o obj/utils.o obj/local_layer.o obj/shortcut_layer.o obj/im2col.o obj/data.o obj/batchnorm_layer.o obj/dropout_layer.o obj/image.o obj/convolutional_layer.o obj/gru_layer.o obj/detection_layer.o obj/avgpool_layer.o obj/col2im.o obj/normalization_layer.o obj/inferencer.o obj/train.o obj/lstm_layer.o obj/network.o obj/crnn_layer.o obj/layer.o obj/deconvolutional_layer.o obj/rnn_layer.o obj/reorg_layer.o obj/crop_layer.o obj/softmax_layer.o obj/box.o obj/list.o obj/matrix.o obj/connected_layer.o obj/gemm.o obj/parser.o obj/option_list.o obj/activations.o obj/cuda.o obj/blas.o obj/activation_layer.o obj/maxpool_layer.o obj/route_layer.o obj/tree.o obj/cost_layer.o /opt/openblas/lib/libopenblas.a /home/NNPACK/lib/libpthreadpool.a -o libsensor.so
/usr/bin/ld: /home/NNPACK/lib/libpthreadpool.a(threadpool-pthreads.c.o): relocation R_X86_64_32 against `.text' can not be used when making a shared object; recompile with -fPIC
/home/NNPACK/lib/libpthreadpool.a: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
Makefile:93: recipe for target 'libtest.so' failed
make: *** [libsensor.so] Error 1


sharedの引数に2つの.aファイルを追加しています。
libopenblas.a(新たに試した.a) 
libpthreadpool.a(もともとの.a)

追加の質問

このエラーについて-fPICを追加する必要があるように思ったのですが、
すでに付いている認識でいます。どこを変更すれば宜しいでしょうか?

もしくは.aファイル作成時(cmake)に必要なのでしょうか。
つまり.aファイルを作り直す?

よろしくお願いします。

makeファイル変更点
・ifeq ($(OPENBLAS), 1)部分追加
・$(DLIB)の引数にlibopenblas.a、libpthreadpool.aを追加

(省略)
ifeq ($(OPENBLAS), 1)
INCLUDE+= -static -DOPENBLAS -I/opt/openblas/include
CFLAGS+= -DOPENBLAS -DSTBI_NO_HDR -DSTBI_NO_LINEAR
LDFLAGS+=/opt/openblas/lib/libopenblas.a
endif

ifeq ($(NNPACK), 1)
INCLUDE+= -static -DNNPACK -I/home/NNPACK/deps/pthreadpool/include -I/home/NNPACK/include/nnpack -I/home/NNPACK/deps/cpuinfo/include
CFLAGS+= -DNNPACK
LDFLAGS+= /home/NNPACK/lib/libpthreadpool.a /home/NNPACK/lib/libnnpack.a /home/NNPACK/lib/libcpuinfo.a
endif

(省略)

all: $(TARGET) $(DLIB)

$(TARGET): $(OBJECTS)
        $(COMPILER) $(CFLAGS) $(LIBS) -o $@ $^ $(LDFLAGS)

$(DLIB): $(OBJECTS) /opt/openblas/lib/libopenblas.a /home/NNPACK/lib/libpthreadpool.a
        $(COMPILER) $(CFLAGS) -shared $^ -o $@

(省略)

ここから下は当初の内容です

 前提・実現したいこと

makeファイルを用いてc++のコンパイルがしたいです。

 経緯

makeファイル(soファイル作成用makeファイル)を用いてlibtest.soファイルを作成しました。
このファイルは外用(他人に渡す用)のため、
全てのライブラリを含んだ上で渡したいです。

確認のため、自分用にこのlibtest.soファイルとmain.cppファイルを用いて実行ファイルを作るためにコンパイル(実行ファイル作成用makeファイル)しようとすると下記のエラーが発生します。

 発生している問題・エラーメッセージ

g++ -std=gnu++14 -Ofast -fPIC -fopenmp  -o main obj/main.o -lm -lpthread -lgomp ../../libtest.so
../../libtest.so: undefined reference to `pthreadpool_compute_1d'
../../libtest.so: undefined reference to `nnp_convolution_inference'
../../libtest.so: undefined reference to `pthreadpool_compute_2d'
collect2: error: ld returned 1 exit status
Makefile:30: recipe for target 'main' failed
make: *** [main] Error 1

試しに、この実行ファイル用makeファイルにエラーでundifineとされている
関数が組み込まれた.aファイルをLDFLAGSに指定すると問題なく実行ファイルが作成されました。

LDFLAGS+= /home/NNPACK/lib/libnnpack.a /home/NNPACK/lib/libpthreadpool.a /home/NNPACK/lib/libcpuinfo.a


これらの.aファイルはsoファイル用makeファイルにも
同じようにパスを指定していたので、問題ないかと思っていました。

調べてみると、これらの.aファイルを用いてsoファイルを作成する際、
上手く静的に結びついていないのが原因かと思っています。
(そのためundifineになるのかと思っています)

静的リンクにするためso用makeファイルを書き換えましたが、
上手くいかず同じエラーが出続けています。

so用makeファイルはどのように記載すれば、
静的リンクとしてsoファイルに結びつくのでしょうか?

何か勘違いがございましたら、ご指摘のほど宜しく尾根がします。

 該当のソースコード

soファイル作成用makeファイル

NNPACK=1

COMPILER  = g++
CFLAGS :=-std=gnu++14 -Ofast -fPIC -fopenmp -g
CUFLAGS:=-Wall -Wno-unknown-pragmas -Wfatal-errors -Ofast -fPIC -fopenmp
LDFLAGS := -lm -lpthread -lgomp -static-libstdc++ -static-libgcc

INCLUDE   = -I./include -I/usr/include

ifeq ($(NNPACK), 1)
INCLUDE+= -static -DNNPACK -I/home/spot1/NNPACK/include
CFLAGS+= -DNNPACK
LDFLAGS+= /home/NNPACK/lib/libnnpack.a /home/NNPACK/lib/libpthreadpool.a /home/NNPACK/lib/libcpuinfo.a
endif

TARGET    = ./sensor
DLIB      = ./libtest.so
SRCDIR    = ./source
ifeq "$(strip $(SRCDIR))" ""
  SRCDIR  = .
endif
SOURCES   = $(wildcard $(SRCDIR)/*.cpp)
OBJDIR    = ./obj
ifeq "$(strip $(OBJDIR))" ""
  OBJDIR  = .
endif
OBJECTS   = $(addprefix $(OBJDIR)/, $(notdir $(SOURCES:.cpp=.o)))
ifeq ($(GPU), 1)
CU_SOURCES   = $(wildcard $(SRCDIR)/*.cu)
OBJECTS += $(addprefix $(OBJDIR)/, $(notdir $(CU_SOURCES:.cu=.o)))
endif
DEPENDS   = $(OBJECTS:.o=.d)

all: $(TARGET) $(DLIB)
$(TARGET): $(OBJECTS)
        $(COMPILER) $(CFLAGS) $(LIBS) -o $@ $^ $(LDFLAGS)
$(DLIB): $(OBJECTS)
        $(COMPILER) $(CFLAGS) -shared $^ -o $@
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
        -mkdir -p $(OBJDIR)
        $(COMPILER) $(CFLAGS) $(INCLUDE) $(LIBS) -o $@ -c $<
$(OBJDIR)/%.o: $(SRCDIR)/%.cu
        $(NVCC) -std=c++14 $(ARCH) $(INCLUDE) --compiler-options "$(CUFLAGS)" -c $< -o $@

clean:
        -rm -f $(OBJECTS) $(DEPENDS) $(TARGET)

-include $(DEPENDS)

実行ファイル作成用makeファイル
このmakeファイル実行時に問題のエラーが発生しています。

LDFLAGSの./libtest.so後に下記を追加すれば問題なくコンパイルはできるのですが、
外用のため、このmakeファイルでは呼出し不要にしたいです。
home/NNPACK/lib/libnnpack.a /home/NNPACK/lib/libpthreadpool.a /home/NNPACK/lib/libcpuinfo.a

COMPILER  = g++
CFLAGS :=-std=gnu++14 -Ofast -fPIC -fopenmp
LDFLAGS := -lm -lpthread -lgomp ../../libtest.so

INCLUDE   = `pkg-config --cflags opencv` -I./ -I/usr/include
#INCLUDE   = -I./ -I/usr/include
TARGET    = ./main
SRCDIR    =
ifeq "$(strip $(SRCDIR))" ""
  SRCDIR  = .
endif
SOURCES   = $(wildcard $(SRCDIR)/*.cpp)
OBJDIR    = ./obj
ifeq "$(strip $(OBJDIR))" ""
  OBJDIR  = .
endif
OBJECTS   = $(addprefix $(OBJDIR)/, $(notdir $(SOURCES:.cpp=.o)))
DEPENDS   = $(OBJECTS:.o=.d)
all: $(TARGET)
$(TARGET): $(OBJECTS)
        $(COMPILER) $(CFLAGS) $(LIBS) -o $@ $^ $(LDFLAGS)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
        -mkdir -p $(OBJDIR)
        $(COMPILER) $(CFLAGS) $(INCLUDE) $(LIBS) -o $@ -c $<
clean:
        -rm -f $(OBJECTS) $(DEPENDS) $(TARGET)
-include $(DEPENDS)

 補足情報(FW/ツールのバージョンなど)

gcc 5.4.0
ubuntu16.4
C++

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

0

こんにちは。

念の為の確認ですが、/home/NNPACK/lib/libnnpack.a /home/NNPACK/lib/libpthreadpool.a /home/NNPACK/lib/libcpuinfo.aは静的リンク用にビルドされたライブラリであることに間違いないでしょうか?

linuxには詳しくはないのですが、「静的リンク・ライブラリ」と「動的リンク・ライブラリの静的ロード用のファイル」は同じファイル名であることもあります。
前者は当該関数の中身も含まれています。後者は動的リンク・ライブラリをロードする際に必要な情報が入っているだけで中身は入っていません。後者をリンクすると動的リンクになる筈です。
後者の場合、前回の質問の回答でコメントしたようにlinuxでの共有ライブラリのリンクについての現象が起きている可能性があります。

静的リンクにするためso用makeファイルを書き換えましたが、
上手くいかず同じエラーが出続けています。

変更内容を見てみましたが、関連する修正はINCLUDE+= -static -DNNPACK -I/home/spot1/NNPACK/includeを追加しているだけですね? これはリンクには無関係です。

makefileを手で作るためには、ビルドする際の手順について詳しい理解が必須です。まずはスクリプトで直接gccコマンドを記述してビルドすると理解が深まります。
その方が回答も付きやすいと思いますよ。makefileに詳しい方は多くはないと思いますので。
実は私もその一人です。makefileの自動生成ツールのCMakeに任せてますので。これはこれでたいへんですけど、マルチプラットフォーム対応時はかなり楽になります。


【蛇足ですが】
前回、用語について調べてもよく判らなかったら別質問を立てたほうが良い旨書きました。それでこの質問を立てられたのでしたら、ごめんなさい。
同じ課題に関する質問を複数立てるのは良くないです。同じ質問なら、以前の質問に追記した方が好ましいです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/11 22:37

    なるほど。libtest.so ファイルが適切に作られていなかったということみたいですね。

    > もしくは.aファイル作成時(cmake)に必要なのでしょうか。
    > つまり.aファイルを作り直す?

    その通りです。NNPACK(?)のビルド方法説明に -fPIC オプションの付け方が記載されていないでしょうか?
    記載されていればその手順で libnnpack.a らをビルドしましょう。
    記載がない場合はかなりきついことになります。
    NNPACKが使っているビルドツールを習熟する必要があります。それがCMakeなら習熟する価値は十分にあると思いますが、それなりの学習期間が必要になります。(msvcの独特なDebug/Release切り替えに対応しているので非常に便利なのですが、gcc用の情報と混在しているのでかなり苦労しました。)

    キャンセル

  • 2018/07/12 10:16

    ご確認頂きありがとうございます。
    やはり.aファイルらの再ビルドが必要なのですね。

    https://github.com/digitalbrain79/darknet-nnpack
    上記のgit-hubを参考に試してみようと思います。

    キャンセル

  • 2018/07/13 16:55

    色々とアドバイスを頂きありがとうございました。
    ようやくコンパイルができ、問題なく稼働しました。

    ご指摘頂いた通り、.aファイルの再ビルドが必要で、
    作成時に-fPICを追加することで、共有ライブラリへ静的リンクができました。

    キャンセル

0

ちと言ってることが意味不明ですが、

LDFLAGSの./libtest.so後に下記を追加すれば問題なくコンパイルはできるのですが、

これでビルドした実行ファイルは、実際にどういう不具合があるんでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

makeが何をしているか理解していますか?
makefileでの定義に従ってコマンドを実行しているだけです。どのように実行されるか確認してみましょう。
ちょっと調べてみたところ、"make -n" とすると、実際の実行無しに、コマンドの出力があるようです。 (GNU Make の場合) ここから、コンパイラ(g++) にどのような引数が渡されているか分かると思います。この引数の意味を確認する事かではないでしょうか?

関数が組み込まれた.aファイルをLDFLAGSに指定すると

LDFLAGS の本来の意味は、リンクするライブラリの参照パスのようですが、上記の使い方では、単に、リンクするファイルの指定になっているように思えます。従って、問題の発生する場合、リンクファイル (.a)が不足している事を意味していると考えられますが、違うでしょうか?


別の質問の続きでしょうか? それならば、分かるようにして頂いた方が、助かります。 (と言いつつも、未確認)

[追記 7/11]
どこまで解決したか、追い切れていません。既に確認済みでしたら、読み飛ばしを。

"NPACK -shared ..." について、
NPACKがなんであるかは、ちょっと検索した限りでは、確認できませんでした。(以下、推測)
ただ、コマンドラインからすると、複数のオブジェクト(ライブラリを含む)をまとめるツールと思われます。 出力は、libsensor.so で、共有ライブラリ形式(-shared)。
エラーは、libpthreadpool.a のファイルが不正と言っています。共有可能な形式でない(.text が相対アドレスでない)、 -fPIC オプション(共有ライブラリ)で再コンパイルしろ、と。
"-shared" 無しでライブラリ作成すれば、良いのではないかと。ただし、共有ライブラリでない事に注意。
コンパイルは、ここで作成した、ライブラリ(libsensor.so .. 拡張子は適当に) を含めれば、良いのではないでしょうか?

[追記 7/12]
コマンドのオプション(引数)ですが、Helpを見る事はできませんか? シェルから直接、以下のパターンでコマンド実行します。

  • 引数無し (単に NPACK を実行)
  • 引数として、 "-help", "--help" のどちらかを付ける。 ("NPACK -help" or "NPACK --help")
    etc.
    gcc とかも同様と思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/11 17:02

    仰るとおりだと思います。
    .soファイル出力時に静的に.aファイルを組み込めるようにしたいのですが、上手くいっていません。
    方法等アドバイスありましたらお願いします。

    キャンセル

  • 2018/07/12 10:11

    ご確認ありがとうございます。
    このライブラリに関しては下記のURLより詳細が確認できそうです。
    https://github.com/digitalbrain79/darknet-nnpack

    .textという拡張子に違和感がありますが、この部分含めて
    cmakeの時に-fPICをつければ共有可能な形になるのではと考えています。

    キャンセル

  • 2018/07/12 20:15

    .text は、拡張子でなく、オブジェクトファイル内のタグ(? 正確な用語忘れた)です。テキストデータ領域で無かったかと思います。

    キャンセル

  • 2018/07/13 16:57

    アドバイスありがとうございました。
    解決方法はベストアンサーさせて頂いたコメント欄へ記載しましたが、
    ようやく解決が出来ました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る