Make: $(wildcard) holding a directory open - makefile

So there seems to be this problem with GNU Make's $(wildcard) function keeping a directory open on Windows. See (unasnwered) post "make is holding a directory open". Google does not provide much information on the topic.
In short: the Makefile uses the $(wildcard) function at some point, and keeps a directory open, which typically prevents the "make clean" rule to do its work correctly. Re-running "make clean" a second time usually solves it.
I'm using GNU Make version 3.81 under a standard DOS-Box. The author of the post linked to above is using Cygwin.
Has anyone found a fix for this?

Sounds like a file descriptor leak, all right -- harmless for very-short-lived processes (like make) on UNIX, but a right PITA on Windows.
As this is allegedly a bug in make, as opposed to a problem with its usage, it should be addressed first by validating that it still exists when built from source on the newest upstream version, and then by filing a bug report with the GNU make project (or with any distributor with whom you have an appropriate support contract), or diving into the source and attempting to fix it yourself.
It wouldn't hurt to try to reproduce on Linux -- checking for file descriptor leaks are much easier here, as one can just look at /proc/self/fd (or, for a child of make, /proc/$PPID/fd) for things that don't belong.

I did find a workaround for the problem, which at least lets me work in peace.
The problem was that the $(wildcard) function was used to collect the sources files. My clean rule, however, only deletes a directory - no need for the collecting to take please. So I basically put the part of the Makefile that needs to collect the sources files in a conditional statement:
# The clean rule is always parsed
clean:
rm -rf $(OUTPUT_DIRECTORY)
# The compile rule is only interpreted if we did not invoke 'make clean'. We
# can test the value of $(MAKECMDGOALS) for that:
ifeq ($(filter $(MAKECMDGOALS),clean),)
SOURCE_FILES := $(wildcard ...)
compile:
g++ $(SOURCE_FILES) ...
endif

Related

CMake: Generate Unix Makefiles which ignore errors

In Unix Makefile I can prefix a recipe line with - to ignore any error that will occur (as describe in Errors in Recipes).
hello_world: hello_world.cxx
-$(CXX) $(CXXFLAGS) $^ -o $#
I converted my Makefile to CMake:
cmake_minimum_required(VERSION 3.0)
project(HelloWorld)
add_executable(hello_world hello_world.cxx)
and run cmake and the generated Makefile looking fine, except the missing -.
Is it possible to generate Unix Makefile with CMake that will ignore errors (prefix the recipe line with -)?
The best would be to specify it per target level. I know I can run make -i to have the same behaviour but it isn't that convenient.
You cannot.
make is designed to give the user a fine control over commands it runs. CMake's under-the-hood commands are supposed to always succeed.
As a hack, you can generate makefiles and run make --ignore-errors.
But I advice making each of your examples that would fail a separate project, and run them from an external script.

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...)

Generate make file

I have a golang CLI program which generates a makefile to a specific project. While this works, there is an issue when the project already has a makefile. Of course I can check that in advance to avoid collusion, but how is it suggested to do it?
I'm not an expert in makefiles, but how can I create second makefile (maybe with the project name or something) that user can run via make (I guess with additional steps or info to the terminal)
You can generate it as Makefile.project and document to be run as make -f Makefile.project
You can give your Makefile whatever filename. Then make must be executed with parameter -f <your_filename> or --file=<your_filename>. See make manual on filenames.
Which version of make are you using? Some versions run special makefiles before others. For example, GNU make looks for the following files and runs the first one it finds: GNUmakefile, Makefile, makefile.
If you are using GNU make, then name your generated file GNUmakefile and add in the making any makefile already in the directory. That way, anyone running make in the directory will automatically run the generated makefike first.

Conditional linking in Makefile

In my Makefile, I want to link to a library only if it is installed on the machine. So, for example if the library is hwloc, I want to do the following:
xfoo : foo.o
if (hwloc installed)
gcc foo.o -o $# -lhwloc
else
gcc foo.o -o $#
Is there anyway to do something like this? i.e. Is it possible to check if a specific library is installed and use that as a condition in a Makefile?
Here's the wrong answer:
xfoo : foo.o
if (hwloc installed); then gcc foo.o -o $# -lhwloc; else gcc foo.o -o $#; fi
Commands executed from a Makefile do not have to be just simple, single commands. Anything that a shell can execute, can be invoked from a Makefile. Including an entire script, sandwiched into one line.
Here's the right answer:
However, the above approach is the wrong one. You will find that many free software packages do this kind of thing all the time: conditionally link in a library, if it's available.
But the way that it's done is by running a separate configure script, before running make. Go grab the source tarball to a random free software package, of your choosing, and read the installation instructions. They will all tell you to run the configure script first, before running make.
A crushing majority of free software packages use the GNU toolchain to create their build system -- the configure script, and the Makefile. The GNU toolchain consists of autoconf and automake tools (also libtool in many cases). Go Google these, for more information.
There are also a few other, less popular toolchains, but the GNU toolchain is the most frequently one used, for this sort of a thing. So, to do something along the lines of what you're trying to do, the way this gets typically done is:
In the configure.ac file:
AC_CHECK_LIB(hwloc,some_function_in_the_hwloc_library,[LINK_HWLOC=-lhwloc])
AC_SUBST(LINK_HWLOC)
In the Makefile.am file:
hwloc_LDADD=#LINK_HWLOC#
That's it. That's the way this is done the countless number of times most free software packages need to do this exact same thing. autoconf and automake will take care of writing the shell script and the makefile, that implements this.
I don't have access to a Linux machine at the moment so pardon me my answer will be untested.
I will respectfully disagree with both of my predecessors.
First, using autotools to amend an existing Makefile is a bad idea. Autotools are made to avoid worrying about creating a good Makefile in a simple use case. It's as if OP asked "How to change + to - in my Python script" and the answer was "write a shell script to modify the script, save it in temporary file and execute the file"
Second answer, why do something manually when it can be painlessly done automatically?
So, IMHO the correct answer is, this is the exact use case for $(wildcard):
xfoo: foo.o $(wildcard libhwloc.a)
gcc $(patsubst lib%.a, -l%, $^) -o $#
Note: the library is installed or not ahead of time but not to be made during the build.
If you don't want to get involved with the autotools/etc. for this (which while a reasonable solution is also reasonable to want to avoid for something this simple) and you don't want to have to play guessing games about where people may or may not have this hwloc library installed then the best you can do is to let people turn the feature on manually.
Use three (or four) make variables. USE_HWLOC, HWLOC_LDLIBS, HWLOC_CFLAGS and possibly HWLOC_LDFLAGS.
Then when USE_HWLOC is defined you link against the library and use the other three variables in case they have also been set.
ifdef USE_HWLOC
HWLOC:=-lhwloc
else
HWLOC:=
HWLOC_LDLIBS:=
HWLOC_LDFLAGS:=
HWLOC_CFLAGS:=
endif
xfoo : foo.o
gcc foo.o -o $# $(HWLOC_LDLIBS) $(HWLOC)

Getting GNU Make and NMake to use different makefiles by default

I want a project to be buildable with both GNU Make (on Linux) and NMake (on Windows). Obviously, I can have the makefiles called Makefile and Nmakefile and build by using make and nmake /F Nmakefile respectively. Is there a pair of names such that make and nmake without -f//F options work?
According to documentation, NMake looks for .mak files, so I've tried to use Makefile.mk and Nmakefile.mak, but it didn't work.
According to the man page of GNU make, it will first look for a file called GNUmakefile.
from man make:
Normally you should call your makefile
either makefile or Makefile. (We
recommend Makefile because it appears
prominently near the beginning of a
directory listing, right near other
important files such as README.) The
first name checked, GNUmakefile, is
not recommended for most makefiles.
You should use this name if you have a
makefile that is specific to GNU
make, and will not be understood by
other versions of make. If makefile
is `-', the standard input is read.
so call your gnu Makefile GNUmakefile

Resources