I am struggling with making a makefile for the sample code below using curses.h.
#include <stdio.h>
#include <stdlib.h>
#include<curses.h>
int main(){
WINDOW *initscr(void);
initscr();
int endwin(void);
return 0;
}
I included library and header in Netbeans, but when I try to build with makefile:
CC=C:\TDM-GCC-64\bin\gcc
CFLAGS=-std=gnu99 -Werror -Wall -lm -lncurses
DEPS=curses.h
OUTPUT=main
all:
echo "Building all"
$(CC) $(CFLAGS) render.c -o $(OUTPUT)
it gives me :
echo "Building all"
Building all
C:\TDM-GCC-64\bin\gcc -std=gnu99 -Werror -Wall -lm -lncurses render.c -o main
render.c:3:19: fatal error: curses.h: No such file or directory
#include<curses.h>
^
compilation terminated.
make.exe": *** [all] Error 1
BUILD FAILED (exit value 2, total time: 150ms)
Just add -I. -L. to your CFLAGS macro, this adds the project library to the search paths of both the preprocessor and linket. This should work provided you have curses header and library files in your project folder. If the header or library files are in different folders just modify -I or -L flags accordingly.
Your last comment suggested that the preprocessing and compilation went fine but the linker could not locate the library file.
As a general note, it would be a good idea to put compiler flags to CFLAGS and linker flags to a different macro, say LDFLAGS.
Macro DEPS should also be used to enable incremental compilation. It is usually used as a dependency to the compilation rule but since you don't have it separately you could put it besides all such as this:
all : $(DEPS)
Here is what I did, it works, but it still returns 8 errors.
Solution to fix 1 of the 8 errors is listed further down.
I cd to the location of thadgavin.c
( for me it is "pset1/source")
For ubuntu (I used 16.04)
$ cc thadgavin.c -lm -lncurses
$ ./a.out
You can rename a.out to thadgavin (same as "make" would have done if it would have worked).
$ mv a.out thadgavin
There you go, hope this helps resolve the last of the errors.
Note:
There is an easy error fix in main(), you need to specify it as an int first. I believe it is on line 61?
Eg;
"int main()" shows only as "main()" due to "int" being up at the top with the abstracted layout syntax I do not believe it knows it has been called as an int. I may be wrong, hopefully someone else can shed light to this problem.
https://youtu.be/oOUgU0z4qeY
If you solve any of the rest of the errors, please post to my video or email Python253#gmail.com for others to benefit from your solution.
Thank you,
My name is Daniel Paul Evans
.... And this is CS50!
Related
I was looking at the net-snmp code and I found something odd in the Makefile of the snmplib itself. The last couple of thousands of lines are nothing but rules in this form:
./dir_utils.lo: ../include/net-snmp/output_api.h
for EVERY library object and header file. Even those that are not compiled, depending on which flags are selected in the configure script.
I looked at the "make" manual but I didn't find this exact case. It may be (as stated in 5.9) that they do this to exclude the possibility that an implicit recipe is called on the target, but other than that I have no idea.
Another reason might be to "break" the compilation if the library is tampered with (deleting whatever header in the project causes in fact the makefile to crash because it can't execute the rule).
This is an educated guess but I would like to know the theory behind this. I mean the makefile already builds whatever it has to build, why include all these rules in explicit form?
Thanks
As I expect you know, the Makefile is generated by the ./configure script.
All the lines that interest you are auto-generated dependencies. Actually,
they are just the appended contents of the file Makefile.depend in the same
directory, which is part of the distribution and was generated with the aid
of gcc ahead of time.
So e.g.
./dir_utils.lo: ../include/net-snmp/output_api.h
just informs make of the vitally important fact that ./dir_utils.lo
depends on ../include/net-snmp/output_api.h. Then if ./dir_utils.lo
is older than ../include/net-snmp/output_api.h, make will re-make
./dir_utils.lo provided it has some recipe to do that, which it has.
Here is a project:
main.c
#include "hw.h"
#include <stdio.h>
int main(void)
{
puts(HW);
return 0;
}
hw.h
#ifndef HW_H
#define HW_H
#define HW "Hello World"
#endif
Makefile
CC := gcc
.PHONY: all clean
all: hw
hw: main.o
$(CC) -o $# $<
clean:
rm -f hw main.o
Build and run it:
$ make && ./hw
gcc -c -o main.o main.c
gcc -o hw main.o
Hello World
But there's a bug in the makefile. It doesn't know that main.o
depends on hw.h:
$ touch hw.h
$ make
make: Nothing to be done for 'all'.
Append that dependency to the makefile:
main.o: hw.h
and retry:
$ make
gcc -c -o main.o main.c
gcc -o hw main.o
Bug fixed.
It seems to be a common issue but I can't wrap solve this problem.
I have some .c code that I compile using a makefile. The goal is to create a shared object (.so) so that I can run the C code from R.
Here is my makefile:
obs = R_wrapper.o G.o develop.o utilities.o
CFLAGS = -arch x86_64 -std=gnu99 -I/Library/Frameworks/R.framework/Resources/include -I/Library/Frameworks/R.framework/Resources/include/x86_64 -DNDEBUG -I/usr/local/include -fPIC -g -O3 -c
LFLAGS = -arch x86_64 -std=gnu99 -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -L/usr/local/lib -O3 -lgsl -lm -lgslcblas
R_wrapper : $(obs)
$gcc $(LFLAGS) $(obs) -o R_wrapper.so
R_wrapper.o : R_wrapper.c constants.h develop.h G.h
$gcc $(CFLAGS) R_wrapper.c
G.o : G.c G.h constants.h utilities.h develop.h
$gcc $(CFLAGS) G.c develop.c
develop.o : develop.c develop.h G.h constants.h
$gcc $(CFLAGS) develop.c
utilities.o : utilities.c develop.h
$gcc $(CFLAGS) utilities.c
It works fine on the computer in my lab but it doesn't work on my personal computer. What causes this issue is these two lines at the beginning of my R_wrapper.c.
#include </opt/local/include/gsl/gsl_randist.h>
#include </opt/local/include/gsl/gsl_rng.h>
I have tried to move these files around and give different paths, put the files in the gal_type.h files in the same directory as my R_wrapper file, I have tried to rename my directories so that the path is more conventional but the OS did not give me the right to rename opt into usr (which probably makes obvious sense). I haven't created the makefile and don't fully get it. I would suppose I'd need to modify the path after the -I argument somewhere in CFLAGS OR LFLAGS.
EDIT 1
I changed R_wrapper.c on my lab computer to get rid of the whole path in #include <...>. Compilation failed as #Beta predicted. Then, I changed my makefile to add -I/opt/local/include/gsl to CFLAGS. I don't know what you mean by Verify that the makefile still works. I tried to compile with my edited makefile on my lab computer and it failed. I then re-edited my makefile changing -I/opt/local/include/gsl to -I/usr/local/include/gsl because on my lab computer the gsl folder is at /usr/local/include/gsl. -I/opt/local/include/gsl is the location of the gsl folder on my computer. So I am stuck here in your procedure.
Edit 2
I moved my gsl folder around my computer trying to include from different paths. And some interesting stuff happen. For example when I put my gsl folder in Users/remi/Documents/Biologie/programing/C/ and write (in CFLAGS)
-I/Users/remi/Documents/Biologie/programing/C/
I get this error:
R_wrapper.c:43:10: fatal error: 'gsl_randist.h' file not found
#include <gsl_randist.h> // goal.
When I write (in CFLAGS)
Users/remi/Documents/Biologie/programing/C/gsl
I get this error message:
"In file included from R_wrapper.c:43: /Users/remi/Documents/Biologie/programing/C/gsl/gsl_randist.h:22:10: fatal error:
'gsl/gsl_rng.h' file not found
#include <gsl/gsl_rng.h>"
Transferring comment to answer
Judging from the message about gsl/gsl_rng.h not being found that is mentioned in Edit 2, you should be writing
#include <gsl/gsl_randist.h>
(with the path prefix of gsl/ before the header name) in your source code. This is a common convention. You then specify in the -I option the name of the directory containing the gsl subdirectory that contains the gsl_*.h headers. In your Edit 2, you say you put the gsl directory into /Users/remi/Documents/Biologie/programing/C/, so you are then correct to use:
-I/Users/remi/Documents/Biologie/programing/C/
on the command line as you tried.
You should read the documentation, and if it says write either of these:
#include <gsl/gsl_randist.h>
#include "gsl/gsl_randist.h"
then that is what you should write in your code, because (as you've discovered the hard way) if you don't, it won't work.
Beta's answer also states
In general it's a bad idea to write paths into the #include statements unless you really have to; it causes just this kind of problem.
I agree, but would state it more strongly:
Do not write complete paths into the #include statements ever.
If you do write them, it radically limits the portability of your code. You can't rely on other people's machines having software installed in the same place as it is installed on your system. If you tried it in open source software, you'd be laughed out of court.
Be wary of people who get cute with ../somedir/header.h too — see What are the benefits of a relative path such as "../include/header.h" for a header?.
I observe that the GNU Scientific Library manual has an example program which starts:
#include <stdio.h>
#include <gsl/gsl_sf_bessel.h>
and the section on Compiling and Linking says:
The library header files are installed in their own gsl directory. You should write any preprocessor include statements with a gsl/ directory prefix thus,
#include <gsl/gsl_math.h>
If the directory is not installed on the standard search path of your compiler you will also need to provide its location to the preprocessor as a command line flag. The default location of the gsl directory is /usr/local/include/gsl.
In general it's a bad idea to write paths into the #include statements unless you really have to; it causes just this kind of problem.
On your lab computer, edit R_wrapper.c:
#include <gsl_randist.h>
#include <gsl_rng.h>
The build should now fail. If so then this verifies that you don't have other versions of these headers floating around, or links to them, or whatever. Confirm that it fails, then back out the change, and confirm that it works again.
Then add -I/opt/local/include/gsl to CFLAGS. Verify that the makefile still works.
Then edit R_wrapper.c again; now the build should succeed.
Decide where you would like to keep these files (gsl_randist.h and gsl_rnd.h) on your personal computer, and modify CFLAGS accordingly on your home version of the makefile.
Once all of that is working perfectly, we can show you how to write one makefile that will work on both machines.
Also, you can improve your makefile rules in other ways, but I must ask one question first:
G.o : G.c G.h constants.h utilities.h develop.h
$gcc $(CFLAGS) G.c develop.c
Does G.o really require develop.c? If so then you should probably reexamine your source files, because this is really unhygienic.
I have a C programming exercise, which I have written (and runs perfectly) in Visual Studio on Windows. I now have to make sure it runs OK on Linux as well, and need to create a makefile for it (it is part of the assignment). Here is my makefile:
all: genericdfs.a sudSolver
genericdfs.a: genericdfs.c genericdfs.h
gcc -Wvla -c genericdfs.c
ar rs genericdfs.a genericdfs.c
sudSolver.o: sudSolver.c sudTree.h genericdfs.h
gcc -Wvla -c sudSolver.c -lm
sudukutree.o: sudTree.c sudTree.h
gcc -c sudTree.c -lm
sudSolver: sudSolver.o sudTree.o genericdfs.a
gcc -Wvla sudSolver.o sudTree.o -L. -lgenericdfs -o sudukusolver -lm
clean:
rm -f sudSolver.o
rm -f sudTree.o
rm -f genericfs.o
OK so the main C file is sudSolver which has includes for sudTree.h and math.h (hence the -lm)
sudTree.c includes sudTree.h and genericdfs.h as well.
One of the requirements is to create a .a library which should be linked to the main C file at the linkage operation.
We were given next to nothing of an explanation as how to write these makefiles so all I wrote above was according to makefile tutorials I found online.
This makefile however doesn't work, there seems to be a problem with the linkage to the library as this is the error that is being returned:
cannot find cannot find -lgenericdfs
I tried shifting things around but nothing seems to work, another error which appeared when I put -L. genericfs.a in the linkage line:
genericdfs.a: error adding symbols: Archive has no index; run ranlib to add one
Could anyone please explain how I link to the .a library which was created? I suppose its not that complicated but for the life of me I cannot get it to work
Thank you to anyone who helps!
EDIT
I managed to make it work by changing the line
ar rs genericdfs.a genericdfs.c
into
ar rs libgenericdfs.a genericdfs.o
and updating final linkage line to libgenericdfs.a
But now there is a different problem. I included a couple rm -f commands to a clean: tag, but they don't delete the files written there when i run "make" from the terminal.
If I run "make clean" then everything gets removed. Do I need to add "clean" to the "all" tag at the top? I read that you should not do that
gcc is passed libraries by using
gcc -Lfull/path/to/library
Or if the library name starts with 'lib' and is on a library search path then you can use -l with lib and .a removed. For example with library called libtest.a .
gcc -ltest
There are a couple of special cases for well used libraries like maths -lm and zlib I think.
On the PI, I needed the i2c.so library using this git: https://github.com/silentbobbert/pi_sensors. When running makefile from this git to get the i2c.so, i received this error:
Here are the .c and the .h files:
https://github.com/silentbobbert/pi_sensors/tree/master/Info/LinuxInterface
For reference, here is the contents of makefile:
SHELL = /bin/sh
CC = gcc
FLAGS = -c -Wall -Werror -fpic
DEBUGFLAGS = -O0 -D _DEBUG
RELEASEFLAGS = -O2 -D NDEBUG
TARGET = i2c.so
SOURCES = $(shell echo *.c)
HEADERS = $(shell echo *.h)
OBJECTS = $(SOURCES:.c=.o)
PREFIX = $(DESTDIR)/usr/local
BINDIR = $(PREFIX)/bin
all:
$(CC) $(FLAGS) $(RELEASEFLAGS) $(SOURCES)
$(CC) -shared -o $(TARGET) $(OBJECTS)
as others have said, this is C code not C#.
Anyhow, you have two errors (and they do not relate directly) to the makefile but rather your compilation environment and the code itself.
OK, so how to approach something like this. First notice the first line in your screen-capture, that is the command that is being executed that is generating the error messages, I'll reproduce it here for you;
gcc -c -Wall -Werror -fpic -O2-D NDEBUG i2c_get.c i2c_set.c i2cbusses.c i2cset.c util.c
With this command we are compiling (note the -c flag) a bunch of source files into a single object file, the presence of the `c' flag implies that no linking is performed here. This is relevant so we know where along the tool-chain we are, and the type of errors we can expect (typically either syntax errors or missing header files).
The first error;
i2cset.c: In function 'check_funcs'
i2cset.c:56:2 error: implicit declaration of function 'iotcl' [-Werror=implicit-function-declaration]
is kinda saying, "hey, I can see that ioctl is a function, but you haven't told me anything about it so I'm going to assume that its signature is int ioctl() — a function with an indeterminate (but fixed, not variadic) argument list that returns an int". Given that you are compiling on a Linux-based system, adding #include <sys/ioctl.h> to the top of the file should fix this error.
The second error;
i2cset.c:63:7: error: 'I2C_SMBUS_BYTE' undeclared (first use in this function)
is related to the first error; and it is kinda saying 'hey, you haven't told me anything about I2C_SMBUS_BYTE'. Again, the most common reason for seeing this error is a missing header file. Looking at the source files you've provided a link to, it seems that I2C_SMBUS_BYTE is defined in
the header file i2c-dev.h, which however appears to be included in i2cset.c by: #include <linux/i2c-dev.h>.
At this point I'd insure that your compiler (gcc) can find the header file. From the error messages you are getting, I'm guessing that it is not, but you should be seeing an error message from the compiler about not being able to find the file. Also, if the file is on your system check to see if has the appropriate contents as compared to the git site.
Finally, the remain errors that you are seeing should be fixed as well as they are all basically the same thing.
So I'm having trouble getting even a simple Makefile to work. Heres what I have:
proj : driver.o
icc -g -O3 -openmp driver.o -o proj
driver.o : driver.c driver.h
icc -g -O3 -openmp driver.c
I feel like it's pretty straight forward. Proj only depends on driver.o which in turn depends on driver.c and driver.h. When run, the compiler fails with 'could not open source file "driver.h" ' at the include within the driver.c file. What am I missing?
You should give icc a -I. option to get it to look for include files in the current directory.
icc -I. -c -g -O3 -openmp driver.c
(I took the liberty of also adding the -c flag to prevent linking.)
Assuming you run make from the directory where all source files and headers reside, make sure you use quotes in your include directive:
#include "driver.h"
...rather than:
#include <driver.h>
The latter will search the system include path (and you will have to add the current directory to that path as larsmans suggested).
Is it in the correct folder? also the way you're compiling you might have to add -c to the command line to compile driver.o instead of trying to create a complete exectuable (only used to gcc so this might not be required).
Other than that (and the possible addition of the -I flag larsmans mentioned I can't see any other issue.