change prerequisites in makefile at runtime - makefile

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.

Related

How to let make know about folders?

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)

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

automake - target folder in source blocks executing destination

I am trying to understand a makefile from a project I am working on. It's using automake/autotools and contains this simple rule:
DEPS_SRC = $(shell cd $(srcdir); find . -name '*.ez')
DEPS = $(basename $(DEPS_SRC))
all : $(DEPS)
$(DEPS) : % : %.ez
$(UNZIP) -o $<
Say the directory structure is:
my-app/deps/
build/
When executing make my-app in the build folder the rule will basically unpack *.ez files located in the my-app/deps/ folder into build/my-app/deps/ folder.
I don't know if that's enough information to solve the problem that I am going to explain as I don't know enough about automake/autotools. Please ask if any additional information is needed.
The problem is that I noticed that having the unpacked directory in the source folder prevents make from unpacking the archive in the target folder. For example, given the following structure in the source folder:
my-app/deps/archive1.ez
my-app/deps/archive2.ez
my-app/deps/archive2/
make will only unpack archive1.ez in the build folder:
build/my-app/deps/archive1/
I would like to know if this is a bug in my makefile or a feature of automake. If the later, is there any workaround or setting or variable available to disable it?
This is primarily a GNU make question, not particularly specific to the Autotools. However, since the target system's make is of GNU's flavor (else none of this works), we can assume that the Makefile generated by configure uses GNU make's VPATH feature as part of its support for out-of-source (a.k.a. VPATH) builds such as the one you are performing.
The value of the VPATH variable that configure will have inserted into the Makefile is used as a search path for prerequisites that are not found relative to the build directory. The key point, however, is that it is also used as a search path for rule targets. That makes a certain amount of sense, especially for targets that are prerequisites of other rules.
In your case, however, that leads directly to the behavior you describe:
the default target depends on ./my-app/deps/archive2
resolving that name against the build directory does not produce a valid file name
before attempting to build that target, make looks in the directories listed in the VPATH, which, in your example case, will contain .. or an equivalent
make finds .././my-app/deps/archive2 in this VPATH search, and therefore determines that the specified target already exists, and does not need to be built
Thus, the behavior you observe is normal for GNU make, supposing the Makefile is constructed by Autoconf from an Automake-generated template.
is there any workaround or setting or variable available to disable it?
Do you really need one? If the archive file has already been unpacked in the source tree, then you can expect make to find its contents, too, via the VPATH. At least if the Makefile is well-prepared overall for for out-of-source builds.
But if you want to be certain to get the archive files unpacked in the build directory then you can specify that explicitly. This ought to do it:
DEPS_SRC = $(shell cd $(srcdir); find . -name '*.ez')
DEPS = $(basename $(DEPS_SRC))
LOCAL_DEPS = $(addprefix $(abs_builddir)/,$(DEPS))
all : $(LOCAL_DEPS)
$(LOCAL_DEPS) : $(abs_builddir)/% : %.ez
$(UNZIP) -o $<
That prefixes the name of each dependency with the absolute path to the build directory, and updates the rule for unzipping the archives to accommodate it. Targets with absolute paths such as that cannot be located in the VPATH.

how to compile from src directory to bin directory?

I have a src directory that contains main.ml and compose.ml files, and i need to compile from that directory and store the binary result in bin directory.
How can i make it?
I am assuming here that main.ml is the main program and compose.ml a module it uses. Then the compilation process will produce files compose.cmo (or compose.cmx), compose.cmi, and the final binary.
It is not quite clear, where you want the intermediate files (compose.cmo and compose.cmi) to go.
If you are fine with them being in src, you can use the -o command line option in the final compilation step.
If you want to keep the source directory clean but are fine with extra stuff going to bin, I suggest symlinking your source files to bin and compile there.
If you want to keep both src and bin clean, you can use a third directory like build, where you symlink the sources, compile, and copy the final binary to bin.
The easiest solution is probably to use ocamlbuild:
ocamlbuild -I src -no-links main.native
ln -f _build/src/main.native bin/main
This will leave the temporary files in the _build directory, which you can later remove with ocamlbuild -clean or rm -r _build.
Use main.byte instead of main.native instead if you want to build the bytecode version.

makefile how can I generate obj files in a subfolder?

I want to generate my obj files in a subfolder, I have tried this:
lib/*.o: source/*.cpp
clang++ $(CC_FLAGS) -c -Iinclude source/*.cpp
But it still generates the obj files in the project root and not in the lib/
The project tree that I'm trying to have:
Project/
source/(cpp files)
include/(header files)
lib/(obj files)
You don't show your current makefile, but my suspicion is that it's wrong. However as we can't see it, we'll leave that alone.
The compiler does not support writing multiple object files to a different directory. If you pass multiple source files along with the -c flag then it will write out multiple object files but only to the current directory... as you've discovered the -o flag can't be specified on compile lines which generate multiple output files.
You can change your recipe to look like this:
cd lib && clang++ $(CC_FLAGS) -c -I../include ../source/*.cpp
this will cause all the object files to be written to the lib directory because it's now the current directory.
However, putting this into a makefile is not simple, because make itself is designed to have a single recipe create a single target. However you have this problem with your existing makefile which you don't show, as well.

Resources