Automake fails when trying to run platform-specific build - makefile

I am using autotools to build a project that I want to cross-compile for both Linus and Mac OSX. I am building two libraries, libevent.la and libaffinity.la. libevent should be build when automake is run on both platform. However, libaffinity.la should be build only if the platform is MACOSX. To this end, I have the following in my configure.ac file:
#Detect the target system
case "$host_os" in
darwin*)
build_darwin=yes
;;
esac
AM_CONDITIONAL([DARWIN], [test "$build_darwin" = "yes"])
The variableDARWIN will be set if the proejct is being build on Mac OS. And in the Makefile.am I have following:
extlibdir = $(libdir)/guile/$(GUILE_EFFECTIVE_VERSION)/extensions
extlib_LTLIBRARIES = libevent.la
AM_CFLAGS = -I$(srcdir) $(WARN_CFLAGS) $(DEBUG_CFLAGS)
libevent_la_SOURCES = libevent.c
libevent_la_CFLAGS = $(AM_CFLAGS) $(GUILE_CFLAGS) -Wno-error -Wno-nullability-completeness -Wno-expansion-to-defined
libevent_la_LIBADD = $(GUILE_LIBS)
libevent_la_LDFLAGS = -export-dynamic -module
$(GOBJECTS): libevent.la
if DARWIN
extlib_LTLIBRARIES += libaffinity.la
affinity_la_SOURCES = affinity.c
affinity_la_CFLAGS = $(AM_CFLAGS) $(GUILE_CFLAGS) -Wno-error -Wno-nullability-completeness -Wno-expansion-to-defined
affinity_la_LIBADD = $(GUILE_LIBS)
affinity_la_LDFLAGS = -export-dynamic -module
$(GOBJECTS) += libaffinity.la
endif
When I run make, it fails with the following error:
extlib_LTLIBRARIES += affinity.la
make[1]: extlib_LTLIBRARIES: No such file or directory
make: *** [all] Error 2
However, as you can see, extlib_LTLIBRARIES is defined above the if statement.
How can I fix this? Or is there a better way to do this so that I can selectively build libaffinity.la based on the platform?

The main problem turns out to have been that the lines in the conditional section were indented with tabs. These are not particularly significant to Automake, but they will have been carried through to its generated Makefile.in, and, from there, to the Makefile generated by configure. Tabs are significant to make: a leading tab is how make recognizes the lines of a rule's recipe. (Only a tab will do; spaces do not have the same significance.)
The effect, then, was that make interpreted extlib_LTLIBRARIES += libaffinity.la as one of the commands in the recipe for some rule, so that when it tried to apply the rule, it wanted to execute a system command named extlib_LTLIBRARIES. There being no such executable command found in the path, the shell failed and reported "No such file or directory", which message make forwarded on to its own output.
The fix is to avoid indenting with tabs in your Makefile.am (spaces are ok), except where you actually intend to write a recipe for a make rule (for which an initial tab is obligatory).

Related

Trying to run old makefile, "missing separator"

I've looked through the other posts similar to mine, which have been resolved by fixing a tab or spaces, but that didn't work for me (or I'm not looking in the right place). I'm trying to download the Swarm software, whose last stable release was in the early 2000s. Maybe this is a lost cause (or I might just have to suck it up and run this in a virtual machine) but I'm getting the error "Makefile.am:1: *** missing separator. Stop." The first part of my makefile code is:
if USEBUILTINAVCALL
SUBDIRS = $(LIBOBJCDIR) avcall etc src tools java COM m4 tests
else
SUBDIRS = $(LIBOBJCDIR) etc src tools java COM m4 tests
endif
EXTRA_DIST = VERSION macosx/buildlibs.sh macosx/ChangeLog macosx/configure.sh macosx/INSTALL.MacOSX macosx/README.MacOSX macosx/swarm.xcode/project.pbxproj
SWARM_INSTALL = #SWARM_INSTALL#
install-data-local:
$(mkinstalldirs) $(DESTDIR)$(includedir)
$(INSTALL_DATA) swarmconfig.h $(DESTDIR)$(includedir)
$(INSTALL_DATA) externvar.h $(DESTDIR)$(includedir)
$(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(datadir)/swarm
$(INSTALL_PROGRAM) $(top_builddir)/libtool $(DESTDIR)$(bindir)/libtool-swarm
if test $(SWARM_INSTALL) = install-sh; then $(INSTALL_PROGRAM) $(srcdir)/install-sh $(DESTDIR)$(bindir); fi
install-recursive: install-data-local
This looks to me like a Makefile.in file, not a Makefile. That is, it's intended to be converted by configure or automake.
GNU make doesn't support an if statement (it has ifdef and ifeq and ifneq, but not if). And tokens like #SWARM_INSTALL# are meant to be replaced.

Wrong expansion of variable in Makefile.am

I am stuck with a strange variable expansion. Let me explain.
I have a project that uses automake, composed by configure.ac, Makefile.am.
Basically, in Makefile.am I'm doing:
ARCH = $(shell ${CURDIR}/./arch.sh)
...
noinst_HEADERS = license/${ARCH}/lchecker.h
proj_SOURCES = main.c license/${ARCH}/lchecker.c
proj_LDFLAGS = -avoid-version -Llicense/${ARCH}
./arch is doing just uname -m to determine the architecture needed, because I have to enter the correct directory.
When I run the build, I have this error:
Makefile:622: license/x86_64/.deps/lchecker.Po: No such file or directory
make[1]: *** No rule to make target 'license/x86_64/.deps/lchecker.Po'. Stop.
and if I enter the license directory, I notice a new dir created called ${ARCH}/ where I find the missing .deps from license/x86_64.
I'm pretty sure it is an incorrect expansion problem; I've tried many ways but I failed.
Can anyone explain to me the right way to do this? Reading around the net I see that Makefile.am has a different syntax from Makefile.
UPDATE:
I tried to add some changes to see if the variable is corretly defined:
AC_DEFINE([ARCH], ["$ARCH"], [arch check])
echo ARCH = "$ARCH" printf x86_64
so the variable in defined in configure.ac, but the expansion is not correct again in Makefile.am.
In your configure.ac, use the macro AC_SUBST(varname,[value])
to create a make-variable varname in each the generated makefiles that will
have the value to which value was evaluated at the time when the makefile was generated.
value may be a shell-expansion. So e.g.
AC_SUBST(ARCH,[`./arch.sh`])
in configure.ac will create in each makefile the assignment:
ARCH = x86_64
assuming that x86_64 is the standard output of ./arch.sh at ./configure-time
in the build directory. You may then assume that this variable is so assigned
in your Makefile.am and write the like of:
noinst_HEADERS = license/${ARCH}/lchecker.h

GNU autotool:No rule to make target

my first question in stack overflow!
Quick overview of my question: I use autotool to generate a C program. When I use make command, I meet the error:
No rule to make target `../lib_foo/libfoo.a', needed by `mistery_foo'. Stop.
Something detail of my questions:
I am doing an assignment of my teacher, in which I should use GNU autotool to generate a very simple C program.
File structure: /project: main, lib_foo, Makefile.am, configure.ac
/project/main: main.c, main.h, Makefile.am
/project/lib_foo: foo.c, foo.h, Makefile.am
Following is what I write for configure.ac and makefile.am:
I. "project/configure.ac":
AC_PREREQ([2.67])
AC_INIT([project1],[0.01],[cwentai01#gmail.com])
AM_INIT_AUTOMAKE([1.9 foreign])
AC_CONFIG_SRCDIR([./lib_foo/foo.c])
AC_CONFIG_HEADERS([config.h])
AC_PROG_CC
AC_PROG_RANLIB
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <mistery.h>]],\
[[ mistery_value(1);]])],\
[AC_DEFINE([MISTERY_VALUE_ONEPARAM], [],[CONSTANT])],[])
AC_SEARCH_LIBS([mistery_value],[magic vadoo mistery],[],[AC_MSG_ERROR([Libraries (mistery, magic, vadoo) not found])])
AC_CONFIG_FILES([Makefile lib_foo/Makefile main/Makefile])
AC_OUTPUT
P.S. the AC_COMPLIE_IFELSE is used to judge the number of the parameters in function mistery_value(). I think it has nothing to do with the error.
II. project/Makefile.am:
SUBDIRS = main lib_foo
III. project/main/Makefile.am
LDADD = ../lib_foo/libfoo.a
mydir = ../uselessbin
my_PROGRAMS = mistery_foo
mistery_foo_SOURCES = main.c main.h
mistery_foo_LDADD = ../lib_foo/libfoo.a
IV. project/lib_foo/Makefile.am
noinst_LIBRARIES = libfoo.a
libfoo_a_SOURCES = foo.c foo.h
Then I run with the order of commands:
>cd project
> aclocal
> autoheader
> automake -a
> autoconf
> ./configure
> make
> make install
> ./uselessbin/mistery_foo
When I run make command, I got the error:
No rule to make target `../lib_foo/libfoo.a', needed by `mistery_foo'. Stop.
I suppose the problem may be that I don't have libfoo.a properly installed. But the library libfoo.a should not be installed but only compiled so I have to use 'noinst_' in lib_foo/Makefile.am. That's why I get stucked here.
Any answers will be appreciated.
Thanks for your help!
The problem is that you're using recursive automake, and in this case, dependencies crossing directory paths will just not resolve to extra rules: main/Makefile.am does not know how to make targets in lib_foo.
The quick fix up is to change your SUBDIRS declaration in the top-level Makefile.am to:
SUBDIRS = lib_foo main
This way main/mystery_foo will only be built after lib_foo and its targets are built. Of course this does not allow you to just make in main/ and have it work.
The other suggestion from the previous post, to use non-recursive automake is a more proper solution, because then all the dependencies can be resolved from a single Makefile.am.
Your procedure looks mostly totally fine. I just found a few possible mistakes:
Your configure.ac should have LT_INIT instruction
In project/main/Makefile.am I would change ../lib_foo/libfoo.a to libfoo.a
If the previous doesn't work, I would recommend to have a single Makefile.am and not recursive Makefile.am (Recursive Makefile.am can be harder to code and might damage the performance of the compilation)

Trouble with simple makefile in C

I am somewhat of a beginner in C and have a project due where I need to include a makefile to compile my single file program that uses pthreads and semaphores. My makefile looks like:
# Makefile for pizza program
pizza: pizza.o
gcc -lrt -lpthread -g -o pizza pizza.o
pizza.o: pizza.c
gcc -lrt -lpthread -g -c pizza.o pizza.c
and I keep getting:
make: Nothing to be done for 'Makefile'.
I have done several makefiles before and have never gotten this message. I've tried different semantics in the makefile and have only gotten this same message. And yes, the command is tabbed after the target and dependency line.
Using gcc on tcsh. I have read other makefile posts on SO but I wasn't able to use any of the answers to figure it out for my case.
Any help would be greatly appreciated!
The arguments to make are the targets to be built.
You are running make Makefile which is telling make to try to build the Makefile target.
There is no such target in your makefile, make has no built-in rule that applies to that target and the file exists (and is assumed to be up-to-date) which is what that message is telling you.
To run the default target (by default the first target listed) you can just run make (assuming you are using a default name like Makefile for your makefile).
You can also use the -f argument to make to select an alternate makefile name.
So make -f Makefile will in this case (since Makefile is a default searched name) do the same thing as make.

Makefile not rebuilding dependencies

I'm new to using makefiles and trying to produce a basic makefile as part of an exercise for university. I have two source code files, chello.c and writeexit.s, which have to be compiled/assembled and then linked to produce chello.
This is the code I have so far for the makefile:
chello: chello.o writeexit.o
ld -N chello.o writeexit.o -o chello
chello.o: chello.c
gcc -c chello.c -o chello.o
writeexit.o: writeexit.s
as writeexit.s -o writeexit.o
The whitespace before ld, gcc and as are all tabs, so I think the whitespacing is fine. When I call 'make makefile', it returns 'make: Nothing to be done for `makefile'.' However, if I change the dependencies of chello, like chello.c, the same message is returned and chello's behaviour is not modified.
From man make:
make executes commands in the makefile to update one or more target
names, where name is typically a program. If no -f option is present,
make will look for the makefiles GNUmakefile, makefile, and Makefile,
in that order.
make makefile will actually execute your "makefile" (because it is listed among the default names in the man page) file, trying to build the "makefile" target (because of the argument you are passing), which already exists
What you need is to build the "chello" binary, so you have to type:
make chello
Or alternatively:
make -f makefile chello
Alternative account here, it seems to work fine if I just call "make" instead of "make makefile". This question can be ignored.

Resources