Make could not see commands (recipes) except gcc - linux

My system is windows 8.1. I'm working on cygwin 32 bit version (first i set up 64 bit version and could not uninstall completely , later set up 32 bit version).I simply want to use 'make' utility. All my makefiles' extensions are 'makefile'.
When i try this below (to see them work , I only use simple makefiles)
make kernel.o (in shell)
kernel.o : kernel.c
<tab>gcc - ffreestanding -c $< -o $#
it works , and compiles.
But these ones below do not work. And for testing purposes and keeping things simple, each source and corresponding makefiles are in own directory. And all make commands've been made in the current directory where source and corresponding makefiles are located.
All executables (nasm ,ld ,objcopy ,cat) that cygwin needs to run the recipes are in the same directory (that is c:\cygwin\bin\)
If i command the recipes from shell, they work.
I also changed source files to see what would happen.
I also thought that maybe the problem is from cygwin itself , and i set up linux ubuntu desktop version to my machine. But they are (recipes below) not working too.(and also If i command the recipes from shell, they work.)
make kernel_entry.o (in shell)
make: *** No rule to make target 'kernel_entry.o'.
Rule:
kernel_entry.o : kernel_entry.asm
<tab>nasm $< -o $# -f coff (coff for windows)
//--------------------------------
make os-image.bin (in shell)
make: *** No rule to make target 'os-image.bin'.
Rule:
os-image.bin: boot.bin kernel.bin
<tab>cat $< > $#
//--------------------------------
make boot.bin
make: *** No rule to make target 'boot.bin'.
Rule :
boot.bin : boot.asm
<tab> nasm $< -f bin -o $#
*recipes with ld and objcopy also does not work.*
Thank you in advance...
These are my files and directory appearance :
C:\cygwin\bin --> where gcc.stays
C:\cygwin\bin --> where make.exe stays
C:\cygwin\bin --> where objcopy stays
C:\cygwin\bin --> where nasm.exe stays
C:\cygwin\bin --> where ld stays
C:\cygwin\home\me\OS\boot --> where boot.makefile stays and also boot.asm source code
C:\cygwin\home\me\OS\kernel --> where kern.makefile stays ( working sample ) and also kernel.c source code
And this is cygwin shell appearance:
me#Me ~/os/kernel
$ dir
kern.makefile kernel.c kernel_entry.asm
**in my kern.makefile the existing rule is as follows
kernel_entry.o : kernel_entry.asm
nasm $< -o $# -f coff
and boot directory
me#Me ~/os/boot
$ dir
boot.asm disk_load.asm print_hex.asm print_string_pm.asm
boot.makefile gdt.asm print_string.asm switch_to_pm.asm
**in my boot.makefile the existing rule is as follows
boot.bin : boot.asm
nasm $< -f bin -o $#

Make does not see your makefiles.
From the GNU make manual:
If no -f option is present, make will look for the makefiles GNUmakefile, makefile, and Makefile, in that order.
From what I see, your makefiles (kern.makefile, boot.makefile) are simply not found by your call to make (which does not have a -f option). This makes make rely on its internal rules, which do not include any %.o: %.asm dependency or somesuch (for make, assembly ends in .s, assembly with preprocessing to be done in .S).
This can become bloody confusing when your *.c and *.S files are compiled into *.o files, because make does have internal rules for those -- which, of course, stubbornly refuse to take any compiler options into account that you might have defined in that makefile of yours that make doesn't actually read. ;-)
So either call
make -f kern.makefile kernel.o
or (and this is my recommendation), rename <whatever>.makefile to Makefile (which is the canonical way of naming those).

Related

Issue with dependency files using Makefiles; file.d exist

I have the following sub-section of makefile that's used to generate the .d files
-include $(wildcard $(patsubst %,$(OBJ_PATH)/%.d,$(basename $(SRCS))))
%.o: %.cpp
#$(CC) -I$(INCLUDE_PATH) $(CFLAGS) $< -MM -MT $(#:.d=.o) > $(OBJ_PATH)/$(notdir $*.d)
${CC} -I$(INCLUDE_PATH) $(CFLAGS) -c $< -o $(OBJ_PATH)/$(notdir $#)
Sometimes when I build the project, I get the following error /bin/sh: /path/to/my/build/dir/file.d: File exists, although .d files does not exist.
Then I keep getting this error, the only way to get rid of it is to remove the whole enclosing directory and use git restore and the system will build successfully.
System info:
git version 2.27.0
GNU Make 4.2.1
Red Hat Enterprise Linux 8.5 (Ootpa)
Free inodes: 426798634
You should remove the # from your line that creates the .d file, so you can see what the command line actually is. It's always a bad idea to add # before your makefile is working 100% correctly. Then you could cut and paste a full failure example into your question, including the command that generated the error message.
Your build lines are not right. During the compilation, you need to use $# not $(OBJ_PATH)/$(notdir $#). It's always wrong to build a file that is not exactly $#.
During the creation of the dependency file $(#:.d=.o) is useless because $# is already set to xxx.o so changing the .d suffix to .o doesn't do anything. You should just use -MT $# here.
You can replace $(OBJ_PATH)/$(notdir $*.d) with the simpler %*.d.
This error is being shown by the shell and there's really no way we can understand what the problem is with the info given. Why would the shell give a "File exists" error when you use ">" to overwrite it?
I have a suspicion that it's not actually this command that is generating that error.

Primitive makefile failure for compiling

I am trying to learn makefile, but I fail badly.
One example (which is very primitive) but I should understand it to go ahead is this one
f90_simple: f1.o
gfortran f1.o
mv a.out f90_simple
f90_simple.o: f1.f90
gfortran -c f1.f90
it does not work, and I get this error
I get this error
make: *** No rule to make target `f1.o', needed by `f90_simple'. Stop.
could you please advise me?
thanks
Your first rule says that before f90_simple can be built, the target f1.o must be built.
But there's no rule in your makefile that tells make how to build the target f1.o, and make can't find any built-in rule that can build it (based on the source files make has available), so it prints that error.
You do have a rule that tells make how to build a target f90_simple.o... but that's not the target make is looking for. Most likely you want your makefile to either be:
f90_simple: f1.o
gfortran $^
mv a.out $#
f1.o: f1.f90
gfortran -o $# -c $<
or else:
f90_simple: f90_simple.o
gfortran $^
mv a.out $#
f90_simple.o: f1.f90
gfortran -o $# -c $<
but you can't mix and match them, or make doesn't know what to do.
I think you would really benefit from reading at least the introductory chapters in The GNU Make Manual.

How to specify directory when use "gcc -c" to generate *.o files? [duplicate]

I am wondering why gcc/g++ doesn't have an option to place the generated object files into a specified directory.
For example:
mkdir builddir
mkdir builddir/objdir
cd srcdir
gcc -c file1.c file2.c file3.c **--outdir=**../builddir/objdir
I know that it's possible to achive this with separate -o options given to the compiler, e.g.:
gcc -c file1.c -o ../builddir/objdir/file1.o
gcc -c file2.c -o ../builddir/objdir/file2.o
gcc -c file3.c -o ../builddir/objdir/file3.o
... and I know that I can write Makefiles via VPATH and vpath directives to simplify this.
But that's a lot of work in a complex build environment.
I could also use
gcc -c file1.c file2.c file3.c
But when I use this approach my srcdir is full of .o garbage afterwards.
So I think that an option with the semantics of --outdir would be very useful.
What is your opinion?
EDIT: our Makefiles are written in such a way that .o files actually placed into builddir/obj. But I am simply wondering if there might be a better approach.
EDIT: There are several approaches which place the burden to achieve the desired behavior to the build system (aka Make, CMake etc.). But I consider them all as being workarounds for a weakness of gcc (and other compilers too).
This is the chopped down makefile for one of my projects, which compiles the sources in 'src' and places the .o files in the directory "obj". The key bit is the the use of the patsubst() function - see the GNU make manual (which is actually a pretty good read) for details:
OUT = lib/alib.a
CC = g++
ODIR = obj
SDIR = src
INC = -Iinc
_OBJS = a_chsrc.o a_csv.o a_enc.o a_env.o a_except.o \
a_date.o a_range.o a_opsys.o
OBJS = $(patsubst %,$(ODIR)/%,$(_OBJS))
$(ODIR)/%.o: $(SDIR)/%.cpp
$(CC) -c $(INC) -o $# $< $(CFLAGS)
$(OUT): $(OBJS)
ar rvs $(OUT) $^
.PHONY: clean
clean:
rm -f $(ODIR)/*.o $(OUT)
How about changing to the directory and running the compile from there:
cd builddir/objdir
gcc ../../srcdir/file1.c ../../srcdir/file2.c ../../srcdir/file3.c
That's it. gcc will interpret includes of the form #include "path/to/header.h" as starting in the directory the file exists so you don't need to modify anything.
A trivial but effective workaround is to add the following right after the gcc call in your Makefile:
mv *.o ../builddir/objdir
or even a soft-clean (possibly recursive) after the compilation is done, like
rm -f *.o
or
find . -name \*.o -exec rm {} \;
You can use a simple wrapper around gcc that will generate the necessary -o options and call gcc:
$ ./gcc-wrap -c file1.c file2.c file3.c --outdir=obj
gcc -o obj/file1.o -c file1.c
gcc -o obj/file2.o -c file2.c
gcc -o obj/file3.o -c file3.c
Here is such a gcc_wrap script in its simplest form:
#!/usr/bin/perl -w
use File::Spec;
use File::Basename;
use Getopt::Long;
Getopt::Long::Configure(pass_through);
my $GCC = "gcc";
my $outdir = ".";
GetOptions("outdir=s" => \$outdir)
or die("Options error");
my #c_files;
while(-f $ARGV[-1]){
push #c_files, pop #ARGV;
}
die("No input files") if(scalar #c_files == 0);
foreach my $c_file (reverse #c_files){
my($filename, $c_path, $suffix) = fileparse($c_file, ".c");
my $o_file = File::Spec->catfile($outdir, "$filename.o");
my $cmd = "$GCC -o $o_file #ARGV $c_file";
print STDERR "$cmd\n";
system($cmd) == 0 or die("Could not execute $cmd: $!");
}
Of course, the standard way is to solve the problem with Makefiles, or simpler, with CMake or bakefile, but you specifically asked for a solution that adds the functionality to gcc, and I think the only way is to write such a wrapper. Of course, you could also patch the gcc sources to include the new option, but that might be hard.
I believe you got the concept backwards...?!
The idea behind Makefiles is that they only process the files that have been updated since the last build, to cut down on (re-)compilation times. If you bunch multiple files together in one compiler run, you basically defeat that purpose.
Your example:
gcc -c file1.c file2.c file3.c **--outdir=**../builddir/objdir
You didn't give the 'make' rule that goes with this command line; but if any of the three files has been updated, you have to run this line, and recompile all three files, which might not be necessary at all. It also keeps 'make' from spawning a seperate compilation process for each source file, as it would do for seperate compilation (when using the '-j' option, as I would strongly suggest).
I wrote a Makefile tutorial elsewhere, which goes into some extra detail (such as auto-detecting your source files instead of having them hard-coded in the Makefile, auto-determining include dependencies, and inline testing).
All you would have to do to get your seperate object directory would be to add the appropriate directory information to the OBJFILES := line and the %.o: %.c Makefile rule from that tutorial. Neil Butterworth's answer has a nice example of how to add the directory information.
(If you want to use DEPFILES or TESTFILES as described in the tutorial, you'd have to adapt the DEPFILES := and TSTFILES := lines plus the %.t: %.c Makefile pdclib.a
rule, too.)
Meanwhile I found a "half-way" solution by using the -combine option.
Example:
mkdir builddir
mkdir builddir/objdir
cd srcdir
gcc -combine -c file1.c file2.c file3.c -o ../builddir/objdir/all-in-one.o
this "combines" all source files into one single object file.
However, this is still "half-way" because it needs to recompile everything when only one source file changes.
I think that telling pass gcc doesn't have an separate option to say where to put object file, since it already has it. It's "-c" - it says in what directory to put object.
Having additional flag for directory only must change meening of "-c".
For example:
gcc -c file.c -o /a/b/c/file.o --put-object-in-dir-non-existing-option /a1/a2/a3
You can not put /a/b/c/file.o under /a1/a2/a3, since both paths are absolute. Thus "-c" should be changed to name object file only.
I advise you to consider a replacement of makefile, like cmake, scons and other.
This will enable to implement build system as for for simple project as well as for bigger one too.
See for example how it's easy to compile using cmake your example.
Just create file CMakeList.txt in srcdir/:
cmake_minimum_required(VERSION 2.6)
project(test)
add_library(test file1.c file2c file3.c)
And now type:
mkdir -p builddir/objdir
cd builddir/objdir
cmake ../../srcdir
make
That's all, object files will reside somewhere under builddir/objdir.
I personaly use cmake and find it very convinient. It automatically generates dependencies and has other goodies.
I am trying to figure out the same thing. For me this worked
CC = g++
CFLAGS = -g -Wall -Iinclude
CV4LIBS = `pkg-config --libs opencv4`
CV4FLAGS = `pkg-config --cflags opencv4`
default: track
track: main.o
$(CC) -o track $(CV4LIBS) ./obj/main.o
ALLFLAGS = $(CFLAGS) $(CV4FLAGS)
main.o: ./src/main.cpp ./include/main.hpp
$(CC) $(ALLFLAGS) -c ./src/main.cpp $(CV4LIBS) -o ./obj/main.o
``
This is among the problems autoconf solves.
If you've ever done ./configure && make you know what autoconf is: it's the tool that generates those nice configure scripts. What not everyone knows is that you can instead do mkdir mybuild && cd mybuild && ../configure && make and that will magically work, because autoconf is awesome that way.
The configure script generates Makefiles in the build directory. Then the entire build process happens there. So all the build files naturally appear there, not in the source tree.
If you have source files doing #include "../banana/peel.h" and you can't change them, then it's a pain to make this work right (you have to copy or symlink all the header files into the build directory). If you can change the source files to say #include "libfood/comedy/banana/peel.h" instead, then you're all set.
autoconf is not exactly easy, especially for a large existing project. But it has its advantages.
Personally for single files I do this,
rm -rf temps; mkdir temps; cd temps/ ; gcc -Wall -v --save-temps ../thisfile.c ; cd ../ ; geany thisfile.c temps/thisfile.s temps/thisfile.i
temps folder will keep all the object, preprocessed and assembly files.
This is a crude way of doing things and I would prefer above answers using Makefiles.

Makefile rule is not executing in Linux

I am trying to build the Atmel BitCloud v3.2 sample application Blink with the makefile in Linux and Mac. Everything works fine in Windows. But in Posix-like systems the following lines are not working:
all: directories images root_files size
$(OBJ_PATH)/%.o: $(SRCS)
$(CC) $(CFLAGS) $(filter %/$(subst .o,.c,$(notdir $#)), $(SRCS)) -o $#
Therefore, the compiler is not being executed and object files are not being created. As the result the linker displays error messages such as
avr-gcc: error: All_MegaRf_Atmega256rfr2_8Mhz_Gcc/Obj/blink.o: No such file or directory
The line $(OBJ_PATH)/%.o: $(SRCS) is the source of the problem.
If I substitute it with smth like $(OBJ_PATH)/blink.o: ../../src/blink.c the corresponding object-file is being successfully created.
I was even able to build the whole application by manually setting build targets as follows:
$(OBJ_PATH)/blink.o: ../../src/blink.c
$(CC) $(CFLAGS) $(filter %/$(subst .o,.c,$(notdir $#)), $(SRCS)) -o $#
$(OBJ_PATH)/stdPdsEvents.o: ../../../../BitCloud/Components/PersistDataServer/std/src/stdPdsEvents.c
$(CC) $(CFLAGS) $(filter %/$(subst .o,.c,$(notdir $#)), $(SRCS)) -o $#
for all the .c files in the project.
The list of sources on the other hand is defined like this:
SRCS = \
../../src/blink.c \
../../../../BitCloud/Components/PersistDataServer/std/src/stdPdsMemAccess.c \
../../../../BitCloud/Components/PersistDataServer/std/src/stdPdsTimer.c \
Can anyone help me to figure out why is the pattern matching not working and how to recover it.
Note: Similar topic has already been open here, but the solution found by th author himself wasn't explained well in my opinion, so I couldn't solve my problem.
The construct to have each object file depend on all source files and then have the compilation step fish the actually useful file out of the list of sources is quite dubious. A better approach would be to generate a Makefile snippet and include it, something like this:
makefile.d:
echo "$(SRCS)" \
| tr ' ' '\n' \
| sed -n 's%\(.*\)/\([^/]*\)\.c$$%$(OBJ_PATH)/\2.o: \1/\2.c%p' >$#
include makefile.d
All details of sed are not properly standardized, so you may be better off rewriting the substitution in Perl or something. The beef here is how we capture the path and the base name and generate a specific rule for each dependency.
Managed to solve it finally.
In order to make it compile both in Windows and Linux one should change the makefile as shown below:
objects := $(patsubst %.c,$(OBJ_PATH)/%.o,$(notdir $(SRCS)))
$(objects): $(SRCS)
#$(OBJ_PATH)/%.o: $(SRCS)
$(CC) $(CFLAGS) $(filter %/$(subst .o,.c,$(notdir $#)), $(SRCS)) -o $#
where $(OBJ_PATH)/%.o: $(SRCS) shall be commented or removed.
After having done this way the project can be built under linux or mac and under windows both in Atmel Studio 6.2 and Atmel Studio 7. The latter was not able to build just like it was not possible in linux or mac.

Makefile with multiple targets

Hopefully this is a very simple question. I have a makefile pattern rule that looks like this:
%.so : %.f %.pyf
f2py -c -L${LAPACK_DIR} ${GRASPLIBS} -m $* $^ ${SOURCES} --opt='-02' --f77flags='-fcray-pointer' >> silent.txt
I want the makefile to build a number of .so files, so I tried to get it to build two files (radgrd_py.so and lodiso_py.so) by doing this:
radgrd_py.so lodiso_py.so:
%.so : %.f %.pyf
f2py -c -L${LAPACK_DIR} ${GRASPLIBS} -m $* $^ ${SOURCES} --opt='-02' --f77flags='-fcray-pointer' >> silent.txt
and then tried this:
radgrd_py.so:
lodiso_py.so:
%.so : %.f %.pyf
f2py -c -L${LAPACK_DIR} ${GRASPLIBS} -m $* $^ ${SOURCES} --opt='-02' --f77flags='-fcray-pointer' >> silent.txt
But in each case, it only builds the first target that I specify. If I run 'make radgrd_py.so' it works fine, I'm just not sure how to specify a list of files that need to be built so I can just run 'make'.
The usual trick is to add a 'dummy' target as the first that depends on all targets you want to build when running a plain make:
all: radgrd_py.so lodiso_py.so
It is a convention to call this target 'all' or 'default'. For extra correctness, let make know that this is not a real file by adding this line to your Makefile:
.PHONY: all
Best way is to add:
.PHONY: all
.DEFAULT: all
all: radgrd_py.so lodiso_py.so
Explanations:
make uses the first target appearing when no .DEFAULT is specified.
.PHONY informs make that the targets (a coma-separated list, in fact) don't create any file or folder.
all: as proposed by schot

Resources