Compiles with Visual Studio, but not g++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <sstream>
#include <vector>
#include <filesystem>
#include <fstream>
#include <shlobj.h>
#include <locale>
#include <codecvt>
#include <windows.h>
#include "data.h"

// ...

int createShortcut(const std::string& path, const std::string& appName)
{
	std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;

	CoInitialize(NULL);
	IShellLink* pShellLink = NULL;
	HRESULT hres;
	hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL,
		IID_IShellLink, (void**)&pShellLink);

	if (SUCCEEDED(hres))
	{
		std::string filePath{ path + "\\" + appName};
		pShellLink->SetPath(filePath.c_str());
		pShellLink->SetDescription(appName.c_str());
		pShellLink->SetIconLocation(filePath.c_str(), 0);

		IPersistFile* pPersistFile;
		hres = pShellLink->QueryInterface(IID_IPersistFile, (void**)&pPersistFile);

		if (SUCCEEDED(hres))
		{
			std::string linkPath{ getenv("USERPROFILE") };
			linkPath += "\\Desktop\\" + appName + ".lnk";
			std::wstring wLinkPath = converter.from_bytes(linkPath);
			hres = pPersistFile->Save(wLinkPath.c_str(), TRUE);
			pPersistFile->Release();
		}

		else
			return 2;

		pShellLink->Release();
	}

	else
		return 1;

	return 0;
}


This compiles fine in Visual Studio 2019 in a blank project without having to link anything or set additional include paths, but when I try to compile with g++, it fails with the following:

C:\Users\Admin\AppData\Local\HexLoader>g++ impl.cpp -o new.exe
C:/ProgramData/mingw64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\Admin\AppData\Local\Temp\ccfaepkX.o:impl.cpp:(.text+0x9af): undefined reference to `__imp_CoInitialize'
C:/ProgramData/mingw64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\Admin\AppData\Local\Temp\ccfaepkX.o:impl.cpp:(.text+0x9e5): undefined reference to `__imp_CoCreateInstance'
C:/ProgramData/mingw64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\Admin\AppData\Local\Temp\ccfaepkX.o:impl.cpp:(.rdata$.refptr.IID_IPersistFile[.refptr.IID_IPersistFile]+0x0): undefined reference to `IID_IPersistFile'
C:/ProgramData/mingw64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\Admin\AppData\Local\Temp\ccfaepkX.o:impl.cpp:(.rdata$.refptr.IID_IShellLinkA[.refptr.IID_IShellLinkA]+0x0): undefined reference to `IID_IShellLinkA'
collect2.exe: error: ld returned 1 exit status


I haven't used gcc/g++ very much. I read that the functions it can't find are defined in Ole32.lib, part of the Windows SDK, so I tried:

g++ impl.cpp -o new.exe -L"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\um\x64"


..and got the same output. Anyone know what I can do here?
The -L option only tells the linker where to look.
You also need to use the -l option to state which library you want to actually reference.

As a guess, you might try -lole32

The GNU linker has some implied naming rules when on Linux, I don't know how those are implemented on Windows, so there might be a bit of fussing to get the syntax right.

You should also examine the build log of your VS build to see if further libraries are also required.
Perhaps:
https://stackoverflow.com/questions/6705396/undefined-reference-to-imp-coinitialize4

VS by default will include certain lib files:

kernel32.lib
user32.lib
gdi32.lib
winspool.lib
comdlg32.lib
advapi32.lib
shell32.lib
ole32.lib
oleaut32.lib
uuid.lib
odbc32.lib
odbccp32.lib

Other compilers may not and required ones may need to be manually included.
Cool thank you, I tried:

g++ impl.cpp -o new.exe -L"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\um\x64" -lole32 -luuid


and it gave me:

C:/ProgramData/mingw64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: new.exe:.retplne: section below image base


..but if I remove the search directory and just specify the libs:

g++ impl.cpp -o new.exe -lole32 -luuid


..it compiles.

My program generates data.h and impl.cpp in app data, and compiles a new bin with g++. It's a pretty lightweight application (and already needs to autoinstall chocolatey with PowerShell, then autoinstall MinGW with chocolatey) so I don't want the end user to have to download Win SDK as well. I'm thinking I'll just store the two lib files as resources, and write them to the app data folder before compilation.

Thanks again.
When using GCC from MinGW (or mingw-w64), you should not use the -L option to add the Windows SDK "Lib" directory. That is because MinGW (or mingw-w64) already comes with its own import libraries and header files for the Win32 API! If you use -L option to add the Windows SDK "Lib" directory, then GCC will now link the import libraries from the Windows SDK, rather than linkingit its own ones – but it will still be using the MinGW-provided header files for compilation, because you haven't used the -I option! Of course, you could use option -I to force GCC to use the header files from the Windows SDK "Include" directory, in order to at least be consistent – but that may cause other problems. So, just use the header files and the import libraries that come with MinGW (or mingw-w64) and that's it 😏
Last edited on
The import libraries for the WinAPI are different for each compiler, a different format. It is recommended you use GCC libs for GCC/G++ and the WinAPI libs for MSVC.

GCC/MinGW links different machine code than what MSVC links even though it theoretically performs the same function(s).
Topic archived. No new replies allowed.