c++windowsmingw

Properly Link Libraries in the Command Line


Preface: I'm fairly new to C++ and am just beginning to seriously program.

Post-Preface: I tried to post a link for the functions/pages I mention in this post, but Stack Overflow yelled at me because I don't have enough reputation to post more than two links.

I'm attempting to make a few simple GUIs in C++ with the Windows API using MinGW and the command line. I'm trying to change the window background, and one function which helps do this is the CreateSolidBrush function. This function requires the gdi32 library, but each time I try to compile/link to this library, I receive an error along the lines of "can't find that library, sucka".

Page1 and page2 provide useful information about MinGW's library functionality. Stack Overflow post # 5683058 and # 17031290 describe what I think are similar questions/problems to mine. I've searched far and wide for a simple and direct answer about how to link files/libraries from other directories (especially Windows libraries), but no luck in implementing the knowledge from these pages. Perhaps the answer is staring me right in the face, but my valiant efforts to "see the cat, draw the tiger" are in vain. It's possible that I'm entering the incorrect path/name (lib vs dll?), or maybe I'm completely overlooking something more fundamental (missing a header?). One command I've tried to use is

g++ -LC:\WINDOWS\System32 -lgdi32 gui.cpp

but this doesn't seem to work (note: source file named "gui.cpp").

Question 1: To start simple, what is the proper notation/command to link to individual header/source files which are not in the current directory?

Question 2: What is the proper notation/command to link to a library which is in the current directory?

Question 3: What is the proper notation/command to link to a library which is not in the current directory?

I realize these questions are sorta-kinda answered in a variety of ways on other pages, but they're often mingled with directions regarding Visual Studio, Eclipse, Code::Blocks, etc. and therefore unclear for the novices who forgo the luxuries of an IDE. I would appreciate a straightforward answer for your typical, run-of-the-mill noob. Many thanks in advance for any help or guidance.

I'll post my code, but I'm thinking only a couple of the first five lines are relevant:

#include <windows.h>
#include <string>

COLORREF desired_color = RGB(200,200,200);
HBRUSH hBrush = CreateSolidBrush(desired_color);

static char str_class_name[]  = "MyClass";
static char str_titlebar[] = "My Window Title";
static int window_width = 300;
static int window_height = 300;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

static HINSTANCE program_global_instance = NULL;

int WINAPI WinMain(HINSTANCE program_current_instance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    program_global_instance = program_current_instance;
    WNDCLASSEX window_class;
    HWND window_handle;
    MSG window_message;

    window_class.cbSize        = sizeof(WNDCLASSEX); // size of struct; always set to size of WndClassEx
    window_class.style         = 0; // window style
    window_class.lpfnWndProc   = WndProc; // window callback procedure
    window_class.cbClsExtra    = 0; // extra memory to reserve for this class
    window_class.cbWndExtra    = 0; // extra memory to reserve per window
    window_class.hInstance     = program_global_instance; // handle for window instance
    window_class.hIcon         = LoadIcon(NULL, IDI_APPLICATION); // icon displayed when user presses ALT+TAB
    window_class.hCursor       = LoadCursor(NULL, IDC_ARROW); // cursor used in the program
    window_class.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // brush used to set background color
    window_class.lpszMenuName  = NULL; // menu resource name
    window_class.lpszClassName = str_class_name; // name with which to identify class
    window_class.hIconSm       = LoadIcon(NULL, IDI_APPLICATION); // program icon shown in taskbar and top-left corner

    if(!RegisterClassEx(&window_class)) {
        MessageBox(0, "Error Registering Class!", "Error!", MB_ICONSTOP | MB_OK);
        return 0;
    }

    window_handle = CreateWindowEx(
        WS_EX_STATICEDGE, // dwExStyle: window style
        str_class_name, // lpClassName: pointer to class name
        str_titlebar, // lpWindowName: window titlebar
        WS_OVERLAPPEDWINDOW, // dwStyle: window style
        CW_USEDEFAULT, // x: horizontal starting position
        CW_USEDEFAULT, // y: vertical starting position
        window_width, // nWidth: window width
        window_height, // nHeight: window height
        NULL, // hWndParent: parent window handle (NULL for no parent)
        NULL, // hMenu: menu handle (Null if not a child)
        program_global_instance, // hInstance : current window instance
        NULL // lpParam -Points to a value passed to the window through the CREATESTRUCT structure.
        );

    if (window_handle == NULL) {
        MessageBox(0, "Error Creating Window!", "Error!", MB_ICONSTOP | MB_OK);
        return 0;
    }

    ShowWindow(window_handle, nCmdShow);
    UpdateWindow(window_handle);

    while(GetMessage(&window_message, NULL, 0, 0)) {
        TranslateMessage(&window_message);
        DispatchMessage(&window_message);
    }

    return window_message.wParam;
}

// window_handle: window ID
// uMsg: window message
// wParam: additional message info; depends on uMsg value
// lParam: additional message info; depends on uMsg value
LRESULT CALLBACK WndProc(
    HWND window_handle, 
    UINT Message, 
    WPARAM wParam, 
    LPARAM lParam
    ) {
    switch(Message) {
        case WM_CLOSE:
            DestroyWindow(window_handle);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(window_handle, Message, wParam, lParam);
    }
    return 0;
}

Solution

  • Question 1: To start simple, what is the proper notation/command to link to individual header/source files which are not in the current directory?

    That's not linking, that's compiling/including (unless you compile those source files to object files, first).

    So:

    gcc {other options} -o gui.exe gui.cpp /path/to/source_file_one.cpp /path/to/source_file_n.cpp
    

    or, compile the others first:

    gcc {other options} -c -o source_file_one.o /path/to/source_file_one.cpp
    gcc {other options} -c -o source_file_n.o /path/to/source_file_n.cpp
    gcc {other options} -o gui.exe source_file_n.o source_file_one.o gui.cpp
    

    -c tells gcc not to try and link things together, as this is done in the last step.

    {other options} can contain -I{include dirs} to inform gcc where to look when you #include something.

    Question 2: What is the proper notation/command to link to a library which is in the current directory?

    See 3; -L. should work.

    Question 3: What is the proper notation/command to link to a library which is not in the current directory?

    You're doing it right, so far: -L tells gcc about paths to look into for libraries, and -l{libname} links against a library.