I'm trying to track down a failure to link with a mapfile on Solaris. The missing mapfile causes the following error when I try to run our self tests:
$ ./cryptestcwd v
ld.so.1: cryptestcwd: fatal:
/export/home/cryptopp/.libs/libcryptopp.so.6: hardware capability
(CA_SUNW_HW_1) unsupported: 0x4800000 [ AES SSE4.1 ]
Killed
I've gotten as far as this Automake rule. libcryptopp_la_LINK, which I believe is the shared object, is missing AM_LDFLAGS. AM_LDFLAGS holds the -M cryptopp.mapfile option.
libcryptopp_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
$(CXXFLAGS) $(libcryptopp_la_LDFLAGS) $(LDFLAGS) -o $#
I tried to patch it with sed after configure runs:
libcryptopp_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
$(CXXFLAGS) $(libcryptopp_la_LDFLAGS) -M cryptopp.mapfile $(LDFLAGS) -o $#
I confirmed the sed is successful, but the same test fails again. When the commands are invoked -M <mapfile> is missing.
The libtool manual talks about -M arguments on Cygwin, but not Solaris (and the discussion only applies to GCC, and not other compilers like IBM XL C/C++, Sun C/C++ and LLVM Clang):
Note that you also need to ensure that the standard Unix directories (like /bin, /lib, /usr, /etc) appear in the root of a drive. This means that you must install Cygwin itself into the C:/ root directory (or D:/, or E:/, etc)—instead of the recommended installation into C:/cygwin/. In addition, all file names used in the build system must be relative, symlinks should not be used within the source or build directory trees, and all -M* options to gcc except -MMD must be avoided.
There is no other mention of -M.
And there is no diagnostic, like "Removing -M <mapfile> options to Sun linker" or "Warning: libtool does not understand option -M <mapfile>".
My question is, does libtool discard -M and its arguments for some reason?
Libtool does drop some link options when creating a library. The manual explains:
When creating a shared library, but not when compiling or creating a
program, libtool drops some flags from the command line provided by
the user. This is done because flags unknown to libtool may interfere
with library creation or require additional support from libtool, and
because omitting flags is usually the conservative choice for a
successful build.
Personally, I find the justification for this behavior to be a bit cavalier, and I furthermore think it warrants a warning from libtool when it occurs, but unless you care to raise an issue against it, that's pretty much moot.
Experimentation shows that -M is indeed among the options that libtool strips. In particular, if I specify LDFLAGS containing an -M option on the make command line then I can observe it echoed in the make output when it runs the libtool link, but not in libtool's own echo of the link command that is actually executed:
$ make LDFLAGS="-M mapfile"
/bin/sh ./libtool --tag=CC --mode=link gcc -g -O2 -M mapfile -o libmylib.la -rpath /usr/local/lib x.lo y.lo
libtool: link: gcc -shared -fPIC -DPIC .libs/x.o .libs/y.o -O2 -Wl,-soname -Wl,libmylib.so.0 -o .libs/libmylib.so.0.0.0
The libtool docs suggest two workarounds to pass link options that otherwise would be stripped:
For bona fide linker options, you can use one or more -Wl, or -Xlinker options to pass your options through libtool and the linker driver to the linker itself. For example,
LDFLAGS=-Wl,-M,cryptopp.mapfile
For options directed specifically to the linker driver, the docs suggest adding the flags to the compiler driver command (CC="gcc -M mapfile"), but this is ineffective because the $(CC) variable is expanded by make to form the libtool command line, leaving any options expressed in it exposed to libtool for stripping.
Additionally, however, there is
The -XCClinker option by which options can be passed through to the linker driver (as opposed to the linker itself), but its behavior seems a bit quirky: it seems to ignore options that don't start with a hyphen (such as the name of your map file).
Related
I would like to create a dynamic library for c++ program on linux.
In c++ program/system I`m using libconfig++ library, libpqxx library, some boost and c++11.
My steps:
1)
g++ -Wall -I/usr/local/include/ -std=c++0x -lconfig++ -Wall -lpqxx -lpq -fPIC -c ../SourceFiles/DBHandler.cpp ../SourceFiles/ParamServer.cpp ../SourceFiles/Functions.cpp
2)
g++ -shared -Wl,-soname,libctest.so.1 -o libctest.so.1.0 *.o
3)
ln -sf libctest.so.1.0 libctest.so.1
4)
ln -sf libctest.so.1.0 libctest.so
5) compile
g++ -Wall -I/path/to/include-files -L/path/to/libraries program.cpp -I/usr/local/include/ -std=c++0x -lconfig++ -lpqxx -lpq -lctest -o prog
After execute above command :
/usr/bin/ld: cannot find -lctest
collect2: ld returned 1 exit status
What am I doing wrong?
Here is the reference:
enter link description here
In step 5, you forgot -L. to look for libraries in the current directory.
By default, only a [long] list of system directories is used when searching for libraries.
You will also need to add . to the LD_LIBRARY_PATH environment variable before executing your program, so that the current directory is searched at runtime, too. Running ldconfig will avoid this, but if you are only testing your library and do not want to persistently affect your system, I would stick to the LD_LIBRARY_PATH approach.
An alternative is to "install" your library into one of those directories, such as /usr/local/lib (or your equivalent). You should use ldconfig after doing this, so that the dynamic library cache and all your symlinks are set up for you. This is the canonical approach but may not be suitable during iterative development of said library.
You need to ldconfig update the dynamic library cache -- it will also create the symbolic links for you.
See eg Section 3.5 of this Linux Documentation Project HOWTO
I try to compile .cpp file with g++ in terminal:
g++ -o main main.cpp \
-I/usr/include/glib-2.0 \
-I/usr/include/json-glib-1.0 \
-I/usr/lib/x86_64-linux-gnu/glib-2.0/include/ \
-L/usr/lib/x86_64-linux-gnu -ljson-glib-1.0 -lglib-2.0
And it works.
But I want to add these .so libraries and include files for g++ permanently so that I don't need to type these every time. And I also want to make it apply for other applications.
I am using ubuntu.
Could anyone help me out? Thank you a lot in advance.
Here is a very basic example of a Makefile using pkg-config, which you should really use with glib anyway, takes a lot of the pain away:
CXXFLAGS += $(shell pkg-config --cflags glib-2.0) $(shell pkg-config --cflags json-glib-1.0)
LIBS += $(shell pkg-config --libs glib-2.0) $(shell pkg-config --libs json-glib-1.0)
all: main
main: main.o
$(CXX) $(CXXFLAGS) main.o -o main $(LIBS)
clean:
rm -f main main.o
Might be wise to find yourself a gnu make tutorial, so that you can better understand this example.
Now instead of running your manually typed shell command, you can just do 'make'.
The best, most flexible way to do this is via a build system, using Make or CMake or something similar. But there is a serious learning curve. It may be simpler for right now to just create a script file to run the same commands that you have successfully used from the command line.
I assume you are using the bash shell. You can just edit a file -- call it "compile.bash". At the first line of the file, type "#!/bin/bash". That tells the system to interpret this file as a bash script file. Then on one or more subsequent lines, type the commands you just provided in you question, exactly as you use them previously. Save the file. Then run this command from the command line: "chmod +x compile.bash" (without the quotes). Make sure that the new file is located in the directory that you compile from, and you can just type:
"compile.bash" instead of the long command line you were using before.
Example file "compile.bash"
#!/bin/bash
g++ -o main main.cpp -I/usr/include/glib-2.0 -I/usr/include/json-glib-1.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include/ -L/usr/lib/x86_64-linux-gnu -ljson-glib-1.0 -lglib-2.0
There are three different things you need to investigate further:
Environment variables affecting your compiler. Since you are using GCC, I can point out this page. In particular, you should read about:
LIBRARY_PATH
The value of LIBRARY_PATH is a colon-separated list of
directories, much like PATH. When configured as a native compiler, GCC
tries the directories thus specified when searching for special linker
files, if it can't find them using GCC_EXEC_PREFIX. Linking using GCC
also uses these directories when searching for ordinary libraries for
the -l option (but directories specified with -L come first).
The manner in which your OS searches for shared, dynamic libraries. Since you are using Linux, I would recommend this page (discussing ldconfig).
And, most importantly:
What is a software construction tool or Makefile. For that you can refer to the Scons page, the CMake page, or the GNU Make page. Briefly, each option provides you with the means for you to describe how to build your software, and then actually building it using a simple command (scons, cmake, or make, depending on what system you chose).
So, all in all I don't have an answer to your question. I can only advice you to look into these.
I'm trying to compile this source code from the makefile in a VPS, but its not working. The VPS is a 64 Cent OS
Here's the full error
# make
gcc -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/amx/*.c
g++ -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/*.cpp
g++ -c -O3 -w -DLINUX -I../SDK/amx/ *.cpp
g++ -O2 -fshort-wchar -shared -o "TCP_V1.so" *.o
/usr/bin/ld: TCP-LINUX_V1.o: relocation R_X86_64_32 against `.rodata.str1.8' can not be used when making a shared object; recompile with -fPIC
TCP-LINUX_V1.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [all] Error 1
Here's my makefile:
GPP=g++
GCC=gcc
OUTFILE="TCP_V1.so"
COMPILE_FLAGS=-c -O3 -w -DLINUX -I../SDK/amx/
all:
$(GCC) $(COMPILE_FLAGS) ../SDK/amx/*.c
$(GPP) $(COMPILE_FLAGS) ../SDK/*.cpp
$(GPP) $(COMPILE_FLAGS) *.cpp
$(GPP) -O2 -fshort-wchar -shared -o $(OUTFILE) *.o
Anyone know what's wrong?
Do what the compiler tells you to do, i.e. recompile with -fPIC. To learn what does this flag do and why you need it in this case, see Code Generation Options of the GCC manual.
In brief, the term position independent code (PIC) refers to the generated machine code which is memory address agnostic, i.e. does not make any assumptions about where it was loaded into RAM. Only position independent code is supposed to be included into shared objects (SO) as they should have an ability to dynamically change their location in RAM.
Finally, you can read about it on Wikipedia too.
In my case this error occurred because a make command was expecting to fetch shared libraries (*.so files) from a remote directory indicated by a LDFLAGS environment variable. In a mistake, only static libraries were available there (*.la or *.a files).
Hence, my problem did not reside with the program I was compiling but with the remote libraries it was trying to fetch.
So, I did not need to add any flag (say, -fPIC) to the compilation interrupted by the relocation error.
Rather, I recompiled the remote library so that the shared objects were available.
Basically, it's been a file-not-found error in disguise.
In my case I had to remove a misplaced --disable-shared switch in the configure invocation for the requisite program, since shared and static libraries were both built as default.
I noticed that most programs build both types of libraries at the same time, so mine is probably a corner case. In general, it may be the case that you rather have to enable shared libraries, depending on defaults.
To inspect your particular situation with compile switches and defaults, I would read out the summary that shows up with ./configure --help | less, typically in the section Optional Features. I often found that this reading is more reliable than installation guides that are not updated while dependency programs evolve.
Fixed it with -no-pie option in linker stage:
g++-8 -L"/home/pedro/workspace/project/lib" -no-pie ...
It is not always about the compilation flags, I have the same error on gentoo when using distcc.
The reason is that on distcc server is using a not-hardened profile and on client the profile is hardened. Check this discussion:
https://forums.gentoo.org/viewtopic-p-7463994.html
Simply cleaning the project solved it for me.
My project is a C++ application (not a shared library). I randomly got this error after a lot of successful builds.
I had the same problem. Try recompiling using -fPIC flag.
I'm getting the same solution as #camino's comment on https://stackoverflow.com/a/19365454/10593190 and XavierStuvw's reply.
I got it to work (for installing ffmpeg) by simply reinstalling the whole thing from the beginning with all instances of $ ./configure replaced by $ ./configure --enable-shared (first make sure to delete all the folders and files including the .so files from the previous attempt).
Apparently this works because https://stackoverflow.com/a/13812368/10593190.
We had the same problem. It turned out to be a mix-up in a Makefile. The error occurred when the linker was gcc, but the C++ compiler clang++. Changing the linker to clang++ fixed it.
I am trying to compile an OpenCL project under Eclipse using Cygwin Gcc/G++ compiler and i got some Undefined References for OpenCL API functions. I saw many threads about this problem, I tried the suggested solutions but I still have these errors.
Basically my code just retrieves OpenCL infos about the platform and device I use so I dont give it here but I can if you want (even if I dont think it is very interesting).
Here is my makefile :
RM := rm -rf
OpenCLEnvInfos.o: ../OpenCLEnvInfos.cpp
g++ -IINCLUDE_DIR1 -IINCLUDE_DIR2 -g3 -Wall -c ../OpenCLEnvInfos.cpp -o OpenCLEnvInfos.o
#echo ' '
OpenCL_infos.o: ../OpenCL_infos.cpp
g++ -IINCLUDE_DIR1 -IINCLUDE_DIR2 -g3 -Wall -c ../OpenCL_infos.cpp -o OpenCL_infos.o
#echo ' '
# All Target
all: OpenCLEnvInfos.exe
# Tool invocations
OpenCLEnvInfos.exe: OpenCLEnvInfos.o OpenCL_infos.o
g++ -o OpenCLEnvInfos.exe OpenCLEnvInfos.o OpenCL_infos.o -LOpenCL -LGAL-fb
#echo ' '
# Other Targets
clean:
-$(RM) OpenCLEnvInfos.o OpenCL_infos.o OpenCLEnvInfos.d OpenCL_infos.d OpenCLEnvInfos.exe
#echo ' '
I tried everything (Libs order in linking command), -l instead of -L (but the compiler doesnt find them) ... Eclipse makefile generation make more errors occurs that's why I had to rewrite it...
I hope someone has the answer :p
Baptiste
You misuse compiler switches. Read the GCC manual for more information.
With -L you should provide the path to the directory where to search for libraries. In your case, where libOpenCL.a or OpenCL.a are located. For example:
-LD:/Libraries/OpenCL/lib
With -l you specify the library you want to link against. In your case, that would be libOpenCL.a or OpenCL.a. Like this:
-lOpenCL
The order is correct. In other words, you should keep these -l switches after all *.o files (in the invocation of g++ for linkage stage) if these *.o files depend on the libraries specified by -l, what in your case is indeed true.
I am new to Linux. I have access to two Linux machine, one 40 core server(A) and a cluster(B). I am trying to do the same on both machines, it works on A and doesn't on B. I have sudo rights on neither. A runs on debian squeeze/sid. B runs on kernel 2.6.18-238.el5. I could not find any release info file under /etc. A has gcc 4.6.2, whereas B gcc 4.1.2.
I compiled and installed locally on both machines a given meshing software Pkg1, and Pkg2, a given solver. Both need Libtool and automake. Pkg2 is a .so file. All work fine, I could run the examples. The code was built with mpicxx. Both have different mpi compilers. A uses openmpi154, B uses qlogicmpi_gnu-0.1.0.
Now I introduce my code, say Pkg3, a few .cpp files. I built a .so out of it. I did not use Libtool and automake. A simple make file, with gcc as compiler and linker (also tried mpicxx) was used.
On A, Pkg3 runs fine. On B, Pkg3 crashes. It crashes when it tries to dynamically cast some type in Pkg3 to a type defined in Pkg2 with message St8bad_cast. For another data file, it crashes when a function in Pkg2 tries to cast a type from Pkg3, with message 'element type is N5ngfem8FE_Segm2E expected type is N5ngfem19ScalarFiniteElementILi1EEE '
Where do I look for problems? Sorry for being vague. All the software here is opensource, but the packages are too big to make a self contained repro with little amount of work. I have neither worked with automake and Libtools, nor with mpi yet, which compounds the issue. I looked into the makefiles of Pkg1 and Pkg2 and tried to map the CXX, LDFLAGS etc with my simple makefile, but the multiple indirections created by automake/libtools makes it difficult.
I understand the symbols in Pkg2 are mangled differently in the symbol table than the ones in Pkg3. But that should have been taken care of the linker?! I have tried with both with and without '-Wl,-E' options for Pkg3. -fPIC is always there. The rule to link Pkg3, points to library Pkg2 (). I have posted the body of Pkg3's makefile.
%.o : %.cpp
gcc -O2 -fopenmp -fPIC -DNETGEN_ELTRANS -DUSE_TIMEOFDAY -DLAPACK -I. -I$(NETGENDIR)/../include -c $? -o $#
libmyngsolve.so : $(objects)
gcc -shared -Wl,-E -fopenmp -fPIC $(objects) -L/home/lv70227/elan/ng/lib -lngsolve -o $#
clean:
rm *.o libmyngsolve.so
Note 1:
The ./configure command for Pkg2 has -Wl,--start-group -lmkl_intel_lp64 -lmkl_sequential -lmkl_core -Wl,--end-group -lpthread
i.e., it does not have -E flag. But that is how it was specified to me, as reference.
Note 2:
The path defined in the link rule, -L/home/lv70227/elan/ng/lib,
has pkg2.so.0.0.0, two symbolic links to it, and pkg2.la, not pkg2.sa since it was created by libtools.
Any hint as to where the problem could lie is appreciated. I have followed the same procedure on both machine, making minimum deviations to accommodate the different mpi, gcc, mkl libraries installed in A and B.
Thank you,
Elan.
As I told you in comments, GCC 4.1 and GCC 4.6 are so different that a possible solution could be to install a GCC 4.6 (perhaps by compiling its source code, and required dependencies) on your older machine.