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

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

新規登録して質問してみよう
ただいま回答率
85.37%
make

make は、ビルド作業を自動化するツールです。さまざまなファイルの最終変更時刻を比較し、従属するファイルよりも「ターゲット」のファイルが古いことがわかったときユーザーが設定していた命令を実行する事が可能です。

makefile

make は、プログラムのビルド作業を自動化するツールです。コンパイル、リンク、インストール等のルールを記述したテキストファイルをmakefileと呼び、このルールに従ってmakeが自動的にビルドを実行する。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

14885閲覧

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

MF_19

総合スコア27

make

make は、ビルド作業を自動化するツールです。さまざまなファイルの最終変更時刻を比較し、従属するファイルよりも「ターゲット」のファイルが古いことがわかったときユーザーが設定していた命令を実行する事が可能です。

makefile

make は、プログラムのビルド作業を自動化するツールです。コンパイル、リンク、インストール等のルールを記述したテキストファイルをmakefileと呼び、このルールに従ってmakeが自動的にビルドを実行する。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/07/10 13:26

編集2018/07/11 12:03

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

もともと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++

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

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 03:00

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

MF_19

2018/07/11 05:56

ありがとうございます。質問は重複しないようにします。 教えて頂いたURLでは試し方が違うのか上手くいってませんが、 とりあえず、.aファイルを使用せずにmakeし、.oファイルをobjディレクトリに出力しました。 そのobjディレクトリ内で下記を実行してsoファイルを作成しました。 (これが共有ライブラリと思っていますが、勘違いあればご指摘お願いします) g++ -std=gnu++14 -Ofast -fPIC -fopenmp -g -DNNPACK -shared *.o libnnpack.a libpthreadpool.a libcpuinfo.a -o libtest.so このsoファイルを用いて実行用のmakeファイルで実行ファイルを作ると問題なく動作しました。 ただmakeで.aファイルを含んだsoファイルを作成できるようにしないといけない状況なので、 そこが上手く行っていません。 追加コードは質問文に追加します。
Chironian

2018/07/11 06:16

問題は、 libnnpack.a libpthreadpool.a libcpuinfo.aが静的リンク用のライブラリ・ファイルなのか?、動的リンク用のライブラリ・ファイルなのか?です。この両者は全く異なります。 回答にも記載したように、これらの .a ファイルが動的リンク用のものでしたら、お困りの事象が発生します。 これらの .a ファイルが静的リンク用なら大丈夫な筈なのですが。 あ、思い出しました。これらの .a ファイルが静的リンク用のものだったとしても、-fPICオプションなしでビルドされていると駄目です。その場合は、-fPICオプションをつけろというようなエラー・メッセージがでます。
MF_19

2018/07/11 07:38

$ file libnnpack.a libnnpack.a: current ar archive $ ar tv libnnpack.a rw-r--r-- 0/0 26576 Jan 1 09:00 1970 init.c.o rw-r--r-- 0/0 203304 Jan 1 09:00 1970 convolution-inference.c.o rw-r--r-- 0/0 20736 Jan 1 09:00 1970 fully-connected-inference.c.o rw-r--r-- 0/0 30696 Jan 1 09:00 1970 pooling-output.c.o rw-r--r-- 0/0 17576 Jan 1 09:00 1970 softmax-output.c.o rw-r--r-- 0/0 22952 Jan 1 09:00 1970 relu-output.c.o ....
MF_19

2018/07/11 07:39

ターミナルで上記の結果になっているので、静的リンク用のライブラリになっているという認識でいます。 他の2つのファイルも同様の出力でした。
Chironian

2018/07/11 08:12

なるほど、確かに静的リンク・ライブラリですね。 ちょっと考えにくいですが、libtest.soが静的リンク・ライブラリになっている可能性はないでしょうか? arコマンド等で確認できると思います。 あと、gccのコマンドに詳しくないので外しているかも知れませんが、.so ファイルを直接リンク指定しても良いのでしょうか? Windowsではたいてい .dll を造った時に .lib も一緒にできるので .lib を指定します。linuxでも確か .a ファイルを指定していたと思います。
MF_19

2018/07/11 08:19

$ file libtest.so libtest.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=687a37c015ed433baf56408a93941c56d5fb764a, not stripped
MF_19

2018/07/11 08:24

上記となりますので、soファイルはダイナミックリンクになっています。 すいません、最後にご提案頂いた内容があまり分かってません。 gccの引数にsoとaファイルを使用するようにするということでしょうか。
Chironian

2018/07/11 08:36

確かに共有ライブラリですね。 gccコマンドについては私が知っている範囲では、次のサイトの例11のような指定をします。 http://www.ysr.net.it-chiba.ac.jp/data/cc.html gcc -g -o test -L. test.o -lgw -lでフルパスで指定することもできます。その時はlibと.aを省略できません。このれいだと -l./libgw.a と書くことになります。 後者のケースで私は .aではなく.soを指定したことはないので、.soを直接指定できるかどうか把握していません。
MF_19

2018/07/11 12:05

ご提案頂いた部分と間接的に関係があると思うのですが、質問を更新させて頂いたので 拝見頂けると幸いです。
Chironian

2018/07/11 13:37

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

2018/07/13 07:55

色々とアドバイスを頂きありがとうございました。 ようやくコンパイルができ、問題なく稼働しました。 ご指摘頂いた通り、.aファイルの再ビルドが必要で、 作成時に-fPICを追加することで、共有ライブラリへ静的リンクができました。
guest

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/10 13:56

編集2018/07/11 21:47
pepperleaf

総合スコア6385

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

MF_19

2018/07/11 08:02

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

2018/07/12 01:11

ご確認ありがとうございます。 このライブラリに関しては下記のURLより詳細が確認できそうです。 https://github.com/digitalbrain79/darknet-nnpack .textという拡張子に違和感がありますが、この部分含めて cmakeの時に-fPICをつければ共有可能な形になるのではと考えています。
pepperleaf

2018/07/12 11:15

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

2018/07/13 07:57

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

0

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

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

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

投稿2018/07/10 13:35

y_waiwai

総合スコア88024

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問