Calling CMake Makefile with another Makefile - makefile

I am attempting to call the auto-generated CMake makefile from outside of the CMake directory using make.
In order to accomplish this, I have made another makefile in the parent directory of my project. This file should cd into the CMake directory and call the makefile contained in there.
Unfortunately, I am having issues with the external makefile. The contents are as follows:
clean:
cd cmake-build-debug && $(MAKE) clean
I have a tab following the final line, but am still getting a separation error.

From the make man-page:
-C dir, --directory=dir
Change to directory dir before reading the makefiles or doing
anything else. If multiple -C options are specified,
each is interpreted relative to the previous one:
-C / -C etc is equivalent to -C /etc. This is typically
used with recursive invocations of make.
So, your clean rule can be:
clean:
$(MAKE) -C cmake-build-debug clean

Related

ocamlbuild: Nothing to be done for `all'

I'm using ocamlbuild in makefile to build my code and want to recompile when there is any code change. But make returns with error message: make: Nothing to be done for `all'.
My makefile code:
all: test1 test2
test1:
ocamlbuild $(INCLUDES) $(FLAGS) $(TEST1_BYTE)
mv $(TEST1_BYTE) test1.out
test2:
ocamlbuild $(INCLUDES) $(FLAGS) $(TEST2_BYTE)
mv $(TEST2_BYTE) test2.out
clean:
rm -f test1.out test2.out
rm -rf _build
I expect make will do the recompilation instead of make clean; make. It only works with make clean; make now.
Make your targets phony then the make utility will always rebuild them. And ocamlbuild will track the dependencies with all the knowledge of the OCaml infrastructure, and will never rebuild anything unnecessary. Here's how to declare your targets phony, add this to your Makefile
.PHONY: test1 test2
Also, it looks like that you're still learning both make and ocamlbuild utilities, and given that you're going to invest your time in learning the tools it is better to focus on something that is not that legacy. While getting accustomed to make could be considered as useful, the ocamlbuild tool is more or less deprecated with the newer, dune and much better documented. It is very easy, just create a new file named dune and put the following contents there,
(executable
(name test1))
(executable
(name test2))
Now you can build your targets with dune build test1.exe. You can still create a Makefile as a courtesy to those who don't know how to invoke dune. And as usual, don't forget to make your targets phony in the makefile.
This Makefile specifically says that test1 and test2 depend on nothing. As long as they both exist, make will say there's nothing to do.
I don't know anything about ocamlbuild, but I suspect you should be using it by itself rather than combining it with make, which is a separate (very flexible, but very old) build system.
For what it's worth, it seems to me that many current OCaml developers are switching to dune for a build system.

What is the reason for fatal error: *** No rule to make target 'install'. Stop

The error occurs when I tried to run the command make install under Ubuntu 16.04 that
*** No rule to make target 'install'. Stop.
I have already run make command with several errors fatal: bad revision 'HEAD', which didn't lead to halting the command. I have no idea whether these errors matter.
My makefile is:
SUBDIRS := $(wildcard */.)
all: $(SUBDIRS)
$(SUBDIRS):
make -C $#
install:
for dir in $(SUBDIRS); do \
make -C $$dir install; \
done
.PHONY: all $(SUBDIRS)
Specifically, I want to know how the makefile works after install:.
The project should install an APP on the connected phone Nexus 5. But actually, there's no such APP on my phone.
I suppose your Makefile is properly formatted, with tabs where they should be, etc.
Then, when you run make install in the top level directory, your Makefile does have a rule to make the target install: it says to loop on your subdirectories, enter each one of them, and run make install there (this is what the -C option does). One of those sub-makes fails, most probably because, in its respective subdirectory, it doesn’t find a Makefile with an install recipe in it. When the sub-make fails, the loop goes on with the remaining sub-makes (unless the shell was instructed otherwise by means of the -e switch), and the final return code of the whole recipe will be the return code of the last sub-make.
There are some points worth discussing in your Makefile (for example, install should be listed as a .PHONY target), but you don’t provide enough information to clarify them: for example, is it really necessary to have the shell loop through the subdirectories in a particular order? Usually, a better policy is to have make parallelize the sub-makes whenever possible (and, as a side effect, have make stop when the first submake fails...)

Stop GNU make from compiling by default

I just want to use GNU make to compress some files.
So I wrote the Makefile as follows:
lib.tar.lzma: $(shell find ~/lib -name "*")
rm -f lib.tar.lzma
tar -cavf lib.tar.lzma -C ~/ lib/
However, after I run make, it automatically compile the c++ source code in that directory.
How can I stop it from compiling them? I just want to compress them.
Update:
I got the following error:
<builtin>: recipe for target '/home/xxx/lib/app' failed
It seems a built-in recipe.
(We don't know your entire Makefile and your full file tree, so this is only a guess; I assume that you have shown us a fragment of your much bigger Makefile)
However, after I run make, it automatically compile the c++ source code in that directory.
This is probably happening because your $(shell find ~/lib -name "*") is expanded to something containing your object files. Since they are in your dependencies their source file is recompiled if it is newer. BTW you might want to use instead $(shell cd .. ; find lib -name "*") or if lib has no subdirectory even $(wildcard ../lib/*)
You probably don't need any dependency for that lib.tar.lzma target, so just have:
lib.tar.lzma:
rm -f lib.tar.lzma
tar -cavf lib.tar.lzma -C ~/ lib/
BTW, that -C ~/ perhaps should be -C $$HOME since make use /bin/sh to run commands, and that POSIX shell don't know about ~ ; perhaps a -C .. might be better ...
Perhaps you might write some shell script make-backup.sh to do a more clever tar and you would then code
lib.tar.lzma: make-backup.sh
./make-backup.sh $#
However, perhaps you do have dependencies (e.g. if you need to archive some generated files). Then you need to list them explicitly and wisely (you certainly don't want to depend on all the files; perhaps only the source ones). Also, you might not need to archive any object files *.o, if you have some (but YMMV).
I recommend using make --trace or remake -x to debug your Makefile.
BTW, having a Makefile only for a backup is useless; write a shell script instead.
I also strongly recommend using some version control system (like git) if you don't use any. Notice that git has an archive subcommand which might be a more clever backup.

Specifying path to "makefile" using "make" command

I would like to run a makefile from another place in the file system. How do I pass the location of the makefile to make?
if I stand in "/" and I would like to run a makefile that resists in "/dir/dir2/dir3/makefile", how do I add that to the make command?
I tried:
make --file=dir/dir2/dir3/makefile
but it did not worked.
All relative paths in the makefile will be relative to your current directory and not the directory of the makefile.
Assuming that you understand that and what you want to do is still going to work then you want the -f flag to specify the makefile to use. (Which is in the man page, the manual and the --help output.)
If, instead, what you mean is you want to cd to somewhere else and run make then perhaps you are looking for (cd /some/path && make)?
You can use the -C flag to specify the path to your makefile. This way you can execute it from a different directory.
The -f flag has a different use. With that flag you can execute a makefile with a name other than makefile.

Command line arguments to make for working in Linux and Windows

I have gone through the link
Passing additional variables from command line to make.
I have a project which compiles both on Linux and Windows using makefiles. In Windows it uses gcc while in Linux it uses the ARM version of gcc ie armv7-linux-gcc.
I would like to use a command line variable which tells the makefile which compiler to use depending on Windows or Linux.
For example in Windows it should have something like this:
CC= gcc
CFLAGS= -c -D COMPILE_FOR_WINDOWS
and for Linux:
CC = armv7-linux-gcc
CFLAGS = -c -D COMPILE_FOR_LINUX
These preprocessor defines COMPILE_FOR_WINDOWS and COMPILE_FOR_LINUX are present in the code base and can't be changed.
Also for make clean it should clean up both for Windows and Linux. I can't assume that I people who build this will have Cygwin installed so can't use rm for deleting files.
This answer is only valid if you're using GNU make or similar:
Conditionally set your make variables using an Environment Variable.
For the 'clean' rule to function properly, you may also have to create a make variable for any differences in file extensions for either OS.
Naive example:
ifeq ($(OS), Windows_NT)
CC=gcc
RM=del
EXE=.exe
CFLAGS=-c -DCOMPILE_FOR_WINDOWS
else
CC=armv7-linux-gcc
RM=rm
EXE=
CFLAGS=-c -DCOMPILE_FOR_LINUX
endif
PROG=thing$(EXE)
.PHONY: all
all: $(PROG)
$(CC) $(CFLAGS) -o $(PROG) main.c
.PHONY: clean
clean:
-$(RM) $(PROG) *.o
Maybe you could use ant (with a build.xml file) to build the project.
Else, in a Makefile, you would need to check the system and put some conditions to check wether you are making the project in an Unix environment or a Windows environment.

Resources