Construct a target from results of another target - makefile

I want to write a Makefile that needs to do 2 things:
build files using a tool. The known part of the files is an extension. For example pkg
upload the built files (one by one) using an uploader
wildcard doesn't work for me, because there are no files. I tried .SECONDEXPANSION, but also unhappy.
What I tried:
build:
do some work to produce *.pkg files
uploading: build $(addprefix upload-, $(wildcard *.pkg))
upload-%: $*
run a tool to upload one file

If the build step produces *.pkg files but you do not know which ones you can invoke make twice. One time to build and a second time to discover the built *.pkg files and upload them. And you can use conditionals to distinguish the 2 make runs:
.PHONY: uploading build
.DEFAULT_GOAL := uploading
ifeq ($(STEP),)
build:
do some work to produce *.pkg files
uploading: build
$(MAKE) STEP=2
else
PKGS := $(wildcard *.pkg)
UPKGS := $(addprefix upload-,$(PKGS))
.PHONY: $(UPKGS)
uploading: $(UPKGS)
upload-%:
run a tool to upload one file ($*)
endif
Note: you cannot use $* in the list of prerequisites as you show in your example. But it is not needed here.

Related

Makefile for building and outputting in a bunch of different folders

I have a directory that contains a bunch of folders, all of which contain a .go file that I will want to build, and I'm trying to create a Makefile that can accomplish this. These are the requirements I'm looking to fill:
1.) I want this to be dynamic so that the number of folders can grow and change, and I won't need to update the Makefile every time.
2.) I also want the .go files to be able to have different names than the folder that holds them (for example, if the folder is lambda1 then the .go file shouldn't need to be named lambda1.go).
3.) Lastly, I want each binary to be output in the same folder that its source file is in.
This is what the folder structure looks like with the built binaries included:
lambdas
lambda1
--first.go
--first (binary)
lambda2
--second.go
-- second (binary)
lamba3
--third.go
--third (binary)
...
This is what the actual build commands look like:
GOOS=linux go build -o lambdas/lambda1/first lambdas/lambda1/first.go
GOOS=linux go build -o lambdas/lambda2/second lambdas/lambda2/second.go
and then in a later step I need to zip that binary like this:
zip lambdas/lambda1/function.zip lambdas/lambda1/first
zip lambdas/lambda2/function.zip lambdas/lambda2/second
It seems like what I need is to loop through the lambdas directory, and for each directory, get the name of the .go file, and then using those dir paths and file names, I could create each build command.
I'm brand new to Makefiles and have been trying to figure this out for about a day now and am not having luck. Thank you for any help.
What about something like this:
# Find all the .go files under lambdas
GOFILES := $(shell find lambdas -name \*.go)
GOPROGS := $(GOFILES:%.go=%)
GOZIPS := $(GOPROGS:%=%.zip)
# We want to build all the progs and zips
all: $(GOPROGS) $(GOZIPS)
# How to build each prog from a .go file
$(GOPROGS): % : %.go
GOOS=linux go build -o $# $<
# How to build each zip from a prog file
$(GOZIPS) : %.zip : %
zip $# $<
I'm using static pattern rules here but you could use normal pattern rules as well.
Oh I didn't notice you want the zip files to have the same name. This of course assumes that there will be only one .go file, and hence one program, in every directory? Seems limited.
This is not so simple because the names don't match. Although it could be done via separate rules if you really wanted to, the simplest thing to do is just put both the compile and zip into the same rule:
# Find all the .go files under lambdas
GOFILES := $(shell find lambdas -name \*.go)
GOPROGS := $(GOFILES:%.go=%)
# We want to build all the progs
all: $(GOPROGS)
# How to build each prog from a .go file
$(GOPROGS): % : %.go
GOOS=linux go build -o $# $<
zip $(#D)/function.zip $#

makefile ignore removed file names

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

Building an out-of-tree linux kernel module with separate output directory

I want to build an out of tree kernel module with the output directory being separate from my source directory? How would I do this? I'm willing to go any route. I'm okay with minimal changes to the kernel build system, I'm okay with copying source files (however I do not want to rebuild if I haven't made any changes to the source files and this doesn't work if I copy source files normally), and I'm okay with setting a parameter or something.
many many people face this problem, including me.
To support build external module at separate output directory.
I modify the kbuild:
firstly, modify src variable at scripts/Makefile.build and scripts/Makefile.clean
-src := $(obj)
+src := $(if $(KBUILD_EXTMOD_SRC),$(KBUILD_EXTMOD_SRC)$(patsubst $(KBUILD_EXTMOD)%,%,$(obj)),$(obj))
secondly, modify scripts/Makefile.modpost
-src := $(obj)
+src := $(if $(KBUILD_EXTMOD_SRC),$(KBUILD_EXTMOD_SRC),$(obj))
# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
-include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \
- $(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile)
+include $(if $(wildcard $(src)/Kbuild), \
+ $(src)/Kbuild, $(src)/Makefile)
then build external module like this:
make -c $(kernel_src) M=$(extmod_outpu_dir) KBUILD_EXTMOD_SRC=$(extmod_src_dir) modules

Different set of files and flags for different builds

Using GNU make for a project in Linux. I'd like to have a test and a prod build, and trying to implement it with conditional directives. Test build has different source files and flags etc. from the prod build.
First I found that if block only works when it's following a target.
# More variable definition skipped.
SRCS := some source files
CXXFLAGS := some complile flags
test: ${myBinary}
ifeq (${BUILD}, UNIT)
#echo BUILD == ${BUILD}
SRCS += ${TEST_SRCS}
CXXFLAGS += some test flags
endif
I use this way so that later I can use a pattern to build .o files, instead of listing all source files for 2 different builds. Basically I try to find a way to use patterns to build .o files, yet still have different files, flags, etc. for test/prod builds.
${BUILD_DIR}/%.o : %.cpp
${CXX} -c ${CXXFLAGS} ${INCS} $< -o $#
But after I put it next to a target, still got this error:
make: SRCS: Command not found
make: *** [test] Error 127
How to fix it to meet my goal?
Other advice on organizing the makefile to meet the goal is most welcomed too.
Edit:
The 2 executables produced can have different names but can be in same location.
I wanna put object files are in ${BUILD_DIR} to separate them from source files.
"Command not found" error is gone after unindenting SRCS line.

How to get makefile to depend on any files inside a folder

I have a simple makefile that I use to build some latex files. The syntax looks like this:
pdf: thesis.tex chapters/a.tex chapters/b.tex chapters/c.tex
latexmk -pdf -pdflatex="pdflatex thesis.tex
open:
open thesis.pdf
The files inside chapters folder can increase further with d.tex, e.tex and may even contain subfolders f\section1.tex, f\section2.tex etc.
I manually add all the requried tex files inside my thesis.tex like this which is not a problem.
\input{chapters/a.tex}
\input{chapters/b.tex}
\input{chapters/c.tex}
\input{chapters/d.tex}
\input{chapters/e.tex}
How can I get make target pdf to depend upon any file changes inside chapters and its subdirectories?
How do I write inter task dependency in makefile. If target open depends upon target pdf, how do I write it?
open: pdf will sort-of do what you want for your second question.
Though it would be better to not use the phony pdf target for this.
Instead have a thesis.pdf: target which depends on the right prerequisites and have both pdf: thesis.pdf and open: thesis.pdf targets.
For the first question you can either use something like:
SRCS := $(shell find chapters -name '*.tex')
or use from here:
rwildcard=$(strip $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)))
SRCS := $(call rwildcard,chapters,*.tex)
and then:
thesis.pdf: thesis.tex $(SRCS)
to use that variable as the prereq.
If you wanted to get even fancier you could write a script to pull out the actual filenames from the \input{} directives in thesis.tex and use that as your SRCS variable (but that's probably not worth the effort unless you know you will have other, unrelated, .tex files).

Resources