I am new to automake tools. In "src/Makefile.am", I use "AM_LDFLAGS = -L... -l...".
Then, I run "autoreconf --force --install ; ./configure ; make"
In the last command,
$ g++ -O2 -L... -l... -o target_name [some *.o files]
the compiler complains "undefined reference to ...".
But if I copy it and move "-L... -l..." to the end, and run it independently it is fine (below).
$ g++ -O2 -o target_name [some *.o files] -L... -l...
So the order of options does matter? Anyway, how to smooth it?
Thanks a lot.
For the "-L" options, try using the LDADD or target_name_LDADD variable instead (where target_name is replaced with the actual target name). This places these flags at the end of the linking command.
The order of "-l" and "-L" does make a difference. From http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html:
-l library
Search the library named library when linking. ... It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded. ... The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined.
So libraries should appear after object files/other libraries that depend upon them.
Related
I've got a C++ program with a Makefile, building (g++) and running on Windows cmd. Thing is, sometimes it takes a while to run and save the results, and I want to run it with different parameters at the same time so that I can do something else while I wait for the first instance to finish. It doesn't work though, because of the executable I guess:
>make
g++ -c -o main.o main.cpp
Assembler messages:
Fatal error: can't create main.o: Permission denied
make: *** [main.o] Error 1
You have two problems: The one you ask about, and the reason you ask this question in the first place.
Lets start with the problem you have...
Judging by the Makefile you show, you have it all wrong.
Rules are in the format
target: sources_the_target_depend_on
The target is usually a file that need to be created. For an object file that is the name of the actual object file itself. The source files that the object files then depend on should be on the right-hand side.
To take an example from you Makefile (before you edited it away):
graph2: graph2.o
g++ -g -c graph.cpp -o graph2.o
Here you tell make that the file graph2 depends on the file graph2.o, and then it creates the graph2.o file. That's wrong. The rule should be that the file graph2.o depends om the file graph.cpp and go on to generate the file graph2.o:
graph2.o: graph.cpp
g++ -g -c graph.cpp -o graph2.o
This indirectly leads to the problem you have, with this line (deduced from your error and the Makefile):
main: main.o utils.o graph.o heuristics.o
g++ -g main.cpp -o main.o utils.o graph.o heuristics.o
This contains the same error as discussed above: You say that the file main depends on main.o and then the rule create main.o. Your rule should be
main: main.cpp utils.o graph.o heuristics.o
g++ -g main.cpp -o main utils.o graph.o heuristics.o
Note also how I no longer name the executable file main.o, as that is supposed to be used for object files.
Now lets continue with the reason you have the problem in the first place: That you need to edit the code to change data or values.
This is a problem that you need to solve. One common way to solve it is through command line arguments. If your program parses the command line arguments passed to your program you can pass it the values that could change from run to run.
How to do this is whole chapter on its own, so I wont give you any more details. There are plenty of tutorials online.
Lastly, you can simplify your Makefile considerably, by using implicit rules and variables.
I would simply create the Makefile to look something like this
# The compiler to use
CXX = g++
# Flags to pass to the compiler (add warnings when building)
CXXFLAGS = -Wall
# The main executable file to generate
TARGET = main
# List the object files needed to generate the main executable file
OBJECTS = main.o utils.o graph.o heuristics.o
# The all target depends on your main executable file
# Also as the first target in the Makefile, if no specific target is specified
# this will be the one that is used (it's the "default" target for the Makefile)
all: $(TARGET)
# The main executable file depends on the object files
$(TARGET): $(OBJECTS)
This is really it. the object files will be built automatically from their respective source files, and then the executable program will be linked using the object files listed.
I have a project that basically compiles from the command line in the following form:
g++ -o stack_raster stack_raster.cpp -lgdal -lboost_filesystem -lboost_system
I made a Makefile, and this is the content:
CXX =g++
LDDFLAGS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rm -f stack_raster
However I got a collect2: error: ld returned 1 exit status.
A second variation of my Makefile I tried was:
CXX = g++
CPPFLAGS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rem -f stack_raster
but I still receive the following message (even though the compile flags appear as they should for my program to compile successfully).
collect2: error: ld returned 1 exit status
<builtin>: recipe for target `stack_raster` failed
make: *** [stack_raster] Error 1
Does anyone could help me with a reference or hint about my problem, and how could I tackle it?
Does anyone could help me with a reference or hint about my problem, and how could I tackle it?
To begin with, you should have a look at the actual link command that make executed. It should have been echoed to make's output just before the error message from collect2. Understanding what's wrong with the command is the first step in determining how to fix your makefile.
In the first case, the command is probably something like
g++ stack_raster.cpp -o stack_raster
In the second, it is probably something like
g++ -lgdal -lboost_system -lboost_filesystem stack_raster.cpp -o stack_raster
The latter is probably also very similar to what you would get with the first makefile if you corrected the spelling of LDDFLAGS to LDFLAGS.
You will note that the library flags come in a different place in that command than they do in your manual command, and I assume you know that the order of objects and library flags on the linker command line is significant to Unix-style linkers such as GNU's (which is the one that the g++ driver will use).
You can certainly fix this by writing an explicit rule, as you describe in your own answer, but your makes' built-in rules may be up to the task, too. If you are using GNU make then they certainly are. For this purpose it is useful to know what the built-in rules actually are, and essential to know what the variables on which these rules depend mean.
Specifically,
LDFLAGS provides options to pass when invoking the linker, and conventionally, they appear on the command line before the objects being linked. As a result, this variable typically is not appropriate for specifying libraries (but it is fine for other link-specific options, such as -L to add directories to the library search path).
CPPFLAGS provides options for modulating the behavior of the C preprocessor (including when compiling C++). These do not typically appear at all in link(-only) commands executed by make, but they will appear (early) in commands for compiling object files from C or C++ sources, and in rules for building executables directly from C or C++ sources.
Neither of those is what you want, but if you are using GNU make, then its documentation for the former explicitly tells you what (with that make implementation) you should do instead:
Extra flags to give to compilers when they are supposed to invoke the
linker, ‘ld’, such as -L. Libraries (-lfoo) should be added to the
LDLIBS variable instead.
(emphasis added)
In GNU make, and perhaps some others, the LDLIBS variable serves exactly the purpose you need: to specify the libraries to link. These will appear at the end of the link command line from built-in rules, as you can confirm from GNU make's catalog of implicit rules, or from the list obtainable by running make -p in a directory containing no makefile.
So, with GNU make you can get the build you seem to want from the built-in rules, with this:
CXX = g++
LDLIBS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rm -f stack_raster
In closing, I note that cleaning before building by default, as your examples do and mine imitates, largely defeats the purpose of using make instead of a simple script. Part of the point of make is to do the minimum work necessary, and if your target executable is present and not out of date with respect to its sources then there is no reason to force it to be rebuilt.
Check out the answer:
Set up my makefile to compile C with just "make"
YOu have to specify in the Makefile the file you want to create in this case stack_raster.exe and the objective file in this case stack_raster.cpp and specify the command line arguments you normally pass for compiling. So the Makefile would be something like:
CXX=g++
stack_raster.exe: stack_raster.cpp
g++ -o stack_raster.exe stack_raster.cpp -lgdal -lboost_filesystem -lboost_system
all: clean stack_raster.exe
clean:
rm -f stack_raster.exe
In a later stage of the gnu-make process gmake sent a command similar to:
gcc -static foo.so.0 bar.o bizz.o buzz.o -pthreads -lrt
In that command, what dos the -lrt mean?
That has not related to make; make will never add a flag like that on its own. Whomever wrote your makefile will have added that flag to the link line themselves. That is a compilation command, and -lrt is a flag passed to the compiler. The -l flag specifies that you should link with a library, and the name of the library follows; so for -lrt it means "link with the rt library". This causes the linker to go look for libraries named librt.a or librt.so (for shared libraries) and link them with the output file.
I have an issue regarding the linking of a shared library with a non-standard naming convention under several directories. I need the generated executable to search for the shared library within the executables current location, but cannot find a command line parameter to force this behavior.
To demonstrate this behavior all that is required is a shared library that is under a directory.
gcc -shared mylib.c -o some/dir/mylib.so
gcc main.c -o main -Lsome/dir -l:mylib.so
The executable main gives the following ldd output:
ldd main
some/dir/mylib.so (0xf76e2000)
The output that I require is:
ldd main
mylib.so => some/dir/mylib.so (0xf7700000)
This output can be created if the library is named conventionally as libmylib.so rather than mylib.so like so:
mv some/dir/mylib.so some/dir/libmylib.so
gcc main.c -o main -Lsome/dir -lmylib
This also drops the path some/dir in the ldd listing as required.
I have investigated the use of rpath, and command line options for both the ld and gcc but I am unable to find a satisfactory solution. The strict requirements of a non-standard name and directory structure cannot be changed easily in this case.
My question is how can I force the dependency of the library to be relative to the current directory rather than absolute as in the second ldd through gcc command line options.
Thank you for your time, I hope I have explained the problem reasonably.
Jon.
Try to add soname in your shared library:
$ gcc -shared mylib.c -o some/dir/mylib.so -Wl,-soname=mylib.so
$ gcc main.c -o main -Lsome/dir -l:mylib.so
$ LD_LIBRARY_PATH=some/dir:$LD_LIBRARY_PATH ldd main
mylib.so => some/dir/mylib.so (0x00007fa7a4fd6000)
There's a magic variable you can pass to rpath to do this: $ORIGIN. See man ld.so for details.
I think in your case, the command should look like this (untested):
gcc main.c -o main -Lsome/dir -lmylib -Wl,-rpath,'$ORIGIN/some/path'
Note that you mustn't let the shell expand $ORIGIN as a shell variable.
BTW, this was the first Google hit for "rpath relative".
I have two files -> fact.h and main.c in the /home/snyp1/new folder. main.c has the main function which calls the fact(int x) function in fact.h. I am creating a .a archive with the ar command ->
snyp1#Snyp:~/new$ ar -r -s libfact.a fact.o
ar: creating libfact.a
fact.h fact.o libfact.a main.c
snyp1#Snyp:~/new$ gcc main.c -L/home/snyp1/new -lfact -o main
/home/snyp1/new/libfact.a: could not read symbols: Archive has no index; run ranlib to add one
collect2: ld returned 1 exit status
snyp1#Snyp:~/new$ ranlib libfact.a
snyp1#Snyp:~/new$ gcc main.c -L/home/snyp1/new -lfact -o main
/home/snyp1/new/libfact.a: could not read symbols: Archive has no index; run ranlib to add one
collect2: ld returned 1 exit status
I am on ubuntu 12.04. Please let me know whats wrong. (Also, if I don't use the -L/.../new, gcc will say it can't find "lfact", maybe its because its not in /usr/local/lib)
EDIT: OK I have found the cause. Its due to the fact that I was using fact.h to build the fact.o and then putting it in the library, it wasn't working as expected. So I now changed it into file.c and is working fine now. I should have provided that information, I'm sorry. Though I don't know why this kind of problem should arise. Aren't libraries possible to make without at least one .c file in it?
I was using fact.h to build the fact.o and then putting it in the library, it wasn't working as expected.
Do you mean you were compiling fact.h to produce fact.o?
If so, that wasn't doing what you expect. When you invoke gcc on a header file it produces a precompiled header, not an object file. So although you got a file called foo.o it wasn't a valid object file. If you had just run gcc -c fact.h it would have produced a precompiled header fact.gch, but presumably you ran gcc -c fact.h -o fact.o which causes the file to be called fact.o even though it's still a precompiled header. file fact.o would have shown that:
$ file fact.o
fact.o: GCC precompiled header (version 013) for C
You could have forced GCC to treat the file as C code, not a header, by running gcc -x c -c fact.h -o fact.o (the -x c says to treat the input as C code instead of inferring the type from the file extension) but it's probably simpler and less confusing to just name your file correctly instead of trying to compile a header.
Aren't libraries possible to make without at least one .c file in it?
They need at least one object file (i.e. .o file) but you didn't have a valid object, you had a precompiled header misleadingly named as .o, but it was not actually an object file.
if I don't use the -L/.../new, gcc will say it can't find "lfact", maybe its because its not in /usr/local/lib
The linker doesn't only look in /usr/local/lib, there are other default places it looks, but yes, that's basically the problem. Note that you can also say -L. if the library is in the current directory, that's easier than giving an absolute path.
I'm not sure ar supports a dash on anything other than the first option. Try
ar -rs libfact.a fact.o
or just
ar rs libfact.a fact.o
Mind you, I don't know why running ranlib didn't work though.