I've been crash-learning Go (1.15.8) on Windows for the past two days, and I'm at the point where I need to call C (C++) from my Go program. I've scoured the Interewebs, but almost everything is for Linux--I'm on Windows.
Instead of monkeying with golang.org/x/sys/windows to try and wrap these calls, I've created a shared library that makes a number of pretty low-level Win32 API calls. It is compiled as C++, but it has a C interface that calls into the C++ function. This interface method has been wrapped in extern "C" to make it visible to Go. The header file has only this C interface function defined.
My cgo settings within the Go file look like:
// #cgo CFLAGS: -Imetadata
// #cgo LDFLAGS: -L. -lmetadata -lkernel32 -lole32
The shared library is called "metadata.dll". I compiled it with:
cl /c /EHsc /DUNICODE /D_UNICODE /Imetadata metadata/metadata.cpp
link /DLL /OUT:metadata.dll metadata.obj /MACHINE:X64 /INCREMENTAL:NO "kernel32.lib" "ole32.lib"
The library header looks like:
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
int metadata_comment(const char* filename, int is_dir, char* comment, int buffer_size);
#ifdef __cplusplus
} // extern "C"
#endif
When I try to build (or just run, for that matter), I get just:
# command-line-arguments
abnormal program termination
I tried using the -x flag to see if I could get more information, but there's really nothing happening there. As soon as it lists the env values, it dumps into the above message. Before aborting, my build line with the -x option looks like:
WORK=N:\Temp\go-build527705418
mkdir -p $WORK\b001\
cd M:\Projects\ls
TERM='dumb' CGO_LDFLAGS='"-g" "-O2" "-LM:\\Projects\\ls" "-lmetadata" "-lkernel32" "-lole32"' "D:\\Go\\pkg\\tool\\windows_amd64\\cgo.exe" -objdir "$WORK\\b001\\" -importpath command-line-arguments -- -I "$WORK\\b001\\" -g -O2 "-IM:\\Projects\\ls\\metadata" "M:\\Projects\\ls\\ls.go"
I've been using github.com/arrieta/golang-cpp-basic-example as a reference for this (but even there, he's using gcc and Linux).
Might this be a bug in this version of Go, or am I just doing something stupid? I was blazing along really well until I hit this brick wall. Any help or insights will be appreciated.
Visual Studio can debug DLL's - just tell it what command line is needed to start the executable which will load your DLL. That can be a Go executable; VS will know that it's just debugging metadata.dll. Since this is a native debugger, it will catch the crash as it happens.
Ok, this is straight from the horse's mouth:
Go uses and supports only mingw-w64 on windows, so you can only link
things that you can link with mingw and static libs created with msvc
isn't one of them. You can however dynamic link to msvc dlls.
So, what I have discovered is that, on Windows, (c)Go will not link directly to either a static or a dynamic library. Explicit MSVC support is something they are working on, but if you want to directly link to either kind of library, you currently have to use the mingw environment. He mentions that (c)Go will "link" to a dynamic library (i.e., DLL), but I could not get it to even do that.
However, what you can do is build your DLL with whatever lower-level accesses you need, and then load that DLL at runtime and access your visible function in your Go code. Here is some example Go code based on what I'm using now that completely solved my problem:
dll_metadata := windows.MustLoadDLL("metadata.dll")
proc_metadta := dll_metadata.MustFindProc("metadata_comment")
result := ""
const METADATA_BUFFER_SIZE = 1024
buffer := make([]byte, METADATA_BUFFER_SIZE)
var pBuffer *byte
pBuffer = &buffer[0]
len, _, _ := proc_metadata.Call(
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(filename))),
uintptr(unsafe.Pointer(pBuffer)),
uintptr(METADATA_BUFFER_SIZE))
if len != 0 {
r := UTF16BytesToString(buffer)
result = r[:len]
}
I hope this helps others who might also be struggling with Go on Windows while trying to learn from the available examples which are virtually all based on some UN*X variant.
Related
I was trying to include the GMP library, which was simply the code below(I did nothing else):
#include <gmpxx.h>
However, when I tried to compile the code, the following error from g++ compiler occured:
myCode.cpp:3:10: fatal error: gmpxx.h: No such file or directory
#include <gmpxx.h>
^~~~~~~~~~~~~~~~~~~~~~
I have tried everything I searched online, putting the GMP lib here and there, adding INFINITE includepaths in c_cpp_properties.json, still, it keeps showing the message, although, I can find the file through "Go to Definition" option.
Is there any known solution to this?
It's not enough to configure VS Code includes, you need to pass those options to the compiler as well.
You don't mention your platform at all, so I'm going to use an example from my personal machine, a Macbook Pro with the fmt library.
When compiling with the fmt library, I have to provide three more options to the compiler.
-I/usr/local/include // Tells the compiler where to look for extra includes
-L/usr/local/lib // Tells the compiler where to look for extra libraries
-lfmt // fmt-specific command to use fmt library
So the full command ends up looking like this:
g++ -Wall -std=c++17 -I/user/local/include -L/usr/local/lib -lfmt main.cpp
I need all three options because fmt is installed in a non-standard location that the compiler doesn't check by default. According to the documentation, you can get away with just -lgmp and -lgmpxx if you installed the library in a standard location (happens by default with *nix and a package manager, I imagine).
If you use build tasks in VS Code, this can be set up and automated for you.
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)
I am building a shared library which uses Boost.thread internally. As a result, Boost.system is also used since Boost.thread depends on that. My shared library exports a C interface, so I want to hide all my internal exception handling and thread usage etc from the end user. It is supposed to be a black box so to speak. However, when I link with a client application, while the program runs fine - as soon as it is time to stop the processing by invoking a library function I get:
terminate called after throwing an instance of 'boost::thread_interrupted'
I catch this exception internally in the library, so I have no idea why it is not actually being caught. The end user's program is not meant to know about or handle Boost exceptions in any way. When building the shared library, I use static linking for both Boost.thread and Boost.system so the outside world is never meant to see them. I am on GCC 4.7 on Ubuntu 12. On Windows, I have no such problems (neither with MSVC or MinGw).
(EDIT)
I am editing the question to show a minimalistic example that reproduces the problem, as per the requests in the comments.
Here first is the code for testlib.cpp and testlib.h.
testlib.cpp:
#include <boost/thread/thread.hpp>
void thread_func()
{
while(1)
{
boost::this_thread::interruption_point();
}
}
void do_processing()
{
// Start a thread that will execute the function above.
boost::thread worker(thread_func);
// We assume the thread started properly for the purposes of this example.
// Now let's interrupt the thread.
worker.interrupt();
// And now let's wait for it to finish.
worker.join();
}
And now testlib.h:
#ifndef TESTLIB_H
#define TESTLIB_H
void do_processing();
#endif
I build this into a shared library with the following command:
g++ -static-libgcc -static -s -DNDEBUG -I /usr/boost_1_54_0 -L /usr/boost_1_54_0/stage/lib -Wall -shared -fPIC -o libtestlib.so testlib.cpp -lboost_thread -lboost_system -lpthread -O3
Then, I have the code for a trivial client program which looks as follows:
#include "testlib.h"
#include <cstdio>
int main()
{
do_processing();
printf("Execution completed properly.\n");
return 0;
}
I build the client as follows:
g++ -DNDEBUG -I /usr/boost_1_54_0 -L ./ -Wall -o client client.cpp -ltestlib -O3
When I run the client, I get:
terminate called after throwing an instance of 'boost::thread_interrupted'
Aborted (core dumped)
I am not explicitly catching the thread interruption exception, but according to the Boost documentation Boost.thread does that and terminates the given thread only. I tried explicitly catching the exception from within the thread_func function, but that made no difference.
(End OF EDIT)
(EDIT 2)
It is worth noting that even with -fexceptions turned on, the problem still persists. Also, I tried to throw and catch an exception that is defined in the same translation unit as the code that catches and throws it, with no improvement. In short, all exceptions appear to remain uncaught in the shared library even though I definitely have catch handlers for them. When I compile the client file and the testlib file as part of a single program, that is to say without making testlib into a shared library, everything works as expected.
(End OF EDIT 2)
Any tips?
I finally figured it out. The -static flag should never be specified when -shared is specified. My belief was that it merely told the linker to prefer static versions of libraries that it links, but instead it makes the generated dynamic library unsuitable for dynamic linking which is a bit ironic. But there it is. Removing -static solved all my problems, and I am able to link Boost statically just fine inside my dynamic library which handles exceptions perfectly.
Maybe this?
If you have a library L which throws E, then both L and the
application A MUST be linked against X, the library containing the
definition of E.
Try to link executable against boost, too.
A shared library that itself includes statically linked libraries is not such a good idea, and I don't think that this scenario is well supported in the GNU toolchain.
I think that your particular problem arises from the option -static-libgcc, but I've been unable to compile it in my machine with your options. Not that linking statically-dinamically to libpthread.so sounds as such a good idea either... What will happen if the main executable wants to create its own threads? Will it be compiled with -pthread? If it is, then you will link twice the thread functions; if it isn't, it will have the functions but not the precompiler macros nor the thread-safe library functions.
My advice is simply not to compile your library statically, that's just not the Linux way.
Actually that should not be a real problem, even if you don't want to rely on the distribution version of boost: compile your program against the shared boost libraries and deploy all these files (libboost_thread.so.1.54.0, libboost_system.so.1.54.0 and libtestlib.so) to the same directory. Then run your program with LD_LIBRARY_PATH=<path-to-so-files>. Since the client is not intended to use boost directly, it doesn't need the boost headers, nor link them in the compiler command. You still have your black box, but now it is formed by 3 *so files, instead of just 1.
I'm trying to create a program that uses some of the code from WebKit/GTK+. Specifically, I want to load a string, use WebKit's parser to construct a DOM tree and then iterate over that tree.
I'm trying to use a class called HTMLDocument. WebKit/GTK+ doesn't expose this as part of its API and I'm running into some trouble linking against it.
I'm able to build WebKit/GTK+ normally, which gives me a file called: libwebkit-1.0.so. My program is:
#include <iostream>
#include <WebCore/config.h>
#include <WebCore/html/HTMLDocument.h>
using namespace WebCore;
int main() {
String title = "test";
RefPtr<HTMLDocument> d = HTMLDocument::create(0);
d->open();
d->write("<!doctype html><html><head><title>" + title + "</title></head><body></body></html>");
}
This compiles fine (I'm using the same include directives used by webkit to build), but results in linking errors.
...test_doc.cpp:18: undefined reference to `WebCore::String::String(char const*)'
...test_doc.cpp:21: undefined reference to WebCore::Document::open(WebCore::Document*)'
...(similar for every function I use)
If I run:
nm -C .libs/libwebkit-1.0.so | grep 'WebCore::Document::open'
I see:
003b1830 T WebCore::Document::open(WebCore::Document*)
which seems to indicate that the function is available. I have a reasonable amount of C++ experience, but not much experience with linking files under Linux.
I'm not expecting this exact problem to be solved, but I'm hoping someone can correct me if I have conceptual problems. My main question is why I see "undefined reference" errors when I'm linking with an .so file that lists that function as being defined. Is another file or build step needed?
Thank you very much.
Using:
Ubuntu 9.10
g++ 4.4.1
g++ is invoked with:
g++ --debug -DHAVE_CONFIG_H -I. `pkg-config --cflags libsoup-2.4` \
-DBUILDING_CAIRO__=1 -DBUILDING_GTK__=1 -DWTF_CHANGES -DWTF_USE_ICU_UNICODE=1 \
-DNDEBUG -I./WebCore -I./WebCore/accessibility -I./WebCore/bindings/js \
-I./WebCore/bridge -I./WebCore/bridge/c -I./WebCore/css -I./WebCore/dom \
...many more webkit include directories...
-DDATA_DIR=\"/usr/local/share\" \
test_doc.cpp -o test_doc.out \
./webkit-1.1.15.3/.libs/libwebkit-1.0.so
(I get the same result with -L/path/to/lib -lwebkit-1.0)
I think you might be running into an ordering problem: man g++ specifies that the order of the -l option is significant, and from memory the linker will only look for symbols in objects which have preceeded the current file on the command line.
I suspect what is happening is that the linker is trying to link test_doc before it's seen libwebkit-1.0.so, so it hasn't seen any of those symbols yet and bails.
You should use the -L/path/to/web and -lwebkit-1.0.
Also, I would compile your .cpp file in to a .o and then build your executable separately to make sure things are isolated.
Anyway, you may need to set your $LD_LIBRARY_PATH environment variable to include the path where that .so is stored. If you link to a shared library, you will need that library at run-time. Therefore, you do not want to have your webkit SO stored in its build directory (build/.libs). You want to install it. If you are not root, then you should ./configure with a --prefix=/some/path to install it to some local directory. Alternatively, you can link against the static library. One way to do this is to use the -bstatic (or similar) flag before your -lwebkit-1.0.
This is a good resource for Linux library creation and use.
I think you're issue is that the symbols you need are not exported. You can do objdump --dynamic-syms libwebkit-1.0.so to see which symbols are available. In the WebKit GTK build files there is use of the -fvisibility=hidden flag to restrict the symbols. Check your generated GNUMakefile and you'll see SYMBOL_VISIBILITY = -fvisibility=hidden. You should be able to modify the build files to get what you need.
I am trying to port a fairly large C++ project to using g++ 4.0 on Mac OS X. My project compiles without errors, but I can't get GDB to work properly. When I look at the stack by typing "bt" on the GDB command line, all file names and line numbers displayed are wrong.
For example, according to the GDB stack trace, my main() function is supposed to be in stdexcept from the Mac OS X SDK, which does not make any sense.
What could cause GDB to malfunction so badly? I've already checked for #line and #file statements in my code and made sure that the code only has unix line endings. I've also cleaned and rebuilt the project. I've also tried debugging a Hello World project and that one did not have the same problem.
Could the problem have to do with one of the third party libraries I am linking and the way those are compiled? Or is it something completely different?
Here are two exemplary calls to gcc and ld as executed by Xcode. AFAIK all cpp-files in my project are compiled and linked with the same parameters.
/Developer/usr/bin/gcc-4.0 -x c++
-arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fpascal-strings -fasm-blocks -O0 -fpermissive -Wreturn-type -Wunused-variable -DNO_BASS_SOUND -D_DEBUG -DXCODE -D__WXMAC__ -isysroot /Developer/SDKs/MacOSX10.5.sdk
-mfix-and-continue -fvisibility-inlines-hidden -mmacosx-version-min=10.4 -gdwarf-2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -D__WXDEBUG__ -D__WXMAC__ -c "/Users/adriangrigore/Documents/Gemsweeper
Mac/TSDLGameBase.cpp" -o
"/Users/adriangrigore/Documents/Gemsweeper
Mac/build/Gemsweeper
Mac.build/Debug/Gemsweeper
Mac.build/Objects-normal/i386/TSDLGameBase.o"
/Developer/usr/bin/g++-4.0 -arch i386
-isysroot /Developer/SDKs/MacOSX10.5.sdk
"-L/Users/adriangrigore/Documents/Gemsweeper
Mac/build/Debug"
-L/Developer/SDKs/MacOSX10.5.sdk/usr/local/lib
-L/opt/local/lib "-F/Users/adriangrigore/Documents/Gemsweeper
Mac/build/Debug"
-F/Users/adriangrigore/Library/Frameworks
-F/Developer/SDKs/MacOSX10.5.sdk/Library/Frameworks
-filelist "/Users/adriangrigore/Documents/Gemsweeper
Mac/build/Gemsweeper
Mac.build/Debug/Gemsweeper
Mac.build/Objects-normal/i386/Gemsweeper
Mac.LinkFileList"
-mmacosx-version-min=10.4 /opt/local/lib/libboost_program_options-mt.a
/opt/local/lib/libboost_filesystem-mt.a
/opt/local/lib/libboost_serialization-mt.a
/opt/local/lib/libboost_system-mt.a
/opt/local/lib/libboost_thread-mt.a
"/Users/adriangrigore/Documents/Gemsweeper
Mac/3rd
party/FreeImage/Dist/libfreeimage.a"
"/Users/adriangrigore/Documents/Gemsweeper
Mac/3rd
party/cpuinfo-1.0/libcpuinfo.a"
-L/usr/local/lib -framework IOKit -framework Carbon -framework Cocoa -framework System -framework QuickTime -framework OpenGL -framework AGL -lwx_macd_richtext-2.8 -lwx_macd_aui-2.8 -lwx_macd_xrc-2.8 -lwx_macd_qa-2.8 -lwx_macd_html-2.8 -lwx_macd_adv-2.8 -lwx_macd_core-2.8 -lwx_base_carbond_xml-2.8 -lwx_base_carbond_net-2.8 -lwx_base_carbond-2.8 -framework SDL -framework Cocoa -o "/Users/adriangrigore/Documents/Gemsweeper
Mac/build/Debug/Gemsweeper
Mac.app/Contents/MacOS/Gemsweeper Mac"
Please note that I have already asked a similar question regarding the Xcode debugger here, but I am reposting since I just learned that this is in fact not Xcode's fault, but a problem with GCC / ld / GDB.
Edit: My project makes use of the following third-party libraries: SDL, Boost, wxWidgets. I am not sure if this matters for this problem, but I just wanted to mention it just in case it does.
I've tried compiling an Xcode SDL project template and did not experience the same problem, so it must be due to something special in my project.
Second Edit: As I just found out, I made a mistake while searching files with the string "This is an automatically generated". I just found several dozen files with the same string, all belonging to FreeImage, one of the third party libraries I am using. So, the problem seems to be related to FreeImage, but I am not still not sure how to proceed.
I got those symptoms, when my gdb version didn't match my g++ version.
Try to get the newest gdb.
Your cpp files certainly have debug symbols in them (the -gdwarf-2 option).
Do you use a separate dSYM file for the debug symbols? Or are they inside the object files. I would first try to use DWARF in dSYM files and see if that helps (or vice versa)
The third party libraries appear to be release builds though (unless you renamed them yourself of course) e.g. I know for sure boost uses the -d monniker in the library names to denote debug libraries (e.g. libboost_filesystem-mt-d.a).
Now, this shouldn't really pose a problem, it should just mean you can't step into the calls made to third party libraries. (at least not make any sense of it when you do ;) But since you have problems, it might be worth a try to link with debug versions of those libraries...
Are you compiling with optimization on? I've found that O2 or higher messes with the symbols quite a bit, making gdb and core files pretty much useless.
Also, be sure you are compiling with the -g option.
Can it be that you are using SDL? SDL redefines main so your main will be named SDL_main and that the SDL parts might be heavy optimized so down there you'll have problem getting good gdb output.
...just a thought
Read this
For a test, you could check if addr2line gives you expected values. If so, this would indicate that there's nothing wrong with the ELF generated by your compile/link parameters and casts all suspicion on GDB. If not, then suspicion is still on both the tools and the ELF file.
I've tried compiling an XCode SDL
project template and did not
experience the same problem, so it
must be due to something special in my
project.
Correct. Your project settings are the thing that is different.
You will need to disable the debug optimizations in the Xcode project settings for the debug build. Xcode unfortunately makes GDB jump to weird lines (out of order) when you would expect it to move sequentially.
Go to your project settings. Set the following
1) Instruction Scheduling = None
2) Optimization Level = None [-O0]
3) ZERO_LINK = None
Your problems should go after after doing this.
Here is the project settings screen that you need to change the settings on:
From your flags the debug information should be in the object files.
Does your project settings build the executable in one location then move the final executable to another location when completed? If this is the case then gdb may not be finding the objectects files and thus not correctly retrieving the debug information from the object files.
Just a guess.
I encountered this several years ago when transitioning from the Codewarrior compilers to Xcode. I believe the way to get around this is to put the flag "-fno-inline-functions" in Other C Flags (for Dev only).
This problem was more pronounced on the PowerPC architecture for us.
What about if you remove the "-fvisibility-inlines-hidden" and "-mfix-and-continue" flags?
I've never had the "fix and continue" feature work properly for me.
WxWidgets do also define their own main if you use their IMPLEMENT_APP() macro
From here
As in all programs there must be a "main" function. Under wxWidgets main is implemented using this macro, which creates an application instance and starts the program.
IMPLEMENT_APP(MyApp)
See my answer here
I have now downloaded and compiled the FreeImage sources and yes, the file b44ExpLogTable.cpp is compiled into libfreeimage.a. The problem looks like the script gensrclist.sh just collects all .cpp files without skipping the one with a main in. That script generates a file named Makefile.srcs but one is already supplied. (running it on my Leopard failed, some problem with sh - it worked if I changed sh to bash)
Before you have changed anything this gives an a.out
c++ libfreeimage.a
The file Makefile.srcs has already been created so you should be able to remove the file b44ExpLogTable.cpp from it. Then do
make -f Makefile.osx clean
make -f Makefile.osx
When this is done the above c++ libfreeimage.a should give the following error
Undefined symbols:
"_main", referenced from:
start in crt1.10.5.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
I have a new thing you can try.
Just before your own main you can write
#ifdef main
# error main is defined
#endif
int main(int argc, char *argv[]) {
this should give an error if you have some header that redefines main.
If you define an own you might get an warning where a previous definition was made
#define main foo
int main(int argc, char *argv[]) {
You can also try to undef just before your main
#undef main
int main(int argc, char *argv[]) {