Override an Include (Remove Path) - makefile

There is a library that I have downloaded that has the following include;
#include <http-parser/http_parser.h>
They provide their own library for it, which resides in the http_parser folder.
The ESP-IDF have http_parser.h included. If I change the #include to be #include <http_parser.h>, it compiles.
I'm curious - can this be done using the Make or CMake system without having to edit the .c source file?

If you can't/don't want to fix the source file, you can manipulate directory structure to match, e.g.:
$ cat Makefile
CPPFLAGS = -I.
test: test.o
test.o: http_parser/http_parser.h
http_parser/%.h : %.h
mkdir -p $(#D)
ln -sfr $< $(#D)
It will create a requested folder and make a symbolic link to an existing file, which will allow compilation to proceed:
$ cat test.c
#include <http_parser/http_parser.h>
int main(int argc, char *argv[])
{
return 0;
}
$ make
mkdir -p http_parser
ln -sfr http_parser.h http_parser
cc -I. -c -o test.o test.c
cc test.o -o test
$ ls -l http_parser
lrwxrwxrwx 1 raspy raspy 16 Mar 11 22:29 http_parser.h -> ../http_parser.h

Related

Why does Makefile re-compile when source file copied from other directory

My Makefile has
all: depends hello.o
depends:
cp other_dir/hello.c ./hello.c
hello.o: hello.c
cc -c $< -o $#
Why it's compiling object file hello.o everytime when i copy source file from other_dir to present working directory
Your last rule says build hello.o from hello.c when the latter is newer than the former. When you copy hello.c from depends/ it will update timestamp on hello.c and hence considered newer.
$ stat hello.c|grep Modif
Modify: 2022-12-29 23:56:31.041115631 -0500
$ make
cp other_dir/hello.c ./hello.c
cc -c -o hello.o hello.c
$ stat hello.c|grep Modif
Modify: 2022-12-29 23:56:42.225075833 -0500
You can ask cp, with the option --preserve=timestamp to not update timestamp when it's being copied:
$ make
cp --preserve=timestamp other_dir/hello.c ./hello.c

Why doesn't this Makefile work?

I have this C file:
// test.c
#include <stdio.h>
int main()
{
printf("Hello World!\n");
return 0;
}
And this Makefile
OBJS=$(patsubst %.c,%.o,$(wildcard *.c))
EXEC=hello.exe
all: $(EXEC)
$(EXEC): $(OBJS)
.PHONY: all
When I do make it doesn't create my target hello.exe why?
$ make
cc -c -o hello.o hello.c
It doesn't either work with hello.exe:
$ make hello.exe
make: Nothing to be done for 'hello.exe'.
And hello.exe doesn't exist:
$ ls hello.exe
ls: cannot access 'hello.exe': No such file or directory
I use this version of GNU Make
$ make --version
GNU Make 4.2.1
Built for x86_64-unknown-cygwin
Copyright (C) 1988-2016 Free Software Foundation, Inc.
EDIT
It actually works when I name my executable the same of any of my files. So it works with:
EXEC=hello
See:
$ make
cc -c -o hello.o hello.c
cc hello.o -o hello
That said I don't understand why it only works that way.
The version with hello.exe does not work because make has no implicit rule to tell it how to turn a bunch of *.o into a single *.exe.
But it does have implicit rules (at least those specified by POSIX) to turn hello.c into hello.o and link into hello.
Remember, Unix is not DOS. Forget the .exe when you're on Unix.

gfortran makefile 'can't open included file'

I'm having an issue with a makefile compiling and I'm not sure where to start diagnosing this. It was generated for a colleague's OS X system, and I'm trying to implement it on my linux system. It worked on the OS X computer. I've updated library locations to represent where they live on my computer - and this is likely the biggest source of error, as gfortran procedure shouldn't be different, no?
The included files: file0.i, ... fileN.i all live in the same directory as the makefile.
I'm certain if I could compile the first object file I could get through the rest and complete my PhD or save the world or something.
A snippet of the file follows:
# %W% %G%
# Makefile for directory ~/Documents/workstuff/project/program
#
fflags = -O3 -I. -I/usr/local/include -frecord-marker=4 -ffree-form
## -fdefault-real-8 -fdefault-double-8
lflags = -L/usr/local/lib -lnetcdf -lnetcdff
# for debugging, use these options
fflags = -g
lflags = -g
chem = ~/Documents/workstuff/project/chem
main.o: $(chem)/code/main.f file0.i file1.i file2.i
gfortran -c $(fflags) $(chem)/code/main.f
And I receive the following error:
~/Documents/workstuff/project/program/chem/code/main.f:11: Error: Can't open included file 'file0.i'
makefile:14: recipe for target 'main.o' failed
make: *** [main.o] Error 1
I thought it might be an executable issue, so we went from 644 to 744:
username$ file file0.i
file0.i: ASCII text
username$ stat -c '%A %a %n' file0.i
-rwxr--r-- 744 file0.i
Still same error. Double-check that my flags are pointing to the right place:
username$ nf-config --fflags
-I/usr/local/include
username$ nf-config --flibs
-L/usr/local/lib -lnetcdff -lnetcdf -lnetcdf
For what its worth, file0.i contains the following, which I have of course filled with nonsense numbers for sharing online:
$Id: file0.i,v 1.12 2012/12/31 04:25:23 username Exp $
PARAMETER (NLT=19,NHT=51,DZETA=0.5/3.,Psurf=100.)
PARAMETER (NLT1=NLT+1,NHT1=NHT+2,NLT2=3*NLT+1,NHT2=4*NHT+1)
PARAMETER (NDYEAR=33,NTN=75,NTCV=14,NLV=21,NPOL=8,NGSP=3)
PARAMETER (NDIST=111,TD1=110.,NVC=1,NVSP=1,NVTIME=3)
Does anything obvious stick out to anyone?
I do not know gfortran very well, so I may be completely wrong, but for gcc, if a C source file contains:
#include <foo.h>
and if gcc is called with -I., foo.h will be searched in the same directory as the source file, not in the directory where you call gcc from. Example:
$ ls foo
bar.c bar.h
$ cat foo/bar.c
#include <bar.h>
int main(int argc, char **argv) {
return 0;
}
$ gcc -I. foo/bar.c
foo/bar.c:1:10: error: 'bar.h' file not found with <angled> include; use "quotes" instead
#include <bar.h>
^~~~~~~
"bar.h"
1 error generated.
$ gcc -Ifoo foo/bar.c
$
So, it could be that you should put your header files in the same directory as your source file or use a -I<path> where <path> is the absolute path of where you call gfortran from.

g++ output: file not recognized: File format not recognized

I am trying to build program with multiple files for the first time.
I have never had any problem with compliling program with main.cpp only.
With following commands, this is the result:
$ g++ -c src/CNumber.cpp src/CNumber.h -o src/CNumber.o
$ g++ -c src/CExprPart.cpp src/CExprPart.h -o src/CExprPart.o
$ g++ -c src/CExpr.cpp src/CExpr.h -o src/CExpr.o
$ g++ -c src/main.cpp -o src/main.o
$ g++ src/CNumber.o src/CExprPart.o src/CExpr.o src/main.o -o execprogram
src/CNumber.o: file not recognized: File format not recognized
collect2: error: ld returned 1 exit status
What could cause such error and what should I do with it?
Using Linux Mint with gcc (Ubuntu/Linaro 4.7.2-2ubuntu1).
Thank you
This is wrong:
g++ -c src/CNumber.cpp src/CNumber.h -o src/CNumber.o
You shouldn't "compile" .h files. Doing so will create precompiled header files, which are not used to create an executable.
The above should simply be
g++ -c src/CNumber.cpp -o src/CNumber.o
Similar for compiling the other .cpp files
I ran into this error in building something - it turned out to be due to a previous build failing while compiling a source file to an .o file - that .o file was incomplete or corrupted, so when I tried another build it gave this error on that file.
The solution was to just delete the .o file (or run make clean, if you have a makefile with that target).
Try putting all of the following files in one directory:
example.cpp:
#include<iostream>
#include<string>
#include "my_functions.h"
using namespace std;
int main()
{
cout << getGreeting() << "\n";
return 0;
}
my_functions.cpp:
#include<string>
using namespace std;
string getGreeting()
{
return "Hello world";
}
my_functions.h:
#ifndef _MY_FUNCTIONS_H
#define _MY_FUNCTIONS_H
#include<string>
using namespace std;
string getGreeting();
#endif
Then issue these commands:
$ g++ example.cpp my_functions.cpp -o myprogram
~/c++_programs$ ./myprogram
Hello world

Beginner's question, trying to understand how the linker searches for a static library

I have a working setup, where all files are in the same directory (Desktop). The Terminal output is like so:
$ gcc -c mymath.c
$ ar r mymath.a mymath.o
ar: creating archive mymath.a
$ ranlib mymath.a
$ gcc test.c mymath.a -o test
$ ./test
Hello World!
3.14
1.77
10.20
The files:
mymath.c:
float mysqrt(float n) {
return 10.2;
}
test.c:
#include <math.h>
#include <stdio.h>
#include "mymath.h"
main() {
printf("Hello World!\n");
float x = sqrt(M_PI);
printf("%3.2f\n", M_PI);
printf("%3.2f\n", sqrt(M_PI));
printf("%3.2f\n", mysqrt(M_PI));
return 0;
}
Now, I move the archive mymath.a into a subdirectory /temp. I haven't been able to get the linking to work:
$ gcc test.c mymath.a -o test -l/Users/telliott_admin/Desktop/temp/mymath.a
i686-apple-darwin10-gcc-4.2.1: mymath.a: No such file or directory
$ gcc test.c -o test -I/Users/telliott_admin/Desktop/temp -lmymath
ld: library not found for -lmymath
collect2: ld returned 1 exit status
What am I missing? What resources would you recommend?
Update: Thanks for your help. All answers were basically correct. I blogged about it here.
$ gcc test.c /Users/telliott_admin/Desktop/temp/mymath.a -o test
edit: gcc only needs the full path to the library for static libraries. You use -L to give a path where gcc should search in conjunction with -l.
To include the math libraries, use -lm, not -lmath. Also, you need to use -L with the subdirectory to include the library when linking (-I just includes the header for compiling).
You can compile and link with:
gcc test.c -o test -I/Users/telliott_admin/Desktop/temp /Users/telliott_admin/Desktop/temp/mymath.a
or with
gcc test.c -o test -I/Users/telliott_admin/Desktop/temp -L/Users/telliott_admin/Desktop/temp -lmymath
where mymath.a is renamed libmymath.a.
See link text for comments (search for "bad programming") on the practices of using -l:
In order for ld to find a library with -l, it must be named according to the pattern libyourname.a. Then you use -lmymath
So, there is no way to get it to take /temp/mymath.a with -l.
If you named it libmymath.a, then -L/temp -lmymath would find it.

Resources