94509


##### 質問内容

以下のmakefileですがエラーの原因がわかりません。なぜ`$(ALL_OBJ)`を`$(BINDIR)/%.o`で指定しているのに  
以下のエラーが発生するのでしょうか？

##### 確認したこと

コンソールに変数の中身を出力  
chatGPTで質問  
./include/の各ディレクトリ内と./includeディレクトリにヘッダーファイル  
./src/の各ディレクトリと./srcディレクトリ内にソースファイル  
があることを確認

##### 参考サイト

make .phony <https://yu-nix.com/archives/makefile-
phony/#Makefile%E3%81%AEPHONY%E3%81%A7%E4%BE%BF%E5%88%A9%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92%E6%9B%B8%E3%81%84%E3%81%9F%E3%82%89%E4%B8%96%E7%95%8C%E3%81%8C%E5%A4%89%E3%82%8F%E3%81%A3%E3%81%9F>  
make 関数 https://tex2e.github.io/blog/makefile/functions

##### Error

[code]

    $ make
    ALL_SRC:  ./src/systems/WindowContext.cpp  ./src/utils/Shader.cpp  
    ALL_OBJ: ./build/obj/WindowContext.o ./build/obj/Shader.o
    make: *** 'build/lib/libFrameWork.a' に必要なターゲット 'build/obj/WindowContext.o' を make するルールがありません.  中止.
    
    
[/code]

##### ディレクトリ構造

[code]

    ├── build
    │   └── obj
    │   └── lib
    ├── include
    │   └── framework
    │       ├── FrameWork.hpp
    │       ├── components
    │       ├── entities
    │       ├── scenes
    │       ├── systems
    │       └── utils
    ├── resources
    │   ├── fonts
    │   ├── models
    │   ├── shaders
    │   └── textures
    ├── scripts
    ├── src
    │   ├── components
    │   ├── entities
    │   ├── scenes
    │   ├── systems
    │   │   └── WindowContext.cpp
    │   └── utils
    │       └── Shader.cpp
    └── test
    
    
[/code]

##### makefile

[code]

    CXX=g++
    CXXFLAGS=-std=c++11 -Wall -Wextra -O3
    LDFLAGS=-lglfw -lGL -lGLEW
    
    SRCDIR=./src
    INCDIR=./include
    BINDIR=./build/obj
    DEPDIR=./build/obj
    LIBDIR=./build/lib
    
    ALL_SRC_DIR=$(shell find $(SRCDIR) -type d)
    ALL_SRC_FLIES=$(wildcard $(ALL_SRC_DIR)/*.cpp)
    ALL_SRC=$(foreach dir,$(ALL_SRC_DIR),$(wildcard $(dir)/*.cpp))
    
    ALL_OBJ=$(addprefix $(BINDIR)/, $(notdir $(ALL_SRC:.cpp=.o)))
    
    
    DEP=$(ALL_OBJ:.o=.d)
    INC=-I$(INCDIR)
    
    TARGET=$(LIBDIR)/libFrameWork.a
    
    .PHONY: all clean
    
    all: $(TARGET)
    
    
    $(TARGET): $(ALL_OBJ)
        ar rcs $@ $^
    
    $(BINDIR)/%.o: $(ALL_SRC_DIR)/%.cpp
        $(CXX) -c -MMD -MP $< -o $@ $(CXXFLAGS) $(INC)
    -include $(DEP)
    
    
    clean:
        rm -rf $(BINDIR)/* $(TARGET)
    
    
    $(info ALL_SRC: $(ALL_SRC))
    $(info ALL_OBJ: $(ALL_OBJ))
    
    
    
[/code]


CC BY-SA 4.0
2023-04-12T12:45:41.030
94499
2023-04-14T11:02:25.657
55177
question
c++ makefile
makefile「'〇〇.a' に必要なターゲット '〇〇.o' を make するルールがありません. 」の原因が知りたい


提示コードの

[code]

    $(BINDIR)/%.o: $(ALL_SRC_DIR)/%.cpp
        $(CXX) -c -MMD -MP $< -o $@ $(CXXFLAGS) $(INC)
    -include $(DEP)
    
[/code]

部を

[code]

    $(BINDIR)/%.o: $(ALL_SRC)
        $(CXX) -c -MMD -MP $< -o $@ $(CXXFLAGS) $(INC)
    -include $(DEP)
    
    
[/code]

と編集して`make clean`したら

[code]

    $ make
    ./build/obj/WindowContext.o ./build/obj/Shader.o
    g++ -O3 -c -MMD -MP src/systems/WindowContext.cpp -o build/obj/WindowContext.o -L/lib/x86_64-linux-gnu -lglfw -lGLEW -lGL 
    g++ -O3 -c -MMD -MP src/systems/WindowContext.cpp -o build/obj/Shader.o -L/lib/x86_64-linux-gnu -lglfw -lGLEW -lGL 
    ar rcs build/lib/libFrameWork.a build/obj/WindowContext.o build/obj/Shader.o
    
[/code]

と表示され成功しました。


CC BY-SA 4.0
2023-04-13T08:14:34.490
94503
2023-04-14T11:02:25.657
2023-04-14T11:02:25.657
55177
55177
94499
answer


`ALL_SRC_DIR` にはおそらく `src/components src/entities src/scenes src/systems
src/utils` というようなリストが入っているので、

[code]

    $(BINDIR)/%.o: $(ALL_SRC_DIR)/%.cpp
    
[/code]

は

[code]

    ./build/obj/%.o: src/components src/entities src/scenes src/systems src/utils/%.cpp
    
[/code]

と展開されます。このパターンは、ソースが `src/utils/` にあるときのみ適用されるので、`WindowContext.o`
を作るルールが見つからないわけです。しかも `$<` は `src/components` なので何もコンパイルできません。

* * *

`$(BINDIR)/%.o` を作りたいときにソースがどこにあるか見つけなければなりません。3通りの解決法を紹介します。

#### 複数のパターンを用意する

[code]

    $(BINDIR)/%.o: src/systems/%.cpp
        $(CXX) -c ...
    $(BINDIR)/%.o: src/utils/%.cpp
        $(CXX) -c ...
    
[/code]

のようにサブディレクトリ毎にパターンを書いておけば適切なものにマッチしてくれます。

#### ディレクトリ構造をマッチさせる

オブジェクトファイルもサブディレクトリに入れると話は簡単です。`ALL_OBJ` が
`./build/obj/systems/WindowContext.o ./build/obj/utils/Shader.o`
のようにサブディレクトリも入るようにすれば、`%` にサブディレクトリ名のマッチングも任せられるので、1つのパターンだけで済みます。

[code]

    $(BINDIR)/%.o: src/%.cpp
        -/bin/mkdir -p $(dir $@)
        $(CXX) -c ...
    
[/code]

#### [VPATH](https://www.gnu.org/software/make/manual/make.html#Directory-
Search) で検索させる

make がファイルを探すときにカレントディレクトリ以外からも探すように指定できます。

[code]

    VPATH=$(ALL_SRC_DIR)
    $(BINDIR)/%.o: %.cpp
        $(CXX) -c ...
    
[/code]


CC BY-SA 4.0
2023-04-13T13:21:10.623
94509
2023-04-13T22:40:21.493
2023-04-13T22:40:21.493
3475
3475
94499
answer