I'm pretty new to C and to programming so I hope you guys have a little patience.
However I try to describe my problem as precise as possible.
I'm using mingw32 on my Windows 7 computer and I just learned about 'make'.
I have written some source-code files and a Makefile. What I want is, that the Makefile
compiles my source-code int object code and then link it together to one executable
(I guess that's nothing wild for a pro).
So here is my code:
first.c:
#include<stdio.h>
#include"second.h"
int main()
{
float x = 12.0;
printf("Result is: %.2f\n",go_to_the_other(x));
return 0;
}
second.h
float go_to_the_other(float f);
second.c
float go_to_the_other(float f)
{
float calc = f + 10;
return calc;
}
And the Makefile is (and yes, I used only tabs):
second.o: second.c second.h
gcc -c second.c
first.o: first.c
gcc -c first.c
first: first.o second.o
gcc first.o second.o -o first
This is just an easy example, but it pretty much describes my problem.
I have all files in the same directory, and I use the command line:
mingw32-make first
But instead of compiling my files, I only get the message:
cc first.c -o first
process_begin: CreateProcess(NULL, cc first.c -o first, ...) failed
make (e=2): The system cannot find the file specified.
<builtin>: recipe for target 'first' failed
mingw32-make: ***[first] Error 2
I guess it's probably something really stupid, but I just can't figure out
what I'm doing wrong. I really appreciate any help on this.
Thank you so much in advance.
So I went and tried it and... it works for me with MinGW-4.7.1 on a Win7 machine.... I'm wondering if make it picking up an environment variable or some such.
Try verifiying the version of make and gcc are what you expect
mingw32-make -v
gcc -v
mingw32-gcc -v
Also Try this makefile and see what happens.
CC = mingw32-gcc
second.o: second.c second.h
$(CC) -c second.c
first.o: first.c
$(CC) -c first.c
first: first.o second.o
$(CC) first.o second.o -o first
Note convert spaces to tabs!
And compile via
mingw32-make SHELL=cmd.exe first
See what happens.
Related
I am porting a project written in C from a CentOS 7 (Core) to an Ubuntu 20.04.1 LTS (Focal Fossa) system. The project relies heavily on the <cpuset.h> library, and compiles and executes correctly on the CentOS system. However, when I try to use functions from cpuset.h on the Ubuntu system, I get 'undefined reference' errors.
The following code, stored in file test.c, compiles and runs correctly on CentOS:
#define _GNU_SOURCE
#include<stdio.h>
#include <cpuset.h>
int main(){
int x = cpuset_version();
printf("cpuset lib version: %d\n",x );
return 0;
}
How I compile:
gcc -Wall -O2 -std=gnu99 -g -lcpuset test.c -o test
Output:
[xxxx#CentOS]$ ./test
cpuset lib version: 3
However, when I try to compile the same test.c file on the Ubuntu system, I get this error:
xxxx#Ubuntu:$ gcc -Wall -O2 -std=gnu99 -g -lcpuset test.c -o test
/usr/bin/ld: /tmp/ccpxlk4F.o: in function `main':
test.c:8: undefined reference to `cpuset_version'
collect2: error: ld returned 1 exit status
Furthermore, this is not limited to the <cpuset.h> library. I tried to use a simple function from <pthread.h> and it also gave me the same error. Can anyone help with identifying why I cannot use shared libraries on the Ubuntu system? Thanks in advance
Since OP's issue is wrong order of parameters to GCC (many guides do show an incorrect order!), as discussed in the comments to the question, I believe showing a minimal Makefile to handle these is warranted:
CC := gcc
CFLAGS := -Wall -O2 -g
LDFLAGS := -lcpuset
TARGETS := test
.PHONY: all clean
all: $(TARGETS)
clean:
rm -f *.o $(TARGETS)
%.o: %.c
$(CC) $(CFLAGS) -c $^
test: test.o
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $#
Note that the indentation in Makefiles must use Tabs and not spaces. Since this forum converts Tabs to spaces, you will need to fix the above makefile, for example by running sed -e 's|^ *|\t|' -i Makefile.
If you want to compile say foo.c directly to an executable, the recipe is
foo: foo.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $#
You only need to run make (it defaults to using the Makefile in the current directory, and the default target is the first one, above the one named all), to recompile the TARGETS (here, test, but you can supply more by just adding them space-separated to the line).
You can also run make clean test to rebuild test from "scratch", i.e. removing all temporary files and all targets first.
You can override variables like CFLAGS by simply supplying them on the command line; for example, make CFLAGS="-Wall -Wextra -Os" clean all to recompile everything with different compilation flags.
I do not know gcc and c well. In my /home/pi/Desktop/intern/adis16227_generic directory I have following 5 files.
ADIS16227.c
ADIS16227.h
Communication.c
Communication.h
main.c
main.c
#include<stdio.h>
#include "Communication.h" // Communication definitions.
int main() {
printf("hello!!\n");
unsigned char status = 0;
status = SPI_Init(0, 1000000, 1, 1);
printf("%u", status);
return 0;
}
Run command:
$ sudo gcc -L /home/pi/Desktop/intern/adis16227_generic main.c -lCommunication
Error:
/usr/bin/ld: cannot find -lCommunication
collect2: error: ld returned 1 exit status
Question:
What I am missing here?
What do I need to run the code?
-l is for libraries, and you never built a library from your Communication.c. The simplest solution is just add Communication.c to your compiler command line.
For larger projects, compile each translation unit separately with the -c switch like this:
gcc -c -Wall -Wextra -pedantic -omain.o main.c
gcc -c -Wall -Wextra -pedantic -oCommunication.o Communication.c
and so on ... (as a suggestion, I added some common warning options here, they help you spot errors)
The resulting .o files are object code. That's already compiled machine code, but with meta-information needed for a linker to link it with other object code into a complete executable.
Then link them all with one command:
gcc -oprogram main.o Communication.o
If you actually want a library from -- say -- Communication.c and ADIS16227.c, you could compile both to object code:
gcc -c -Wall -Wextra -pedantic -oCommunication.o Communication.c
gcc -c -Wall -Wextra -pedantic --oADIS16227.o ADIS16227.c
and then use ar to create a static library from them:
ar rcs libCommunication.a Communication.o ADIS16227.o
Then your initial compiler command would work (with the -lCommunication switch).
Final piece of advice: Never compile as root. This is completely unnecessary. So remove your sudo here.
those options:
-L /home/pi/Desktop/intern/adis16227_generic -lCommunication
suggest that the linker should find libCommunication.a (or .so) in the /home/pi/Desktop/intern/adis16227_generic directory.
But there are only sources in this directory. The linker won't build the sources of your "Communication" library for you.
So you could build the library and link with it:
gcc -c ADIS16227.c Communication.c
ar r libCommunication.a ADIS16227.o Communication.o
but maybe the fastest & quickest way to achieve a successful build would be:
sudo gcc -o main *.c
so it compiles all the files of the directory into the executable called main
Of course, it makes compilation times longer, but maybe it's not noticeable.
First move into the /home/pi/Desktop/intern/adis16227_generic directory:
cd /home/pi/Desktop/intern/adis16227_generic
Then, compile the source:
gcc ADIS16227.c Communication.c main.c -I .
You can now run your compiled program (called by default a.out):
./a.out
You have to compile separatedly files and then compile main with related obj file.
gcc -c Communication.c Communication.h
gcc main.c Communication.o -o main
I am trying to compile a simple dll following the cygwin tutorial. I have been able to successfully do all but the last step. When I execute the command:
gcc -o myprog myprog.c -L./ -lmydll
I get an error saying that hello() is not declared in that scope. I followed the tutorial verbatim, yet I am still not able to compile the simple project and am lost as to why.
The code for the individual files are as follows:
(myprog.c)
int main(void){
hello();
}
(mydll.c)
#include <stdio.h>
int hello(){
printf("Hello World!\n");
return 0;
}
The example is working fine for me in my Cygwin
armathew#3NJ2VQ1 /cygdrive/d/userdata/armathew/Desktop/WWWW
$ ls
mydll.c myprog.c
armathew#3NJ2VQ1 /cygdrive/d/userdata/armathew/Desktop/WWWW
$ gcc -c mydll.c
armathew#3NJ2VQ1 /cygdrive/d/userdata/armathew/Desktop/WWWW
$ gcc -shared -o mydll.dll mydll.o
armathew#3NJ2VQ1 /cygdrive/d/userdata/armathew/Desktop/WWWW
$ gcc -o myprog myprog.c -L./ -lmydll
armathew#3NJ2VQ1 /cygdrive/d/userdata/armathew/Desktop/WWWW
$ ./myprog.exe
Hello World!
What is the Cygwin version you are using? Mine is 1.7.5
armathew#3NJ2VQ1 /cygdrive/d/userdata/armathew/Desktop/WWWW
$ uname -r
1.7.5(0.225/5/3)
well, the statement for linking library may be incorrect.
It should be
-L<library path> -lyoulibrarymane
as there is no "./" after the library path.
here is an example that I used, it may be helpful. the -I/usr/local/include is the header file path
gcc -o hello-world helloopencv.c -I/usr/local/include -L/usr/local/lib -lopencv_highgui -lopencv_core -lopencv_imgproc
You need to add a declaration at the top of myprog.c:
int hello(void);
Or you could put this in a new mydll.h and #include that in myprog.c.
I have Ubuntu 64 bit installed, and when I compile C files using the flags:
gcc -g -m32 -ansi -Wall -c -o *.o *.c
it compiles the files, but when I try to run them in the terminal, nothing happens.
So I decided to try to compile and run just one simple file without a makefile, with the following code:
#include <stdio.h>
int main()
{
printf("Hello World");
return 0;
}
The compilation succeeds but when I try to run the file I get nothing...
Note: I already tried to install lib32gcc1, libc6-i386, and g++-multilib.
How can I fix this problem?
Replace -o *.o by -o programname. The -o parameter receives the executable name of the program you're generating. And here is gcc manual:
http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Overall-Options.html#Overall-Options
For a simple test, leave every option out:
> cat test.c
#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
> gcc test.c
> ./a.out
Hello World
and see if that works.
Let us assume you (already) have two object files a.o and b.o, their corresponding source file a.c and b.c and some common header ch.h; then your (incorrect) command line
gcc -g -m32 -ansi -Wall -c -o *.o *
might be expanded as:
gcc -g -m32 -ansi -Wall -c -o a.o b.o a.c b.c ch.h a.o b.o
(actually, that would be even worse, e.g. if you have some Makefile or some backup files from your editors like a.c~, as remarked by William Pursell)
which would compile but not link, the files b.o a.c b.c ch.h a.o b.o which does not means much.
You should understand that the shell is expanding first the arguments before executing any gcc program (in a new process). To understand what is expanded, consider replacing gcc by echo (or by gcc -v which would show what is really happening)
Then, you should read the GCC documentation about invoking GCC
Actually, you need to spend several hours in reading, e.g. Advanced Bash Scripting Guide (which does have some mistakes perhaps) and Advanced Linux Programming. Several wikipedia pages could also be useful to read.
I'm new to makefiles, so I apologize in advance if this is a silly question. Also I removed most variables from my makefile because they weren't working properly (gnu make tells me that $(myvar) should be completely replaces by the value of myvar, however the output of make was showing me that this was not happening), so I apologize for the ugliness and the more than 80 character lines.
acolibobj = acoLibInit acoGlobalDefs
acolibinterface: $(acolibobj).o
acoLibInit.o:
gcc -fPIC -g -c -Wall -I/usr/include/dc1394 -o acoLibinit.o acoCommands/acoLibInterface/acoLibInit.c
acoGlobalDefs.o:
gcc -fPIC -g -c -Wall -I/usr/include/dc1394 -o acoGlobalDefs.o acoCommands/acoLibInterface/acoGlobalDefs.c
When I run this makefile I get:
gcc -fPIC -g -c -Wall -I/usr/include/dc1394 -o acoLibinit.o acoCommands/acoLibInterface/acoLibInit.c
cc acoLibInit.o -o acoLibInit
gcc: acoLibInit.o: No such file or directory
gcc: no input files
make: *** [acoLibInit] Error 1
So far as I can tell, what's happening is that make is trying to compile AND link, even though I explicitly added the -c flag. When I run "gcc -fPIC -g -c..." myself (from bash), I do not get any problems at all. Why does make go on to try "cc acoLibInit.o -o acolibInit"?
make is trying to build acoLibInit. It probably has built-in rule that specifies "whatever" can be produced by linking "whatever.o", which is why you get that cc line.
This line:
acolibinterface: $(acolibobj).o
expands to:
acolibinterface: acoLibInit acoGlobalDefs.o
(note the absence of .o on the first dependency). This is why it's trying to link acoLibInit.
Try this:
acolibinterface: $(addsuffix .o,$(acolibobj))
if you want only the .o files as dependencies for that target.
$(acolibobj).o expands to acoLibInit acoGlobalDefs.o. Thus, you're really saying:
acolibinterface: acoLibInit acoGlobalDefs.o
Simply define acolibobj = acoLibInit.o acoGlobalDefs.o and use acolibinterface: $(acolibobj).