How to make install using path with space and dot - macos

I want to make install(sudo make install) using path with space and dot. (e.g. /Applications/Sample App.app/Contents/Resources)
However, following error invoked.
ginstall: target 'App.app/Contents/Resources/lib/libserialport.a' is not a directory
If I use the path with only space, sudo make install really works well with \ escape character.

Makefiles and pathnames which contain spaces do not mix well. Make uses whitespace to split strings into lists. For example, of you write this:
SOURCES = foo.c bar.c baz.c
OBJECTS = $(patsubst %.c,%.o, $(SOURCES))
program: $(OBJECTS)
Then make will treat the variables SOURCES and OBJECTS as lists of strings, split on whitespace characters, and program will depend on the three items foo.o, bar.o, baz.o.
Make does not know at all that some strings should not be split this way (because they refer to pathnames). Like many early scripting languages, it is completely based on string interpolation. This is true for the shell script fragments used to write the build steps as well.
There are some workarounds possible, but they all depend on how variables are used within the makefile. Recursive makefiles can pose additional problems if the contents of these variables are passed down explicitly to the invoked make command using the shell.
In some cases, the fix is rather simple, so if there is an install rule like this:
install: program
$(INSTALL) -m 755 program $(DESTDIR)$(bindir)/program
It may be sufficient to add quotes, like this:
install: program
$(INSTALL) -m 755 program "$(DESTDIR)$(bindir)/program"
But this really depends on the makefile in question.
If the project uses automake (like libserialport), the simplest solution is to use the DESTDIR support in the generated makefile to install the whole thing to a path which does not contain spaces, and then move it to the final destination afterwards. This assumes that the project does not internally embed the final installation path, though.

Related

Finding dependencies by grep in Make

I'm working on a rather large project in pure C, and for various reasons we are not using CMake.
We have a good system which uses various shell commands to require very little maintanence. It will automatically find new headers and C files and add the headers to the dependencies and will compile the C files and include them in the output. However, we've gotten to the point where any changes we make to the header files becomes a problem because it requires a recompilation of the entire project, rather than just the C files that include it directly or indirectly.
I've worked on a system to ensure that the only header files which are added as dependencies are ones which are required by the C file itself (recursively up the tree).
I had thought I would be able to solve this myself, but it seems that make has rather inconsistent rules for expansion of variables.
The solution I came up with was to try to use ag and get all the includes out of the file. This works as intended, and I pipe it into tr so that I can ensure that no newlines are added, thereby messing up make. The issue that I'm having though is in determining which file to search in. This is the recipe that it's using for the section in question:
$(GAMEOBJDIR)/%.o : $(GAMEDIR)/%.c $(shell ag -o '(?<=(^#include "))(.*?)(?=("$$))' $(GAMEDIR)/%.c | tr '\n' ' ')
$(CC) $(CFLAGS) $(if $(RELEASE),$(RELFLAGS),$(DBFLAGS)) -c -o $# $<
The problem is that $(GAMEDIR)/%.c is expanding to src/game/%.c and not src/game/<filename>.c. I'm unsure how to fix this issue based on the expansion rules of make.
Once I can figure this out I'll be able to make sure this walks up the chain of header files too, but until I can get this figured out I have no reason to work on that.
Make's rules for expansion are completely consistent... but sometimes they aren't what people want. That's not the same thing :)
Rules for expansion are explained in the manual. In your case you're working with a prerequisite list which means the variables are expanded as the makefile is parsed. That includes the shell command and all other variables. Because you are working with a pattern rule, it means that at the time the makefile is parsed it doesn't match any particular file, it's just defining the pattern rule itself. So, % can't be expanded here. It will be expanded later, when make starts walking the dependency graph and trying to locate ways to build targets.
In general your method cannot work efficiently. You could defer the expansion of these parts of the prerequisites list using Secondary Expansion. However, that means every time make wants to TRY to use this pattern it will run these commands--that will just be slow.
Have you considered using a more standard way to manage detecting prerequisites? Try reading this description for example to see if it would work for you.

Makefile pattern rules not working

I am learning makefiles, and can't just wrap my head around this problem i am having, and would like to understand how/why this fail.
I have half a dozen erlang files in a src directory. I want to compile these into a ebin directory, without having to define a rule for each and every one of them. According to the Gnu make documentation, pattern rules should be right up my alley.
However, with the following makefile, all I get from make is make: *** No targets. Stop. Why is that?
ebin/%.beam: src/%.erl
mkdir -p ebin
erlc -o ebin $<
Edit: Based on this answer, I now understand that i would have to explicitly declare the targets, for instance by using make ebin/cmplx.beam. However, i still do not understand how i should write my makefile to get my desired behaviour - since I have half a dozen targets (and in other projects even more), this seems like an unnecessary hassle. Is there not a way to define targets based on the source file names?
The target rule tells make that whenever it needs to produce a beam file in the ebin directory, and there exists a corresponding erl file in the src directory, it can use erlc.
However, this doesn't tell make that this is what it needs to do. You could explicitly tell make what it needs to do by giving it a target on the command line:
make ebin/foo.beam
If you don't give a target on the command line, make will pick the first non-pattern rule in the makefile as its target. However, your makefile doesn't have any non-pattern rules, so there is no target.
What you probably want is that for each existing erl file in src, make should consider the corresponding beam file in ebin to be a target. You can achieve that by calling wildcard and patsubst:
erl_files=$(wildcard src/*.erl)
beam_files=$(patsubst src/%.erl,ebin/%.beam,$(erl_files))
ebin/%.beam: src/%.erl
mkdir -p ebin
erlc -o ebin $<
all: $(beam_files)
(The indented lines need to be actual physical tabs, not spaces.)
That way, running make will rebuild all beam files that are out of date. all gets chosen as the default target, and it in turn depends on all beam existing or potential, each of which in turn depends on the corresponding erl file.
This trick is described in the GNU make manual.

Automake default rule for targets with no extension?

Is there a generic was to specify a rule for something that goes from something with an extension to something with no extension? (in this case, '.in' to '')?
I have a project that's using automake. I have some config file templates that need substitutions before installing them. For example, I have a 'foo.ini.in' file that I want to use to create 'foo.ini'. I have a few of these scattered throughout the codebase. However, for each one, I need to create a custom Makefile rule to make them work. Is there a better way? I currently do this in Makefile.am:
bazdir=$(libdir)/#PACKAGE_NAME#/baz
EXTRA_DIST = foo.ini.in bar.ini.in
CLEANFILES = foo.ini bar.ini
foo.ini: foo.ini.in
sed -e 's|#LIBDIR#|$(bazdir)|g' $< > $#
bar.ini: bar.ini.in
sed -e 's|#LIBDIR#|$(bazdir)|g' $< > $#
This works fine, but I need to duplicate the rule for every file. I'd like to write one rule that will do the substitution for any 'ini.in' files to 'ini' files. I've tried:
%.ini.in: %.ini
sed ....
but autoconf complains that % pattern substitution is a non-portable gnumake-ism. It also doesn't like
.ini.in.ini:
sed .....
.. which I can't really blame it for not liking, because I can't even parse that.
Is there a way to do this?
NOTE: I can not use AC_CONFIG_FILES to do this substitution, because 'bazdir' is not fully expanded in that case.
Fortunately, there's a much better way: let the 'configured' files be generated from the templates using the configure script itself. As I mentioned in the comment, I don't see any reason to try to expand $bazdir in the Makefile.am itself. Maybe you can clear this up for me if there's some special reason for this.
In the configure.ac script, substitution variables are defined with the AC_SUBST macro. I'm guessing you want to replace LIBDIR with the value of $bazdir. Note that LIBDIR isn't a good choice of name, as libdir is already used in configure scripts; so let's use a variable name prepended with a project name: BAZ_LIBDIR
1/. set bazdir in the configure script: bazdir="${libdir}/${PACKAGE_NAME}/baz", and substitute with: AC_SUBST(BAZ_LIBDIR, $bazdir). Alternatively, just assign the value to BAZ_LIBDIR and use the single argument form of AC_SUBST. BAZ_LIBDIR is now ready for substitution...
2/. At the end of configure.ac, specify the files to be generated from their <file>.in templates, with AC_CONFIG_FILES. Typically this will list Makefile's, as well as data files, where the .in suffix is implicit.
Assuming a projectdir tree... could be any sort of tree layout of course:
BAZ_LIBDIR="${libdir}/${PACKAGE_NAME}/baz"
AC_SUBST(BAZ_LIBDIR)
...
AC_CONFIG_FILES([Makefile projectdir/Makefile])
AC_CONFIG_FILES([projectdir/foo.ini projectdir/bar.ini])
...
AC_OUTPUT
Instances of #BAZ_LIBDIR# in the <file>.ini.in files will be replaced with the substitution value. No arcane sed invocations are required to generate <file>.ini files.
Another nice feature is that you needn't add foo.ini.in or bar.ini.in to the EXTRA_DIST variable in the Makefile.am - and make distclean will clean the bar.ini and foo.ini files.

Get makefile directory

I am distributing my cpp files along with a makefile. Now the makefile is located in the same directory as the cpp file.
What is the variable (if any) in makefile that allows me to retrieve the current directory where the makefile is located? In this way I can use that variable to specify my cpp path for compilation.
My makefile is as follows:
all:
g++ ($makeFileDir)/main.cpp ($makeFileDir)/hello.cpp ($makeFileDir)/factorial.cpp -o ($makeFileDir)/hello.exe
Edit: I am running my makefiles on Windows
I remember I had the exact same problem. It's not possible, as far as I remember.
The best bet you can have is to pass it as a variable. That is both cross platform and guaranteed to work, as you know the makefile dir at invoke time (otherwise you can't invoke it).
In alternative, you can do a very dirty trick, meaning you try to combine your current path (you can obtain with $(CURDIR) in gnu make) with the path of the invocation of the makefile (which can be tricky, and depends on your make)
Here is a cross-platform way to get the directory of the Makefile, which should be fully shell-agnostic.
makeFileDir := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
Note that this will give you the directory of the Makefile being currently interpreted. You might have bad (or good!) surprises if you include a Malefile using this statement from another.
That should be enough if you use a recent implementation of make for windows, i.e. Chocolatey's.
Issues with older make for Windows
Depending on the version of make you're using on Windows, there can be inconsistencies in the handling of backslashes. You might need one of the following variant. That's the case for GnuWin's make 3.81 binary for example.
Make the path separator consistent. The statement below uses forward slashes only, just swap \ and / to get the opposite behavior. From my experience (with GnuWin's make), you might have to use forward slashes to use such a variable for make include statements or to use it in VPATH.
But you would of course need backslashes in the DOS shell, and therefore in recipes... You might need two versions of the variable, but at least the substitution makes sure that the path separator is consistent!
makeFileDir := $(subst \,/,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
The abspath function of GnuWin make 3.81 is broken and doesn't handle paths with drive letters in it. Here is a workaround to handle Windows absolute paths (with drive letter) as well. You can then use it to get the directory of the Makefile (here with the path separator substitution as well).
I won't explain the details, but the workaround simply returns the argument if that's already a Windows absolute path, i.e. if there is : in the root of the path, and uses the builtin abspath otherwise.
define fixabspath
$(if $(findstring :,$(firstword $(subst /, ,$(subst \,/,$(1))))),$\$
$(1),$\
$(abspath $(1)))
makeFileDir := $(subst \,/,$(dir $(call fixabspath,$(lastword $(MAKEFILE_LIST)))))
Remarks
There might be sources I'm omitting here and I'm sorry for that. It's been a long time ago.
In the fixabspath definition, $\ are just here to split the line for readability.
The MAKEFILE_LIST variable contains a list of the Makefiles being interpreted, the last one being the current one. See the corresponding manual page.
If I remember correctly, this also works with macOS' native make.
For 'cygwin' and 'linux' use I've solves this by calling pwd directly from the rule in the makefile:
do.%: %.cpp
echo "Running command in " `pwd`
somecommand $^
you can use $(srcdir)
then ./configure --srcdir="/your/path/to/the/source/directory"

Separating objects and source with a makefile

I have been having troubles getting my makefiles to work the way I want. First off, I would like to say this is POSIX make, as in http://www.opengroup.org/onlinepubs/009695399/utilities/make.html I am needing my build system to work with both BSDs and GNUs(Linux).
What I am wanting is a zero maintenance makefile. I want it to just compile all .c and .asm files in src/ and place the object files in objs/ and then to link everything in objs/ to a binary file.
I can do a lot, but I can't get it to separate the source and obj files.
I am ok if this requires a little built-in shell scripting (using POSIX defined /bin/sh), but I can just not get the dependencies to work right. I want it to only build the object file if the source file is newer.
My closest is this:
${C_OBJS}: ${HDRS} ${*:objs/%=src/%}.c
${CC} ${CFLAGS} -c ${*:objs/%=src/%}.c -o $*.o
This has the problem that I must still specify C_OBJS=objs/foo.o and such and also it is just barely not POSIX and therefore, compiles with BSD make but not GNU make.
The POSIX version of make does not explicitly support file names with slashes in them, nor does it make provision for separating source files in a different directory from the object files. And, as noted by #caskey, it does not support any notation using '%' characters, though it notes that such rules exist and recommends that they be reserved for use as metacharacters.
Consequently, you probably cannot do what you want with standard POSIX make.
In practice, you can often do what you seek with specific implementations of make, but the resulting makefile has limited portability.
Consider using a makefile generation systems of some sort - cmake or the auto-tools (autoconf, libtool, automake, etc). Or one of the many reworkings of the basic concepts of make:
scons
ant
cake
cook
bras
...and a dozen I've forgotten or not heard of...
POSIX make doesn't support constructs like?
objs/%.o : src/%.c
${CC} ${CFLAGS} -c $< -o $#
Forgot the question mark at the end, hope that makes my comment more clear.

Resources