How to build library function? [duplicate] - c++

This question already has answers here:
Unresolved external symbol in object files
(31 answers)
Closed 1 year ago.
I want to build a small reusable library.
I have 2 projects, project A to build a library function (must dynamic library), and project B to run tests on it.
My problem encountered the following error:
In project B I used the following code:
#include "StdAfx.h"
#include "C:\......\projectA\Ent extension.h" (same folder with "Ent extension.cpp")
void Call_plot()
{
...=fent_select(..);
}
however when I build the project I always get an error:
Error LNK2019 unresolved external symbol "class Ent __cdecl fent_select(wchar_t const ,enum Mode)" (?fent_select##YAPEAVEnt##PEB_WW4Mode#Db###Z) referenced in function "void __cdecl" Call_plot (?Call_plot##YAXXZ)
How i can fix this problem?
Thanks you!

You need to link the object codes from both source code files together (and when you compile source code, it often turns into an object code). How to do this is somewhat dependent on your operating system and compiler. But, for example using GNU's gcc compiler, it would take the following compilation lines.
Step 1, compile the base code you want include:
gcc -g -o Ent_extension.o Ent_extension.cpp
Step 2, compile your code that wants to use the extension, telling it where the header file is for the base projectA using -I (include path):
gcc -I C:\......\projectA\ -g -o project_B.o project_B.cpp
But neither of these files is executable yet until you link them together, which takes the last step:
Link them together into an executable:
gcc -o myprogram project_B.o C:\......\projectA\Ent_extension.o
Which will create myprogram out of both your code bases.
Note: the even more advanced way is to turn the projectA code into a library and link that in, but that should be a future task.

Related

Symbol lookup error when using -Wl,--defsym GCC option

I've got a question regarding using one of the GCC linker options: -Wl,--defsym.
Some time ago I decided to rewrite one of my projects in C++ but without using its standard library and without even linking to it (I compile .cpp source files to object files using C++ compiler but I link them using C compiler).
For that I used following compiler flags:
-fno-exceptions -fno-rtti -nostdlib -nodefaultlibs
And following linker options:
-Wl,--defsym -Wl,__cxa_pure_virtual=0
Using those flags I got my shared library compiling and linking fine.
But after I try to use my shared library in some simple program (also compiled and linked using above flags) I get following error while running it:
examples/bin/blink: symbol lookup error: examples/bin/libblink.so: undefined symbol: __cxa_pure_virtual
where blink is the name of the executable and libblink.so is the name of my shared library.
I tried to fix it and it looks like replacing --Wl,--defsym linker flag (for both executable and library) with this function:
extern "C" void __cxa_pure_virtual
{
while (true);
}
does the job. Why is the --Wl,--defsym not working in this case?
I'd also like to mention that I tested this under Windows and it works fine there.
I think that I've found an answer to my question.
Changing the symbol address from 0 to any other value fixes my issue.
So instead of having:
--Wl,--defsym --Wl,__cxa_pure_virtual=0
I have:
--Wl,--defsym --Wl,__cxa_pure_virtual=1
This way runtime linker does not look for a symbol (which I think is the case when the address is set to 0).

How to use a dynamic lib in eclipse?

Here is an small example I did with clang++ :
===filename===
calc_mean.cpp
===filename===
===filecontent===
double mean(double a, double b) {
return (a+b) / 2;
}
===filecontent===
===filename===
calc_mean.h
===filename===
===filecontent===
double mean(double, double);
===filecontent===
===filename===
commands.sh
===filename===
===filecontent===
#/usr/bin/env bash
clang++ -c calc_mean.cpp -o calc_mean.o
ar rcs libmean.a calc_mean.o
clang++ -c -fPIC calc_mean.cpp -o calc_mean.o
gcc -shared -W1,-soname,libmean.so.1 -o libmean.so.1.0.1 calc_mean.o
clang++ main.cpp -L. -lmean -o dynamicmain -v
===filecontent===
===filename===
main.cpp
===filename===
===filecontent===
#include <stdio.h>
#include "calc_mean.h"
int main(int argc, char const* argv[])
{
double v1, v2, m;
v1 = 5.0;
v2 = 6.0;
m = mean(v1, v2);
printf("Mean: %f\n", m);
return 0;
}
===filecontent===
It worked perfectly. Now turn to eclipse, I created a project with the dynamic lib generated above in the libs folder:
(source: p.im9.eu)
Adjusted -L and -l settings accordingly:
(source: p.im9.eu)
Got these errors:
(source: p.im9.eu)
Other things I have tried:
(source: p.im9.eu)
(source: p.im9.eu)
The errors stayed the same. I almost want to bang my head against a wall now. Should I start learning cmake already?
update
I added the header file also this time, but eclipse still can't resolve the function mean (through code analysis).
It compiles without an error though, but when I run the output binary, it says:
dyld: Library not loaded: libmean.so
Referenced from: /Users/kaiyin/personal_config_bin_files/workspace/testuselib/Debug/testuselib
Reason: image not found
Edit2:
It hit me that you're on Mac, and I remembered that there's something funny about library loading. So, there are a couple reasons why you'd get Image Not Found. The below still applies, but there's another reason it could be failing. See dyld: Library not loaded: libqscintilla2.5.dylib
I don't know if eclipse on Mac even ships with GCC, or if it's clang only on that platform, but try setting DYLD_LIBRARY_PATH as a quick test to see if it's just Mac Being Special. https://superuser.com/questions/282450/where-do-i-set-dyld-library-path-on-mac-os-x-and-is-it-a-good-idea
Edit:
Yay it compiles! Now we're hitting a linking error. This one is actually pretty fun, and isn't the "common" one I listed below (namely, Unresolved Symbols). This error, "Image Not Found" usually means that the Linker found the library, but could not use it because it was compiled in an incompatible manner.
Why is it in any incompatible format? Welcome to the one feature of C++ that I hate is missing, and one of the reasons pretty much every library out there provides a C interface instead of a C++ interface.
C++ Does Not Provide a stable ABI (Application Binary Interface). This means that libraries compiled with different compilers (or even just different versions of the same compiler may not work together. 99/100 they will just outright refuse to link/work, but even if they do link, you'll get very weird, hard-to-impossible to track down bugs, etc.
Here's the tl;dr: If you want your static lib to be C++ (which i recommend) and have a C++ interface, you need to make sure the exact same version of the compiler is used to compile both your application and the static library. The easiest way to do this is to have eclipse build both the static library and the application.
This is hopefully changing with the next version of C++, as Herb Sutter has put forward a proposal to create a platform defined C++ ABI.
Original:
You need to add the folder containing calc_mean.h to the "Additional Includes" for c++ generation. You can think of include statement as cutting and pasting the contents of the file at that exact line. The error is saying "hey, i went looking for a file called calc_mean.h and couldn't find it." You need to link the library and the header (so main.cpp knows the function)
If it was an error saying "unresolved symbols", with the symbols being in your library, then you would know you've messed up with adding the library or library path (-L).
Cmake is a good tool, but it is nice to know how to use an ide. The basic steps (add library name, add library path, add directory containing library headers) are the same in eclipse, netbeans, visual studio, xcode, etc)

referenced in section `.rodata' of

Hey friends
I am stuck at a serious linking error, I am getting an error like this referenced in section .rodata' of xxx defined in discarded section .text._xxx.
This is how I am compiling my program
g++ main.o CPQENReportBB1.o CPQENReportBB2.o CPQ10minRecord.o PQ10minconfiguration.o ENReportConfig.o CPQFreeRecording.o CPQFreeHistogramReport.o
I have 8 files, it is compiling correctly but while linking I get the previously mentioned error. (i am using g++ version 3.4.3)
In two files I am getting this error message; I tried to shuffle the files in linking but then it is giving error in another two files.
Please give any suggestion to solve this. I am using c++ templates
2 possible reasons:
the file format and the machine architecture.
the use of __attribute__((section))

Undefined reference to MySQL libraries using g++

I am getting undefined reference to 'mysql_suchandsuch##' messages when trying to link my program with the MySQL libraries supplied with the 5.5 server. When MySQL was installed, I used the default path, which for me on Windows is C:\Program Files\MySQL\MySQL Server 5.5\. Originally, I had thought that the spaces are causing my grief, but I think I've correctly worked out how to point to the library path without spaces (still with no luck). If there's another probable cause, please let me know.
I have reviewed a series of questions on this site trying to resolve my issue...
Question 1
Question 2
Question 3
Question 4
Question 5
Question 6
Question 7
Using mingw/g++, I have tried to link using the following options, based on my own research as well as suggestions here:
-L"C:\Program Files\MySQL\MySQL Server 5.5\lib\" -llibmysql.lib
-L"C:\Program Files\MySQL\MySQL Server 5.5\lib\" -lmysqlclient.lib
-L"C:\Progra~1\MySQL\MySQLS~1.5\lib\" -llibmysql.lib
-LC:\Progra~1\MySQL\MySQLS~1.5\lib\ -lmysqlclient.lib
-L"C:\Progra~1\MySQL\MySQLS~1.5\lib\" -lmysql
In all cases, I have put the -L/-l options at the right-most part of the statement, as I understand this can matter.
I have confirmed the libraries do exist. In the /lib dir, I have libmysql.lib, mysqlclient.lib, and libmysql.dll. I have not tried to link with the .dll, as no tutorial/forum I've reviewed suggested that.
I am not using MAKEFILES.
Does anyone have specific experience with g++/MySQL?
The following commands work fine for me using a GCC 4.6.1 from November 2011:
g++ my.cpp -I D:\Opt\MySQL5.5\include ^
D:\Opt\MySQL5.5\lib\libmysql.dll -o myWithDll.exe
g++ my.cpp -I D:\Opt\MySQL5.5\include ^
-L D:\Opt\MySQL5.5\lib -lmysql -o myWithLib.exe
So both linking against the LIB and the DLL do work.
You may get a warning (see Gaffi's comment). This is because the linker does fuzzy linking for you without you having it specified; normally, it would have failed to link. It is being nice, though, and making it work for you, at the same time warning you about things happening without your having requested them. The way to suppress the warning is to make fuzzy linking explicit:
g++ -Wl,--enable-stdcall-fixup my.cpp -I D:\Opt\MySQL5.5\include ^
D:\Opt\MySQL5.5\lib\libmysql.dll -o myWithDll.exe
g++ -Wl,--enable-stdcall-fixup my.cpp -I D:\Opt\MySQL5.5\include ^
-L D:\Opt\MySQL5.5\lib -lmysql -o myWithLib.exe
This is a Cygwin/RedHat/MinGW extension to the linker; the docs are here:
--enable-stdcall-fixup
--disable-stdcall-fixup
If the link[er] finds a symbol that it cannot resolve, it will attempt to
do “fuzzy linking” by looking for another defined symbol that differs
only in the format of the symbol name (cdecl vs stdcall) and will
resolve that symbol by linking to the match. For example, the
undefined symbol _foo might be linked to the function _foo#12, or the
undefined symbol _bar#16 might be linked to the function _bar. When
the linker does this, it prints a warning, since it normally should
have failed to link, but sometimes import libraries generated from
third-party dlls may need this feature to be usable. If you specify
--enable-stdcall-fixup, this feature is fully enabled and warnings
are not printed. If you specify --disable-stdcall-fixup, this feature is
disabled and such mismatches are considered to be errors. [This option
is specific to the i386 PE targeted port of the linker]
did you try -lmysql as the linker automatically prepends lib and appends .lib

compiling a Fortran program with multiple parts

I'm very very new to Fortran and the whole Intel compiler thing (I'm using the Windows-based Intel compiler with IMSL library w/o Visual Studio integration, therefore command line only).
The problem should be extremely simple: I have a Fortran program that I needed to compile that's stored as four different source code parts. The main program (and some subroutines) are stored in the code file named central.for, and there are also three files, let's call them s1.for, s2.for and s3.for, each of which contains only one subroutine (lets call them sub1-sub3) and no main program. The main program calls the subroutines stored in s1-s3 as well as in central.for.
The question is how should I compile it:
When I try to compile the central.for, it gives error LNK2019: unresolved external symbol _SUB1 referenced in function _MAIN__. Similarly it gives the same message for SUB2 and SUB3.
When I try to compile s1.for-s3.for, it gives error LNK2019: unresolved external symbol _MAIN__ referenced in function _main
It seems obvious that I need to link them somehow. However, I have no idea how
You need to compile the pieces of the program without linking first, then link them all together. So your command line will look like this:
ifort /c s1.for
ifort /c s2.for
ifort /c s3.for
ifort /c central.for
where the /c is short for /compile-only; /nolink would also work. This will generate files s1.o, s2.o, s3.o, and central.o, respectively. The above can be done in any order. Now the individual pieces get linked together, and you'll do something like
ifort /exe:central.exe central.o s1.o s2.o s3.o
to build the executable.
Note that this gets one step more complicated if you're compiling modern fortran code that uses modules, and (for instance) the main program in central.for has a line like use s2. In that case, you have to compile (even with /c) s2 before central; when you compile s2 in that case you'd get an extra output file, s2.mod. That s2.mod file would be needed to compile central.for. But given the filename extensions, this likely is an older code and modules probably aren't an issue.
This is how I have done it. Each of the supporting functions compile in a Static Library. Then in the main program project add an existing item and selected the static library .lib file (Output from compilation). The just call the functions as if their source was part of the main code (with CALL MYLIBFUN())
Good Luck.