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

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

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

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

C++

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

Q&A

解決済

2回答

2940閲覧

Windows実行用Makefileの記述方法について

ladybug_10

総合スコア3

makefile

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

C++

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

0グッド

0クリップ

投稿2021/03/21 12:32

編集2021/03/22 00:21

実施したいこと

  • LinuxとWindowsで共通のMakefileを使用し、C++のソースをコンパイルしたいです。
  • コンパイラは、ARMクロスコンパイラを使用しています。ビルドファイルを、ARMコア搭載のRaspberry Pi等で使用します。

前提

  • Makefileを使ってC++のソースをコンパイルする。
  • コンパイルしたいディレクトリの構成は以下の通り。

txt

1. 2├── Makefile 3├── include 4│ ├── subdir 5│ │ │── subheader1.h 6│ │ │── subheader2.h 7│ │ └── ... 8│ │── header1.h 9│ │── header2.h 10│ └── ... 11| 12└── source 13 ├── subdir 14 │ ├── subsource1.cpp 15 │ ├── subsource2.cpp 16 │ └── ... 17 │── source1.cpp 18 │── source2.cpp 19 └── ...
  • ソースファイルのルートディレクトリは、sourceである。sourceは任意のサブディレクトリおよびソースを含む。
  • ヘッダーファイルのルートディレクトリは、includeである。includeは任意のサブディレクトリおよびヘッダーを含む。
  • Makefile によるコンパイル後のディレクトリ構成は以下の通り。

txt

1. 2├── Makefile 3├── example.exe 4├── include 5│ ├── subheader 6│ │ │── subheader1.h 7│ │ │── subheader2.h 8│ │ └── ... 9│ │── header1.h 10│ │── header2.h 11│ └── ... 12| 13|── source 14| ├── subsource 15| │ ├── subsource1.cpp 16| │ ├── subsource2.cpp 17| │ └── ... 18| │── source1.cpp 19| │── source2.cpp 20| └── ... 21| 22└── object 23 ├── subsource 24 │ ├── subsource1.o 25 │ ├── subsource2.o 26 │ └── ... 27 │── source1.o 28 │── source2.o 29 └── ...
  • オブジェクトファイルのルートディレクトリは、objectである。objectは、sourceと同じディレクトリ構造を持つ。

該当のソースコード

リンク先のサイトを参考にさせていただきました。

makefile

1# コンパイラの指定 2CXX := arm-linux-gnueabihf-g++ 3 4# コンパイラオプションの指定 5CXXFLAGS := -g -O1 -Wall -Wextra -Wuninitialized -std=c++11 6 7# インクルードディレクトリの指定 8INCDIR := -I./include -I./include/% 9 10# ライブラリへのリンクの指定 11LIBS := -lm 12 13# コンパイルするソースの拡張子の指定 14EXTENSION := cpp 15 16# 生成するターゲット名 17TARGET := ./example.exe 18 19# ソースファイルのルートディレクトリ 20SRCROOT := ./source 21 22# ソースルートディレクトリの中を(shellの)findコマンドで、サブディレクトリを含めてリスト化する 23SRCDIRS := $(shell find $(SRCROOT) -type d) 24 25# ソースディレクトリを元にforeach命令で全ファイルをリスト化する 26SRCS := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.$(EXTENSION))) 27 28# 中間バイナリファイルの出力ルートディレクトリ 29OBJROOT := ./object 30 31# ソースディレクトリと同じ構造でオブジェクトファイル名を指定 32OBJS := $(patsubst $(SRCROOT)/%.o, $(OBJROOT)/%.o, $(patsubst %.$(EXTENSION), %.o, $(SRCS)) ) 33 34# クリーン用コマンド 35RM := rm -rf 36 37# Windows用コマンド 38ifeq ($(OS),Windows_NT) 39 RM := cmd.exe /C del /q 40endif 41 42$(TARGET): $(OBJS) 43 $(CXX) $(CXXFLAGS) -o $@ $^ 44 45$(OBJROOT)/%.o: $(SRCROOT)/%.$(EXTENSION) 46 @if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi 47 $(CXX) $(CXXFLAGS) $(LIBS) $(INCDIR) -o $@ -c $< 48 49.PHONY: all clean 50 51all: $(TARGET) 52 53clean: 54 $(RM) $(TARGET) $(OBJROOT)

発生している問題

  • Linuxでは問題なく実行できるのですが、Windowsでは実行できずにエラーとなります。
  • エラーメッセージは文字化けしていて内容が不明ですが、おそらくSRCDIRSおよび`$(OBJROOT)/%.o: $(SRCROOT)/%.$(EXTENSION)

`のレシピでシェルのコマンドを使用しているので、Windowsではオブジェクトファイル用のサブディレクトリを生成できないことが、エラーの原因と思われます。

  • RMのコマンドのように、上記のオブジェクト用ディレクトリ生成コマンドも、Linux用とWindows用で自動で切り替わるようにしたいです。Windowsコマンドのいい書き方が分からなかったので、ご教示いただきたいです。
  • そのほか加筆修正事項がありましたら、ご指摘お願いいたします。

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

  • PC OS:Windows10バージョン2004
  • CPU:Intel Core i5
  • 使用しているLinux OS:WSL(Windows Subsystem for Linux)Ubuntu 20.04.1 LTS
  • コンパイラ:arm-linux-gnueabihf-g++(ARMクロスコンパイラ) 4.8.3

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

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

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

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

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

dodox86

2021/03/21 13:32 編集

とりあえず気になったこととして、Intel x86(i386)/AMD64(x86-x64)のLinux UbuntuでC++コンパイラがarm-linux-gnueabihf-g++ と言うのはちょっとあり得ないのですが。それはARM用のクロスコンパイラのはずです。CPUがARMの、Raspberry Piなどで動かしていませんか。Windows用ではMinGWのg++になるはずです。 エラーメッセージが文字化けしてしまうのであれば、makeを実行する前に $ export LANG=C などと実行してからmakeを実行してみてください。
ladybug_10

2021/03/22 00:38

ご指摘ありがとうございます。補足情報を修正いたしました。 ARMクロスコンパイラを使用してビルドしています。ビルドは、Intel CoreのWindowsまたはLinuxで行い、ビルドファイルをARMコア搭載のRaspberry Pi等で使用するイメージです。
matsuand

2021/03/22 03:49

Windows側の make がどのようなものか使ったこともないのでわかりませんが、そもそも wildcard 関数などは GNU Make 固有のものではなかったかな(?) 汎用性を(今後のことも含めて)考えるなら、あまりそれらを多用しない方がよいようにも感じます。SRCS の定義にて foreach を用いていますが、ここはサブディレクトリごとに、それぞれ Makefile を作れば解決しそうに思います(その手法はここでは説明しきれませんが)。
guest

回答2

0

自己解決

Windowsの場合は、コマンドプロンプトのコマンドを使用することで、とりあえず動作することができました。SRCDIRSとオブジェクトファイル生成箇所を以下のように修正しました。

makefile

1ifeq ($(OS),Windows_NT) 2 SRCDIRS := $(sort $(SRCROOT) $(filter-out %.$(EXTENSION), $(wildcard $(SRCROOT)/*))) 3else 4 # (shellの)findコマンドを使用 5 SRCDIRS := $(shell find $(SRCROOT) -type d) 6endif

makefile

1$(OBJROOT)/%.o: $(SRCROOT)/%.$(EXTENSION) 2ifeq ($(OS),Windows_NT) 3 @if not exist "$(@D)" (mkdir "$(@D)") 4else 5 @if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi 6endif 7 $(CXX) $(CXXFLAGS) $(LIBS) $(INCDIR) -o $@ -c $<

投稿2021/03/23 11:01

編集2021/03/24 07:41
ladybug_10

総合スコア3

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

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

0

こういう用途ではmakefile単体で頑張るのはあまり賢くなくて、cmakeなんかでmakeを吐くほうがはるかに一般的でうまくいくのではないでしょうか。中間ファイルの管理も勝手にいい感じにしてくれます。

投稿2021/03/22 07:20

yumetodo

総合スコア5852

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

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

ladybug_10

2021/03/23 10:54

アドバイスをありがとうございます。CMakeを知らなかったので、調べてみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問