Make build to build multiple make files in parallel - makefile

I have something like the following:
3 libs (libA, libB, libC), libB and libC depends on libA.
Is there anyway to parallel build libB and libC once libA finish building using make ?

If your makefile looks like this:
all: libA libC libC
libA:
...
libB: libA
...
libC: libA
...
then just running make -j 4 will cause make to parallelize what it can across 4 processes.
you can even parallelize by default by doing this:
all:
$(MAKE) -j $$(nproc) libA libB libC
libA:
...
libB: libA
...
libC: libA
...

Related

How to build cockroach DB with customized CFLAGS, CXXFLAGS and LDFLAGS?

I would like to build cockroach DB with CFLAGS += -O, CXXFLAGS += -O and
LDFLAGS ?= -static. How would I do that?
There are a couple of ways to do that.
(1) If you are building with make. You can simple open the make file and just find and override these flags.
(2) If you are building with bazel. You can set these flags with these bazel command options: --cxxopt=-O, --copt=-O, --linkopt=-static. For example: bazel build pkg/cmd/cockroach-oss --cxxopt=-O --copt=-O --linkopt=-static
(3) If you are building with crdb's dev tool (a wrapper of bazel). You can pass in the same options as (2) but following an extra --. For example, dev build oss -- --cxxopt=-O --copt=-O --linkopt=-static

On macOS with Autotools, how to tell libA to find its dependency libB at a custom location instead of compiler defaults?

I have libA and libB, libA depends on libB. Both use Autotools as the build system.
Problem
On macOS, libA always try to find libB under /usr/local/lib, while the source code structure is like this
libA
libB
i.e., they are side by side under the same parent folder.
Question
How do I instruct libA that libB is at the custom location instead of the compiler defaults? Note that libA may depend on other things, which may be system default. Only libB is at the custom location.
Workaround
I do know I could use Homebrew to cheat a bit on dependency hassles. But I'd really love to build from source in this case.
Solved it myself.
libA's ./configure supports custom compiler flags such as LDFLAGS, CFLAGS. In my case, it even comes with custom flags libB_CFLAGS and libB_LIBS.
So with those custom flags set, and ./configure LDFLAGS="$LDFLAGS -lB". I'm good to go.

Automatic dependency detection not working in GFortran

I the GCC Wiki it is stated that support for auto-detection of dependencies has been available since version 4.6:
Support the generation of Makefile dependencies via the -M... flags of GCC; you may need to specify additionally the -cpp option. The dependencies take modules, Fortran's include, and CPP's #include into account. Note: Using -M for the module path is no longer supported, use -J instead.
In my program I have two Fortran files: module_1.f08 and main.f08, where main uses module_1. I am using the following command to try to auto-detect dependencies of main:
gfortran -cpp -M main.f08
If module_1 has been already compiled, the command above returns a list of dependencies as expected, though if module_1 has not been compiled yet, I get an error message instead saying that module_1.mod does not exist.
The way I'm seeing this is that every time a new module is added to the code, it has to be compiled separately before running make all (or we might run make all before using the module in any other file, then use the module and compile again) or else any dependency of it might be compiled before the module itself and a compilation error will be returned.
Another thing is that dependency files have to be created gradually and one-by-one as the project grows, and if .mod files and dependency files got deleted at some point (with a make clean command for example), there will be no way to generate dependency files all at once using the auto-detection feature.
Is there a way to get around these limitations? Is there a way for auto-detection to work even if .mod files do not exist yet?
To start with, you need to add snippets to your Makefile to actually use the dependency generation feature. Additionally, you can use the -MD option to generate dependency files automatically for each target, so you don't need a special target to regenerate your dependencies. For an example project like yours above with a main.f90 that uses a module defined in mod1.f90 a simple Makefile using dependencies could look like:
FC := gfortran
FFLAGS := -O2 -g
LIBS := # Needed libs like -lopenblas
SRCS := mod1.f90 main.f90
OBJS := ${SRCS:f90=o}
DEPS := ${OBJS:o=d}
myprog: $(OBJS)
$(FC) $(FFLAGS) -o $# $^ $(LIBS)
.PHONY: clean
clean:
-rm -f $(OBJS) *.mod
-include $(DEPS)
%.o: %.f90
$(FC) $(FFLAGS) -cpp -MD -c -o $# $<
When you run make you'll see that it generates files main.d and mod1.d containing the dependencies for the corresponding source file.
A (minor?) problem here is that your SRCS variable containing your list of source files must be listed in an order that allows the files to be compiled from left to right before you have any .d files. So the dependency stuff as it's done here doesn't help with ordering a build before the .d files have been generated. (Thus I'd recommend distributing the .d files as part of the source package.)

GNU make - enforcing target order

Could someone please tell me if there is a way to enforce sequential execution of specific Makefile targets. For example, I have a Makefile that builds Libraries and Executables. Now, Executables depend on Libraries, so they must be built after the Libraries are built and staged. This is what I currently have in a single Makefile:
.PHONY: all
all: all_lib all_bin
.PHONY: all_lib
all_lib: $(dep_lib)
.PHONY: all_bin
all_bin: $(dep_bin)
I have two targets all_lib and all_bin, one builds all libraries and the other builds all binary executables. When I pass -j to make to run parallel jobs, I get build failures, because all targets run in parallel and binaries can't find shared library objects and staged header files.
I tried changing it to this to try and force some dependency order:
.PHONY: all
all: all_bin
.PHONY: all_lib
all_lib: $(dep_lib)
.PHONY: all_bin
all_bin: all_lib $(dep_bin)
But for some reason all targets still run in parallel I still get the same build failures. Any ideas?
Make is entirely built around the concept of dependencies. You are simply not using it that way.
If an executable depends on a library, then you should list that library in the prerequisites list of the executable. I can't give you a relevant example because you don't provide any details about the contents of dep_lib or dep_bin above, but for example:
exe1 : exe1.o liblib1.a liblib2.a
etc. Now, exe1 won't attempt to be linked until after the liblib1.a and liblib2.a targets have been created.

Makefile library prerequisite

I have a makefile, which I am using to cross-compile for and embeded ARM platform with gcc. Specifcally, I am using arm-none-eabi-gcc, but the same appiles to avr-gcc, msp430-gcc, etc. Typically when using make+gcc (and not cross compiling) I list libs as prerequisite as follows:
programA.elf: programA.o foo.o -lm ...etc
programB.elf: programB.o bar.o -lftdi ...etc
%.elf:
gcc $(LDFLAGS) -o $# $^
Make handles this "-lsyntax" very nicely, and its very convienient if you are building multiple progams/targets and want to have a generic rule for linking. The problem I have run into durring cross-compiling is that arm-none-eabi-gcc obviously has a different libm.a than my system's gcc libm.so (for example), but Make doesn't know whats going on here and keeps trying to use the x86 libm instead of the ARM base one. I can get things to work by adding the line:
.LIBPATTERNS = /usr/lib/arm-none-eabi/newlib/lib%.a
but it seems kinda clunky and exposes anyone wanting to compile the project to knowing a little more about the toolchain's install locations than is normally expected.
My question is: "Is there a better convention to list a binary's lib dependencies I should be using here that wont break when cross-compiling?"
This can be done. But a general solution is complex. I have Makefiles which build arm, x86, and c67 executables from a single set of sources. The page you reference eludes to the key: VPATH. I suggest a separate subdirectory for each architecture. The following is not working code, but it gives the idea
all: arm/pgma x86/pgma
vpath %.c $(CURDIR)
arm x86:
mkdir -p $#
arm/pgma: arm/main.o arm/sub.o | arm
x86/pgma: x86/main.o x86/sub.o more.o | x86
arm/%: CC=arm-none-eabi-gcc
arm/%: CFLAGS += -march=armv7-a -mtune=corex-a8
x86/%: CC=gcc
arm/%: VPATH = /usr/lib/arm-none-eabi/newlib
# Notice, VPATH not needed for x86 since it is the native host
This entire concept can be extend to build dependency file is each subdirectory as well debug and release variants. I have not tried this with the -lfoo, but it should work. E.g.,
arm/pgma: arm/main.o arm/sub.o -lmylib | arm

Resources