How to cross-compile with SDL 2 from Linux for Windows - c++

I tried to compile a simple C++ program that uses SDL 2 with the mingw-w64-g++ compiler on my Arch Linux (64bits).
For this I downloaded SDL2-devel-2.0.4-mingw.tar.gz from here
prog.cpp:
#include <SDL.h>
int main ()
{
SDL_Init (SDL_INIT_VIDEO);
SDL_Window *sdlWnd = SDL_CreateWindow ("Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 800, 600, 0);
SDL_Event event;
bool running = true;
while (running) {
while (SDL_PollEvent (&event)) {
if (event.type == SDL_QUIT) {
running = false;
break;
}
}
}
return 0;
}
Makefile:
GPP = x86_64-w64-mingw32-g++
prog.exe: prog.o
$(GPP) -o prog.exe prog.o -LSDL2-2.0.4/lib/x64 -lSDL2main -lSDL2
prog.o: prog.cpp
$(GPP) -o prog.o -c -ISDL2-2.0.4/include prog.cpp
Now making gives the error:
x86_64-w64-mingw32-g++ -o prog.exe prog.o -LSDL2-2.0.4/lib/x64 -lSDL2main -lSDL2
Warning: corrupt .drectve at end of def file
SDL2-2.0.4/lib/x64/SDL2main.lib(./x64/Release/SDL_windows_main.obj):(.text[main]+0x1c): undefined reference to `SDL_main'
Why undefined reference to `SDL_main' ? Although I specified -lSDL2main ?
What did I do wrong? :(

Okay, it was because of the main functions signature, that has to be declared as:
int main(int argc, char *argv[])
according to the official SDL FAQ:
Make sure that you are declaring main() as:
#include "SDL.h"
int main(int argc, char *argv[])
You should be using main() instead of WinMain() even though you are
creating a Windows application, because SDL provides a version of
WinMain() which performs some SDL initialization before calling your
main code. If for some reason you need to use WinMain(), take a look
at the SDL source code in src/main/win32/SDL_main.c to see what kind
of initialization you need to do in your WinMain() function so that
SDL works properly.

Related

SDL2 undefined reference to `SDL_CreateWindowAndRenderer'

This is my class code:
#include <SDL2/SDL.h>
#include "graphics.h"
/* Graphics class
* Holds all information dealing with graphics for the game
*/
Graphics::Graphics() {
SDL_CreateWindowAndRenderer(640, 480, 0, &this->_window, &this->_renderer);
SDL_SetWindowTitle(this->_window, "Cavestory");
}
Graphics::~Graphics() {
SDL_DestroyWindow(this->_window);
}
this is the error:
g++ "-LC:\\MinGW\\lib" -o cavestory-developement.exe "source\\src\\cavestory-developement.o" "source\\src\\graphics.o" -lmingw32 -lSDL2main -lSDL2
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: source\src\graphics.o: in function `ZN8GraphicsC2Ev':
C:\Users\John Park\eclipse-workspace\cavestory-developement\Debug/../source/src/graphics.cpp:10: undefined reference to `SDL_CreateWindowAndRenderer'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\John Park\eclipse-workspace\cavestory-developement\Debug/../source/src/graphics.cpp:11: undefined reference to `SDL_SetWindowTitle'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: source\src\graphics.o: in function `ZN8GraphicsD2Ev':
C:\Users\John Park\eclipse-workspace\cavestory-developement\Debug/../source/src/graphics.cpp:17: undefined reference to `SDL_DestroyWindow'
collect2.exe: error: ld returned 1 exit status
19:06:06 Build Failed. 5 errors, 0 warnings. (took 223ms)
______________________________________________________________________________________________________
not sure why SDL_SetWindowTitle is recognized (shows parameters and details about the function) when I hover over it with my mouse, but SDL_CreateWindowAndRenderer and SDL_DestroyWindow are not.
It compile fine for me on Fedora 32 x86_64, both as a native program and as a Windows program:
echo 'struct Graphics { Graphics(); ~Graphics(); SDL_Window *_window; SDL_Renderer *_renderer; } g;int main(int argc,char **argv){return 0;}' >graphics.h;g++ -o sdl2 sdl2.C -Wall -g $(pkg-config --cflags --libs sdl2);sudo dnf install mingw64-SDL2 mingw64-gcc-c++;x86_64-w64-mingw32-c++ -o sdl2.exe sdl2.C -Wall -g $(/usr/x86_64-w64-mingw32/sys-root/mingw/bin/sdl2-config --cflags --libs);(d=$PWD;cd /usr/x86_64-w64-mingw32/sys-root/mingw/bin;wine64 $d/sdl2.exe)

How can I invoke a function with multiple distinct signatures (as glibc invokes main)?

The C++ Standard indicates that the main can have two possible signatures.
int main() // (1)
int main(int, char*[]) // (2)
Moreover, main() is typically called from __libc_start_main, which is defined in csu/libc-start.c in the glibc source code. The invocation of main inside this function is copied below.
result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
We observe that the call here uses three arguments, and this appears to not produce any linker errors, despite the fact that the signature does not match either of the above two forms.
I am writing a threading library which defines main(), and would like the application to be able to define one of the following two functions.
int AppMain() // (1)
int AppMain(int, char*[]) // (2)
Unfortunately, if I declare AppMain using the second form above and invoke it from my library's main, and the application uses the first form instead, then I get a unresolved reference linker error indicating that the function I invoked does not exist.
Since this does not seem to be a problem for glibc with respect to main, how might I write my invocation or declaration in a way that avoids the linker error?
Here is an easy way to reproduce the problem.
Makefile
CCFLAGS=-Wall -Werror
all: libLib.a App
libLib.a: Lib.o
ar rcs $# $^
App: App.o libLib.a
g++ -o $# $< -L. -lLib
%.o: %.cc
g++ $(CCFLAGS) -O3 $(LIBS) -fPIC -c -o $# $<
Lib.cc
#include <stdio.h>
int AppMain(int argc, char** argv);
#undef main
int main(int argc, char** argv){
printf("Hello World\n");
AppMain(argc, argv);
}
App.cc (Working Version)
#include <stdio.h>
int AppMain(int argc, char** argv){
printf("Application says Hello world\n");
return 0;
}
App.cc (Non-Working Version)
#include <stdio.h>
int AppMain(){
printf("Application says Hello world\n");
return 0;
}
Under the second version, here is the linker error.
./libLib.a(Lib.o): In function `main':
Lib.cc:(.text.startup+0x24): undefined reference to `AppMain(int, char**)'
collect2: error: ld returned 1 exit status
Makefile:9: recipe for target 'App' failed
make: *** [App] Error 1
Regardless of suggestions to do it differently, I just answer your question
how might I write my invocation or declaration in a way that avoids the linker error?
You may write your definition in App.cc as
extern "C" int AppMain()
{
…
and your declaration in Lib.cc as
extern "C" int AppMain(int argc, char** argv);
to avoid that name mangling, the same as it's most probably done in glibc. There may be C++ compilers where this doesn't work, but it certainly works with the GCC.

Using GCC/Sublime to compile SDL programs on Linux

How can I use either GCC or the Sublime IDE to compile my SDL based project on Linux?
gcc main.cpp -o main -lSDL2
I have tried this and I just get errors that seem to be pointing to the idea that either the program isn't pointing at the library the right way or the compiler isn't recognizing the library. On Sublime I have essentially done the same thing by creating my own build system for SDL, but it doesn't really seem to do anything at all. What might I be doing wrong?
{
"cmd" : [ "gcc", "$file", "-o", "-lSDL2" ]
{
I hope this question is appropriate on this stack, it can be considered Linux tooling but the Linux and Unix stack doesn't suggest programming questions unless they consist of shell scripting.
Here is just the basic Hello World that I am testing (Obviously not quite formatted correctly, but you get the idea.) :
#include <SDL2/SDL.h>
int main(int argc, char *argv[]) {
int win = 1;
SDL_Event event;
SDL_Init(SDL_INIT_EVERYTHING);
SDL_WM_SetCaption("Window", NULL);
SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE);
while (win) {
SDL_WaitEvent(&event);
if (event.type == SDL_QUIT)
win = 0;
}
SDL_Quit();
return 0;
}
When the program is compiled I use the GCC command posted at the top and get these errors:
main.cpp: In function ‘int main(int, char**)’:
main.cpp:19:37: error: ‘SDL_WM_SetCaption’ was not declared in this scope
SDL_WM_SetCaption("Window", NULL);
^
main.cpp:20:36: error: ‘SDL_HWSURFACE’ was not declared in this scope
SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE);
^
main.cpp:20:49: error: ‘SDL_SetVideoMode’ was not declared in this scope
SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE);
^
I have also tried pointing directly to header files in GCC with:
gcc main.cpp -o main -l/usr/include/SDL2
I did check to make sure that the header files were in usr/include/SDL2, maybe the actual library isn't installed in the right place for development?
The errors from GCC were cause by calling functions in SDL2 that didn't exist. Changing the previous SDL Video calls to:
SDL_CreateWindow(
"Window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
SDL_WINDOW_OPENGL
);
was the right way to create a window in SDL 2;
Following with the GCC commands:
gcc main.cpp -o main -lSDL2
Compiled the code correctly and thus made it executable. Thank you for pointing that out #HolyBlackCat

LLVM JIT-compiled program cannot find external functions

My program which JIT compiles a LLVM IR module and calls a function foo defined therein fails at runtime if foo uses an externally-defined function:
LLVM ERROR: Program used external function 'glutInit' which could not be resolved!
My program:
// foo1.cpp
#include <GL/glut.h>
extern "C" void foo()
{
glutInit(0,0);
}
// foo2.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <llvm/Support/raw_ostream.h>
#include <llvm/LLVMContext.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/IRReader.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/ExecutionEngine/JIT.h>
#include <llvm/ExecutionEngine/RuntimeDyld.h>
int main(int argc, char **argv)
{
using namespace llvm;
InitializeNativeTarget();
LLVMContext context;
SMDiagnostic error;
std::ifstream ir_file("foo1.s");
std::string ir((std::istreambuf_iterator<char>(ir_file)),
(std::istreambuf_iterator<char>()));
Module *m = ParseIR(MemoryBuffer::getMemBuffer(StringRef(ir)), error, context);
if(!m)
{
error.print(argv[0], errs());
}
ExecutionEngine *ee = ExecutionEngine::create(m);
Function *func = ee->FindFunctionNamed("foo");
if(func == 0)
{
std::cerr << "Couldn't find Function foo" << std::endl;
std::exit(-1);
}
typedef void (*fcn_ptr)();
fcn_ptr foo = reinterpret_cast<fcn_ptr>(ee->getPointerToFunction(func));
foo();
delete ee;
return 0;
}
Here's how I build my program:
$ clang -S -emit-llvm foo1.cpp
$ g++ -rdynamic foo2.cpp `llvm-config --cxxflags` `llvm-config --libs` `llvm-config --ldflags` -lglut
The output:
$ ./a.out
LLVM ERROR: Program used external function 'glutInit' which could not be resolved!
It fails with a similar error any time I try to use an externally-defined function which is not in the C++ standard library (e.g., printf, malloc, & free are no problem). What am I doing wrong?
Make sure that glutInit was linked into a.out. If your host code (the thing executing the JIT) didn't call it, it could have been nixed by the linker. If that's the case, you have to add a dummy reference to it or use linker scripts / flags.
Adding the command line option -Wl,-no-as-needed immediately before -lglut will prevent the linker from dropping the glut library, which it otherwise thinks is not needed:
$ g++ -rdynamic foo2.cpp `llvm-config --cxxflags` `llvm-config --libs` `llvm-config --ldflags` -Wl,-no-as-needed -lglut

OpenGL Loader Generator undefined reference to gl::BindBuffer, etc (OpenGL Functions)

I have a problem when using OpenGL Loader Generator, which when I try to compile my code, it doesn't work. It throws an error saying undefined reference to any opengl function I use, such as gl::BindBuffer, gl::GenBuffers, etc. I'm using pointer_cpp/func_cpp style.
My simple code that I'm using is
#include "gl_core_3_3.hpp"
#include <GL/glfw.h>
int main(int argc, char *argv[]) {
glfwInit();
glfwOpenWindow(1024, 768, 0, 0, 0, 0, 0, 0, GLFW_WINDOW);
gl::exts::LoadTest didLoad = gl::sys::LoadFunctions();
if(!didLoad) {
glfwTerminate();
return 1;
}
return 0;
}
When I compile that, it says undefined reference to gl::sys::LoadFunctions too. The command I'm using to compile is
g++ main.cpp -lglfw -lGL -lGLU
I'm on Arch Linux and using Vim with clang as my IDE.
g++ main.cpp -lglfw -lGL -lGLU
I don't see where you're including the generated source file. It's not a header-only loading system. It doesn't generate a library, but it does generate source code, which must be compiled.