Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Post History
Each rule in the Makefile represents a single target. This means that your first makefile has a single target: obj/library.o. I guess that if there is only one target, make assumes that this is the...
Answer
#2: Post edited
- Each rule in the Makefile represents a single target. This means that your first makefile has a single target: `obj/library.o`. I guess that if there is only one target, `make` assumes that this is the target you want to build and does not require targets to be provided by the command line. As a result, your Makefile works "as expected".
- In the second Makefile your rule has a wildcard and thus represents infinitely many targets. Now `make` is unable to guess what you actually want to build, hence the error. However, you can still use this makefile by providing the targets you want to build on the command line: `make obj/library.o` should provide the exact same results as your initial attempt. If you are only interested in re-building (i.e. all files already exist), you could even use `make obj/*.o` to re-build all files with this Makefile.
- Your third Makefile introduces the standard target `all`, which is intended to solve the problem with your second makefile: tell `make` which targets to build when no command line arguments are given. The targets provided here are interpreted as literal strings. As a result, the makefile will look for the literal target `%.o`, which does not exist and fail the build.
- ---
- Now, if you would look closer at the proposed solution in Stackoverflow, you would notice that the proposed answer does not use any wildcards, but specifies all targets that need to be build. It can be helpful to be explicit about which targets you wish to build (as proposed in the stackoverflow answer), however it is often too convenient to simply use wildcards.
- Luckily it is possible to use wildcards, but not in the way you might have hoped. Instead of directly specifying a wildcard, you have to create a list of all targets that you wish to build. Because these targets typically won't exist the first time you build the project, you have to somehow generate this list. One way to do that, is by following the [documentation](https://www.gnu.org/software/make/manual/html_node/Wildcard-Function.html), which would lead to the following Makefile:
- ```
- DIR_INC=include
- DIR_LIB=lib
- DIR_OBJ=obj
SOURCES := $(wildcard *.c)OBJECTS := $(patsubst %.c,$(DIR_OBJ)/%.o,$(SOURCES))- all: $(OBJECTS)
- $(DIR_OBJ)/%.o: $(DIR_LIB)/%.c $(DIR_INC)/%.h
- gcc -c -o $@ $<
- ```
- I hope that clears things up for you.
- Each rule in the Makefile represents a single target. This means that your first makefile has a single target: `obj/library.o`. I guess that if there is only one target, `make` assumes that this is the target you want to build and does not require targets to be provided by the command line. As a result, your Makefile works "as expected".
- In the second Makefile your rule has a wildcard and thus represents infinitely many targets. Now `make` is unable to guess what you actually want to build, hence the error. However, you can still use this makefile by providing the targets you want to build on the command line: `make obj/library.o` should provide the exact same results as your initial attempt. If you are only interested in re-building (i.e. all files already exist), you could even use `make obj/*.o` to re-build all files with this Makefile.
- Your third Makefile introduces the standard target `all`, which is intended to solve the problem with your second makefile: tell `make` which targets to build when no command line arguments are given. The targets provided here are interpreted as literal strings. As a result, the makefile will look for the literal target `%.o`, which does not exist and fail the build.
- ---
- Now, if you would look closer at the proposed solution in Stackoverflow, you would notice that the proposed answer does not use any wildcards, but specifies all targets that need to be build. It can be helpful to be explicit about which targets you wish to build (as proposed in the stackoverflow answer), however it is often too convenient to simply use wildcards.
- Luckily it is possible to use wildcards, but not in the way you might have hoped. Instead of directly specifying a wildcard, you have to create a list of all targets that you wish to build. Because these targets typically won't exist the first time you build the project, you have to somehow generate this list. One way to do that, is by following the [documentation](https://www.gnu.org/software/make/manual/html_node/Wildcard-Function.html), which would lead to the following Makefile:
- ```
- DIR_INC=include
- DIR_LIB=lib
- DIR_OBJ=obj
- SOURCES := $(wildcard $(DIR_LIB)/*.c)
- OBJECTS := $(patsubst $(DIR_LIB)/%.c,$(DIR_OBJ)/%.o,$(SOURCES))
- all: $(OBJECTS)
- $(DIR_OBJ)/%.o: $(DIR_LIB)/%.c $(DIR_INC)/%.h
- gcc -c -o $@ $<
- ```
- I hope that clears things up for you.
#1: Initial revision
Each rule in the Makefile represents a single target. This means that your first makefile has a single target: `obj/library.o`. I guess that if there is only one target, `make` assumes that this is the target you want to build and does not require targets to be provided by the command line. As a result, your Makefile works "as expected". In the second Makefile your rule has a wildcard and thus represents infinitely many targets. Now `make` is unable to guess what you actually want to build, hence the error. However, you can still use this makefile by providing the targets you want to build on the command line: `make obj/library.o` should provide the exact same results as your initial attempt. If you are only interested in re-building (i.e. all files already exist), you could even use `make obj/*.o` to re-build all files with this Makefile. Your third Makefile introduces the standard target `all`, which is intended to solve the problem with your second makefile: tell `make` which targets to build when no command line arguments are given. The targets provided here are interpreted as literal strings. As a result, the makefile will look for the literal target `%.o`, which does not exist and fail the build. --- Now, if you would look closer at the proposed solution in Stackoverflow, you would notice that the proposed answer does not use any wildcards, but specifies all targets that need to be build. It can be helpful to be explicit about which targets you wish to build (as proposed in the stackoverflow answer), however it is often too convenient to simply use wildcards. Luckily it is possible to use wildcards, but not in the way you might have hoped. Instead of directly specifying a wildcard, you have to create a list of all targets that you wish to build. Because these targets typically won't exist the first time you build the project, you have to somehow generate this list. One way to do that, is by following the [documentation](https://www.gnu.org/software/make/manual/html_node/Wildcard-Function.html), which would lead to the following Makefile: ``` DIR_INC=include DIR_LIB=lib DIR_OBJ=obj SOURCES := $(wildcard *.c) OBJECTS := $(patsubst %.c,$(DIR_OBJ)/%.o,$(SOURCES)) all: $(OBJECTS) $(DIR_OBJ)/%.o: $(DIR_LIB)/%.c $(DIR_INC)/%.h gcc -c -o $@ $< ``` I hope that clears things up for you.