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

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

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

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

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

C++

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

Q&A

解決済

1回答

1201閲覧

opencvを使用するファイルのリンクが上手くできない mac

bamm

総合スコア8

make

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

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

C++

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

0グッド

0クリップ

投稿2020/04/15 10:18

編集2020/04/17 12:03

Macでopencvを用いた図形の表示をしようとしています.ソースコード(opencv.cpp)からプリプロセス,コンパイル,アセンブルまでは無事実行され,opencv.oのファイルができたのですが,その後のリンク時にどうしてもエラーが表示されてしまいます.
自分ではライブラリのパスが上手く出来ていないせいかと考え,パスを通したり,makefileを用いた方法などがあることを知りました.しかし,これらを自分で上手く噛み砕くことができず,最終手段としてそのコードを丸写ししてみたのですが,以下のようなエラーが表示され,やはりできませんでした.下記のソースコードはブログ上のものを丸写ししたものです.

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

エラーメッセージ ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) ### 該当のソースコード(opencv.cpp) #include <opencv2/opencv.hpp> int main(void) { // 画像を格納するオブジェクトを宣言する // # CV_8UC3 : 8bit 3channel フルカラー画像 cv::Mat image(400, 400, CV_8UC3); for (int n = 0; n < 4; n++) { int lineType, lineWidth; switch (n) { case 0: // 線幅1、8連結で描く lineType = cv::LINE_8; lineWidth = 1; break; case 1: // 線幅1、4連結で描く lineType = cv::LINE_4; lineWidth = 1; break; case 2: // 線幅1、アンチエイリアシングで描く lineType = cv::LINE_AA; lineWidth = 1; break; case 3: // 線幅4、アンチエイリアシングで描く lineType = cv::LINE_AA; lineWidth = 4; break; } // 画像を白色で塗りつぶす // # 色を Scalar(Blue, Green, Red) で指定する。BGRの順番であることに注意 image = cv::Scalar(255, 255, 255); for (int i = 0; i < 360; i += 10) { // 始点と終点の座標 // # cv::Pointで整数座標(x,y)を指定する。行列Matと違って(x,y)の並びであることに注意 cv::Point p1(200, 200); // 始点座標(200,200) cv::Point p2; // 終点座標 下の計算式で、円周上に10度おきに配置 p2.x = cos(i * CV_PI / 180) * 200 + p1.x + 0.5; p2.y = sin(i * CV_PI / 180) * 200 + p1.y + 0.5; // 線を引く // # line(画像, 始点座標, 終点座標, 色, 線幅, 連結) cv::line(image, p1, p2, cv::Scalar(255, 0, 0), lineWidth, lineType); } cv::imshow("画像", image); cv::waitKey(); } return 0; }

コンパイルのコマンド

$ g++ -std=c++11 -S opencv.cpp

アセンブルのコマンド

$ as -std=c++11 -o opencv.o opencv.s

リンクのコマンド

$ g++ -o opencv opencv.o

試したこと

ヘッダーファイルでもエラーが表示されたのですが,ヘッダーファイルは直接(/usr/local/include)のディレクトリへ入れ込んでみたところ,上手くいきました.ライブラリでも同様のことをしょうとしたのですが,ライブラリのあるディレクトリはユーザが編集できなかったため,入れ込むことができず,パスを作成するかmakefileを作るしかないのでは,と現段階では考えています.
しかし,パスは通し方が調べるほど色々な方法があり,理解することができず,makefileはターミナルにmakeを打ち込んでも make: *** No targets specified and no makefile found. Stop. と表示されてしまい,できませんでした.(MakefileはCotEditorで作成し,make自体も確認したところ,PC内に入っていました.xcodeもダウンロードしていますが,ターミナルで実行可能ファイルまで作成したいと思っています)

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

opencv 4.3.0
MacOS Catalina
Xcode ver11.4

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

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

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

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

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

yuki23

2020/04/16 01:38

コンパイル、リンクなどのコマンドを質問文に書いてください
hoshi-takanori

2020/04/17 06:50

opencv はどうやって入れましたか? 私は brew で入れましたが、以下のコマンドで行けました。 c++ -std=c++11 `pkg-config --cflags opencv4` `pkg-config --libs opencv4` opencv.cpp
bamm

2020/04/17 11:55

opencvは,brew install opencv で入れました.提示いただいたコマンドを実行したところ,a.outは作成されました.しかし,ファイルを開く際に『ファイルを開けるアプリケーションが無い』との忠告が出てきたため,もともと入っていた写真アプリを指定し,開けようとしたのですが,アプリで開いたところ『写真なし』と表示されてしまいました.どの様なアプリでしたら,画像を見ることができるのでしょうか?
hoshi-takanori

2020/04/19 02:21

コンパイルすると a.out というファイルができると思いますが、もしかしてこれをダブルクリックして起動しようとしてますか? だぶんそれだとエラーになるので、ターミナルで ./a.out として実行しましょう。
bamm

2020/04/19 03:42

ありがとうございます.無事画像が表示されました. 先日,提示いただいたpkg-configの仕組みを教えていただけないでしょうか?自分なりに調べ,ライブラリやヘッダファイル のパスを提供する手段だと分かったのですが,もう少し具体的な解釈をしたいと考えています.宜しくお願いいたします.
guest

回答1

0

ベストアンサー

とりあえず Makefile を書くとしたらこんな感じでしょうか。(インデントはタブにしてください。)

Makefile

1TARGET = a.out 2SRCS = opencv.cpp 3OBJS = $(SRCS:.cpp=.o) 4 5CXXFLAGS = -std=c++11 `pkg-config --cflags opencv4` 6LDFLAGS = `pkg-config --libs opencv4` 7 8$(TARGET): $(OBJS) 9 $(CXX) $(LDFLAGS) $(OBJS) -o $(TARGET) 10 11clean: 12 $(RM) $(TARGET) $(OBJS)

使い方は、make と打つとコンパイル・リンクが行われます。

$ make c++ -std=c++11 `pkg-config --cflags opencv4` -c -o opencv.o opencv.cpp c++ `pkg-config --libs opencv4` opencv.o -o a.out $ ./a.out

また、make clean と打つとコンパイルしたものが削除されます。

$ make clean rm -f a.out opencv.o

Makefile の前に、まず C や C++ の分割コンパイルについて説明します。
例えば main.cpp と sub.cpp から a.out を作る場合、次のコマンドを打ちますよね。

$ c++ main.cpp sub.cpp -o a.out

これを、次のようにコンパイルとリンクを分けて実行することもできます。
この場合、main.cpp と sub.cpp をそれぞれコンパイルして main.o と sub.o が作られ、最後に main.o と sub.o をリンクして a.out が作られます。
(上のように一行で実行する場合も、実は内部でコンパイルとリンクが行われています。)

$ c++ -c main.cpp -o main.o $ c++ -c sub.cpp -o sub.o $ c++ main.o sub.o -o a.out

また、pkg-config ですが、普通に実行するとこんな感じになります。
-I はコンパイラに対するオプションで、#include <〜> するファイルのありかを指定します。
-L と -l はリンカに対するオプションで、-L がライブラシの場所を、-l はリンクするライブラリをしていします。

$ pkg-config --cflags opencv4 -I/usr/local/Cellar/opencv/4.3.0/include/opencv4/opencv -I/usr/local/Cellar/opencv/4.3.0/include/opencv4 $ pkg-config --libs opencv4 -L/usr/local/Cellar/opencv/4.3.0/lib -lopencv_gapi -lopencv_stitching -lopencv_alphamat -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib -lopencv_dnn_objdetect -lopencv_dnn_superres -lopencv_dpm -lopencv_highgui -lopencv_face -lopencv_freetype -lopencv_fuzzy -lopencv_hfs -lopencv_img_hash -lopencv_intensity_transform -lopencv_line_descriptor -lopencv_quality -lopencv_rapid -lopencv_reg -lopencv_rgbd -lopencv_saliency -lopencv_sfm -lopencv_stereo -lopencv_structured_light -lopencv_phase_unwrapping -lopencv_superres -lopencv_optflow -lopencv_surface_matching -lopencv_tracking -lopencv_datasets -lopencv_text -lopencv_dnn -lopencv_plot -lopencv_videostab -lopencv_videoio -lopencv_xfeatures2d -lopencv_shape -lopencv_ml -lopencv_ximgproc -lopencv_video -lopencv_xobjdetect -lopencv_objdetect -lopencv_calib3d

で、コマンドラインでバッククオートで括って実行してますが、この場合、バッククオートで括った部分の実行結果をコマンドラインに埋め込んでさらに実行します。つまり、

$ c++ -std=c++11 `pkg-config --cflags opencv4` -c -o opencv.o opencv.cpp $ c++ `pkg-config --libs opencv4` opencv.o -o a.out

は、それぞれ実際には以下のコマンドが実行されることになります。

$ c++ -std=c++11 -I/usr/local/Cellar/opencv/4.3.0/include/opencv4/opencv -I/usr/local/Cellar/opencv/4.3.0/include/opencv4 -c -o opencv.o opencv.cpp $ c++ -L/usr/local/Cellar/opencv/4.3.0/lib -lopencv_gapi -lopencv_stitching -lopencv_alphamat -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib -lopencv_dnn_objdetect -lopencv_dnn_superres -lopencv_dpm -lopencv_highgui -lopencv_face -lopencv_freetype -lopencv_fuzzy -lopencv_hfs -lopencv_img_hash -lopencv_intensity_transform -lopencv_line_descriptor -lopencv_quality -lopencv_rapid -lopencv_reg -lopencv_rgbd -lopencv_saliency -lopencv_sfm -lopencv_stereo -lopencv_structured_light -lopencv_phase_unwrapping -lopencv_superres -lopencv_optflow -lopencv_surface_matching -lopencv_tracking -lopencv_datasets -lopencv_text -lopencv_dnn -lopencv_plot -lopencv_videostab -lopencv_videoio -lopencv_xfeatures2d -lopencv_shape -lopencv_ml -lopencv_ximgproc -lopencv_video -lopencv_xobjdetect -lopencv_objdetect -lopencv_calib3d opencv.o -o a.out

次に Makefile の読み方を解説します。

まず最初の部分は変数定義です。
TARGET は最終的にできるプログラムの名前です。
SRCS はソースコード (.cpp ファイル) で、複数指定できます。(なので変数名が複数型。)
OBJS は SRCS の拡張子 .cpp を .o にしたもので、この場合は opencv.o になります。
なお、TARGET, SRCS, OBJS という名前は習慣的なもので、別の名前でも構いません。

TARGET = a.out SRCS = opencv.cpp OBJS = $(SRCS:.cpp=.o)

CXXFLAGS と LDFLAGS は飛ばして、次の部分がルール記述になります。

$(TARGET): $(OBJS) $(CXX) $(LDFLAGS) $(OBJS) -o $(TARGET)

Makefile のルールの書き方は次のとおりで、make 作りたいもの と打つと、まず必要なものを作って、それより作りたいものが古ければ、作るためのコマンドを実行します。

作りたいもの: 必要なもの (タブ) 作るためのコマンド

また、$(変数名) は変数が展開されるので、実際には次のようになります。
(ちなみに、CXX は make の組み込み変数 (C++ コンパイラの意味) で、値は c++ になってます。)

これの意味ですが、a.out を作るには opencv.o が必要で、opencv.o から a.out を作るコマンドが次の行に書いてあるということになります。

a.out: opencv.o c++ `pkg-config --libs opencv4` opencv.o -o a.out

ところで、opencv.o はどうやって作るかというと、make にはメタルールと言って、ある拡張子のファイルから別の拡張子のファイルを作るためのルールを定義することができます。

例えば、.cpp から .o を作るためのメタルールはこんな感じです。(ここで、$@ は作りたいもの、$< は必要なものです。)

%.o: %.cpp $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<

つまり、opencv.cpp から opencv.o を作るためのルールはこうなります。(CPPFLAGS と TARGET_ARCH は空です。)

opencv.o: opencv.cpp c++ -std=c++11 `pkg-config --cflags opencv4` -c -o opencv.o opencv.cpp

最後に make clean ですが、clean というファイルを作ろうとして、普通そんなファイルはないので、毎回指定したコマンドが実行されます。(間違って clean というファイルを作ってしまうと、make clean しても make: `clean' is up to date. と言われて何もしてくれません。)

clean: $(RM) $(TARGET) $(OBJS)

投稿2020/04/19 14:12

hoshi-takanori

総合スコア7895

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

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

bamm

2020/04/19 15:23

分かりやすく丁寧に教えてくださり,ありがとうございます.makeコマンドやpkg-configについて,自分の中で噛み砕いて理解することができました. makeを使いこなして,opencv.cpp以外のファイルもこれからどんどん実行できる様に頑張ろうと思います.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問