How to compile an example SDL program written in C? - c

I'm getting started with SDL and C programming. I have experience with other programming languages, but linking/compiling libraries in C is new to me. I am using Mac 10.8 and have installed latest stable 2.0 using the instructions in the read me (./configure; make; make install). Here is the sample code that I am trying to compile:
#include <stdlib.h>
#include <stdio.h>
#include "SDL.h"
int main(void)
{
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) {
fprintf(stderr, "\nUnable to initialize SDL: %s\n", SDL_GetError());
return 1;
}
atexit(SDL_Quit);
return 0;
}
When I try to compile my script using gcc example.c, I get an error:
example.c:3:17: error: SDL.h: No such file or directory
example.c: In function ‘main’:
example.c:7: error: ‘SDL_INIT_VIDEO’ undeclared (first use in this function)
example.c:7: error: (Each undeclared identifier is reported only once
example.c:7: error: for each function it appears in.)
example.c:7: error: ‘SDL_INIT_TIMER’ undeclared (first use in this function)
example.c:8: warning: format ‘%s’ expects type ‘char *’, but argument 3 has type ‘int’
example.c:8: warning: format ‘%s’ expects type ‘char *’, but argument 3 has type ‘int’
example.c:11: error: ‘SDL_Quit’ undeclared (first use in this function)
I tried searching the wiki, and tutorials, and any kind of documentation that I could find, but I could not find any example anywhere that showed how to properly compile a C program that uses SDL.
What do I need to do to compile this program?

A general hint for C beginners: read error logs top-down: often fixing first error will resolve all other. In your case first error is:
example.c:3:17: error: SDL.h: No such file or directory
As others have said, you need to instruct gcc where to find SDL.h. You can do this by providing -I option.
To check where SDL.h is installed by default I would issue
./configure --help
in the directory where you did build libsdl. Then look for --prefix, under Linux default prefix is often /usr/local. To compile your example I would issue (on Linux):
gcc example.c -I/usr/local/include
But the above command compiles and links the code. After successful compilation, gcc would throw another bunch of errors, one of them being undefined reference.
To prevent that, full command line to build your example (on Linux at least) would be:
gcc example.c -I/usr/local/include -L/usr/local/lib -lSDL
Where:
-I points compiler to directory with SDL.h,
-L points linker to directory with libSDL.a (or libSDL.so),
-l instructs linker to link with library, in our case libSDL.a or libSDL.so. Note that the lib prefix and .a/.so suffix is missing.
Please note that I didn't check this instruction, even on Linux machine (on the other hand I have no access to Mac OS machine).
One more thing: by default binary with the compiled and linked example will be called a.out. To change that you can provide -o option to gcc.

I found out you can use a tool called pkg-config to find out the compiler flags expected for a specific library.
$ pkg-config --cflags --libs sdl2
-D_THREAD_SAFE -I/usr/local/include/SDL2 -I/usr/X11R6/include -L/usr/local/lib -lSDL2
$ gcc example.c $(pkg-config --cflags --libs sdl2)
If you are using a Makefile, you need to prefix the command with shell:
all:
gcc example.c $(shell pkg-config --cflags --libs sdl2)

tl;dr
sudo apt install libsdl1.2-dev
You are missing the SDL library files. Just instal them and everything should work out of the box.
Different versions ans extensions
There are multiple versions of SDL, make sure you install the one that is required by your application. There are also additional libraries (called projects) for SDL that you also need to install if you use their features. For example if you use TTF fonts or image related functionalities. Just press TAB twice after you typed in sudo apt install libsdl to see all the available packages.

Related

Linking EFI application with LLVM on MacOS

I'm attempting to cross-compile and link a very simple EFI application that is using the EFI headers from the Zircon kernel. Despite my best efforts, I am unable to link a working PE executable under macOS Montery (with apple silicon), due to the LLD flag -subsystem:efi_application not being valid. The full error is:
FAILED: test.efi: && /opt/local/bin/clang -target x86_64-none-elf -ffreestanding -nostdlib -fuse-ld=lld -dll -WX -Wl,-subsystem:efi_application -Wl,entry:efi_main src/main.c.obj -o test.efi && :
ld.lld: error: unknown argument '-subsystem:efi_application'
Several guides indicate that lld-link is required to compile this correctly, however adding -fuse-ld=lld-link results in errors stating:
clang: error: invalid linker name in argument '-fuse-ld=lld-link'
This occurs despite the fact that I have lld-link in my $PATH. If I, instead, pass the full lld-link path to -fuse-ld=, I get the following error:
FAILED: test.efi: && /opt/local/bin/clang -target x86_64-none-elf -ffreestanding -target x86_64-none-elf -nostdlib -dll -WX -Wl,-subsystem:efi_application -Wl,-entry:efi_main -fuse-ld=/opt/local/bin/lld-link src/main.c.obj -o test.efi && :
lld-link: warning: ignoring unknown argument '--eh-frame-hdr'
lld-link: warning: ignoring unknown argument '-m'
lld-link: warning: ignoring unknown argument '-dynamic-linker'
lld-link: warning: ignoring unknown argument '-o'
lld-link: warning: ignoring unknown argument '-L/opt/local/libexec/llvm-13/bin/../lib'
lld-link: warning: ignoring unknown argument '-L/usr/lib'
lld-link: error: could not open 'elf_x86_64': No such file or directory
lld-link: error: could not open '/lib64/ld-linux-x86-64.so.2': No such file or directory
lld-link: error: could not open 'test.efi': No such file or directory
lld-link: error: src/main.c.obj: unknown file type
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I am using the MacPorts LLVM-13 package. The result of $ lld-link --version is LLD 13.0.0.
For reference, the code I'm attempting to compile and link is, simply:
#include "efi/protocol/graphics-output.h"
#include "efi/protocol/loaded-image.h"
#include "efi/system-table.h"
#include "efi/types.h"
#define ERR(x) if (EFI_ERROR((x))) { return (x); }
efi_status efi_main(efi_handle handle __attribute__((unused)), efi_system_table* st) {
efi_status status;
/* clear the screen */
status = st->ConOut->ClearScreen(st->ConOut);
ERR(status);
/* print 'Hello World' */
status = st->ConOut->OutputString(st->ConOut, u"Hello World");
ERR(status);
return EFI_SUCCESS;
}
What do I need to change above in order to build an EFI application using LLVM on macOS?
I'd also be curious to know any ideas as to why -fuse-ld=lld-link would fail when it exists in my PATH, and why using -fuse-ld=/opt/local/bin/lld-link would result in other implicit linker flags not succeeding.
System Details:
Compiler Suite: LLVM-13 (Macport Installation)
Host OS: macOS Monterey (Apple Silicon, M1 Pro)
Target Arch: x86_64
Build System: CMake using custom toolchain (which passes the -nostdlib, -target ... args, etc.)
You can try to use clang-cl to compile your code, using /c option to compile only: do not link yet. Use /Fo option to specify the output object file.
The clang-cl offers compatibility options from MSVC cl.exe. For further details, run clang-cl --help. The build target of clang-cl is default to windows, so you don't have to reset the build target in order to compile for EFI applications.
Be warned that clang-cl does not have full support to MSVC intrinsics. Intrinsics like __vmx_vmptrld, __svm_vmload, etc. are broken. clang-cl would generate a call instruction rather than the specific instruction. Define them in inline assembly in GCC's syntax, if you want to use these intrinsics.
After you compiled all source files into object files, run lld-link to link all output object files with /SUBSYSTEM:EFI_APPLICATION parameter into an EFI application.
I haven't used the header files from Zircon yet, but I tried compiling EDK II libraries with LLVM into .lib files on Windows.
With the help of these .lib files, I made some simple EFI applications. For instance, you can check this partition enumerator out.
The batch scripts might not work on MacOS, but, by reading them, you can definitely figure out the general ideas about how to specify the parameters.
If you want to use EDK II by virtue of its rich libraries, you might want to install Netwide Assembler as well, in that the assembly codes in EDK II libraries are NASM.

SQLite: trouble building FTS5 loadable extension

I'm on Mac trying to build FTS5 as loadable extension.
I've downloaded the SQLite sources, successfully executed ./configure and make fts5, obtained fts5.{c,h} files.
Now when trying to build the dynamic library for the extension I get:
gcc -g -fPIC -dynamiclib -o fts5.dylib fts5.c
In file included from fts5Int.h:18:0:
fts5_storage.c: In function 'sqlite3Fts5StorageOpen':
fts5_storage.c:305:9: error: 'sqlite3_api_routines' has no member named '__builtin___snprintf_chk'
In file included from /usr/include/secure/_string.h:33:0,
from /usr/include/string.h:192,
from fts5Int.h:21:
fts5_storage.c:305:26: warning: passing argument 1 of '__builtin_object_size' makes pointer from integer without a cast
fts5_storage.c:305:26: note: expected 'const void *' but argument is of type 'int'
In file included from fts5Int.h:18:0:
fts5_storage.c:308:11: error: 'sqlite3_api_routines' has no member named '__builtin___snprintf_chk'
In file included from /usr/include/secure/_string.h:33:0,
from /usr/include/string.h:192,
from fts5Int.h:21:
fts5_storage.c:308:28: warning: passing argument 1 of '__builtin_object_size' makes pointer from integer without a cast
fts5_storage.c:308:28: note: expected 'const void *' but argument is of type 'int'
What am I doing wrong?
I've tried gcc 4.9 and 5.5 from MacPorts on macOS
Interesting enough, on Linux (and with gcc5) I'm getting this error:
❯ gcc -g -fPIC -shared -o fts5.so fts5.c
fts5.h:24:21: fatal error: sqlite3.h: No such file or directory
compilation terminated.
And sure enough there's no sqlite3.h in the root of the sources directory, though I expect it should be created during the make step?
I can of course install libsqlite3-dev but I already have all the sqlite sources, why should I?
Thanks to Dan Kennedy from the SQLite dev team the issue is now resolved.
The 1st issue appeared to be the actual problem with SQLite source code when compiled on macOS, and it's now fixed here: http://www.sqlite.org/src/info/cd0471ca9f75e7c8
The 2nd problem was about the header file not generated because it requires a separate make step. So the full build instructions actually look like this:
./configure
make fts5.c sqlite3.h sqlite3ext.h
gcc -O2 -fPIC -shared fts5.c -o fts5.dylib

Linking libusb-1.0 to mycfile.c fails

Despite downloading and compiling libusb-1.0 to /usr/local, to know exactky where it is, gcc still can't find it;
gcc -o usb -L/usr/local/lib -llibusb-1.0.so -I/usr/local/include myusbcfile.c
gives;
usbtest.c:4:15: error: storage size of ‘brd_ftdi’ isn’t known
libusb_device brd_ftdi;
^
usbtest.c:5:22: error: storage size of ‘brd_ftdi_handle’ isn’t known
libusb_device_handle brd_ftdi_handle;
^
usbtest.c:6:16: error: storage size of ‘context’ isn’t known
libusb_context context;
^
This clearly indicates gcc can't find the library, tried different forms of this command, everyone giving this error.
I think your problem is this one :
-lxxxx tells the linker : 'find a library called libxxxx', so what you're asking in your command line is to find the library liblibusb-1.0.so
Maybe you should try this :
gcc -o usb -L/usr/local/lib -lusb-1.0.so -I/usr/local/include myusbcfile.c
This way, the linker should be looking for a library called libusb-1.0.so

Weird flags when building LLVM project with Make using the Clang Compiler

I recently built LLVM into the following path: C:\LLVM\llvm-new-build. I then added this path to my Environmental Variables/Path, C:\LLVM\llvm-new-build\Debug\bin. I'm trying to build my LLVM project, but I'm getting some weird output from Clang:
clang `llvm-config --cflags` -Wall -Iincludes/ src/*.c -c src/*.c
clang.exe: error: unknown argument: '-wd4146'
clang.exe: error: unknown argument: '-wd4180'
clang.exe: error: unknown argument: '-wd4244'
clang.exe: error: unknown argument: '-wd4258'
clang.exe: error: unknown argument: '-wd4267'
clang.exe: error: unknown argument: '-wd4291'
clang.exe: error: unknown argument: '-wd4345'
clang.exe: error: unknown argument: '-wd4351'
clang.exe: error: unknown argument: '-wd4355'
clang.exe: error: unknown argument: '-wd4456'
clang.exe: error: unknown argument: '-wd4457'
clang.exe: error: unknown argument: '-wd4458'
clang.exe: error: unknown argument: '-wd4459'
clang.exe: error: unknown argument: '-wd4503'
clang.exe: error: unknown argument: '-wd4624'
clang.exe: error: unknown argument: '-wd4722'
clang.exe: error: unknown argument: '-wd4800'
clang.exe: error: unknown argument: '-w14062'
clang.exe: error: unknown argument: '-we4238'
clang.exe: error: no such file or directory: 'C:/Program Files (x86)/Git/DWIN32'
clang.exe: error: no such file or directory: 'C:/Program Files (x86)/Git/D_WINDO
WS'
clang.exe: error: no such file or directory: 'C:/Program Files (x86)/Git/W3'
clang.exe: error: no such file or directory: 'C:/Program Files (x86)/Git/MP'
Makefile:22: recipe for target 'all' failed
make: *** [all] Error 1
It says there are no arguments like -wd4146 etc, but I haven't passed those to the clang compiler, and a quick google search shows know helpful answers on what these mean. This is what my build file looks like:
LCC = clang
LCXX = clang++
LLVM_CC_FLAGS=`llvm-config --cflags`
LLVM_LINK_FLAGS=`llvm-config --libs --cflags --ldflags core analysis executionengine jit interpreter native`
C_FLAGS = -Wall -Iincludes/
CXX_FLAGS = -Wall -Wextra -Wno-self-assign
SOURCES = src/*.c
all: ${SOURCES}
${LCC} ${LLVM_CC_FLAGS} ${C_FLAGS} ${SOURCES} -c ${SOURCES}
${LCXX} ${LLVM_LINK_FLAGS} *.o ${LLVM_FLAGS} -o j4
-rm *.o
The output from llvm-config --cflags
-IC:/LLVM/llvm/include -IC:/LLVM/llvm-new-build/include /DWIN32 /D_WINDOWS /W3
/MP -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEP
RECATE -D_CRT_NONSTDC_NO_WARNINGS -D_SCL_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_WA
RNINGS -wd4146 -wd4180 -wd4244 -wd4258 -wd4267 -wd4291 -wd4345 -wd4351 -wd4355 -
wd4456 -wd4457 -wd4458 -wd4459 -wd4503 -wd4624 -wd4722 -wd4800 -w14062 -we4238 -
D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
This question really has several layers, so I'm going to try to break this down into three parts: a discussion of what is happening inside the backticks, the unknown argument errors, and the no such file or directory errors.
What is llvm-config?
llvm-config is a tool for the LLVM infrastructure that gets configuration information needed to compile programs that need LLVM. So in response to the comment at 1, llvm-config actually is intended for use with clang when clang is used to compile an LLVM project.
The --cflags option gives C compiler flags including LLVM headers, which you saw in the output to llvm-config --cflags. You said
"It says there are no arguments like -wd4146 etc, but I haven't passed those to the clang compiler"
But by putting it in backticks, your shell took the output from llvm-config --cflags and pasted it into your original command. So you did include those arguments, you just didn't realize it!
I will also note that the output from llvm-config is highly dependent on your build system and the version of LLVM. For example, when installed on Ubuntu Linux 14.05, LLVM 3.5 with GNU Make and Ninja generators, the output from llvm-config --cflags is:
-I/.../llvm-3.5.0/llvm/include -I/.../llvm-3.5.0/build/include -fPIC -Wall -W -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -pedantic -Wno-long-long -Wno-comment -ffunction-sections -fdata-sections -g -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
It noticeably doesn't include any of your offending options like -wd4146 or -wd4180 nor any reference to Windows or preprocessor arguments.
What are those weird options like /DWIN32, /D_WINDOWS, /W3, and /MP?
/D defines a preprocessing symbol for a source file, in this case WIN32 and _WINDOWS. 2
/W3 directs MSVC to display level 1, level 2 and level 3 (production quality) warnings. 3
/MP causes MSVC to create multiple instances of itself and attempt to build the project in parallel. 4
The problem is that they're passed to the compiler's arguments prefixed with a forward slash (notice that all other options were passed with a hyphen). As a result, your build is attempting to handle those as file names, as indicated by the resulting errors, for example:
clang.exe: error: no such file or directory: 'C:/Program Files (x86)/Git/DWIN32'
Why it's looking in C:/Program Files (x86)/... is up to some aspect of your LLVM installation and/or your operating system. I'm going to guess it's the last location in your execution path or it is your present working directory.
What are those weird options like -wd4146 and -wd4180?
Those are options to disable certain warnings emitted for MSVC. For example, C4146 is "unary minus operator applied to unsigned type, result still unsigned" and C4180 is "qualifier applied to function type has no meaning; ignored"
Here's an example of doing the exact same thing, but from inside a GNU Make file instead of from the command line (look at the block beginning if (MSVC))
So why isn't my project building?
I can't answer this authoritatively without inspecting your LLVM build. However,
Unknown argument: You've discovered an incompatibility between your version of llvm-config and clang. You noted that you added C:\LLVM\llvm-new-build\Debug\bin to your path, but that doesn't assure that the binary actually executed for each of llvm-config and clang came from the same location. If you had previously installed a canonical, pre-built binary of clang for generic compilation usage, its location will be earlier in your path than C:\LLVM\llvm-new-build\Debug\bin. It's unlikely that llvm-config was included in your pre-built binaries. The reason this matters is that if there's a mismatch between versions, the required include flags generated by llvm-config might not match the required include flags needed by clang. You can verify that execution path shadowing is not happening using which on Unix-like machines and where.exe on Windows machines after Windows Server 2003. We expect that they will both reflect that the execution path is in fact C:\LLVM\llvm-new-build\Debug\bin. If not, there's your problem. I believe that this is what created the issues with options like -wd4146 and -wd4180, etc.
No such file or directory: When you built LLVM, cmake detected you were building on Windows, and produced Visual Studio generator files. Meanwhile, your project appears to use some sort of GNU Make-like build system. See here for more discussion of selecting generators at installation. I believe that the mix between MSVC and another GNU Make-like build system is what created the issues with options like /DWIN32, /D_WINDOWS, /W3, and /MP.

Using GraphicsMagick C API, Unknown Type Image Compile Error

I'm trying to use GraphicsMagick and got odd build errors, so I added #include <magick/magick.h> to
#include <stdio.h>
int main(int argc, char *argv[]){
printf("hello magick");
return 0;
}
just to see WTF was going on. Obviously hello_world compiles fine. Simply adding the magick header causes tons of errors compiling with any of the following:
clang or gcc -o test.o $(pkg-config --cflags --libs GraphicsMagick) test.c
clang or gcc -o test.o $(GraphicsMagick-config --cflags --libs) test.c
From clang:
zsh/2 1791 % clang -o test.o $(pkg-config --cflags --libs GraphicsMagick) test.c
In file included from test.c:2:
/usr/include/GraphicsMagick/magick/magick.h:19:9: error: unknown type name 'Image'
typedef Image
^
/usr/include/GraphicsMagick/magick/magick.h:20:28: error: unknown type name 'ImageInfo'
*(*DecoderHandler)(const ImageInfo *,ExceptionInfo *);
The solution suggested by Mr. Hale (#1) works perfectly for the test. Trying in the real project; gcc spits thousands of line of errors like:
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.1/include/f16cintrin.h: In function ‘__m128i mm256_cvtps_ph(__m256, int)’: /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.1/include/f16cintrin.h:73:66: error: cannot convert ‘__m256 {aka float}’ to ‘__vector(8) float’ for argument ‘1’ to ‘__vector(8) short int __builtin_ia32_vcvtps2ph256(__vector(8) float, int)’ return (__m128i) __builtin_ia32_vcvtps2ph256 ((__v8sf) __A, __I);
Since the only change from having the project build successfully and the above was uncommenting either one or both of the following:
#include <magick/api.h>
#include <magick/magick.h>
I'm quite sure I've got something wrong with the build settings. I'm not having success finding documentation on what particular restrictions GraphicsMagick places on compiler/linker options. Finding that might well solve the problem.
Use the <magick/api.h> header; this ensures types and forward declarations appear in the correct order.
Changing from using std=c++0x to std=gnu++11 in the project-wide CXXFLAGS seems to have resolved the issue. For whatever reason, it seems that graphicsmagick 1.3.18-3 is not usable from the c/c++ APIs with std=c++0x. I know this is not a complete explanation or answer, but it makes things build.
This has been fixed in GraphicsMagick 1.3.20.
I have found this in the ChangeLog:
2014-06-15 Bob Friesenhahn
wand/magick_compat.h: Use MAGICK_ATTRIBUTE definition from magick/common.h.
magick/common.h (MAGICK_ATTRIBUTE): Don't undefine __attribute__ since this may be used >by system or compiler headers. Define private macro instead. Resolves SourceForge bug #270 "Compile error with g++ -std=c++11".
RHEL/Fedora/CentOS users, check GraphicsMagick update request for EPEL7 in RedHat Bugzilla, Bug ID 1131926

Resources