How to let make know about folders? - makefile

My directory structure looks like this,
source/
|-Makefile
|-a.c
|-b.c
|-c.c
include/
|-arch1/
|-arch2/
|-common/
|-arch1-c_files/
If make a.i is the command then it's straight forward to write a.i as target & a.c, corresponding headers with their paths as dependencies which would look like this,
a.i: a.c ../include/arch1/file.h ../include/arch2/file.h
command
but it'll be long and tedious Makefile. I saw %.i shortcut. But how to write a generic dependency list that'd work for all the files in source directory?
and even, what to be written as target so that generated target would be placed in different directory and also won't get compiled every time? (Think of output object files)

Related

change prerequisites in makefile at runtime

I am relatively new to make and don't know how to do one specific thing:
The overall process should look something like this:
the source files are java sources in a directory like src/org/path/to/packages/*.java
I want only to translate a specific java file, but the translation process will automatically translate all dependencies (I say 'translate' because I use j2objc to translate the java files to obj-c files - but that should be of no concern for this question)
The translated files will be put into the build/ directory with a folder structure reflecting the source folder structure (so build/org/path/to/packages/.m+.h)
These *.m and *.h files will then be compiled with j2objcc (a clang wrapper) into *.o files -> this step has to be done per file so every file is compiled with a command like j2objcc -c build/org/path/to/packages/file1.m -o build/org/path/to/package/file1.o
these shall be combined into a static library using ar
My problem is that I know which (one) java file I am starting with, but after step 2 I don't know which *.m and *.h files are generated/translated into the build directory. I'd like to read the contents of the build dir after step 2 with a command like find ./build -name '*.m' at make runtime but I don't know how to use this as a prerequisite in the make target.

Include a third makefile with a path relative to second, when second isn't in directory of first

I have a Makefile with only project-level definitions: which source files to use, what binary or library to make, etc..
It includes ../../Make.Arch for architecture-specific definitions (such as compiler command).
In turn, Make.Arch is meant to include ../etc/Makefile.Standard for all the boilerplate of actually allowing the make system to work .
But include requires a path relative to where the makefile is actually being run (or maybe where the first Makefile is), not relative to the second... What to do?
Make interprets relative paths from the working directory, the directory in which Make is being run. You haven't specified how you're running Make, so I'll assume your running it in the directory with Makefile.
If you are allowed to modify the makefiles, you can change the paths.
You could change Make.Arch from this:
include ../etc/Makefile.Standard
to this:
include ../../../etc/Makefile.Standard
but that would require that any makefile that uses Make.Arch be two directories down from it. That's clearly not a good idea. But we can use a variable:
include $(ARCH_DIR)/../etc/Makefile.Standard
which is provided by Makefile (or any other makefile that uses Make.Arch):
ARCH_DIR := ../..
include $(ARCH_DIR)/Make.Arch
If you are not allowed to modify the makefiles, then you must cheat. One way is to create a symbolic link to Makefile.Standard.
mkdir ../etc
ln -s ../../../etc/Makefile.Standard ../etc
Now Makefile will work. (It ought to be possible to make a link to etc/, but for some reason I can't get that to work right now.)

How to create this makefile? Sources in subdirectories, separate output path, linking objects in subdirectories

Is there a way to create a makefile that does this?
I gave up after trying to follow the docs and lots of trial and error so I'll just post a description of what the makefile should do.
general directory structure:
src/ - contains c source files in various subdirectories (written manually by maintainer)
inc/ - contains h header files in subdirectories matching src (written manually by maintainer)
obj/ - contains o header files in subdirectories matching src (autogenerated by a make call)
bin/ - should contain binary (autogenerated by a make call)
makefile
so for example at a given point of time the project might look like
src/
main.c
sub1/
other1.c
other2.c
sub2/
sub3/
other3.c
inc/
sub1/
other1.h
other2.h
sub2/
sub3/
other3.h
obj/
main.o
sub1/
other1.o
other2.o
sub2/
sub3/
other3.o
bin/
release
makefile
(probably not relevant: Note that main doesn't have a header file but most likely every other c file will have a matching h file.)
I want to be able to call make, and have it:
use gcc to recompile only changed c files into respective o files in obj/, generating missing subdirectories if needed.
for example, from the above state, if I add a new subdirectory sub4 inside src/sub1/, and then create other4.c inside src/sub1/sub4/, I would like make to generate sub4 inside obj/sub1/ and then generate other4.o inside obj/sub1/sub4/
create a binary at bin/release by linking all object files (from all subdirectories in obj/)
I don't want to have to change the makefile each time I add directories in src
I don't want to manually have to create directories in obj, the makefile should take care of it. if this is not possible, maybe have it rename all obj o files to a flat naming pattern? i.e. obj/sub2_sub3_other3.o instead of obj/sub2/sub3/other3.o (although this can cause issues)
probably not relevant here, but the C files use include statements in this format:
#include "sub2/sub3/other3.h"
so -I./inc would be included in the gcc call. Whereas the linker would receive inputs like -s -O3. I want to make sure those options (compiler options, linker options) are listed at the top of the makefile in variables (CFLAGS, LDFLAGS, etc) and not passed incorrectly to the targets.
is this even possible? if not, what's the closest possible?
Also, can this makefile be made to work on both POSIX systems and on Windows based systems? e.g. work the same on linux/gcc and win/mingw

How to create a makefile to call a buildscript?

Hi I have a build script called "buildMyJava" that builds a bunch of Java source code. Assuming those source code are in differnet directories such as "folder1" and "folder2", the output goes to some folder called "classes". How do I create a makefile so it KNOWS to build only when the source code meaning the *.java in those two directories have changed as well as the output classes is missing?
I have something like the following but it ALWAYS builds, dependencies are not working.
all: task
task: folder1/*.java folder2/*.java classes/
buildMyJava
First of all, the build script produces the .java files, thus the .java files should be targets, not prerequisites. So you should have something like this:
folder1/%.java folder2/%.java:
buildMyJava
The only problem with this is that if you do a make -j2, buildMyJava will run multiple times (once for folder1, and once for folder2). In fact, this is a limitation to makefiles -- you cannot have multiple targets invoke the same recipe only once. There is a good discussion on this here: http://www.cmcrossroads.com/article/rules-multiple-outputs-gnu-make
Notice though that a 'pattern' target counts as a single target though -- which means, if you can get a pattern to match all targets, you can invoke the recipe only once. A small caveat to that -- the % symbol cannot represent /'s. Thus you cannot do folder%.java, as that would not match folder1/file1.java... If you can split your script to output only to one directory at a time though, you may be able to do the following:
folder1/%.java:
buildMyJava folder1
folder2/%.java:
buildMyJava folder2
John

Makefile to compile Fortran source files in different directories

Here is my problem: I have been using Java for many years and enjoy having many directories separating different areas of the code. For my current project I am writing Fortran code, which should compile under Windows and Unix/Linux. For Windows, I am using Eclipse/Photran with MinGW/gfortran tools to set up Makefiles.
Here is the desired project structure (deep nesting tree-like Java-like would be even nicer)
dir1/src/*.f95
dir1/make/Makefile_lib1.any
dir1/make/Makefile_lib1.win
dir1/make/Makefile_lib1.unix
dir2/src/*.f
dir2/make/Makefile_lib2.any
dir2/make/Makefile_lib2.win
dir2/make/Makefile_lib2.unix
...
dir_main/src/*.f or *.f95
dir_main/make/Makefile_main.any
dir_main/make/Makefile_main.win
dir_main/make/Makefile_main.unix
I would like to call make Makefile_main.unix, which would set up any Unix-specific variables and then include Makefile_main.any, Makefile_lib1.any, ...
(similar for making on Windows)
I got to the stage where I can see all source files in a given directory, e.g.
SRCS := $(wildcard $(SRC_DIR)/*.$(SRC_EXT))
Now I am struggling with how to make all dependencies as in Fortran 95 each source generates *.o and *.mod.
Is there a way to switch between directories when compiling so that all targets/dependencies do not have dir-path in their names? Note that I am calling make from some other service directory where the Eclipse project lives. Any suggestions how to proceed?
I really do not want to do the usual Fortran style of having just one directory with
all the mess together with the code.
There are two major strategies you can take.
You can place a makefile in each subdirectory and have it support targets like all, clean etc, then use recursive make invocations from the top-level makefile to make the same target (e.g. all) in every subdirectory.
Alternatively, you can handle it all in one make invocation, without recursing, but then you'll have to work with relative paths containing subdirectory names. Personally I don't see a problem with it, and I've maintained a system of makefiles based on this approach.
Here is what you can do in your case, assuming that SRC is set correctly to the list of relative paths to every source you need to compile.
# This replaces the SRC_EXT suffix with .o in each filename
OBJ = $(SRC:%.$(SRC_EXT)=%.o)
$(BINARY_NAME): $(OBJ)
...link command...
%.o: %.$(SRC_EXT)
...compile command...

Resources