I'm currently doing some C programming and I actually want to use the SDL library. I want to build a Small 2D game in C on Linux to sharp my skills a bit.
My issue is I'm not a super Makefile user nor library on Linux super user, I just configure things once when on a project and that's it.
So I have some trouble compiling SDL2 programs on UBUNTU 14.04.
I downloaded the latest SDL library from : http://www.libsdl.org/download-2.0.php
Then I installed it with the default step:
./configure
make
sudo make install
After that I can see that there is something in /usr/include/SDL2 so I guess it is installed.
#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
int main(int argc, char *argv[])
{
printf(“SDL test\n”);
return 0;
}
Because I'm still learning Makefiles and SDL I didn't figure it out to make it.
but I found this Makefile to compile the old SDL not the SDL2
CPP=gcc
CFLAGS=-O3
LDFLAGS=-lSDL -lSDL_mixer #Linker
EXEC=test
all: ${EXEC}
${EXEC}: ${EXEC}.o
${CPP} $(CFLAGS) -o ${EXEC} ${EXEC}.o ${LDFLAGS}
${EXEC}.o: ${EXEC}.c
${CPP} $(CFLAGS) -o ${EXEC}.o -c ${EXEC}.c
clean:
rm -fr *.o
mrproper: clean
rm -fr ${EXEC}
But this Makefile is not working for me it says that it doesn't know the lSDL_Mixer and other stuff.
How can I build a workable Makefile to compile C program with SDL2 using Makefiles and vim editor.
Thanks in advance for your help
I'll go ahead and clean up that Makefile for you.
CFLAGS = -O3
LDFLAGS =
appname = test
all: $(appname)
clean:
rm -f $(appname) *.o
.PHONY: all clean
sdl_cflags := $(shell pkg-config --cflags sdl2 SDL2_mixer)
sdl_libs := $(shell pkg-config --libs sdl2 SDL2_mixer)
override CFLAGS += $(sdl_cflags)
override LIBS += $(sdl_libs)
$(appname): test.o
$(CC) $(LDFLAGS) -o $# $^ $(LIBS)
Explanation
Variables in a makefile should be used with $(...), not ${...}.
pkg-config has an entry for SDL_Mixer, sdl-config does not. pkg-config is much more general.
using override with the SDL flags allows you to run something like make CFLAGS="-O0 -g" without breaking SDL support.
This is actually important: the SDL library flags have to be at the end of the command line, in LIBS, due to the fact that the GNU linker is sensitive to the order in which libraries are specified.
You don't need explicit rules for .c files, because GNU Make has implicit rules which are just fine.
Note that there are some very important features missing from this makefile. For example, it won't automatically recompile things when you change your header files. I would recommend that you use another build system, such as CMake or SCons, which handles this automatically. You can also do it with Make, but you'd have to paste several arcane lines of code into your makefile.
You can use sdl2-config as suggested by the SDL Linux FAQ to get the required compiler and linker flags:
SDL_CFLAGS := $(shell sdl2-config --cflags)
SDL_LDFLAGS := $(shell sdl2-config --libs)
CFLAGS := $(SDL_CFLAGS) -O3
LDFLAGS := $(SDL_LDFLAGS) -lSDL_mixer
It will find the location of your SDL.h and return the corresponding flag (e.g. -I/usr/include/SDL2 in your case) among other flags it deems necessary (e.g. for me it gives -D_THREAD_SAFE). And then you can simply #include <SDL.h>, which is the standard way to include SDL.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I'm really desperate when trying to write a C makefile for windows for my school project. I already have my makefile written and used for ubuntu and it works perfectly like this:
all: clean install
install: dynarr.o broadcaster.o main.o
gcc -o freq dynarr.o broadcaster.o main.o
clean:
rm -f *.o
dynarr.o:
gcc -c dynarr.c
broadcaster.o:
gcc -c broadcaster.c
main.o:
gcc -c main.c
I've already tried just about 10 tutorials on various sites and it is getting on my nerve.
I need to compile dynarr.c broadcaster.c main.c in this particular order and the output should be freq.exe. Compiler on the school server is gcc for both versions(linux and windows).
Please help me.
Edit: For some reason our teacher's online validator required freq.exe for both windows and linux and he did not bother to mention it anywhere. Everything I had to edit was freq to freq.exe. Thanks for support.
On Windows, you expect the compiler to produce a file named freq.exe (or the test system does, anyway) but the command you issue tells GCC to emit a file named just freq, instead. The latter seems natural for Linux, so it is not surprising that your build works as expected there.
It is tricky to support different OS families with the same makefile, which is why utilities such as the Autotools and CMake were invented. Supposing that you only need a Makefile for Windows, this variation should suffice:
all: clean install
install: dynarr.o broadcaster.o main.o
gcc -o freq.exe dynarr.o broadcaster.o main.o
clean:
rm -f *.o
dynarr.o:
gcc -c dynarr.c
broadcaster.o:
gcc -c broadcaster.c
main.o:
gcc -c main.c
With that said, I have some suggestions for further improvement:
A rule for building a specific output file should name that file as its target.
Conversely, targets of rules that do not correspond to a file created by that rule should be declared "phony" by naming them as prerequisites of a target named .PHONY.
By convention, an "install" target copies built files from their build location to a permanent system location. Neither your install rule nor anything else in your makefile does that, so you probably don't need an "install" target.
It is perhaps intentional that your rule for the default target cleans before it builds, but that is abnormal, as it defeats one of the major reasons for using make in the first place: to avoid needless work.
It is good form and it protects against errors to use Make's automatic variables to avoid repeating yourself in rules.
There is some divergence of opinion, but I think the general consensus is that a clean target should clean up all built objects, not just intermediate ones.
Applying all those would yield a makefile such as this:
all: freq.exe
freq.exe: dynarr.o broadcaster.o main.o
gcc -o $# $^
clean:
rm -f freq.exe *.o
dynarr.o:
gcc -c dynarr.c
broadcaster.o:
gcc -c broadcaster.c
main.o:
gcc -c main.c
.PHONY: all clean
Personally, I would also suggest introducing variables for the executable target (which would make it easier to adapt the makefile between Windows and Linux / macOS) and for the required object files (which is typical, and which would allow the clean target to be more precise). You could also consider relying on Make's built-in rules for building .o files from .c files, as the explicit rules you're using don't do anything that the is not also done by the built-in one. The result might be:
PROG = freq.exe
OBJS = dynarr.o broadcaster.o main.o
all: $(PROG)
$(PROG): $(OBJS)
gcc -o $# $^
clean:
rm -f $(PROG) $(OBJS)
# Relies on the built-in rules for building object files from C sources
.PHONY: all clean
I encountered this problem while installing some python modules in which had dependencies on their own C libraries. The problem is, cc is not looking into /usr/local/include at all for header files. I made it work for one of those (thinking it was a problem of the modules) by adding /usr/local/include as one of the external include directories.
Then, to test, I wrote a simple hello.c file and added #include "fftw3.h" / #include <fftw3.h> and it failed to compile if I didn't explicitly add -I/usr/local/include.
I added a line in my ~/.bash_profile to export the include the directory path to $PATH; didn't work either.
So, my question is, how do I make cc look for header files in /usr/local/include (or, for that matter, in any custom directory) always without passing -I flag?
FYI: I'm using macbook pro running OSX 10.11
If you are using GCC then you have three environment variables you can use:
CPATH
C_INCLUDE_PATH
CPLUS_INCLUDE_PATH
Take a look here.
EDIT: since you specified you are working with OS X (hence Clang), they should be supported too, take a look ad the end here. It's not uncommon to have Clang mimic GCC specs just to help in compatibility.
I think you should invest some time in understanding build systems. For example gnu make. Here, look at this:
CC = gcc
CFLAGS = -Wall
DEPS = primes.h
OBJ = go.o primes.o
%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -c -o $# $<
go: $(OBJ)
gcc $(CFLAGS) -o $# $^
This gives you:
The freedom to add any compiler you want. In your case that would be cc, in this example it is gcc.
use cflags to control to adjust the compiler - in the example -Wall will turn on the warnings
make your build work reproducible
prepare recipe with complex rules for compilation as your application grow
More information is available here.
I'm tring to compile the bait example from the Scintilla website. I have had ZERO luck in getting it to compile. I can compile scintilla itself just fine, as well as scite but bait is a different story. When I try and compile with the supplied Makefile, I get the following error:
bait.c:1:21: fatal error: gtk/gtk.h: No such file or directory
I have GTK, and using different versions of it.I've tried It doesn't seem to matter what I do. I've scowered the Internet for help, read through man page after man page and I just can't figure out what the problem is. If I don't get that error, then I just get another one.
Here's the original makefile:
.SUFFIXES: .c .o .h .a
INCLUDEDIRS=-I../scintilla/include
CXXFLAGS= -DGTK -DSCI_LEXER -W -Wall
LEXEROBJS=$(wildcard ../scintilla/gtk/Lex*.o)
all: bait
shiz:
gcc `pkg-config --cflags gtk+-2.0` $(INCLUDEDIRS) $(CXXFLAGS) -c $< -o $#
bait: bait.o $(LEXEROBJS) ../scintilla/bin/scintilla.a
gcc `pkg-config --libs gtk+-2.0 gthread-2.0` -lstdc++ -DGTK $^ -o $#
clean:
rm -rf bait *.o
I've also tried using GtkScintilla from codebrainz. I can't even make that work. I always get either the above error, or an error saying:
fatal error: gtk/gtk.h: No such file or directory
I'd really appreciate any and all help on this. Thank you.
Edit: I'm using Linux Mint
Coming back to this... If you've already solved the issue please let me know. What it's starting to look like is this is more trouble than it's worth. :)
here's what I did:
Install Mint 13 on my virtual box
libgtk-3-dev (and supporting packages)
verify I could build with pkg-config --cflags --libs gtk+-3.0
found gtk.h (/usr/include/gtk-3.0/gtk/gtk.h) and supporting files
downloaded bait example
Here's the problems:
bait's Makefile has references to gtk+-2.0 which you need to change to 3.0
bait's Makefile requires you to build in a specific directory (note the INCLUDEDIRS needs you to be in the scintilla directory
archive scintilla.a needs to be built (it's not provided and is required for bait.o)
building the archive needs you to modify the makefile (comment out these lines:
ifdef GTK3
else
GTKVERSION=gtk+-2.0
endif
Once you fix that and build the archive there's about a million more undefined references in: ScintillaGTK.cxx:(.text+0x1374) and the like..
Anyway. I'll give it a little more time, let me know if you close this issue yourself!
i've done with this makefile
##### Makefile #####
# Make file for bait on Linux or compatible OS
# Released to the public domain 2000 by Neil Hodgson neilh#scintilla.org
# This makefile tested with GCC 3.2 and GNOME 2.0
.SUFFIXES: .c .o .h .a
ifdef GTK3
GTKVERSION=gtk+-3.0
else
GTKVERSION=gtk+-2.0
endif
INCLUDEDIRS=-I../scintilla/include
CXXFLAGS= -DGTK -DSCI_LEXER -W -Wall
LEXEROBJS=$(wildcard ../scintilla/gtk/Lex*.o)
all: bait
.c.o:
gcc `pkg-config --cflags $(GTKVERSION)` $(INCLUDEDIRS) $(CXXFLAGS) -c $< -o $#
bait: bait.o $(LEXEROBJS) ../scintilla/bin/scintilla.a
gcc -DGTK $^ -o $# -lstdc++ `pkg-config --libs $(GTKVERSION) gthread-2.0` -lm -lgmodule-2.0
clean:
rm -rf bait *.o
I am currently developing a C project under Linux and Win32. The 'deliverable' is a shared library, and all the development is done under Linux with the GNU tool chain. I am using a Makefile to compile the shared library.
Every now and then I have to build a .dll under Win32 from the same src.
I've installed MinGW on the Win32 box such that I can use make and get far fewer complaints from the compiler (in comparison to MSVC). I'm at a stage where the src code compiles on both platforms
But the Linux Makefile and Win32 Makefile are different. I'm curious as how to best handle this - should I:
have 2 makefiles, e.g. Makefile for linux and Makefile.WIN32 and then run make -f Makefile.WIN32 on the Windows box
Should I make a different target in a single Makefile and do something like make WIN32 on the Windows box
Should I ditch make and use CMake (is the juice worth the squeeze for such a simple project, i.e. 1 shared library)
Use a single make file and put the platform-specifics in conditionals, eg
ifeq ($(OS),Windows_NT)
DLLEXT := .dll
else
DLLEXT := .so
endif
DLL := libfoo$(DLLEXT)
lib : $(DLL)
I use UNAME := $(shell uname) within my Makefile to detect the platform (Linux or MS-Windows).
I provide below a complete example based on make and gcc to build a shared library: *.so or *.dll depending on the platform.
The example is basic/simple/stupid to be more understandable :-)
To use make and gcc on MS-Windows, Cygwin or MinGW can be installed.
The example uses five files:
├── app
│ └── Makefile
│ └── main.c
└── lib
└── Makefile
└── hello.h
└── hello.c
The Makefiles
app/Makefile
app.exe: main.o
gcc -o $# $^ -L../lib -lhello
# '-o $#' => output file => $# = the target file (app.exe)
# ' $^' => no options => Link all depended files
# => $^ = main.o and other if any
# '-L../lib' => look for libraries in directory ../lib
# '-lhello => use shared library hello (libhello.so or hello.dll)
%.o: %.c
gcc -o $# -c $< -I ../lib
# '-o $#' => output file => $# = the target file (main.o)
# '-c $<' => COMPILE the first depended file (main.cpp)
# '-I ../lib' => look for headers (*.h) in directory ../lib
clean:
rm -f *.o *.so *.dll *.exe
lib/Makefile
UNAME := $(shell uname)
ifeq ($(UNAME), Linux)
TARGET = libhello.so
else
TARGET = hello.dll
endif
$(TARGET): hello.o
gcc -o $# $^ -shared
# '-o $#' => output file => $# = libhello.so or hello.dll
# ' $^' => no options => Link all depended files => $^ = hello.o
# '-shared' => generate shared library
%.o: %.c
gcc -o $# -c $< -fPIC
# '-o $#' => output file => $# = the target file (main.o)
# '-c $<' => compile the first depended file (main.cpp)
# '-fPIC' => Position-Independent Code (required for shared lib)
clean:
rm -f *.o *.so *.dll *.exe
The source code
app/main.c
#include "hello.h" //hello()
#include <stdio.h> //puts()
int main()
{
const char* str = hello();
puts(str);
}
lib/hello.h
#ifndef __HELLO_H__
#define __HELLO_H__
const char* hello();
#endif
lib/hello.c
#include "hello.h"
const char* hello()
{
return "hello";
}
The build
Fix the copy-paste of Makefiles (replace leading spaces by tabulation).
> sed -i 's/^ */\t/' */Makefile
The make command is the same on both platforms. The given output is for MS-Windows (unnecessary lines removed).
> cd lib
> make clean
> make
gcc -o hello.o -c hello.c -fPIC
gcc -o hello.dll hello.o -shared
> cd ../app
> make clean
> make
gcc -o main.o -c main.c -I ../lib
gcc -o app.exe main.o -L../lib -lhello
The run
The application requires to know where is the shared library.
On MS-Windows, the simple/basic/stupid way is to copy the library where the application is:
> cp -v lib/hello.dll app
`lib/hello.dll' -> `app/hello.dll'
On Linux, use the LD_LIBRARY_PATH environment variable:
> export LD_LIBRARY_PATH=lib
The run command line and output are the same on both platforms:
> app/app.exe
hello
As somebody who has used both autotools and CMake, I would recommend using CMake over rolling your own Makefiles and using autotools. CMake has so many useful, easy to use benefits, even if it is a simple project. For example, CMake will create an NSIS installer, manage production vs. debug compilation and has a nice testing framework. The one knock I had was that it was kind of hard to find real examples of how to use it. So much open source software uses autotools that realworld examples for it are easy to find. However, if you download the CMake source, there are lots of examples in the Example directory and Test directory.
In other words, the Juice is worth the squeeze.
I had a similar issue a few years back, and found that cmake is much easier for cross-platform compilation AND will use whatever compiler is native for that system. Syntax is clearer and abstracts details that are unnecessary for the most part (sometimes that got in the way, but usually there was a way around it)
As a primary advice, I suggest using libtool, autoconf and automake; they make cross-compilation very easy, and much easier than CMake.
If you are going the hand-crafted route, I would suggest going with different targets. Switching between makefiles tends to hide otherwise obvious errors in Makefiles, e.g. duplicately used objects with different rules. Example: The object foo.o is compiled for the DLL target and for the .so target, but with different flags. If someone switches Makefiles, the existing .o file with wrong flags is used, breaking the build. If you are using one Makefile, this will become obvious through rule conflicts.
If you are willing to use MSYS2 on Windows you might get it to run without
making any changes at all compared to your code written for Linux.
This goes for your C/C++ source code as well as for your makefile.(!)
I have been developing code for Linux exclusively. When I tried running it
inside an MSYS2 terminal, the code turned out to work just fine, and
produced a Windows binary executable. I was positively surprised.
You will need to know how to install and use MSYS2, of course. For example,
to install make and g++, in an MSYS2 terminal run the commands:
yes | pacman -Syu msys/make
yes | pacman -Syu gcc
If you want to find out where in Windows g++ has been installed, you can run
where g++ in the MSYS2 terminal.
References:
https://www.msys2.org/wiki/MSYS2-installation/
https://github.com/msys2/MSYS2-packages/issues/293
I am modifying an old makefile in order to build a C extension for postgreSQL. The Makefile currently looks like this:
PGLIB = /usr/lib/postgresql/8.4/lib
PQINC = /usr/include/postgresql/8.4/server
CC=gcc
override CFLAGS+= $(CFLAGS_SL) -DPG_AGGREGATE
SHLIB = pg_myextlib
SRC = foo.c \
foobar.c
OBJS = foo.o \
foobar.o
all: $(OBJS)
$(CC) -shared -o $(SHLIB)$(DLSUFFIX) $(OBJS) -I$(PQINC)
cp *.so $(PGLIB)
clean:
rm -f $(SHLIB) $(OBJS)
The error I get when I run make is:
common.h:58:22: error: postgres.h: No such file or directory
Which suggests that the include path is not being added (the file exists in $PQINC).
Its a long time since I wrote the Makefile - and I haven't written many since. As an aside, I am pretty sure that 'shared' is not the gcc flag to build shared libs on Ubuntu (my current dev box) - I think the flag should be 'fPIC' - can someone confirm this?
I am runing gcc v4.4.3 on Ubuntu 10.0.4 and compiling for use with PG 8.4
Try moving the -I$(PQINC) from target all to the end of line that starts with override CFLAGS.
Placing -Isomething on the compiler line which turns object files, like those in $(OBJS), into executable will have no effect whatsoever.
You need to do it when you compile the source files.
Since your makefile doesn't explicitly show the rule for processing source files, it may well be using a default one, which is incredibly unlikely to know about PQINC.
You seem to be using the default rules to build foo.o from foo.c, which doesn't have your -I. Try adding the following rule to your Makefile:
.c.o:
$(CC) $(CFLAGS) -c $< -o $# -I$(PQINC)