Fiddling with a build-system mainly based on pure Makefiles, I've come to the following macro to make it easy to test for the existence and set an internal variable of each external tool required by the build process.
define tool-available
$(eval $(1) := $(shell which $(2)))
$(if $($(1)),$(info $(2) available at $($(1))),$(error error: missing tool $(2)))
endef
$(eval $(call tool-available,DOT,dot))
$(eval $(call tool-available,RBIN,R))
$(eval $(call tool-available,FIND,find))
However, experience has shown that it's not common to do so inside a makefile, with third-party build-systems usually preferring external configure scripts and alternative mechanisms.
Besides the fact that the which(1) program has a limited availability along platforms, is there any strong reason for not doing so into a Makefile?
I'm not entirely sure there's any value in explicitly checking that the tool is available in the way your system is; if the program doesn't exist on your path, it's going to fail with a "command not found" error, which is pretty unambiguous, so why waste the time explicitly checking for it?
Checking for the presense of libraries, on the other-hand, I feel does add value. If a library is missing, you may get just a 'file not found', with no indication of which library it comes from, but even then, a clear documents on how to configure the build environment would be better; it's actually far easier to say "this is what you need to build this" than it is to try to handle all the edge cases of weirdly configured systems out there.
Note that my views are quite militant in this regard; if someone doesn't have the wit to read the README or BUILDING instructions and setup their environment appropriately, then they probably have no business attmpting to build it in the first place... people of a less cynical nature may want to take a softer line :)
Related
I have a large project using autotools that contains some code that builds into a utility library. The project has quite a few dependencies and I would like to compile a specific subset of that utility library for mobile environments (Android/iOS). I expect a lot of dependencies to be unnecessary for that particular subset of functionality, and compiling the whole project for those architectures/platforms is impossible for technical reasons.
This mini version of the library would actually be useful not just to me but other people, as well. This is why the maintainer of the project suggested introducing a --enable-mini flag for the configure script. After experimenting a little (I have never done anything inside a configure.ac before) I actually got a build working that builds this extra mini library.
Now to the point: Is there a clean way to exclude all the other project executables and libraries from being built? What I want is a ./configure --enable-mini invocation that will result in only the libutilmini.a/libutilmini.la being built. Sure, there are some components that could be disabled via --disable-X options, but obviously the project was not set up in a way that makes all components optional. Apart from the fact that it does not seem necessary to build everything else just to build the mini library, the whole project will not build for, for instance, the iOS platform.
I really would like to avoid adding an if HAVE_MINI [...] to all the Makefile.ams in every subdirectory, especially since the mini library is not useful to most of the other developers, this does not seem like an elegant approach. Are there any recommended ways of achieving these goals?
I am aware I could just create a new project using the sources I need and build those, but as I said the mini library is useful to some other developers, too.
If you want to conditionally compile something with automake using a regular make command with no arguments, you have to use automake conditionals (the if HAVE_MINI thing you refer to); there is no other way. However, what you can do, alternatively, is to create an extra target (say, build_mini) in your toplevel Makefile.am which depends on everything needed to build your libmini. You could then tell people that if they want to build libmini (and nothing else), they don't run make, but they run make build_mini. This would look something like:
(toplevel Makefile.am)
SUBDIRS = foo bar baz
build_mini:
$(MAKE) -C foo libmini-depends
$(MAKE) -C bar libmini.la
or some such (the details would depend on what is needed to build libmini.la).
You would then have bar/Makefile.am look something like this:
if WANT_MINI
lib_LTLIBRARIES += libmini.la
endif
libmini_la_SOURCES = # ...
the only thing that really needs to be inside the conditional is adding the libmini.la to lib_LTLIBRARIES; everything else can be unconditional. So with this method, you should have only one if FOO...endif construct.
I'm trying to use ccache to speed up my rebuilds and I noticed this in the log:
[2015-04-17T10:41:45.845545 27682] Compiler option -M is unsupported
[2015-04-17T10:41:45.845584 27682] Failed; falling back to running the real compiler
In my experience you need something like the -M flag in order to have make or its equivalent trigger rebuilds correctly. It seems weird that ccache would be tripped up by an option that must be in almost every project's build. Am I missing something? Is there a more preferred option?
This is w/ ccache-3.2.1.
Edit: I tried with -MM as well, no luck.
It is correct that ccache currently doesn't support the compiler options -M and -MM (and it never has supported them).
Some reasons for why the options in question are unupported:
The options tell the compiler to let the preprocessor output make rules instead of the preprocessed source code. This is not a good match for how ccache works; it needs to get hold of the "real" preprocessed output for each compiler invocation (see https://ccache.dev/manual/3.7.11.html#_how_ccache_works).
Nobody has implemented support for the mentioned options, simply put.
It would most likely be possible to implement support by letting ccache run the compiler command twice: one without -M/-MM to retrieve the preprocessed source code (with which the result should be associated) and one with -M/-MM to retrieve the result (make rules).
However, I (speaking as the ccache maintainer for the last six years) have not heard anybody missing support for -M/-MM until now, so my impression is that -M/-MM actually aren't used much.
Am I missing something? Is there a more preferred option?
Yes, I would say that the standard way is to use -MD/-MMD (which are supported by ccache) instead of -M/-MM. -MD/-MMD are superior because they produce both the .o and the .d file in one go, whereas -M/-MM only produce the .d file, so the compiler must in that case be invoked twice by the Makefile for each source code file. See for instance http://www.microhowto.info/howto/automatically_generate_makefile_dependencies.html for how to use -MD/-MMD.
the compilation options are vendor specific (in my knowledge)
so, in makefile, I have to provide,
if FC=ifort
FFLAGS=<long list of options provided by intel>
else
if FC=gfortran
FFLAGS=<same list in gnu way>
end if
is there a way to specify a generic option? by generic, I mean, a vendor
independent way of specifying the options. I don't mind creating them
using autotools(i.e. autoconf, automake). but is there a way?
I am not sure, if this answers your question or provides you any help at all. But, what I use to allow activation of compiler options in a more generic way, is to define variables for specific features, for example warning, debugging, optimization and profiling, and set these according to the compiler currently used.
I am using waf for configuration and building, see for example this build script, where the FCFLAGS are set according to the configured compiler, with different options activated for the various build variants, that are available. I guess, you can do something similar with autotools, or pure make.
I'd like to define a Makefile with implicit rules for a bunch of executables, some of which require linking against a custom-built library (let's call it libedich.a).
My problem is that I'd like to be able to build those executables that do not require libedich.a when the latter hasn't been built yet. If I simply add -ledich to the LDLIBS variable, I get errors when libedich.a doesn't exist:
/usr/bin/ld: cannot find -ledich
How do I tell ld that it's okay to continue linking when a given library doesn't exist?
A common solution is to create a dummy archive so that GCC will find it. Since the executable doesn't need any symbols from the library, it won't error out. Like this,
# create an empty archive.
ar cru libedich.a
or even simpler,
echo '!<arch>' >libedich.a
This is the downside of using one LDLIBS variable to hold all of the library dependencies and re-using it for every target, even though you know some targets only need a subset of the libraries. You have several options:
There are probably fancy IDE's and build tools out there that try to infer library dependencies from context, saving you from manually specifying them for each target.
Switch to using shared libraries.
Fix the target in your Makefile so that it depends on libedich.a (even if it doesn't need to). This will work if you are building everything anyway and don't care what order the targets proceed in.
Manually specify the library dependencies for each target in your Makefile.
The last option is my recommendation; it is more work, but eliminating the false dependencies in your Makefile will enable you to build (perhaps most of) your targets even if one of the dependencies is broken. One convenient way to do this is with target-specific variables:
targetname::LDLIBS+=-ledich
You probably also want to be aware of make --keep-going (make -k)
I have a large legacy codebase with very complicated makefiles, with lots of variables. Sometimes I need to change them, and I find that it's very difficult to figure out why the change isn't working the way I expect. What I'd like to find is a tool that basically does step-through-debugging of the "make" process, where I would give it a directory, and I would be able to see the value of different variables at different points in the process. None of the debug flags to make seem to show me what I want, although it's possible that I'm missing something. Does anyone know of a way to do this?
Have you been looking at the output from running make -n and make -np, and the biggie make -nd?
Are you using a fairly recent version of gmake?
Have you looked at the free chapter on Debugging Makefiles available on O'Reilly's site for their excellent book "Managing Projects with GNU Make" (Amazon Link).
I'm sure that remake is what you are looking for.
From the homepage:
remake is a patched and modernized version of GNU make utility that adds improved error reporting, the ability to trace execution in a comprehensible way, and a debugger.
It has gdb-like interface and is supported by mdb-mode in (x)emacs which means breakponts, watches etc. And there's DDD if you don't like (x)emacs
From the man page on make command-line options:
-n, --just-print, --dry-run, --recon
Print the commands that would be executed, but do not execute them.
-d Print debugging information in addition to normal processing.
The debugging information says
which files are being considered for remaking,
which file-times are being compared and with what results,
which files actually need to be remade,
which implicit rules are considered and which are applied---
everything interesting about how make decides what to do.
--debug[=FLAGS] Print debugging information in addition to normal processing.
If the FLAGS are omitted, then the behaviour is the same as if -d was specified.
FLAGS may be:
'a' for all debugging output same as using -d,
'b' for basic debugging,
'v' for more verbose basic debugging,
'i' for showing implicit rules,
'j' for details on invocation of commands, and
'm' for debugging while remaking makefiles.
I'm not aware of any specific flag that does exactly what you want, but --print-data-base sounds like it might be useful.
remake --debugger all
More info https://vimeo.com/97397484
https://github.com/rocky/remake/wiki/Installing
There is a GNU make debugger project at http://gmd.sf.net which looks quite useful. The main feature supported by gmd is breakpointing, which may be more useful than stepping. To use this, you download gmd from http://gmd.sf.net and gmsl from http://gmsl.sf.net, and do an 'include gmd' in your makefile.