2

I am trying to understand how to properly setup gcc to find stuff in my environmental variables.

Currently I compiled some code, SDL and I added it to my .bashrc and sourced that .bashrc as well.

Here's a simple hello program.

#include "SDL.h"
#include "SDL_ttf.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
#include <stdlib.h>
#include <stdio.h>

SDL_Window* window;
SDL_GLContext* main_context;

int main(int argc, char** argv) {
    printf("hello world %d  %c \n", argc, argv[0][argc]);


    if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
        SDL_Log("sdl failed to core_engine_init, %s", SDL_GetError());
        SDL_Quit();
        return -1;
    }

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
                        SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    window = SDL_CreateWindow(
        "title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 300, 300,
        SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);


    if (NULL == window) {
        SDL_Log("SDL Failed to create window, %s", SDL_GetError());
        SDL_Quit();
        return -1;
    }

    main_context = SDL_GL_CreateContext(window);
    if (NULL == main_context) {
        SDL_Log("SDL failed to create main context, %s", SDL_GetError());
        SDL_Quit();
        return -1;
    }

    return 0;
}

Trying to compile this with gcc -o main main.c I get these errors:

blubee$ gcc -o main main.c
/tmp/cc5hRcaO.o: In function `main':
main.c:(.text+0x3e): undefined reference to `SDL_Init'
main.c:(.text+0x47): undefined reference to `SDL_GetError'
main.c:(.text+0x59): undefined reference to `SDL_Log'
main.c:(.text+0x5e): undefined reference to `SDL_Quit'
main.c:(.text+0x77): undefined reference to `SDL_GL_SetAttribute'
main.c:(.text+0x86): undefined reference to `SDL_GL_SetAttribute'
main.c:(.text+0x95): undefined reference to `SDL_GL_SetAttribute'
main.c:(.text+0xa4): undefined reference to `SDL_GL_SetAttribute'
main.c:(.text+0xb3): undefined reference to `SDL_GL_SetAttribute'
main.c:(.text+0xd8): undefined reference to `SDL_CreateWindow'
main.c:(.text+0xf0): undefined reference to `SDL_GetError'
main.c:(.text+0x102): undefined reference to `SDL_Log'
main.c:(.text+0x107): undefined reference to `SDL_Quit'
main.c:(.text+0x11d): undefined reference to `SDL_GL_CreateContext'
main.c:(.text+0x135): undefined reference to `SDL_GetError'
main.c:(.text+0x147): undefined reference to `SDL_Log'
main.c:(.text+0x14c): undefined reference to `SDL_Quit'
collect2: error: ld returned 1 exit status

adding the SDL2 linker flag this returns an error still:

blubee$ gcc -lSDL2 -o main main.c
/usr/bin/ld: cannot find -lSDL2
collect2: error: ld returned 1 exit status

this command compiles everything fine though

blubee$ gcc -I/opt/SDL2/include/SDL2 main.c -o main -L/opt/SDL2/lib -l
SDL2

the thing is that I've added these paths to my .bashrc although I might have done it incorrectly. Here is my bashrc

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/SDL2/lib
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/SDL_IMAGE/lib
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/SDL_TTF/lib
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/SDL_MIXER/lib

export LD_RUN_PATH=$LD_RUN_PATH:/opt/SDL2/lib
export LD_RUN_PATH=$LD_RUN_PATH:/opt/SDL_IMAGE/lib
export LD_RUN_PATH=$LD_RUN_PATH:/opt/SDL_TTF/lib
export LD_RUN_PATH=$LD_RUN_PATH:/opt/SDL_MIXER/lib

export C_INCLUDE_PATH=$C_INCLUDE_PATH:/opt/SDL2/include/SDL2
export C_INCLUDE_PATH=$C_INCLUDE_PATH:/opt/SDL_IMAGE/include/SDL2
export C_INCLUDE_PATH=$C_INCLUDE_PATH:/opt/SDL_TTF/include/SDL2
export C_INCLUDE_PATH=$C_INCLUDE_PATH:/opt/SDL_MIXER/include/SDL2

echoing these environmental variables show that they are there and should be working but it's not.

What am I doing wrong with this setup?

  • As I understand it, C_INCLUDE_PATH is something that some build systems use to create the appropriate gcc options. It's not something that GCC itself uses. Similarly, you need to specify what to link against, and then ld will use the LD_LIBRARY_PATH etc. – muru Nov 10 '15 at 7:27
  • the thing is echoing my LD_LIBRARY_PATH it does show the correct path but I still have to manually use type it for gcc to pick it up. As you can see from one of the errors ld doesn't find SDL2 which is strange. – user1610950 Nov 10 '15 at 8:18
1

You don't need any environment variables, just pass in right cflags and ldflags that SDL2 wants you to use:

gcc main.c `pkg-config --cflags sdl2` -o main `pkg-config --libs sdl2`

or either

gcc main.c `sdl2-config --cflags` -o main `sdl2-config --libs`

Remember: CFLAGS come before LDFLAGS, and LDFLAGS (and library specification with -l) comes last.

SDL2 comes with sdl2-config script preinstalled. You will need to set your PATH to the directory where it resides to call it successfully:

export PATH=/opt/SDL2/bin:$PATH

If you will run every of *-config commands directly, you will see that they just output right cflags and ldflags for you. That's because the libraries that employ these scripts usually bigger than to specify single -I/-L argument, and it is not portable to specify single -I/-L arguments for them, because number of such arguments can be increased in future.

And you should not install every package in it's own directory. Install everything into /usr/local for example, then you will not need even to specify anything (most distros point you to /usr/local automatically).

  • I have already setup my path with the sdl-config but I still don't get why ld can't find SDL2 when I already set up my LD path. – user1610950 Nov 10 '15 at 8:16
  • LD path is used only when library dependencies (required libraries by your library) are searched and not when libraries are searched. – user140866 Nov 10 '15 at 9:18
  • thank you, using sdl2-config worked. I have will use this for now but I really would like to understand why this stuff works so that I can debug it w/o asking for help so much in the future. @siblynx Much appreciated. – user1610950 Nov 10 '15 at 16:58
  • Did you tried to run sdl2-config --cflags, sdl2-config --ldflags alone in command line? They should output needed cflags and ldflags. The same does pkg-config I mentioned. Many other libraries do not require this, and you can specify just a path to them with -L/-l and to include directory of it's headers with -I. But I really suggest you when you install from source, do not specify --prefix argument, so it will go to /usr/local. – user140866 Nov 11 '15 at 1:32
  • aah running the sdl2-config gives me this output: sdl2-config --cflags -I/opt/SDL2/include/SDL2 -I/usr/include -D_REENTRANT , sdl2-config --ldflags Usage: /opt/SDL2/bin/sdl2-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--cflags] [--libs] [--static-libs] That's interesting to see. So sdl2-config is just saving me some typing. That makes a lot more sense now. The reason I build from source is to get the latest versions, not necessarily the most stable and putting them in /opt/ allows me to just remove it w/o hunting through /usr/local... I've made a mess in there before. – user1610950 Nov 11 '15 at 4:31
1

As can be seen in the Catalogue of Built-In Rules:

Linking a single object file

n is made automatically from n.o by running the linker (usually called ld) via the C compiler. The precise recipe used is:

$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)

and Variables Used by Implicit Rules:

LDFLAGS

Extra flags to give to compilers when they are supposed to invoke the linker, ld, such as -L. Libraries (-lfoo) should be added to the LDLIBS variable instead.

So in this case -lSDL2 should be set or added to LDLIBS, not LDFLAGS.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.