Problem Compiling c++ Code With SLD2 From VS Code - c++

I'm just getting started with c++ and I can't seem to get c++ to compile with SDL2. I am using VS code and MinGW. I have copied the include files from the SDL2 download and the lib files into their respective folders in the mingw64 folder (as according to step 1-5 of this - https://www.caveofprogramming.com/c-for-complete-beginners/setting-up-sdl-windows.html). The code the vs code runs when I "run build task" is below.
C:/msys64/mingw64/bin/g++.exe -fdiagnostics-color=always -g C:\Users\lucya\Downloads\c++\programmingcave\cave.cpp -o C:\Users\lucya\Downloads\c++\programmingcave\cave.exe
I am trying to build some basic code I copy and pasted which is below.
#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
int main(int argc, char* argv[]) {
// Start SDL2
SDL_Init(SDL_INIT_EVERYTHING);
// Create a Window in the middle of the screen
SDL_Window *window = 0;
window = SDL_CreateWindow("Hello World!",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
640, 480,
SDL_WINDOW_SHOWN);
// Delay so that we can see the window appear
SDL_Delay(2000);
// Cleanup and Quit
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
However, This is what comes up when I "run build task":
Starting build...
C:/msys64/mingw64/bin/g++.exe -fdiagnostics-color=always -g C:\Users\lucya\Downloads\c++\programmingcave\cave.cpp -o C:\Users\lucya\Downloads\c++\programmingcave\cave.exe
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\lucya\AppData\Local\Temp\ccOYoA98.o:C:/Users/lucya/Downloads/c++/programmingcave/cave.cpp:6: undefined reference to `SDL_Init'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\lucya\AppData\Local\Temp\ccOYoA98.o: in function `main':
C:/Users/lucya/Downloads/c++/programmingcave/cave.cpp:11: undefined reference to `SDL_CreateWindow'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Users/lucya/Downloads/c++/programmingcave/cave.cpp:18: undefined reference to `SDL_Delay'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Users/lucya/Downloads/c++/programmingcave/cave.cpp:21: undefined reference to `SDL_DestroyWindow'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Users/lucya/Downloads/c++/programmingcave/cave.cpp:22: undefined reference to `SDL_Quit'
collect2.exe: error: ld returned 1 exit status
Build finished with error(s).
Does anyone know what my error is or how to fix it? If you need any other information please just ask! I have spent 2 days trying to get this to work so any help is useful.
Thanks!

Related

Linking glfw g++ [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 1 year ago.
I have been trying to code with OpenGL without using a IDE, but the manual linking is really confusing me. I have a folder with the libglfw3.a, glfw3.h and a .cpp file with this example code.
#include "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 */
glClear(GL_COLOR_BUFFER_BIT);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
I compile it like this.
g++ source.cpp -lglfw3 -o program
Yet I get these errors.
C:\Users\murra\Coding\Manual>g++ source.cpp -lglfw3 -o proc
C:\Users\murra\AppData\Local\Temp\ccO7xs1Q.o:source.cpp:(.text+0x17): undefined reference to `glfwInit'
C:\Users\murra\AppData\Local\Temp\ccO7xs1Q.o:source.cpp:(.text+0x56): undefined reference to `glfwCreateWindow'
C:\Users\murra\AppData\Local\Temp\ccO7xs1Q.o:source.cpp:(.text+0x64): undefined reference to `glfwTerminate'
C:\Users\murra\AppData\Local\Temp\ccO7xs1Q.o:source.cpp:(.text+0x76): undefined reference to `glfwMakeContextCurrent'
C:\Users\murra\AppData\Local\Temp\ccO7xs1Q.o:source.cpp:(.text+0x81): undefined reference to `glfwWindowShouldClose'
C:\Users\murra\AppData\Local\Temp\ccO7xs1Q.o:source.cpp:(.text+0x96): undefined reference to `_imp__glClear#4'
C:\Users\murra\AppData\Local\Temp\ccO7xs1Q.o:source.cpp:(.text+0xa6): undefined reference to `glfwSwapBuffers'
C:\Users\murra\AppData\Local\Temp\ccO7xs1Q.o:source.cpp:(.text+0xab): undefined reference to `glfwPollEvents'
C:\Users\murra\AppData\Local\Temp\ccO7xs1Q.o:source.cpp:(.text+0xb2): undefined reference to `glfwTerminate'
collect2.exe: error: ld returned 1 exit status
I'm quite new to this stuff so help would be appreciated.
When you link a third party lib, you need to "tell" the compiler the location of the headers as well as the location of the libraries.
Typically, one would use -I<header_dir> and -L<lib_dir> in addition to -l<lib_name>
You may also reduce this to 2 steps by using -I<header_dir> and -L<full_lib_path>
If linking causes errors, IMO there are 3 major reasons.
Incorrect path
Mixing shared lib and static lib flags (example - -MT and -MD on VS)
Additional library dependencies that you have not included.
In your case, the missing symbols seem to be from additional libs. Try -lglfw3 -lglew32 -lopengl32 -lgdi32 as additional options. Obviously these need to be on your computer.

Use a library and header files in Gnome Builder

UPDATE I switched to the meson build system. Everything is working fine now!
I am very new to using C++, OpenGl, and Gnome Builder. I have a very very basic foundation with C++ and I know how to link header files and libraries in CodeLite, however after messing around Gnome Builder I want to make the switch. I haven't found any beginner friendly tutorials on using Builder. I am just lost as to how I should link external libraries in Builder. Do I just manually edit the Makefile or is there a setting somewhere that will automate the makefile process with automake? Am I wrong in assuming that this is a makefile problem? Apologies if this is a very novice question.
I am using Ubuntu. I am getting the error "undefined reference to ..." for all the glfw and glew variables and headers. After installing libraries with apt, I have my libraries installed in usr/lib/x86-64-linux-gnu, headers in usr/include.
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
int main ()
{
glewExperimental = true;
if (!glfwInit() )
{
fprintf(stderr, "Failed to initialize GLFW \n");
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window;
window = glfwCreateWindow(1024, 768, "Tutorial 01", NULL, NULL);
if ( window == NULL )
{
fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. \n");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = true;
if (glewInit() != GLEW_OK)
{
fprintf(stderr, "Failed to Initialize GLEW. \n");
return -1;
}
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
do {
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
while ( glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0);
return 0;
}
When trying to build I get this error output~
g++ -o practice -Wall -ggdb -fno-omit-frame-pointer -O2 practice.cpp
/usr/bin/ld: /tmp/ccLx11Ky.o: in function main':
/home/joe/Projects/practice/practice.cpp:30: undefined reference toglewExperimental'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:31: undefined reference to glfwInit'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:36: undefined reference toglfwWindowHint'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:37: undefined reference to glfwWindowHint'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:38: undefined reference toglfwWindowHint'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:39: undefined reference to glfwWindowHint'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:40: undefined reference toglfwWindowHint'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:43: undefined reference to glfwCreateWindow'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:50: undefined reference toglfwMakeContextCurrent'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:51: undefined reference to glewExperimental'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:52: undefined reference toglewInit'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:58: undefined reference to glfwSetInputMode'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:65: undefined reference toglfwWindowShouldClose'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:61: undefined reference to glClear'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:62: undefined reference toglfwSwapBuffers'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:63: undefined reference to glfwPollEvents'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:65: undefined reference toglfwGetKey'
/usr/bin/ld: /home/joe/Projects/practice/practice.cpp:47: undefined reference to `glfwTerminate'
collect2: error: ld returned 1 exit status
make: *** [Makefile:8: practice] Error 1
My default Makefile looks as follows~
all: practice
WARNINGS = -Wall
DEBUG = -ggdb -fno-omit-frame-pointer
OPTIMIZE = -O2
practice: Makefile practice.cpp
$(CXX) -o $# $(WARNINGS) $(DEBUG) $(OPTIMIZE) practice.cpp
clean:
rm -f practice
# Builder will call this to install the application before running.
install:
echo "Installing is not supported"
# Builder uses this target to run your application.
run:
./practice
You need to customize the build command (practice) to include the required libraries. Conside using pkg-config --libs glew (or pkg-config --libs -static glew) to find which libraries are needed, and pkg-config --cflags for command line flags, if any.
Most likely:
Add '-lglfw3' to the 'practice' build command,
If you use static libs, add '-DGLEW_STATIC'
See glfw Errors with glfwWindowHint, and GLEW Linker Errors (undefined reference to `__glewBindVertexArray')

Eclipse CDT undefined reference (package that was downloaded via MYSYS2)

So I basically only coded in Java at College, this time
I want to start my new Project in C++ and want to keep the Eclipse IDE that I have always used. I need the openCV and Tesseract packages (import). I have googled and researched for quite a time and I seem to be doing it right? but maybe some of you can tell me otherwise.
What I did:
Downloaded Eclipse CDT
Downloaded MYSYS2
Followed this instructions (MinGW Compiler)
Open MSYS2 shell from start menu
Run pacman -Sy pacman to update the package database
Re-open the shell, run pacman -Syu to update the package database and core system packages
Re-open the shell, run pacman -Su to update the rest
(Reference)
For 64 bits, run pacman -S mingw-w64-x86_64-toolchain
Select which package to install, default is all
You may also need make, run pacman -S make
Installed the libraries/tools that i need
OpenCV
pacman -S mingw64/mingw-w64-x86_64-opencv
Tesseract
pacman -S mingw64/mingw-w64-x86_64-tesseract-ocr
Included the MinGW to PATH (system environment variables)->restart computer
Started a new Eclipse Project-> C++ -> choose MinGW GCC as Toolchain
Basic Hello World -> Works fine
Basic OpenCV example -> doesnt work
It seems to Resolve the Inclusions correctly.
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
No Errors there.
FullCode:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
if( argc != 2)
{
cout <<" Usage: display_image ImageToLoadAndDisplay" << endl;
return -1;
}
Mat image;
image = imread(argv[1], CV_LOAD_IMAGE_COLOR); // Read the file
if(! image.data ) // Check for invalid input
{
cout << "Could not open or find the image" << std::endl ;
return -1;
}
namedWindow( "Display window", WINDOW_AUTOSIZE );// Create a window for display.
imshow( "Display window", image ); // Show our image inside it.
waitKey(0); // Wait for a keystroke in the window
return 0;
}
What Eclipse says:
16:54:43 **** Incremental Build of configuration Debug for project hello ****
Info: Internal Builder is used for build
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\hello.o" "..\\src\\hello.cpp"
g++ -o hello.exe "src\\hello.o"
src\hello.o: In function `main':
C:\Users\Vaio\Desktop\EclipseProjekte\hello\Debug/../src/hello.cpp:17: undefined reference to `cv::imread(cv::String const&, int)'
C:\Users\Vaio\Desktop\EclipseProjekte\hello\Debug/../src/hello.cpp:25: undefined reference to `cv::namedWindow(cv::String const&, int)'
C:\Users\Vaio\Desktop\EclipseProjekte\hello\Debug/../src/hello.cpp:26: undefined reference to `cv::imshow(cv::String const&, cv::_InputArray const&)'
C:\Users\Vaio\Desktop\EclipseProjekte\hello\Debug/../src/hello.cpp:28: undefined reference to `cv::waitKey(int)'
src\hello.o: In function `cv::String::String(char const*)':
C:/msys64/mingw64/include/opencv2/core/cvstd.hpp:602: undefined reference to `cv::String::allocate(unsigned long long)'
src\hello.o: In function `cv::String::~String()':
C:/msys64/mingw64/include/opencv2/core/cvstd.hpp:648: undefined reference to `cv::String::deallocate()'
src\hello.o: In function `cv::Mat::~Mat()':
C:/msys64/mingw64/include/opencv2/core/mat.inl.hpp:692: undefined reference to `cv::fastFree(void*)'
src\hello.o: In function `cv::Mat::release()':
C:/msys64/mingw64/include/opencv2/core/mat.inl.hpp:804: undefined reference to `cv::Mat::deallocate()'
src\hello.o: In function `cv::Mat::operator=(cv::Mat&&)':
C:/msys64/mingw64/include/opencv2/core/mat.inl.hpp:1371: undefined reference to `cv::fastFree(void*)'
collect2.exe: error: ld returned 1 exit status
16:54:46 Build Finished (took 2s.908ms)
It can't find the librarys????
Whats the point of downloading it through MSYS2 if it doesnt connect the library like it does with iostream
Do I need to add all the library objects to the linker settings C/C++ Build -> Settings -> Tool Settings -> GCC C++ Linker -> Libraries
Okay so I guess that its obv but for those who have the same mistake, MSYS2 just added all opencv and tesseract files.
If you want to use them you need to specify it to the Linker.
filename: libopencv_core.dll.a
you need to exclude the lib at the beginning and the .dll and .a
linker: opencv_core
all libs can be found on the mingw path: (C:\msys64\mingw64\lib)
in the end you link it with -lopencv_core
or through the Eclipse GUI C/C++ Build -> Settings -> Tool Settings -> GCC C++ Linker -> Libraries -> add library -> opencv_core

Linking GLFW in CodeBlocks

CodeBlocks' GLFW Project is outdated and works only with GLFW 2.7. I am using the latest version, which is 3.0.4, and trying to link it in CodeBlocks statically (I hope that I am using the correct terminology). I would be really happy if someone told me how to do it step by step. I would also like to create an empty project if possible and do everything manually.
This is the code that I am trying to run:
#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 */
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
This is what I have in my "Other linker options":
-lmingw32 -lopengl32 -lgdi32
and I also copied GLFW folder that is containing the header files in CodeBlocks/MinGW/include.
This is pretty much all I did and I get the following build log:
-------------- Build: Debug in Initializing OpenGL (compiler: GNU GCC Compiler)---------------
mingw32-g++.exe -o "bin\Debug\Initializing OpenGL.exe" obj\Debug\main.o -lmingw32 -lopengl32 -lgdi32
obj\Debug\main.o: In function `main':
D:/Development/OpenGL/Initializing OpenGL/main.cpp:8: undefined reference to `glfwInit'
D:/Development/OpenGL/Initializing OpenGL/main.cpp:12: undefined reference to `glfwCreateWindow'
D:/Development/OpenGL/Initializing OpenGL/main.cpp:15: undefined reference to `glfwTerminate'
D:/Development/OpenGL/Initializing OpenGL/main.cpp:20: undefined reference to `glfwMakeContextCurrent'
D:/Development/OpenGL/Initializing OpenGL/main.cpp:28: undefined reference to `glfwSwapBuffers'
D:/Development/OpenGL/Initializing OpenGL/main.cpp:31: undefined reference to `glfwPollEvents'
D:/Development/OpenGL/Initializing OpenGL/main.cpp:23: undefined reference to `glfwWindowShouldClose'
D:/Development/OpenGL/Initializing OpenGL/main.cpp:34: undefined reference to `glfwTerminate'
collect2.exe: error: ld returned 1 exit status
Jigger your project config so that the mingw invocation looks something like this:
x86_64-w64-mingw32-g++.exe -Llib -o bin\Debug\glfw-proj.exe obj\Debug\main.o -lglfw3 -lopengl32 -lgdi32
Note the -lglfw3.
Procedure:
Project -> Build options...
Select the top-level configuration (i.e., not Debug or Release)
In the Search directories -> Compiler tab add the path to your GLFW headers (GLFW/glfw3.h and friend)
In the Search directories -> Linker tab add the path to your GLFW library files (libglfw3.a and friends)
In the Linker settings tab add 3 Link libraries: glfw3, opengl32, and gdi32.

Unable to link to SDL2 functions using MinGW

I'm relatively new to programming and I've decided to give SDL a try, but I'm a bit stuck. I haven't been able to build the project in codeblocks and I get 'undefined reference' to all SDL functions. I've seen a lot of similar questions here, but none of the solutions seems to help. I've already added the \include\SDL2 and the \lib folders to search directories, I've added SDL2Main and SDL2 to link libraries in linker options, I've even added -mwindows to other linker options. Also, I tried linking against the 64-bit version as well, but things got even worse.
Here's my source code, pretty much copied straight out of the tutorial I started:
#include <SDL.h>
SDL_Window* g_pWindow = 0;
SDL_Renderer* g_pRenderer = 0;
int main(int argc, char* args[])
{
// initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) >= 0)
{
// if succeeded create our window
g_pWindow = SDL_CreateWindow("Chapter 1: Setting up SDL",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
640, 480,
SDL_WINDOW_SHOWN);
// if the window creation succeeded create our renderer
if(g_pWindow != 0)
{
g_pRenderer = SDL_CreateRenderer(g_pWindow, -1, 0);
}
}
else
{
return 1; // sdl could not initialize
}
// everything succeeded lets draw the window
// set to black // This function expects Red, Green, Blue and
// Alpha as color values
SDL_SetRenderDrawColor(g_pRenderer, 0, 0, 0, 255);
// clear the window to black
SDL_RenderClear(g_pRenderer);
// show the window
SDL_RenderPresent(g_pRenderer);
// set a delay before quitting
SDL_Delay(5000);
// clean up SDL
SDL_Quit();
return 0;
}
And here's the build log:
mingw32-g++.exe -LC:\dev\sdl\SDL2-2.0.1\x86_64-w64-mingw32\lib -o bin\Debug\GeometryProject.exe obj\Debug\main.o -mwindows C:\MinGW\lib\libmingw32.a C:\dev\sdl\SDL2-2.0.1\x86_64-w64-mingw32\lib\libSDL2main.a C:\dev\sdl\SDL2-2.0.1\x86_64-w64-mingw32\lib\libSDL2.a
obj\Debug\main.o: In function `SDL_main':
C:/Users/Kris948/Desktop/ProjectsUni/GeometryProject/main.cpp:7: undefined reference to `SDL_Init'
C:/Users/Kris948/Desktop/ProjectsUni/GeometryProject/main.cpp:13: undefined reference to `SDL_CreateWindow'
C:/Users/Kris948/Desktop/ProjectsUni/GeometryProject/main.cpp:17: undefined reference to `SDL_CreateRenderer'
C:/Users/Kris948/Desktop/ProjectsUni/GeometryProject/main.cpp:27: undefined reference to `SDL_SetRenderDrawColor'
C:/Users/Kris948/Desktop/ProjectsUni/GeometryProject/main.cpp:29: undefined reference to `SDL_RenderClear'
C:/Users/Kris948/Desktop/ProjectsUni/GeometryProject/main.cpp:31: undefined reference to `SDL_RenderPresent'
C:/Users/Kris948/Desktop/ProjectsUni/GeometryProject/main.cpp:33: undefined reference to `SDL_Delay'
C:/Users/Kris948/Desktop/ProjectsUni/GeometryProject/main.cpp:35: undefined reference to `SDL_Quit'
C:\MinGW\lib\libmingw32.a(main.o):main.c:(.text.startup+0xa7): undefined reference to `WinMain#16'
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 0 seconds)
9 errors, 0 warnings (0 minutes, 0 seconds)
Is there anything else I could try? I really would like to get this running and would appreciate any help.
A possible problem is that your linking to a SDL2 library for a different architecture.
You should be using
SDL2-2.0.1\i686-w64-mingw32
instead of
SDL2-2.0.1\x86_64-w64-mingw32
Also after setting the library search path use this notation to link to libraries
-lmingw32 -lSDL2main -lSDL2
It's much easier to read.
Instead of adding full path, try -LC:/PATH_TO_SDL -lSDL2main -lSDL2 (or only one SDL option) instead; the lib and .a is already known by the linker.
(not sure if you have to use either / or \)
Since you are using C++, replace your include with this:
extern "C"
{
#include "SDL.h"
}
This tells the compiler to treat SDL as C - and not C++ - code.
See also: SDL2 won't link properly