I have a simple makefile which takes care of building my website by moving assets from ~/static_source to ~/static. However, when I add my Javascript folder to the makefile, my HTML and CSS stop compiling! When I comment out the JS block, my HTML and CSS compiles again.
Bad Version
LESS = $(wildcard static_source/styles/*.less)
CSS = $(patsubst static_source/%.less,static/%.css,$(LESS))
static/styles/%.css: static_source/styles/%.less static_source/styles/base.less static_source/styles/header.less
lessc $< $#
HTML = $(patsubst static_source/%,static/%,$(wildcard static_source/*.html))
static/%.html: static_source/%.html
ln -s ../$< $#
#This stops CSS and HTML from running. Perhaps it's because static/scripts is a folder?
JS = static/scripts
static/scripts: static_source/scripts
ln -s ../$< $#
all: $(CSS) $(HTML)
Good Version:
LESS = $(wildcard static_source/styles/*.less)
CSS = $(patsubst static_source/%.less,static/%.css,$(LESS))
static/styles/%.css: static_source/styles/%.less static_source/styles/base.less static_source/styles/header.less
lessc $< $#
HTML = $(patsubst static_source/%,static/%,$(wildcard static_source/*.html))
static/%.html: static_source/%.html
ln -s ../$< $#
#This stops CSS and HTML from running. Perhaps it's because static/scripts is a folder?
JS = static/scripts
#static/scripts: static_source/scripts
# ln -s ../$< $#
all: $(CSS) $(HTML)
I do not know why the scripts folder is being created with the "bad" version (nothing depends on it), or why the static/scripts rule prevents HTML and CSS from being created.
The only output from the bad version, as of the second running, is "make: 'static/scripts' is up to date." The output from the good version, as of the second running, is "make: Nothing to be done for 'all'."
Ah, How does "make" app know default target to build if no target is specified? applies - it seems make uses the first "plain" rule as the default. So, since in this case static/scripts is before all, the fix is to explicitly set all to be the default rule. Prepend:
.DEFAULT_GOAL := all
Related
I'm struggling with the correct syntax of a makefile.
This is my folder structure:
project
│ Makefile
│ HERE SHOULD BE THE OUT FILE AFTER make command
│
└───include
│ header.h
│
│
└───src
function1.c
function2.c
How must the makefile look to ensure correct results?
This is my current makefile:
SOURCES = src/function.c src/function.c src/function.c
OBJECTS = $(SOURCES:.c=.o)
CC = cc
RM = rm -f
CFLAGS = -Wall -Wextra -Werror
NAME = output.a
all: $(NAME)
$(NAME):
$(CC) $(CFLAGS) -c $(SOURCES)
ar rcs $(NAME) $(OBJECTS)
clean:
$(RM) $(OBJECTS)
fclean: clean
$(RM) $(NAME)
re: fclean $(NAME)
my current output if i run make all:
cc -Wall -Wextra -Werror -c src/function1.c src/function2.c
ar rcs output.a src/function1.o src/function2.o src/function1.o
ar: src/function1.o: No such file or directory
make: *** [Makefile:15: output.a] Error 1
if i run make flcean the output looks the following:
rm -f src/function1.o src/function2.o
rm -f output.a
So it doesn´t remove anything because the .o files are stored in the root, not the /src subdirectory
I'm struggling with the correct syntax of a makefile.
Your makefile syntax is fine. In fact, your makefile is syntactically valid and reasonably well structured. It looks a lot better than many of the ones we see around here.
I guess what you're actually struggling with is that it doesn't work, even after you fix the weird disagreement between the source file list in the makefile itself and the actual source files on disk. But "doesn't work" is a pretty vague, though lamentably common, description. You would get better help, faster, by saying something along the lines of "the .o files are created in the top-level directory instead of in the src/ directory." (Which is exactly what I expect to happen, and as a result, the ar command will fail, and the clean target will not clean the .o files.)
You need to understand that make itself doesn't know much about building software. What it knows is how to match rules to patterns so as to execute associated recipes of shell commands. The particular kinds of patterns it matches and the built-in rules that come with it are oriented toward building software, but you can't expect it to go very far with anticipating what you mean. It, like any other computer program, will happily do what you say, instead, when that differs. In this case, it just runs the cc command with the arguments you specify, and cc will choose under those circumstances to put the .o files in the working directory.
From a stylistic and best-practices standpoint, it's best to write rules that build only their target file, unlike your rule for $(NAME) that attempts to build not just $(NAME) but also all the component object files. The object files would be better built according to their own rule or rules. Making the object files prerequisites of the rule for $(NAME) will ensure that they get built when needed. That will also allow for them to not be built when that is not needed. That variation on your rule would look like this:
$(NAME): $(OBJECTS)
ar rcs $# $^
Note also that in the recipe, I have substituted automatic variable $# for a repetition of the rule target name. That's good form, but not obligatory. I have also substituted automatic variable $^ for a repetition of the prerequisite list. That's less clear-cut, in part because $^ is specific to GNU make, but if you're ok with that dependency then it's a great way to avoid repeating yourself.
Now, about building the object files: you could write a pattern rule (GNU make only) or a suffix rule that builds an object file from a corresponding C source file, or you could even write a separate rule for each object file. But you don't actually need to do that. make comes with a built in rule that will serve your needs in that area just fine, so your best bet may be to not attempt to provide your own rule for that at all. That is: modifying the rule for $(NAME) as suggested above should be sufficient for successful building, supposing, again, that the contents of your SOURCES variable accurately reflect the source files you want to build.
I'm trying to write a Makefile with a rule to make the project with another main.cpp file, because I'm testing my code with different options
I have different versions of the main function, that I put inside differents files : main.cpp, main_1.cpp, main_2.cpp, ..., to test different versions of my code, and they all have the same dependencies
first I was just commenting and un-commenting the Makefile variable MAIN that define the main.cpp file, but I was hoping there is a way to choose the one I want to try with a specific rule ?
I tried something with target-specific variables but it didn't work :
# # # # # # #
# VARIABLES #
# # # # # # #
NAME = my_program
VPATH = srcs
CXX = c++
CXXFLAGS = -I ./headers
OBJS = $(SRCS:%.cpp=%.o)
MAIN = main.cpp
#MAIN = main_1.cpp
SRCS = $(MAIN) file.cpp
# # # # #
# RULES #
# # # # #
all: $(NAME)
# target-specific variables
test-1: MAIN = main_1.cpp
test-1: re
$(NAME) : $(OBJS)
$(CXX) $(OBJS) -o $(NAME)
clean:
rm -f $(OBJS)
fclean: clean
rm -f $(NAME)
re: fclean all
.PHONY : all clean fclean re
the error output for main test_1 is :
c++ -I ./headers -c -o main.o srcs/main.cpp
c++ -I ./headers -c -o file.o srcs/file.cpp
c++ main_1.o Webserv.o -o my_program
c++: error: main_1.o: No such file or directory
Makefile:21: recipe for target 'my_program' failed
make: *** [my_program] Error 1
I think, then, that target-specific is not the right tool for what I'm trying to do.
Does Make provide a way to accomplish that (modifying the list of srcs files when calling a specific rule, and having the compilation working great with the new srcs files) ?
I'm vaguely thinking something like this.
test-%: main_%.cpp file.cpp
Now, make test-1 will produce an executable with that name from main_1.cpp instead of main.cpp, and similarly test-2 from main_2.cpp, etc.
If you have subsequent targets which hardcode my_program which should actually depend on which version you made, this might not be suitable, or at a minimum, you'd have to refactor those to use the current output executable. Similarly, you might want to add test-[1-9] to the files to remove in the clean target (or perhaps add a realclean target to remove them too).
Tangentially, several of your make variables don't seem to serve any immediate purpose. Putting stuff in variables makes sense for things you want to be able to override at compile time, or vaguely for making a general-purpose Makefile which can be applied with only minor modifications across several projects; but in isolation, these seem like unnecessary complexities you should probably avoid for the time being.
Your immediate problem could perhaps be solved by refactoring the dependency chain, but on the whole, I'd recommend keeping it as simple as possible. make already knows how to compile common source formats; all you really need to put in the Makefile are the dependencies which are not trivially obvious and any .PHONY targets, and overrides to select e.g. a specific default action.
A directory with css files in it and for each file in the directory I want a separate minified .min.css file in the same directory.
So for example my.css get minified into my.min.css in the same directory.
First I tried
css/*.css:
uglifycss $# > $(subst .css,.min.css,$#)
make -B yeaaa victorie its working :D
But after doing make -B again I get a new separate file each time resulting in my.min.css my.min.min.css my.min.min.min.css
Then I tried
.PHONY: clean
css/*.css: clean
uglifycss $# > $(subst .css,.min.css,$#)
clean:
-rm css/*.min.css
DOH! after clean it is still remembering the files it deleted in the first place resulting again in a my.min.min.min.css file
How can I tell make to stop doing my.min.min.min.css?
(make: GNU Make 3.81 OSX)
First get a list of all files with the suffix .css:
ALL := $(wildcard *.css)
then remove files that have the suffix .me.css:
NEW := $(filter-out %.me.css,$(ALL))
and add the suffix to remaining files:
ME := $(patsubst %.css,%.me.css,$(NEW))
Then you add those files as prerequisites to the default target, and add you own recipe that builds those files, in this case a simple echo:
%.me.css:
echo 123 > $#
default: $(ME)
Compared to your approach, this has the benefit that you don't have to use the flag -B, as only the files that need to be built are built. Therefore invoking make is done by simply caling make without any targets or flags (assuming the makefile is named makefile or Makefile):
make
I have a program that some of its sources are generated. the relevant part of the makefile is something like this:
OUTPUT_FILE = libEngine.so
CONF_FILES = foo.tgp bar.tgp
GENERATED = Engine.cfg
SRCS = main.cpp foo.cpp bar.cpp
OBJ_FILES = $(SRCS:%.cpp=$(OBJDIR)/%.o)
all: $(OUTPUT_FILE)
$(OUTPUT_FILE): $(GENERATED) $(OBJ_FILES)
<link command>
$(GENERATED): $(CONF_FILES)
generate -p Engine $(CONF_FILES)
$(OBJDIR)/%.o:%.cpp
<compile command>
'generate' command creates Engine.cfg (a text file), foo.cpp and bar.cpp
When I run it, on some platforms, sometimes, gmake stops after generating and compiling the non-generated, saying that it has no rule for creating the objects from the generated sources.
I think I know what the problem is - gmake evaluated the dependencies before the files were created. However, I don't see how to write it correctly. And I also don't understand why it only fails sometimes.
Edit example code is more complete now. (the original has much more files and options, of course)
Found the problem, and it was related to VPATH. The cpp files are not generated in the current directory, but in another one, somewhere in an included makefile it is defined. I guess VPATH locations don't work if the file doesn't exists.
I fixed it this way:
all: $(GENERATED) $(OBJ_FILES)
$(MAKE) $(OUTPUT_FILE)
$(OUTPUT_FILE): $(GENERATED) $(OBJ_FILES)
<link command>
And so far so good.
I am trying to do this:
From a directory, pick all the C (.c) files, generate .o and add it to
my final target executable. The C files can be added or removed at anytime, so when I
run make for my target, the available C files from the directory has to be picked
to compile and link with my target.
So far, I have the following:
define test_tgt =
DIR = full/path/to/dir
FILES = $(wildcard $(DIR)/*.c)
OBJS = <rule-to-convert-C-to-O>
endef
get_new_files:
$(eval $(test_tgt))
final-target: get_new_files
$(CC) <other-objs> $(OBJS)
Somehow this doesn't seem to work. I see a lot of similar examples, but not sure what
is wrong here. If this approach is not correct, can anyone suggest a better way to
accomplish this.
TIA.
You are trying to program a check that make does by itself.
Just list $(OBJS) as dependencies of final-target.
Something like this should work under GNU make:
DIR = full/path/to/dir
FILES = $(wildcard $(DIR)/*.c)
OBJS = $(subst .c,.o,$(FILES))
final-target: $(OBJS)
$(LD) -o $# $+ # or similar
Full documentation is here: https://www.gnu.org/software/make/manual/html_node/Text-Functions.html