i have n number of cpp files in a project.'A' is the source file which will have main function,'B' is an another source file which contains function definition which will be used by 'A'.
A.cpp
#include "stdafx.h"
#include "b.h"
int main()
{
add(5,4);
return 0;
}
B.h
#include "stdafx.h"
void add(int a ,int b);
B.cpp
#include "stdafx.h"
void add(int a,int b)
{
cout<<(a+b);
}
but the build order is like a.cpp after b.cpp so the add function should be unresolved by linker.
how can i solve the build order problem?
Edit 1:my build file log:-
Build started 22-11-2014 15:57:11.
1>Project "C:\Users\Admin\Documents\Visual Studio 2013\Projects\ConsoleApplication2\ConsoleApplication2\ConsoleApplication2.vcxproj" on node 2 (Build target(s)).
1>Link:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"C:\Users\Admin\Documents\Visual Studio 2013\Projects\ConsoleApplication2\Release\ConsoleApplication2.exe" /INCREMENTAL:NO /NOLOGO /LIBPATH:D:\Glut /LIBPATH:D:\OpenCV\opencv\build\x86\vc11\lib opencv_core246.lib opencv_features2d246.lib opencv_haartraining_engine.lib opencv_calib3d246.lib opencv_highgui246.lib opencv_imgproc246.lib opencv_legacy246.lib opencv_ml246.lib opencv_objdetect246.lib opencv_video246.lib glut32.lib asmlibrary.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /DEBUG /PDB:"C:\Users\Admin\Documents\Visual Studio 2013\Projects\ConsoleApplication2\Release\ConsoleApplication2.pdb" /SUBSYSTEM:CONSOLE /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"C:\Users\Admin\Documents\Visual Studio 2013\Projects\ConsoleApplication2\Release\ConsoleApplication2.lib" /MACHINE:X86 /SAFESEH Release\CLM.obj
Release\FCheck.obj
Release\FDet.obj
Release\IO.obj
Release\Patch.obj
Release\PAW.obj
Release\PDM.obj
Release\Tracker.obj
Release\updated_facetracker_v2.obj
Release\glm.obj
Release\glmimg.obj
Release\glmimg_devil.obj
Release\glmimg_jpg.obj
Release\glmimg_png.obj
Release\glmimg_sdl.obj
Release\glmimg_sim.obj
Release\glm_util.obj
Release\stdafx.obj
1>updated_facetracker_v2.obj : error LNK2001: unresolved external symbol "void __cdecl glmDraw(struct _GLMmodel *,unsigned int)" (?glmDraw##YAXPAU_GLMmodel##I#Z)
1>updated_facetracker_v2.obj : error LNK2001: unresolved external symbol "struct _GLMmodel * __cdecl glmReadOBJ(char *)" (?glmReadOBJ##YAPAU_GLMmodel##PAD#Z)
1>C:\Users\Admin\Documents\Visual Studio 2013\Projects\ConsoleApplication2\Release\ConsoleApplication2.exe : fatal error LNK1120: 2 unresolved externals
1>Done Building Project "C:\Users\Admin\Documents\Visual Studio 2013\Projects\ConsoleApplication2\ConsoleApplication2\ConsoleApplication2.vcxproj" (Build target(s)) -- FAILED.
Build FAILED.
Time Elapsed 00:00:00.81
this is the original projects build file here glm.c is compiled built after the updated_facetracker_v2.cpp file and glm.c did not have any error."
Your linker fais, because B.cpp doesn't compile. The compiler fails to create an object for B.cpp. Since the object isn't there, the linker can't find it, and gives the error. There should be an error about B.cpp further up the error log.
Change B.cpp from:
#include "stdafx.h"
void add(int a,int b)
{
cout<<(a+b);
}
to:
#include "stdafx.h"
#include <iostreams>
void add(int a,int b)
{
std::cout<<(a+b) << std::endl;
}
Build order doesn't matter: The compiler takes each source file and creates an object file. The linker takes the object files and tries to link those to your target executable. The order your compiler generates the object files shouldn't matter.
Also, your main is faulty too:
change:
add(5+4);
to:
add(5, 4);
You are trying to link against add(int) while your function in B.cpp has the signature add(int, int) which is a different function according to the linker.
Related
I have a compiled static library of raylib : raylib.lib. I compiled this library myself with Librarian > General > Additional Dependencies: winmm.lib
This library has a C function like the following:
void CloseWindow(void);
And I also have my very basic C++ project that uses raylib:
// main.cpp
#include "raylib.h"
int main()
{
InitWindow(100, 100, "");
while (!WindowShouldClose())
{
BeginDrawing();
ClearBackground(RAYWHITE);
EndDrawing();
}
CloseWindow();
return 0;
}
Now, when I compile my project with Linker > Additional Dependencies set to:
raylib.lib; user32.lib; shell32.lib; gdi32.lib
It compiles and links without any warning.
But when I swap the order of raylib.lib and user32.lib:
user32.lib; raylib.lib; shell32.lib; gdi32.lib
Then I get a linker error:
Link:
D:\Visual Studio Community 2019\VC\Tools\MSVC\14.29.30133\bin\HostX86\x64\link.exe
/ERRORREPORT:QUEUE /OUT:"bin\MyProject.exe" /INCREMENTAL:NO /NOLOGO /LIBPATH:bin
user32.lib raylib.lib shell32.lib gdi32.lib winmm.lib /MANIFEST
/MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /DEBUG:FULL
/PDB:"bin\MyProject.pdb" /SUBSYSTEM:CONSOLE /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE
/NXCOMPAT /IMPLIB:"bin\MyProject.lib" /MACHINE:X64 obj\Release\MyProject\main.obj
raylib.lib(core.obj) : error LNK2005: CloseWindow already defined in user32.lib(USER32.dll) [D:\example\MyProject.vcxproj]
bin\MyProject.exe : fatal error LNK1169: one or more multiply defined symbols found [D:\example\MyProject.vcxproj]
So how is this possible that it's already defined? Why does the linking order matter?
UPDATE
When I compiled raylib with Librarian > General > Additional Dependencies: winmm.lib; user32.lib then I get this warning (when compiling the library):
Lib:
D:\Visual Studio Community 2019\VC\Tools\MSVC\14.29.30133\bin\HostX86\x64\Lib.exe /OUT:"bin\raylib.lib" winmm.lib user32.lib /NOLOGO /MACHINE:X64 obj\Release\raylib\core.obj
obj\Release\raylib\models.obj
obj\Release\raylib\raudio.obj
obj\Release\raylib\rglfw.obj
obj\Release\raylib\shapes.obj
obj\Release\raylib\text.obj
obj\Release\raylib\textures.obj
obj\Release\raylib\utils.obj
user32.lib(USER32.dll) : warning LNK4006: __NULL_IMPORT_DESCRIPTOR already defined in winmm.lib(WINMM.dll); second definition ignored [D:\example\raylib.vcxproj]
raudio.obj : warning LNK4006: PlaySound already defined in winmm.lib(WINMM.dll); second definition ignored [D:\example\raylib.vcxproj]
core.obj : warning LNK4006: CloseWindow already defined in user32.lib(USER32.dll); second definition ignored [D:\example\raylib.vcxproj]
core.obj : warning LNK4006: ShowCursor already defined in user32.lib(USER32.dll); second definition ignored [D:\example\raylib.vcxproj]
Having raylib compiled this way MyProject does not need to link with user32.lib and it works.
What is the best way to use raylib in this situation? Should I always compile raylib with it's dependencies (user32.lib etc.) and get those warnings or maybe I should link with them later when MyProject is compiled (then I need to make sure that raylib is linked before it's dependencies)?
I just need to do some filesystem operation using #include <filesystem>, however, I get the below link error ... I guess I am missing a library in the xlink command. Below is the error message.
Please let me know your valuable comments.
test_accuracy.obj : error LNK2019: unresolved external symbol wmemcmp referenced in function "public: class std::filesystem::path & __cdecl std::filesystem::path::operator/=(class std::filesystem::path const &)" (??_0path#filesystem#std##QEAAAEAV012#AEBV012##Z)
Debug\test_accuracy.exe : fatal error LNK1120: 1 unresolved externals
Edit
Below you can see the compile and link commands. (thx)
icl -I"C:/Program Files (x86)/IntelSWTools/sw_dev_tools/compilers_and_libraries_2020.2.254/windows/compiler/include" -I/../boost_1_73_0 -Qstd=c++17 -Qdiag-error-limit:3 -O3 -MD -Fo:DEBUG/obj/test_accuracy.obj -c test_accuracy.cpp
xilink /OPT:REF /OPT:ICF /DEBUG:FASTLINK /TLBID:1 ole32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib -LIBPATH:Debug\lib -out:Debug/test_accuracy.exe DEBUG/obj/test_accuracy.obj
The missing symbol is part of the C runtime. Try adding vruntime.lib to your link line, or linking with the MSVC linker (link.exe) instead.
I raised the problem with Intel C++ Community here and it turns out to be a reproducible issue, and they suggested to update my VS 2019 Community Edition. I updated to 16.8.5 and it worked. So may be it is probably the right solution. (at least worked for me.)
I have a working executable here and I'm trying to build a DLL from the same code, but I'm having some strange errors and managed to pinpoint the culprits after a lot of trial an error, I decided to ask for help because I'm really stuck now. I'm linking both SDL2 and Cimgui (Dear Imgui C Wrapper) statically in my code, the executable works perfectly fine:
#include "imgui/imgui.h"
#include "cimgui.h"
#pragma comment(lib, "cimgui.lib")
#include "SDL.h"
#undef main
#pragma comment(lib, "SDL2-staticd.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "imm32.lib")
#pragma comment(lib, "version.lib")
void main()
{
SDL_Init(0);
igCreateContext(0);
printf("OK");
}
So now I switch the project to DLL (I disabled that /IMPLIB option to make sure the only difference in the link command is the /DLL and the extension). When I try to build I get errors regarding cimgui.lib like:
cimgui.lib(imgui_draw.obj) : error LNK2001: unresolved external symbol memcmp
cimgui.lib(imgui_widgets.obj) : error LNK2001: unresolved external symbol memcpy
cimgui.lib(imgui.obj) : error LNK2001: unresolved external symbol memset
Apparently the Visual C runtime isn't being linked anymore, I don't really understand why, I could just add it immediately but let's step back and remove Cimgui from the code:
#include "SDL.h"
#undef main
#pragma comment(lib, "SDL2-staticd.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "imm32.lib")
#pragma comment(lib, "version.lib")
extern "C" __declspec(dllexport) void main()
{
SDL_Init(0);
}
I get 13 errors similar to this:
MSVCRTD.lib(_init_.obj) : error LNK2019: unresolved external symbol _CrtDbgReport referenced in function _CRT_RTC_INIT
So I manually include the libs that contain the missing symbols: ucrtd.lib, vcruntimed.lib, and then the DLL builds fine.
Now I try to add Cimgui again, but it fails to build with errors like these:
MSVCRTD.lib(utility.obj) : error LNK2019: unresolved external symbol __vcrt_initialize referenced in function __scrt_initialize_crt
MSVCRTD.lib(utility.obj) : error LNK2019: unresolved external symbol __acrt_initialize referenced in function __scrt_initialize_crt
the __vcrt definitions are in libvcruntimed.lib, but the __acrt definitions are in libucrtd.lib, which conflicts with ucrtd.lib, and even if I remove ucrtd.lib altogether and try to link just libucrtd.lib, I get errors like:
ucrtd.lib(ucrtbased.dll) : error LNK2005: malloc already defined in libucrtd.lib(malloc.obj)
Which I don't know how to interpret because I'm not linking ucrtd.lib.
I don't really understand why building a DLL isn't just like building an Executable especially because the EXE binary is very similar to the DLL and I could even use it to interop as a DLL but that doesn't feel right. I'm sure there's a way to build this and I just don't know how.
For completeness (and just in case), here are the linker commands for the EXE and DLL:
/OUT:"C:\Projects\BuildTest\x64\Debug\Build.dll" /MANIFEST /NXCOMPAT /PDB:"C:\Projects\BuildTest\x64\Debug\Build.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DEBUG /DLL /MACHINE:X64 /INCREMENTAL /PGD:"C:\Projects\BuildTest\x64\Debug\Build.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"x64\Debug\Build.dll.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /LIBPATH:"C:\Projects\cimgui_build\Debug" /LIBPATH:"C:\Projects\SDL2-2.0.8\build\Debug" /TLBID:1
/OUT:"C:\Projects\BuildTest\x64\Debug\Build.exe" /MANIFEST /NXCOMPAT /PDB:"C:\Projects\BuildTest\x64\Debug\Build.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DEBUG /MACHINE:X64 /INCREMENTAL /PGD:"C:\Projects\BuildTest\x64\Debug\Build.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"x64\Debug\Build.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /LIBPATH:"C:\Projects\cimgui_build\Debug" /LIBPATH:"C:\Projects\SDL2-2.0.8\build\Debug" /TLBID:1
EDIT:
I made a "Minimal, Complete and Verifiable Example" (Self-contained - dependencies included, relative paths, VS2017 project, should compile directly provided you have Windows SDK) and published online here:
https://bitbucket.org/AlanGameDev/buildmvce_so/downloads/
(you can download and extract or clone if you prefer)
If you set the linker flag /VERBOSE to both exe/dll builds and diff the results, you'd get a clue as to what's going on.
In the exe build you'd see
1> Found mainCRTStartup
1> Loaded MSVCRTD.lib(exe_main.obj)
...
1> Found __xi_a
1> Referenced in MSVCRTD.lib(exe_main.obj)
1> Loaded MSVCRTD.lib(initializers.obj)
1>Processed /DEFAULTLIB:kernel32.lib
1> Processed /DISALLOWLIB:msvcrt.lib
1> Processed /DISALLOWLIB:libcmt.lib
1> Processed /DISALLOWLIB:libcmtd.lib
1> Processed /DISALLOWLIB:vcruntime.lib
1>Processed /DEFAULTLIB:vcruntimed.lib
1> Processed /DISALLOWLIB:libvcruntime.lib
1> Processed /DISALLOWLIB:libvcruntimed.lib
1> Processed /DISALLOWLIB:ucrt.lib
1>Processed /DEFAULTLIB:ucrtd.lib
1> Processed /DISALLOWLIB:libucrt.lib
1> Processed /DISALLOWLIB:libucrtd.lib
none of which appear in the dll build. In the dll build you'd see only -
1> Found _DllMainCRTStartup
1> Loaded SDL2-staticd.lib(SDL.obj)
Which is very weird. It seems SDL2 includes its own implementation of the entry point _DllMainCRTStartup, and since the linker takes it from there and not the crt lib - it misses a whole lot of useful /DEFAULTLIB pragmas.
Googling around it seems the _dllMainCRTStartup is included within SDL to satisfy some Watcom needs, and it was already suspected to cause trouble in MSVC.
If you build SDL from sources you should probably just comment out the _dllMainCRTStartup implementation and (hopefully) build successfully.
I'm not sure what's going wrong. I'll describe the problem, followed by my understanding of what's going on. It's a simple code:
#include <iostream>
#include <stdio.h>
#include "stdafx.h"
#include <iViewNG-Core.h>
int main(int argc, char ** args) {
iViewVersion version;
iViewRC rc = iView_GetLibraryVersion(&version);
if (RC_NO_ERROR != rc)
printf("ERROR returned by iView_GetLibraryVersion(): %d\n", rc);
printf("The version of the libiViewNG is: %u.%u.%u.%u\n", version.major, version.minor, version.patch, version.build);
return 0;
}
The error description:
Error LNK2019 unresolved external symbol
__imp__iView_GetLibraryVersion#4 referenced in function _main SMI_TrialTests c:\Users\Rakshit\documents\visual studio 2015\Projects\SMI_TrialTests\SMI_TrialTests\SMI_TrialTests.obj
I confirmed that the code is indeed reading iViewNG-Core.h because the auto-fill lets me use functions declared in the file. I did this by adding the lib and include directory correctly in the appropriate VC++ directories. Since this a linker issue, where am I going wrong?
I am new to C++ and I know there are tons of duplicated LNK2019 questions but none of them seemed to solve my problem.
Linker output:
/OUT:"c:\users\rakshit\documents\visual studio
2015\Projects\SMI_TrialTests\Debug\SMI_TrialTests.exe" /MANIFEST
/NXCOMPAT /PDB:"c:\users\rakshit\documents\visual studio
2015\Projects\SMI_TrialTests\Debug\SMI_TrialTests.pdb" /DYNAMICBASE
"kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib"
"advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib"
"odbc32.lib" "odbccp32.lib" /DEBUG /MACHINE:X86 /INCREMENTAL
/PGD:"c:\users\rakshit\documents\visual studio
2015\Projects\SMI_TrialTests\Debug\SMI_TrialTests.pgd"
/SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'"
/ManifestFile:"Debug\SMI_TrialTests.exe.intermediate.manifest"
/ERRORREPORT:PROMPT /NOLOGO /VERBOSE /LIBPATH:"C:\iView NG
SDK\lib\lib-Windows7-32" /TLBID:1
Examining the symbol __imp__iView_GetLibraryVersion#4, it can be broken into two chunkcs:
__imp_: This means __declspec(dllimport).
_iView_GetLibraryVersion#4: This is the actual symbol, mangled as a C (or extern "C") __stdcall symbol, where the parameters total 4 bytes in size.
Considering this, and going by your code, the function causing the issue is likely:
extern "C" __declspec(dllimport) iViewRC __stdcall iView_GetLibraryVersion(iViewVersion*);
I would suggest checking that the LIB file for the DLL containing this function is being passed to either cl or link (in the former case, cl will pass it to link for you).
I downloaded Crypto++ 5.62 and built it with default project settings. In my project I set up the path to cryptopp.lib and defined its name in "Additional Dependencies". Both Crypto++ and my project - VS 2008.
During building of my project I get:
main.obj : error LNK2001: unresolved external symbol
"class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const CryptoPP::DEFAULT_CHANNEL" (?DEFAULT_CHANNEL#CryptoPP##3V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##B)
main.obj : error LNK2001: unresolved external symbol
"bool (__cdecl* CryptoPP::g_pAssignIntToInteger)(class type_info const &,void *,void const *)" (?g_pAssignIntToInteger#CryptoPP##3P6A_NABVtype_info##PAXPBX#ZA)
dumpbin /all cryptopp.lib shows me in the public symbols section
19471C _imp_?DEFAULT_CHANNEL#CryptoPP##3V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##B
1D6F30 __imp_?g_pAssignIntToInteger#CryptoPP##3P6A_NABVtype_info##PAXPBX#ZA
What's wrong then? Why the linker can't find the symbols?
upd:
linker command line from my project settings
/OUT:"C:\Projects\crypto_hash\Debug\crypto_hash.exe" /NOLOGO /LIBPATH:"e:\libs\cryptopp\cryptopp562\cryptopp\Win32\DLL_Output\Debug" /MANIFEST /MANIFESTFILE:"Debug\crypto_hash.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"C:\Projects\crypto_hash\Debug\crypto_hash.pdb" /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:PROMPT cryptopp.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
Try adding CRYPTOPP_IMPORTS to your project defines.
From config.h:
#ifdef CRYPTOPP_EXPORTS
# define CRYPTOPP_IS_DLL
# define CRYPTOPP_DLL __declspec(dllexport)
#elif defined(CRYPTOPP_IMPORTS)
# define CRYPTOPP_IS_DLL
# define CRYPTOPP_DLL __declspec(dllimport)
#else
# define CRYPTOPP_DLL
#endif
Or include Crypto++'s dll.h. It sets CRYPTOPP_IMPORTS:
#if !defined(CRYPTOPP_IMPORTS) && !defined(CRYPTOPP_EXPORTS) && !defined(CRYPTOPP_DEFAULT_NO_DLL)
# ifdef CRYPTOPP_CONFIG_H
# error To use the DLL version of Crypto++, this file must be included before any other Crypto++ header files.
# endif
# define CRYPTOPP_IMPORTS
#endif
If that does not work...
g_pAssignIntToInteger is from algparams.cpp:
$ grep -R g_pAssignIntToInteger *
algparam.cpp:PAssignIntToInteger g_pAssignIntToInteger = NULL;
algparam.h:CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger;
algparam.h: if (!(g_pAssignIntToInteger != NULL && typeid(T) == typeid(int) && g_pAssignIntToInteger(valueType, pValue, &m_value)))
integer.cpp: if (!g_pAssignIntToInteger)
integer.cpp: g_pAssignIntToInteger = AssignIntToInteger;
Looking at the declaration in algparam.h:
// to allow the linker to discard Integer code if not needed.
typedef bool (CRYPTOPP_API * PAssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt);
CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger;
And the implementation in algparam.cpp:
#ifndef CRYPTOPP_IMPORTS
...
NAMESPACE_BEGIN(CryptoPP)
PAssignIntToInteger g_pAssignIntToInteger = NULL;
...
So you might need to change the implementation to ensure the code uses g_pAssignIntToInteger (to keep it from being discarded). Unfortunately, nothing comes to mind at the moment.
DEFAULT_CHANNEL is declared in cryptlib.h and has storage allocated in cryptolib.cpp:
$ grep -R DEFAULT_CHANNEL *
...
cryptlib.cpp:const std::string DEFAULT_CHANNEL;
...
cryptlib.h:extern CRYPTOPP_DLL const std::string DEFAULT_CHANNEL;
...
This might be a different problem since I'm not used to seeing issues with DEFAULT_CHANNEL. See how CRYPTOPP_IMPORTS works for you, and then ask a different question since this might be a different problem.