So, after spending a couple of hours of manually configuring autotools, I finally managed to create a makefile for my project. Only problem? It gives me problems with the linker.
Let me explain it better: I have a project that is divided in several subprograms, all of which are to be linked to the main program, main.c. My problem is that while I can compile everything properly with gcc, make gives me the dreaded collect2: ld returned 1 exit status error, naming an undefined reference to main as the reason. Now, we all know it's a linking error, and as a proof of that I could compile all the files without linking them adding -c among the CFLAGS in Makefile.am. But we already knew that, I guess.
My question is: what should I add to the Makefile.am (the one inside my src folder, I guess?) file in order to let it link all the files to one another and not separately, so that the linker will find the entry point in main.o? Basically, the equivalent of running "gcc program1.c program2.c main.c". I know automake does it because it builds the files progressively, one at the time, and I know it's a dumb question but it's driving me crazy anyway. It's the first time I use autotools, help me make it not the last!
If foo is your program's name and you're not doing anything fancy,
bin_PROGRAMS = foo
foo_SOURCES = program1.c program2.c main.c
foo_LDADD = # any other libraries go here as -l arguments
should be a sufficient Makefile.am.
Related
I am currently at the beginning stage of learning how to program in C, and I came across some questions regrading header files. For example
I have a header file named header.h,
which has int comp (int, int) declared in header.h and
defined in header.c
In such case, If i were to compile a test.c using the comp function, I would have to go like
gcc test.c header.c
First question: having to add header.c everytime I gcc seems too inconvenient and redundant. Is it a necessity? If not, is there a way I can get around it? If so, why? Or is it, in fact, not redundant compared to its usage, and am I just complaining?
Second question: if I were to use multiple .c files with functions declared in header.h my gcc would have to go
gcc test.c header.c header2.c header3.c .....
and that again seems too redundant. (and from hereon, same questions as First question..)
Thanks in advance. First time asking questions in SO. Please tell me if there is anyway I can improve the clarity of the question.
I think you are looking for the make, that automates the execution of the files you are compiling.
With the use of make, you don't need to write every time the commands like 'gcc test.c header1.c header2.c ...' in the terminal (if you type the commands directly to the terminal, yes, you will need to do this all the time, which is very redundant and costs lots of time). Using make, you only do this one time, and then all you have to do is run the make command.
You can see more about makefile at https://en.wikibooks.org/wiki/Make.
I hope it can help you.
You could make a shell macro or script to execute the command, if it is too much effort to use shell history feature to re-execute the command.
When your project starts to get complicated it's normal to use a build system in which you configure the build commands in the build system, and then you invoke the build system when you want to build. For example, write a Makefile that lists all the .c files using the right syntax for makefiles, and then type make each time you want to build.
You could consider using an Integrated Development Environment which is a (usually) GUI that includes a build system and other useful features, in which case you just need to hit a key to build and run.
It is often desirable to spread out your code across multiple files; this helps to ease code management. Header files provide a unified way to expose functions defined in libraries or source code files to other source code files without including the actual code for those functions. This way, the same header file can be included in multiple source code files without compiling the same code for each of those files. However, this means that the source code for functions in the header file must be given to the compiler also. As such, you have to give your header.c to the compiler each time you compile.
This does mean that you will compile header.c each time you build your project, which is a bit redundant. One way around this is to compile the header.c into an object file, and then give that the compiler when you build:
gcc -c header.c -o header.o
gcc header.o test.c
Furthermore, software developers often like to distribute their program functions to other developer but without providing the actaul code. To do this, they often use software libraries, which contain the compiled source code, along with header files to access this code. This is probably a little more than what your looking for, so I'll leave you read up on it.
All this is used not to reduce redundancy in your compiler commands, but in your compiled programs. To make programmers' lives easier building their programs, makefiles and IDEs are often used. These may be things you might have to read up on, but the other answers posted here should provide a good starting point.
Writing a simple Makefile is very useful for compiling C programs. Here's an example
CC = gcc
CFLAGS = -g -Wall
OBJECTS = main.o cfile1.o cfile2.o cfile3.o
run: $(OBJECTS)
$(CC) $(CFLAGS) -o run $(OBJECTS)
Don't worry about header files when writing a Makefile; only worry about your ".c" files. This example Makefile assumes that you want to compile main.c, cfile1.c, cfile2.c, and cfile3.c. When adding the C files to your Makefile, make sure to use ".o" instead of ".c".
The Makefile should be in the same directory as your C files and must be named "Makefile" with a capital M. Simply type "make" to compile. Then run the program with "./run".
I am want to begin working on the 4th assginment, RSS searcher, of Online Stanford CS107 Programming Paradigms course. However, I am lagging at the very first step; I can not compile the prepared, to-work-on, unfinished program.
I get this error when I type make;
gcc rss-news-search.o -g -Wall -std=gnu99 -Wno-unused-function -g -lnsl -lrssnews -L/media/D/Programming/assn-4-rss-news-search-lib/ -o rss-news-search
/usr/bin/ld: cannot find -lrssnews
collect2: error: ld returned 1 exit status
Makefile:32: recipe for target 'rss-news-search' failed
make: *** [rss-news-search] Error 1
I have installed libexpat-dev.
Here is the link to the course, its the 4th programming assignment, RSS;
https://see.stanford.edu/Course/CS107
Thanks in advance
That the project comes with librssnews.a is good news. This file is a static library called rssnews and this is what you need to compile the project successfully!
Warning: you almost certainly don't need to follow these steps, go on reading to see why.
Put this file in your project's directory (the one you're running the build from) or in the lib directory, if the project contains one (if it doesn't, don't create one).
Run the build again. If it fails with the same error, go on to next steps.
Find out where the compiler normally looks for libraries by compiling a simple code with the -v flag. For example, gcc simple.c -v. You'll get tons of output that will contain the paths the compiler visited to link your program.
Copy the library file to one of these paths and run the build once again.
Given that the library search path is specified explicitly, you can simply put the library into /media/D/Programming/assn-4-rss-news-search-lib/ and skip the steps discussed earlier altogether. But if it wasn't, you'd probably have to follow them.
I am learning C and I just read the term multiple compilation.Till now I had a single file.c and I used the command gcc file.c to compile it and then ./a.out to execute it. But I got confused a little bit. When should I use the multiple compilation instead of the single and which would be the possible reasons that they will lead me to prefer a multiple compilation instead of the single? I searched it and I found some articles but they didn't cover fully my questions. 1 (this is for c++) , 2If i undestood well if I have some files.c in my project eg file1.c, file2.c and then i want to link them, i execute
gcc file1.c
gcc file.c
gcc file1.o file2.o //somehow i have to create the .o files..
Thank you..
Compilation takes time. There's no point in re-compiling C code that hasn't changed. So, for large projects, it makes sense to split the code into multiple files (typically not randomly of course, but into modules of different functionality) and compile them only when needed.
Linking is the process of taking a bunch of object code (what the .o files are called) and turning them into a single program.
There are many steps to compiling.
When you invoke gcc it will create by default an executable file i.e. all steps in one go:
.c -> .i preprocessor
.i -> .s compiler
.s -> .o assembler
*.o -> a.out linker
Generally the first two take up the most time. If you have a large project then recompiling the entire project may take a lot of time when you are developing. So the compiler allows you to stop at a certain point and reuse previous results of files that have not changed:
gcc -E for preprocess only (rarely used)
gcc -S compile, but don't assemble. Useful for debugging or optimising assembly
gcc -c compile, assemble, but don't link. This is the most commonly used one and produces object files. Those contain your assembled functions (object code), but it's not capable of running because not all functions may be present yet, library functions are missing and the executable header has not been linked in.
The final step gcc -o executable *.o will then take all those and link them together to create an executable. Optionally linking libraries into it.
Generally having all functions in one source file will allow the compiler to do the more optimisations (i.e. inlining), but at the cost of compile time.
Have a look at https://cs.senecac.on.ca/~btp200/pages/images/compile_link.png
I am working on a project written in a mix of Fortran 90 and Fortran 77 and now need to link the LAPACK/BLAS libraries, from netlib.org, to the project, all in a Linux environment. I used the gfortran compiler flags OPTS = -O2 -fPIC -m64 in the given Makefile, and then made it using
make blaslib
make
And it finished normally, or at least I think so.
Then, I copied the files in /usr/local/lib and /usr/local/bin/ and /usr/local/lib64/
but it didn't work. I even used the option -L/path/to/lapack/liblapack.a and it didn't work also.
When I compile my code, I get the following error:
qrB.o: In function `qrfactorizeb_':
qrB.f90:(.text+0x64f): undefined reference to `zgeqp3_'
collect2: ld returned 1 exit status
make: *** [run] Error 1
I am really unsure what to make of this error. I tested it in 3 other workstations and it didn't help! Can anyone help me?
I had the same problem some time ago! Dual working with Windows and Linux and also ease of playing with options in Windows taught me something interesting!
Try compiling such as:
[...]$
ifort liblapack.a libblas.a libslatec.a *.o -o profmm
and as you know, it means that I want to use 3 libraries to compile and link my files into profmm output file. It has no syntax error, but it leads to a lot of errors like:
preconditioner3.o: In function factorb_':
preconditioner3.f:(.text+0x1add): undefined reference tozgetrf_'
.
.
preconditioner.o: In function factorpre_':
preconditioner.f:(.text+0x13a2): undefined reference tozgetrf_'
preconditioner.f:(.text+0x18bb): undefined reference to zgetri_'
zbesh.o: In functionzbesh_':
zbesh.f:(.text+0xb3): undefined reference to d1mach_'
zbesh.f:(.text+0xcf): undefined reference toi1mach_'
.
.
.
and many more errors indicating that ifort is unable to read my libraries even though they are here in my current directory!
But simply change the command as follow:
[...]$ ifort *.o liblapack.a libblas.a libslatec.a -o profmm
and it works fine with no error! So it means that now ifort can read my library (local ones)! Also note that changing the order of libraries are very important, and it depends on the order of usage of those subroutines inside the program. So always try to reorder the library chain to check for possible errors.
Hope it helps.
so I've been programming in C++ for almost 2 years now, and the whole while I've had the pleasure of using an IDE (VS) with lovely project settings and automatic linking and the like. I've always stayed away from any external libraries which required me to compile via makefiles, or at least the ones which were meant for linux environments/other compilers.
Anyways I now want to use a super handy utility (Bob Jenkins Perfect Minimal Hash) but it requires me to compile via makefiles, not only that but using the g++ compiler.
I went ahead and got the mingW32-make utility and am now trying to get it to work. Where I'm at now:
Succesfully installed minGW
Succesfully called the make utility
Failed to succesfully make the project.
The error I get is:
C:\gen_progs\ph>mingw32-make
mingw32-make: *** No rule to make
target lookupa.c', needed by lookupa.o'. Stop.
And the makefile itself:
CFLAGS = -O
.cc.o:
gcc $(CFLAGS) -c $<
O = lookupa.o recycle.o perfhex.o perfect.o
const64 : $(O)
gcc -o perfect $(O) -lm
# DEPENDENCIES
lookupa.o : lookupa.c standard.h lookupa.h
recycle.o : recycle.c standard.h recycle.h
perfhex.o : perfhex.c standard.h lookupa.h recycle.h perfect.h
perfect.o : perfect.c standard.h lookupa.h recycle.h perfect.h
Now the error seems reasonable, at least from my minimal understanding of makefiles, I have all the referenced .c, .h files, however I have none of the .o files and there doesn't appear to be any instructions on how to make these. So my question/s are:
am I calling the make utility wrong? Or do I need to compile the object files first? Or... do I need to add something to the make file?
Again I have all the referenced .c and .h files.
Edit: Sorry about that I was actually missing that specific file it seems to have disapeared somewhere along the line. However, adding it back in this is the error I now get:
c:\gen_progs\ph>mingw32-make
cc -O -c -o lookupa.o lookupa.c
process_begin: CreateProcess(NULL, cc -O -c -o lookupa.o lookupa.c, ...) failed.
make (e=2): The system cannot find the file specified.
mingw32-make: *** [lookupa.o] Error 2
Regarding your error "process_begin: CreateProcess(NULL, cc -O -c -o lookupa.o lookupa.c, ...) failed."
This is because the make utility wants to use the "cc" compiler to compile your program, but that compiler is not part of the Mingw-package.
Solution: Change the ".cc.o:" to ".c.o:". This changes the implicit rule which tells Make what compiler to use (gcc on the next line) when compiling .c files (the original line tells it how to compile .cc files).
Saying either make -DCC=gcc at the command line or adding the line CC=gcc to the top of the Makefile would cure the issue as well. Make's built in rules for handling C source code all name the C compiler with the variable CC, which defaults to "cc" for reasons of backward compatibility even in Gnu Make.
It looks like the original Makefile author tried to work around that problem by supplying a custom rule for compiling .cc files, but since there are no .cc files in the project that rule was not actually used.
Specifying the correct value for CC is superior to fixing the explicit rule to name .c files IMHO because Makefiles are generally easier to use and maintain and are the most portable when the least possible information is specified.
I don't think not having .o files is the problem. Make will make them from the source files (the files to the right of the colon).
Your immediate problem seems to be that make can't file the file "lookupa.c". From the rules you posted, it looks to me like that file should be sitting in the same directory as the makefile, but it isn't. You need to figure out where that file is, and how to get it there.
(For some reason I have a mental image of Wile E. Coyote sitting at his computer, seeing that file name, looking up, and getting plastered with an anvil).