I've been struggling with getting SDL and SDL_ttf to work together. My minimal reproducible case (down below) works in VC++ but for the life of me I can't get it to work in a MinGW environment.
SDL version: 2.0.10 (latest at moment of writing)
SDL_ttf version: 2.0.15 (latest at moment of writing)
My set up looks like this:
Copied SDL and SDL_ttf lib and include folders to my project root.
Set up my link and include in my Makefile like so:
SRC_DIR=./app/src
INC_DIR=./app/inc
OBJ_DIR=./.obj
BUILD_DIR=./build
NAME=$(BUILD_DIR)/out
all: $(NAME)
CC=gcc
CXX=g++
CXXFLAGS=-Wall -Wextra -pedantic --std=c++17 -g
# Objects to build
STNAMES=\
main \
OBJECTS=$(patsubst %,$(OBJ_DIR)/%.o, $(STNAMES))
# Windows specific settings
ifeq ($(OS), Windows_NT)
LINK=\
-L./SDL2/lib \
-L./SDL2_ttf/lib \
-lmingw32 \
-lSDL2main \
-lSDL2 \
-lSDL2_ttf \
-lstdc++ \
INCLUDE=\
-I$(INC_DIR) \
-I./SDL2/include \
-I./SDL2_ttf/include \
define mkdir =
if not exist "$(1)" mkdir "$(1)"
endef
define rmdir =
if exist "$(1)" del /S/Q "$(1)"
endef
EXECUTABLE=$(NAME).exe
# macOS specific settings
# UNTESTED, assumes dependencies are installed with brew
else
LINK=$(shell sdl2-config --libs) -lc++
INCLUDE=\
-I$(shell brew --prefix)/include/SDL2 \
define mkdir
mkdir -p $(1)
endef
define rmdir =
rm -rf $(1)
endef
EXECUTABLE=$(NAME)
endif
$(NAME): $(OBJECTS)
#$(call mkdir,$(BUILD_DIR))
$(CC) -o $# $(OBJECTS) $(LINK)
#$(EXECUTABLE)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
#$(call mkdir,$(OBJ_DIR))
#$(CXX) -o $# -c $< $(CXXFLAGS) $(INCLUDE)
re:
#$(call rmdir,$(OBJ_DIR))
make
Added the dlls to MinGW's bin folder.
Here's a minimal reproducible test case which works for me on Visual Studio, but not on MinGW:
#include <iostream>
#include <SDL.h>
#include <SDL_ttf.h>
void drawText(SDL_Renderer* renderer, TTF_Font* font, int x, int y, const char* text) {
auto surface = TTF_RenderText_Solid(font, text, SDL_Color{ 255, 255, 255, 255 });
auto texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_Rect dstRect = { x, y, surface->w, surface->h };
SDL_RenderCopy(renderer, texture, NULL, &dstRect);
SDL_DestroyTexture(texture);
SDL_FreeSurface(surface);
}
int main(int argc, char* argv[]) {
(void)argc;
(void)argv;
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* window = SDL_CreateWindow("some title", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1920, 1080, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
TTF_Init();
bool running = true;
SDL_Event event;
auto font = TTF_OpenFont("assets/courier_prime.ttf", 36);
while (running) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT)
running = false;
}
SDL_SetRenderDrawColor(renderer, 25, 25, 25, 255);
SDL_RenderClear(renderer);
drawText(renderer, font, 10, 10, "Test string");
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255 );
auto rect = SDL_Rect{10, 100, 110, 200};
SDL_RenderFillRect(renderer, &rect);
SDL_RenderPresent(renderer);
}
TTF_CloseFont(font);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
return 0;
}
Regardless of where I place that SDL_RenderFillRect (before or after the drawText), the only thing I see is the text. The Rectangle is no longer visible.
I'm currently dealing with a mixed OS dev environment (mac and windows), hence why I'd like it to build on both using make.
Seems like it was an issue with SDL_RENDERER_ACCELERATED and openGL not being linked. Linking openGL did not fix the issue, however, swapping to the software renderer (SDL_RENDERER_SOFTWARE) did fix the rendering bug. Very strange that it does work on VS though. I guess that'll remain a mystery...
Related
I've been trying to set up a build environment for OpenGL using glfw3 and GLAD. I'm currently using WSL2 Ubuntu with an X Server for compilation and a makefile.
However, when I run my make I receive the following error:
src/glad.c:25:10: fatal error: glad/glad.h: No such file or directory
25 | #include <glad/glad.h>
This is odd to me because it seems that the makefile is able to compile the main.cpp file and create a main.o despite also including "glad/glad.h"
File structure:
-HelloTriangle
--include
---glad
----glad.h
---KHR
----khrplatform.h
--src
---glad.c
---main.cpp
--makefile
This is my make file:
BASE_OBJS = main.o glad.o
SRC_PATH = src
OBJS = $(addprefix $(SRC_PATH)/, $(BASE_OBJS))
CXX = g++
CXXFLAGS = -g -Iinclude
LDFLAGS =
LDLIBS = -lglfw -lGL -lX11 -lpthread -lXrandr -lXi -ldl
HelloTriangle: $(OBJS)
$(CXX) -o $# $(LDFLAGS) $^ $(LDLIBS)
clean:
rm $(OBJS)
This is my main.cpp:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
/*
Function to handle window resizing
*/
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
int main() {
/*
Initialize GLFW
Sets version to Core profile 3.3
*/
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/*
Initialize a window context for OpenGL
Defines the windows width, height, and title
*/
GLFWwindow* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Hello Triangle", NULL, NULL);
if(window == NULL) {
std::cout << "Failed to create GLFW window" <<std::endl;
glfwTerminate();
return -1;
}
/*
Initialize GLAD
Handles OS-specific function pointers
*/
if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
/*
Handle window resizing
*/
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
/*
Render loop
*/
while(!glfwWindowShouldClose(window)) {
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); }
You seem to set the CXXFLAGS (for the C++ compiler), but your glad.c is compiled with the C-compiler (which checks CFLAGS)
On macOS, if I compile with
clang -I. -framework OpenGL main.cpp glad.c /usr/local/Cellar/glfw/3.3.1/lib/libglfw.3.3.dylib
I can build and run the generated executable from the following code:
#define GL_SILENCE_DEPRECATION
#include <stdio.h>
#include "glad/glad.h"
#include "/usr/local/Cellar/glfw/3.3.1/include/GLFW/glfw3.h"
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClearColor(0.9, 0.1, 0.1, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
But I would like to build using a Makefile, so I prepared
CC = clang
XXFLAGS = -g -Wall -v
CPPFLAGS = -I.
LDLIBS = -lm -L/usr/local/Cellar/glfw/3.3.1/lib -lglfw
LDFLAGS = -framework OpenGL
OBJS = main.o glad.o
PROGRAM = main
$(PROGRAM): $(OBJS)
$(CXX) $^ $(XXFLAGS) $(CPPFLAGS) $(LDLIBS) $(LDFLAGS) -o $#
clean:
-rm -f *.o
distclean: clean
-rm -Rf $(PROGRAM)
It actually makes the executable but when I run it I get
$ ./main
Segmentation fault: 11
So I guess there is something wrong in the Makefile, right?
$ make -n
c++ -I. -c -o main.o main.cpp
clang -I. -c -o glad.o glad.c
c++ main.o glad.o -g -Wall -v -I. -lm -L/usr/local/Cellar/glfw/3.3.1/lib -lglfw -framework OpenGL -o main
You didn't define the rule to build OBSJ, so make used its built-in rules. The PROGRAM rule only links object files, and there's no point specifying CPPFLAGS there.
.PHONNY: all
all: clean a.out
a.out:
clang++ -I glad/include -F /Library/frameworks -framework OpenGL main.cpp glad/src/glad.c /usr/local/Cellar/glfw/3.3.1/lib/libglfw.3.3.dylib
clean:
rm a.out
References:
https://www.gnu.org/software/make/manual/make.html
https://opensource.com/article/18/8/what-how-makefile
i'm trying to use the SDL1.2 librairie with c++ files but, i can't compile.
i'm on windows and when i want to compile, the linking cannot be done.
i made a makefile :
CC = gcc
CFLAGS = -Wall -I include
LDFLAGS = -L/lib -lmingw32 -lSDLmain -lSDL -lSDL_image -mwindows
Programme : main.o
$(CC) main.o -o Programme $(LDFLAGS)
main.o : main.cpp
$(CC) $(CFLAGS) -c main.cpp -o main.o
clean :
del -rf *.o
mrproper : clean
del Programme
and here is my main.cpp :
#include <stdio.h>
#include <SDL/SDL.h>
void pause();
int main(int argc, char *argv[])
{
SDL_Surface *ecran = NULL, *imageDeFond = NULL;
SDL_Rect positionFond;
positionFond.x = 0;
positionFond.y = 0;
SDL_Init(SDL_INIT_VIDEO);
ecran = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE);
SDL_WM_SetCaption("Chargement d'images en SDL", NULL);
imageDeFond = SDL_LoadBMP("lac_en_montagne.bmp");
SDL_BlitSurface(imageDeFond, NULL, ecran, &positionFond);
SDL_Flip(ecran);
pause();
SDL_FreeSurface(imageDeFond);
SDL_Quit();
return EXIT_SUCCESS;
}
void pause()
{
int continuer = 1;
SDL_Event event;
while (continuer)
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
}
}
}
and when i run the makefile with the command :
mingw32-make
here is the output :
C:\Users\summire\Desktop\a day in hell>mingw32-make
gcc main.o -o Programme -L/lib -lmingw32 -lSDLmain -lSDL -lSDL_image -mwindows
C:/Program Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lSDLmain
C:/Program Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lSDL
C:/Program Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lSDL_image
collect2.exe: error: ld returned 1 exit status
mingw32-make: *** [makefile:6: Programme] Error 1
can someone please explain me what am i doing wrong ?
also, here is my arborescence :
/
img/
example1.png
include/
SDL/
all the .h files for SDL
lib/
libSDL.a
libSDLmain.a
src/
(nothing yet)
I just started learning c++ and makefiles. Now I'm stuck.
There seem to be dozens of questions like this, but I can't figure out which answer applies to my situation. This answer is probably obvious. Some clues for where to look and reasons for what I am doing is wrong would be greatly appreciated!
This is my error:
Undefined symbols for architecture x86_64:
"App::init(char const*, int, int, int, int, bool)", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [../out/MYAPP] Error 1
This is my code:
main.cpp
#include "App.h"
// our App object
App* a_app = 0;
int main(int argc, char* argv[])
{
a_app = new App();
a_app->init("Hello World", 100, 100, 640, 480, true);
//...etc more code
return 0;
}
App.h
#ifndef __App__
#define __App__
#include <SDL2/SDL.h>
class App
{
public:
App(){}
~App(){}
bool init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen);
//..etc
private:
};
#endif /* defined(__App__) */
App.cpp
#include "App.h"
#include <iostream>
using namespace std;
bool App::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen)
{
// attempt to initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
{
cout << "SDL init success \n";
int flags = 0;
if(fullscreen)
{
flags = SDL_WINDOW_FULLSCREEN;
}
// init the window
m_pWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
//...etc
}
else
{
cout << "SDL init fail \n";
return false; // SDL init fail
}
cout << "SDL init success \n";
m_bRunning = true; // everything inited successfully, start the main loop
return true;
}
And finally my makefile
CXX = clang++
SDL = -framework SDL2 -framework SDL2_image
INCLUDES = -I ~/Library/Frameworks/SDL2.framework/Headers -I ~/Library/Frameworks/SDL2_image.framework/Headers
CXXFLAGS = -Wall -c -std=c++11 $(INCLUDES)
LDFLAGS = $(SDL) -F ~/Library/Frameworks/
SRC = src
BUILD = build
OUT = ../out
EXE = $(OUT)/MYAPP
OBJECTS = $(BUILD)/main.o $(BUILD)/App.o
all: $(EXE)
$(EXE): $(OBJECTS) | $(OUT)
$(CXX) $(LDFLAGS) $< -o $#
$(BUILD)/%.o : $(SRC)/%.cpp | $(BUILD)
$(CXX) $(CXXFLAGS) $< -o $#
$(BUILD):
mkdir -p $(BUILD)
$(OUT):
mkdir -p $(OUT)
clean:
rm $(BUILD)/*.o && rm $(EXE)
You are not linking all the object files.
$(CXX) $(LDFLAGS) $< -o $#
should be
$(CXX) $(LDFLAGS) $^ -o $#
since the $< pseudo-variable expands to only the first dependency, which is main.o. That matches with the linker error.
In fact, making this modification alone makes the error go away on my machine.
I'm using the Allegro5 API to create my window and manage it. It allows me access to the XWindow which it creates with XCreateWindow
I have access to d->window but that's about it. From this, is there a way I could interact with the XEvents sent to this window? I want to implement clipboard functionality. I'm just not sure how I can deal with XSelection events.
You need to create the xevent loop, and to handle specific xevents. Here is a xlib hello world example, and that is how you can do it.
The example is copied from here :
#include<X11/Xlib.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
Display *dpy;
Window rootwin;
Window win;
Colormap cmap;
XEvent e;
int scr;
GC gc;
if(!(dpy=XOpenDisplay(NULL))) {
fprintf(stderr, "ERROR: could not open display\n");
exit(1);
}
scr = DefaultScreen(dpy);
rootwin = RootWindow(dpy, scr);
cmap = DefaultColormap(dpy, scr);
win=XCreateSimpleWindow(dpy, rootwin, 1, 1, 100, 50, 0,
BlackPixel(dpy, scr), BlackPixel(dpy, scr));
XStoreName(dpy, win, "hello");
gc=XCreateGC(dpy, win, 0, NULL);
XSetForeground(dpy, gc, WhitePixel(dpy, scr));
XSelectInput(dpy, win, ExposureMask|ButtonPressMask);
XMapWindow(dpy, win);
while(1) {
XNextEvent(dpy, &e);
if(e.type==Expose && e.xexpose.count<1)
XDrawString(dpy, win, gc, 10, 10, "Hello World!", 12);
else if(e.type==ButtonPress) break;
}
XCloseDisplay(dpy);
}
To build, create a Makefile :
all: hello
hello: hello.o
cc -o hello -Wall -L/usr/X11R6/lib -lX11 hello.o
hello.o: hello.c
cc -o hello.o -Wall -I/usr/X11R6/include -c hello.c