Undefined reference to `WinMain` [duplicate] - c

When I try to build a program using Eclipse CDT, I get the following:
/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106):
undefined reference to `WinMain#16
Why is that? And, how can I solve this issue?

This error occurs when the linker can't find WinMain function, so it is probably missing. In your case, you are probably missing main too.
Consider the following Windows API-level program:
#define NOMINMAX
#include <windows.h>
int main()
{
MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
Now let's build it using GNU toolchain (i.e. g++), no special options. Here gnuc is just a batch file that I use for that. It only supplies options to make g++ more standard:
C:\test> gnuc x.cpp
C:\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem 00000003 (Windows CUI)
C:\test> _
This means that the linker by default produced a console subsystem executable. The subsystem value in the file header tells Windows what services the program requires. In this case, with console system, that the program requires a console window.
This also causes the command interpreter to wait for the program to complete.
Now let's build it with GUI subsystem, which just means that the program does not require a console window:
C:\test> gnuc x.cpp -mwindows
C:\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem 00000002 (Windows GUI)
C:\test> _
Hopefully that's OK so far, although the -mwindows flag is just semi-documented.
Building without that semi-documented flag one would have to more specifically tell the linker which subsystem value one desires, and some Windows API import libraries will then in general have to be specified explicitly:
C:\test> gnuc x.cpp -Wl,-subsystem,windows
C:\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem 00000002 (Windows GUI)
C:\test> _
That worked fine, with the GNU toolchain.
But what about the Microsoft toolchain, i.e. Visual C++?
Well, building as a console subsystem executable works fine:
C:\test> msvc x.cpp user32.lib
x.cpp
C:\test> dumpbin /headers x.exe | find /i "subsystem" | find /i "Windows"
3 subsystem (Windows CUI)
C:\test> _
However, with Microsoft's toolchain building as GUI subsystem does not work by default:
C:\test> msvc x.cpp user32.lib /link /subsystem:windows
x.cpp
LIBCMT.lib(wincrt0.obj) : error LNK2019: unresolved external symbol _WinMain#16 referenced in function ___tmainCRTStartu
p
x.exe : fatal error LNK1120: 1 unresolved externals
C:\test> _
Technically this is because Microsoft’s linker is non-standard by default for GUI subsystem. By default, when the subsystem is GUI, then Microsoft's linker uses a runtime library entry point, the function where the machine code execution starts, called winMainCRTStartup, that calls Microsoft's non-standard WinMain instead of standard main.
No big deal to fix that, though.
All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main:
C:\test> msvc x.cpp user32.lib /link /subsystem:windows /entry:mainCRTStartup
x.cpp
C:\test> dumpbin /headers x.exe | find /i "subsystem" | find /i "Windows"
2 subsystem (Windows GUI)
C:\test> _
No problem, but very tedious. And so arcane and hidden that most Windows programmers, who mostly only use Microsoft’s non-standard-by-default tools, do not even know about it, and mistakenly think that a Windows GUI subsystem program “must” have non-standard WinMain instead of standard main. In passing, with C++0x Microsoft will have a problem with this, since the compiler must then advertize whether it's free-standing or hosted (when hosted it must support standard main).
Anyway, that's the reason why g++ can complain about WinMain missing: it's a silly non-standard startup function that Microsoft's tools require by default for GUI subsystem programs.
But as you can see above, g++ has no problem with standard main even for a GUI subsystem program.
So what could be the problem?
Well, you are probably missing a main. And you probably have no (proper) WinMain either! And then g++, after having searched for main (no such), and for Microsoft's non-standard WinMain (no such), reports that the latter is missing.
Testing with an empty source:
C:\test> type nul >y.cpp
C:\test> gnuc y.cpp -mwindows
c:/program files/mingw/bin/../lib/gcc/mingw32/4.4.1/../../../libmingw32.a(main.o):main.c:(.text+0xd2): undefined referen
ce to `WinMain#16'
collect2: ld returned 1 exit status
C:\test> _

To summarize the above post by Cheers and hth. - Alf, Make sure you have main() or WinMain() defined and g++ should do the right thing.
My problem was that main() was defined inside of a namespace by accident.

I was encountering this error while compiling my application with SDL. This was caused by SDL defining it's own main function in SDL_main.h. To prevent SDL define the main function an SDL_MAIN_HANDLED macro has to be defined before the SDL.h header is included.

Try saving your .c file before building. I believe your computer is referencing a path to a file with no information inside of it.

My situation was that I did not have a main function.

Had same problem. To fix it I clicked save to save my .c file before building. I believe my computer was referencing a path to a file with no information inside of it.

Check that All Files are Included in Your Project:
I had this same error pop up after I updated cLion. After hours of tinkering, I noticed one of my files was not included in the project target. After I added it back to the active project, I stopped getting the undefined reference to winmain16, and the code compiled.
Edit: It's also worthwhile to check the build settings within your IDE.
(Not sure if this error is related to having recently updated the IDE - could be causal or simply correlative. Feel free to comment with any insight on that factor!)

Related

gentoo ld.gold failed on sys-libs/db

I've recently switched from default binutils linker ld.bfd to ld.gold (to get link time optimization working and why not?). It was made by manual (like here: http://wiki.gentoo.org/wiki/Gold). As the result I got chain of symlinks from /usr/bin/ld to ld.gold binary, so linker was changed transparently for build process.
But when I tried to rebuild all packages I discovered that ld.gold sometimes caused configuration/compilation failures like "C compiler cannot create executables":
checking for x86_64-pc-linux-gnu-gcc... x86_64-pc-linux-gnu-gcc
checking whether the C compiler works... no
configure: error: in `/var/tmp/portage/sys-libs/db-6.0.30-r1/work/db-6.0.30/build_unix-abi_x86_64.amd64':
configure: error: C compiler cannot create executables
Which actually was linker problem:
configure: checking whether the C compiler works
/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/../../../../x86_64-pc-linux-gnu/bin/ld: --default-symver: unknown option
/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/../../../../x86_64-pc-linux-gnu/bin/ld: use the --help option for usage information
collect2: error: ld returned 1 exit status
But package can be successfully built with default bfd linker, so question is how to go back to bfd linker for packages that are can't be built with ld.gold?
Problem package is =sys-libs/db-6.0.30-r1 (the one that got my attention for now).
The solution that comes to my mind -- is to use environment per-package modification via package.env. In problem package libtool is used, which invokes gcc as linker, so the thing is needed to add is -Wl,-fuse-ld=bfd (on link-stage, LDFLAGS).
So, full solution is:
mkdir -p /etc/portage/env
echo 'LDFLAGS="${LDFLAGS} -Wl,-fuse-ld=bfd"' >> /etc/portage/env/force-bfd.conf
echo 'sys-libs/db force-bfd.conf' >> /etc/portage/package.env

Eclipse C/C++: external library matio "undefined reference to 'Mat_Open'"

I started experimenting with C/C++ the other day because I needed it for reading level-4 MAT-files without needing to purchase the Matlab editor or compiler. So I found just the library that I needed but I'm not familiar with C or C++ at all so I'm a beginner with those two languages. Anyhow I need to include the 'matio' library. I've tried many things but I've had no luck.
I right clicked on the C/C++ project > properties > C/C++ General > Paths & Symbols > GNU C and added the path to the matio library.
I also went to C/C++ Build > Settings > Tool settings > GCC C Compiler > Includes and added the path there aswell.
Since I'm not any good with makefiles yet I did not specify my own makefile, instead I chose a executable project.
When I try to build my project it complains about a function called 'Mat_Open' in the matio library. When I hover over it, it says "undefined reference to 'Mat_Open'" the header 'matio.h' seems to work fine but it can't refer to 'Mat_Open' for some reason.
How do I solve this?
EDIT:
Here is the whole build console output.
10:42:52 **** Incremental Build of configuration Debug for project Project ****
Info: Internal Builder is used for build
gcc -IC:/matio-1.5.2/src -O0 -g3 -Wall -c -fmessage-length=0 -o CComponent.o "..\\CComponent.c"
gcc -Xlinker -lm -o Project.exe CComponent.o -lC:/matio-1.5.2/src
c:/mingw(x64)/bin/../lib/gcc/x86_64-w64-mingw32/4.8.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lC:/matio-1.5.2/src
collect2.exe: error: ld returned 1 exit status
10:42:53 Build Finished (took 330ms)
This is not necessarily an answer but may be useful for a comparison.
First of all, where did you install it? If your using Linux or Mac OSX you will want to install in the system directories (not sure about Windows). I use OSX so in my makefile (by the way I use Qt):
LIBS += -L/usr/local/lib/ -lmatio
INCLUDEPATH += /usr/local/include
Then of course, in the *.h files of my source I use:
#include "matio.h"
But I assume you have already tried that?

How do I get pthreads to work in Windows?

I was running into errors such as those mentioned bellow when trying to compile code containing pthreads
warning: return type defaults to 'int' [-Wreturn-type]|
|In function 'print_message_function':|
warning: control reaches end of non-void function [-Wreturn-type]|
| undefined reference to `_imp__pthread_create'|
| undefined reference to `_imp__pthread_create'|
| undefined reference to `_imp__pthread_join'|
| undefined reference to `_imp__pthread_join'|
I'm running GCC on Windows 7 but I have mingw installed. I'm using the IDE Code::Blocks and select "compile current file". Here is a screen shot of the linker settings, I'm at a loss here
UPDATE: I added -pthread to the "Other linker options" and it works better. There still are problems. When I compile it says
|In function 'print_message_function':|
warning: control reaches end of non-void function [-Wreturn-type]|
and when I go to run it CodeBlocks says "it appears the program has not been built yet" and when I click on "build" I am shown this error
mingw32-g++.exe -o "SimpleExample.exe" "SimpleExample.o" -static-libgcc -static-libstdc++ -pthread
mingw32-g++.exe: error: unrecognized option '-pthread'
Process terminated with status 1 (0 minutes, 0 seconds)
0 errors, 1 warnings (0 minutes, 0 seconds)
How do I fix this? I want to build/test on Windows but have the program run on a Unix environment. What is the difference between compile and build in an IDE?
this answer come late but ... it worked for me, so I decided to share it.
I downloaded the pthreads library from
ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-9-1-release.zip
I unzipped it, then I copyed header files (.h) in
C:\ProgramFiles\CodeBlocks\MinGW\include
and library files in
C:\ProgramFiles\CodeBlocks\MinGW\lib
I copyed the dll files in the executable folder of my project
(myprojects/bin/debug in my case)
I added the -lpthreadGC2 option in the
Settings -> Compiler -> Linker Settings -> Other Linker Options
of my Code::Blocks IDE
Hope this can help.
It is -lpthread, not -pthread.
Edit:
Libraries can be added to the compile line in a couple of ways. If we have a file called (for example) /usr/lib/libpthread.so we could include the file like this:
cc -o myprog /usr/lib/libpthread.so myprog.c
or, alternatively:
cc -o myprog -lpthread -L /usr/lib myprog.c
Since /usr/lib is a standard directory, we don't normally require the -L option. At runtime we might have to set an environment variable:
export LD_LIBRARY_PATH=/usr/lib
but again, the standard libraries are defaulted, so you don't have to use this unless you are building your own or using 3rd-party libraries.
warning: control reaches end of non-void function [-Wreturn-type]|
Your main does not return a value. Add return 0; at the end of main.
| undefined reference to `_imp__pthread_create'|
You need to link with the thread library. Add -lpthread to the linker command line.
Here's what happens currently as of now when using MinGW Installation Manager (the mingw32 package manager for windows) under Windows with the following packages installed:
mingw32-libpthreadgc-dll
mingw32-libpthreadgce-dll
ERROR: gcc 5.3.0 fails linking pthread e.g.
c:/mingw/bin/../lib/gcc/mingw32/5.3.0/../../../../mingw32/bin/ld.exe: cannot find -lpthread
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minute(s), 0 second
SOLUTION: include sources from MinGW Package Manager, too, i.e. also select
mingw32-libpthreadgc-dev
mingw32-libpthreadgce-dev
MinGW 4.9.2 does not show this effect. GCC 5.4 on Ubuntu also does not require the pthread sources to compile any code.
This one helped me out whilst other tries (using mingw32-libpthread-old or configuring linker settings) failed.

Can I skip cmake compiler tests or avoid "error: unrecognized option '-rdynamic'"

compilation options for cmake (on windows) for ARM target system but when I run configure it's starting compiler tests:
CMake Error at D:/Program Files/CMake 2.8/share/cmake-2.8/Modules/CMakeTestCCompiler.cmake:52 (MESSAGE):
The C compiler "D:/Program Files/yagarto/bin/arm-none-eabi-gcc.exe" is not
able to compile a simple test program.
It fails with the following output:
Change Dir: D:/merge/complex/build/CMakeFiles/CMakeTmp
Run Build Command:D:/PROGRA~1/YAGART~1/bin/make.exe "cmTryCompileExec/fast"
D:/PROGRA~1/YAGART~1/bin/make.exe -f
CMakeFiles/cmTryCompileExec.dir/build.make
CMakeFiles/cmTryCompileExec.dir/build
make.exe[1]: Entering directory
`D:/merge/complex/build/CMakeFiles/CMakeTmp'
"D:/Program Files/CMake 2.8/bin/cmake.exe" -E cmake_progress_report
D:/merge/complex/build/CMakeFiles/CMakeTmp/CMakeFiles 1
Building C object CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.o
"D:/Program Files/yagarto/bin/arm-none-eabi-gcc.exe" -o
CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.o -c
D:/merge/complex/build/CMakeFiles/CMakeTmp/testCCompiler.c
Linking C executable cmTryCompileExec
"D:/Program Files/yagarto/bin/arm-none-eabi-gcc.exe"
"CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.o" -o cmTryCompileExec
-rdynamic
arm-none-eabi-gcc.exe: error: unrecognized option '-rdynamic'
make.exe[1]: *** [cmTryCompileExec] Error 1
Using Yagatdo 4.6.* cross-compilation toolchain
How can I skip this tests or fix -rdynamic error that I am getting?
You can set CMAKE_<LANG>_COMPILER_WORKS to true to suppress further compiler checks for that language.
set(CMAKE_C_COMPILER_WORKS 1)
You can skip the compiler checks by adding NONE to your project call:
project(<projectname> NONE)
but this can have pretty far-reaching effects. For full details, run
cmake --help-command project
I'm not familiar with ARM, so this is probably not your best option here. I guess you'd be better to see if there's a way to fix the -rdynamic flag.
EDIT:
It looks like this was identified as a bug which is effectively still unresolved. The comments in the bug report mention adding the following lines as a workaround (presumably before your project call):
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
It seems you target actually something else than Linux, so you should tell cmake that you are cross-compiling for the generic case:
SET(CMAKE_SYSTEM_NAME Generic)
Followed by (optionally, but nice to specify):
SET(CMAKE_SYSTEM_PROCESSOR arm)
SET(CMAKE_CROSSCOMPILING 1)
However, if you specify (which you likely did because this is stated in a lot of examples online):
SET(CMAKE_SYSTEM_NAME Linux)
Then cmake will load the configuration files from (suppose version 2.8) the file:
/usr/share/cmake-2.8/Modules/Platform/Linux.cmake
from which it is likely to load:
/usr/share/cmake-2.8/Modules/Platform/Linux-GNU.cmake
Here the -rdynamic flag is set for historical reasons:
macro(__linux_compiler_gnu lang)
# We pass this for historical reasons. Projects may have
# executables that use dlopen but do not set ENABLE_EXPORTS.
set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic")
endmacro()
Rather than disabling the tests as indeed is done by specifying NONE as the PROJECT argument, it seems setting the CMAKE_SYSTEM_NAME (to something else than Linux, for instance Generic) is what you actually want to do.
If you're just compiling a static library and you want to avoid having CMake test that the compiler can generate binaries, you can set the variable CMAKE_TRY_COMPILE_TARGET_TYPE.
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
When cross compiling for Windows, where there is no -rdynamic option, you can use
-DCMAKE_SYSTEM_NAME="Windows"
with cmake. Then Cmake will skip the test with -rdynamic.

MinGW linker can't find MPICH2 libraries

MPICH2 is installed in C:\Program Files\MPICH2. There are two subdirectories (of interest), \include which contains .h files, and \lib which contains .lib files.
The readme that comes with MPICH2 has the following instructions:
create a makefile
add –I...mpich2\include
add –L...mpich2\lib
add –lmpi
add the rules for your source files
compile
Since there are no other rules in my project, I don't create a makefile, I just go to the command line and try compiling like this:
g++ -I"C:\Program Files\MPICH2\include" main.cpp -L"C:\Program Files\MPICH2\lib" -lmpi
This gives me a fistful of undefined reference errors on every single MPI symbol in the code. I spent hours trying to fix it, juggling -I, -L and -l switches around, shuffling the order of the parameters, even copied all the .lib files into the same directory as my source, but nothing seems to work.
What kind of voodoo is needed to get this thing to link?
EDIT: I think I found the problem: here's an excerpt of the linker's output in verbose mode (adding -Wl,--verbose to the compile command):
attempt to open C:\Program Files\MPICH2\lib/libmingwex.dll.a failed
attempt to open C:\Program Files\MPICH2\lib/mingwex.dll.a failed
attempt to open C:\Program Files\MPICH2\lib/libmingwex.a failed
attempt to open C:\Program Files\MPICH2\lib/mingwex.lib failed
attempt to open C:\Program Files\MPICH2\lib/libmingwex.dll failed
attempt to open C:\Program Files\MPICH2\lib/mingwex.dll failed
attempt to open C:\Program Files\MPICH2\lib\libmingwex.a failed
Apparently, the linker adds a / instead of a \ to the directory names I supply it with (except when looking for the lib___.a format for some reason), which is obviously not a valid path. Is there any way to tell the linker to use backslashes instead of slashes?
This also caught my eye:
attempt to open /mingw/lib/libmingwex.a succeeded
So I tried compiling like this:
g++ -I"/Program Files/MPICH2/include" -L"/Program Files/MPICH2/lib" objManager.cpp ongom.cpp io.cpp main.cpp -lmpi -lcxx
But I still get the same undefined reference errors.
GCC is able to find your library. Otherwise it would report: cannot find -lmpi.
Somehow it happens that the routines cannot be found in that library. I managed to compile an example with this syntax:
g++ -I../include cpilog.c ../lib/mpi.lib ../lib/mpe.lib
I did that inside msys though. And my directory does not contain spaces.
After removing libmpi.a file, this also works:
g++ -I../include -L../lib cpilog.c -lmpi -lmpe
try adding -lmpicxx (the lib for the c++ bindings), and make sure the -l... come after the cpp source file *. this works for me:
g++ -Iinclude -Llib test/cxxpi.cpp -lmpicxx -lmpi
EDIT: re: "undefined reference to 'MPI_Comm_rank'": could it be that your are mixing up / using c and / instead of c++? MPI_Comm_rank seems to be the c binding - the c++ binding would be MPI::Comm::Get_rank(). maybe try compiling your program as c, or, if you want to use c++, using the proper bindings (see cxxpi.cpp in the examples dir)?
* http://newsgroups.derkeiler.com/Archive/Comp/comp.parallel.mpi/2006-08/msg00036.html
I had the similar problem resulting from linking 32-bit object files with 64-bit MPICH library. Linking with 32-bit libmpi.a solved the problem.
I had a similar issue with mingw: for those library files with a .lib ending, I had to put the name of the library without the ending (e.g. -llibboost_system-mgw34-mt when the filename is libbboost_system-mgw34-mt.lib). For library files with a .a ending, I had to put the name of the library excluding the starting "lib" and the trailing .a (e.g. -lws2_32 for libws2_32.a).
So in your case - try -llibmpi (or whatever your file is called without the .lib ending), perhaps it's the same issue.
from: http://www.mingw.org/node/98/revisions/358/view
Note: some paths were printed with “/” as the path separator while some other was printed with “\” as the path separator. I've substitued all with “/” as MinGW GCC accept both.
So I would not put too much time into finding a way to correct the path seperator. Is your library compiled for mingw?
perhaps: http://www.mingw.org/wiki/LibraryPathHOWTO helps you a bit further.

Resources