linking SDL2 libraries with pkg-config - linux

I am using Ubuntu 14.04LTS. I have installed the SDL2 libraries both by compiling from source (method1 https://askubuntu.com/questions/344512/what-is-the-general-procedure-to-install-development-libraries-in-ubuntu) and using sudo apt-get install libsdl2-dev.
As I understand, the former installed the libraries and headers in /usr/local/(lib and include), while the latter installs them system wide in /usr/(lib and include).
When I tried to compile a simple code to test the functionality:
#include <SDL.h>
#include <stdio.h>
int main(int argc, char* argv[]) {SDL_Window *window;
// Declare a pointer
SDL_Init(SDL_INIT_VIDEO); // Initialize SDL2
// Create an application window with the following settings:
window = SDL_CreateWindow(
"An SDL2 window", // window title
SDL_WINDOWPOS_UNDEFINED, // initial x position
SDL_WINDOWPOS_UNDEFINED, // initial y position
640, // width, in pixels
480, // height, in pixels
SDL_WINDOW_OPENGL // flags - see below
);
// Check that the window was successfully created
if (window == NULL) {
// In the case that the window could not be made...
printf("Could not create window: %s\n", SDL_GetError());
return 1;
}
// The window is open: could enter program loop here (see SDL_PollEvent())
SDL_Delay(3000); // Pause execution for 3000 milliseconds, for example
// Close and destroy the window
SDL_DestroyWindow(window);
// Clean up
SDL_Quit();
return 0;
using: g++ sdl_test.cpp -o sdlout
the compiler outputs:
sdltest.cpp:2:17: fatal error: SDL.h: No such file or directory
#include <SDL.h>
^
compilation terminated.
if I change to #include <SDL2/SDL.h> I get the following error:
/tmp/cc05JSKn.o: In function `main':
sdltest.cpp:(.text+0x15): undefined reference to `SDL_Init'
sdltest.cpp:(.text+0x3a): undefined reference to `SDL_CreateWindow'
sdltest.cpp:(.text+0x4a): undefined reference to `SDL_GetError'
sdltest.cpp:(.text+0x6d): undefined reference to `SDL_Delay'
sdltest.cpp:(.text+0x79): undefined reference to `SDL_DestroyWindow'
sdltest.cpp:(.text+0x7e): undefined reference to `SDL_Quit'
collect2: error: ld returned 1 exit status
Which are the basic functions, so I assume that the shared object libraries are not linked correctly.
I also tried: g++ -Wall sdltest.cpp -o outsdl -I /usr/local/include -L /usr/local/lib
to specify the paths, but again I get:
sdltest.cpp:2:17: fatal error: SDL.h: No such file or directory
#include <SDL.h>
^
compilation terminated.
The only command that worked and successfully compiled, is when using pkg-config g++ sdltest.cpp -o outsdl $(pkg-config --cflags --libs sdl2)
Therefore, I have the following questions:
1) Why is pkg-config necessary and how do compilation and linking flags work?
2) Is it possible to do something else in order to make the compilation command simpler?
3) (if not explained previously) What is the difference between pkg-config and using -I and -L which do not work?
4) what does $(...) actually do in the command line and is it completely the same as `...` ?
Thank you.

The pkg-config command is a more-or-less cross-platform or cross-distro way to provide the correct flags to your compiler to allow it to find header and library files. That way, your system can store files in different locations and everyone can use the same commands to compile your code. It also helps resolve any special requirements of the library you're trying to use.
Using $() is the same as using backticks, so you can execute what is inside the parentheses in order to see what extra arguments are being passed to your compiler to make it work. Here is what I get on my machine when I run pkg-config --cflags --libs sdl2:
-D_REENTRANT -I/usr/include/SDL2 -lSDL2
The reason you're getting SDL.h: No such file or directory is because pkg-config adds -I/usr/include/SDL2 to the include search paths so you can include SDL.h in your code (without the SDL2 subdirectory).
The reason you get undefined reference errors is because you don't have -lSDL2 (which tells the compiler to link libSDL2).

Related

Pytorch Tensor::data_ptr<long long>() not working on Linux

I cannot link my program to pytorch under Linux, get the following error:
/tmp/ccbgkLx2.o: In function `long long* at::Tensor::data<long long>() const':
test.cpp:(.text._ZNK2at6Tensor4dataIxEEPT_v[_ZNK2at6Tensor4dataIxEEPT_v]+0x14): undefined reference to `long long* at::Tensor::data_ptr<long long>() const'
I am building a very simple minimal example:
#include "torch/script.h"
#include <iostream>
int main() {
auto options = torch::TensorOptions().dtype(torch::kInt64);
torch::NoGradGuard no_grad;
auto T = torch::zeros(20, options).view({ 10, 2 });
long long *data = (long long *)T.data<long long>();
data[0] = 1;
return 0;
}
The command used to build it:
g++ -w -std=c++17 -o test-torch test.cpp -D_GLIBCXX_USE_CXX11_ABI=1 -Wl,--whole-archive -ldl -lpthread -Wl,--no-whole-archive -I../libtorch/include -L../libtorch/lib -ltorch -ltorch_cpu -lc10 -Wl,-rpath,../libtorch/lib
Pytorch has been downloaded from the link https://download.pytorch.org/libtorch/cpu/libtorch-cxx11-abi-shared-with-deps-1.7.0%2Bcpu.zip and unzipped (so I have the libtorch folder next to the folder with test.cpp).
Any ideas how to solve this problem? Same program works just fine under Visual C++.
P.S. I know pytorch is kind of designed for cmake, but I have zero experience with cmake and no desire to write a cmake-based build system for my app. Also, the examples they give are seemingly supposed to only work if pytorch is "installed" in the system. So I cannot just download the .zip with libs? And if I "install" it (e.g. from sources or in whatever other way) on an AVX512 system, will the binary I link to it and distribute to end-users work on non-AVX512? The documentation is completely incomprehensible for newbies.
UPDATE: I tried to do this via CMake following the tutorial https://pytorch.org/cppdocs/installing.html and got exactly the same error. Specifically, I renamed my directory to example-app and the source file to example-app.cpp. Then I created CMakeLists.txt in this directory with the following contents:
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(example-app)
find_package(Torch REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
add_executable(example-app example-app.cpp)
target_link_libraries(example-app "${TORCH_LIBRARIES}")
set_property(TARGET example-app PROPERTY CXX_STANDARD 14)
Then
mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH=../../libtorch ..
cmake --build . --config Release
And here's the output:
CMakeFiles/example-app.dir/example-app.cpp.o: In function `long long* at::Tensor::data<long long>() const':
example-app.cpp:(.text._ZNK2at6Tensor4dataIxEEPT_v[_ZNK2at6Tensor4dataIxEEPT_v]+0x14): undefined reference to `long long* at::Tensor::data_ptr<long long>() const'
Makes me think, maybe I forgot to include some header or define some variable?
Oh, this is all on Mint 19.2 (equivalent to Ubuntu 18.04), g++ version is 7.5.0, glibc is 2.27. Compiling with g++-8 gives the same result.
This is not a cmake-related error, it's just how the library was implemented. I do not know why, but it appears that the specialization of T* at::Tensor::data<T> const with T = long long was forgotten/omitted.
If you want to get your signed 64-bits pointer, you can still get it with int64_t:
auto data = T.data<int64_t>();
It's good practice to use these types for which the size is explicit in general, in order to avoid compatibility issues.

How to compile and run a C program with `gcc`?

A complete newbie here. I am learning to read the codes on suckless.org. They are written in C, and are most quite short, so I think it's a good start.
The problem is I know too little to start with. Wandering around on the site, I found that the suckless community has their own coreutils, which are also very short. echo.c on this page is one of the shortests. I include its header here:
/* See LICENSE file for copyright and license details. */
#include <stdio.h>
#include <string.h>
#include "util.h"
I'd like to compile it and see how this version of echo works, and come back to understand the code. The goal is to repeat this process until I'm comfortable enough to read the source codes of their their larger programs like sent, dmenu, dwm.
In the code, the header #include "util.h" suggests me to put util.h, which is another file in the link above, together with echo.c. I also include arg.h and compat.h because the header of util.h says
#include <sys/types.h>
#include <regex.h>
#include <stddef.h>
#include <stdio.h>
#include "arg.h"
#include "compat.h"
I further checked arg.h and compat.h. Neither of them includes customized header files, so I think I'm good to go. Now the folder tree looks like
$ tree
.
├── arg.h
├── compat.h
├── echo.c
└── util.h
and I run $ gcc echo.c -o echo.o. However, I got an error
/usr/bin/ld: /tmp/cc2VjXNO.o: in function `main':
echo.c:(.text+0x20): undefined reference to `argv0'
/usr/bin/ld: echo.c:(.text+0x27): undefined reference to `argv0'
/usr/bin/ld: echo.c:(.text+0x8d): undefined reference to `putword'
/usr/bin/ld: echo.c:(.text+0xc8): undefined reference to `fshut'
collect2: error: ld returned 1 exit status
Apparently, these undefined arguments are in those header files. Searching around on the net, I further tried
$ gcc -c . echo.c -o echo.o
gcc: warning: .: linker input file unused because linking not done
It spits a warning, but anyway an echo.o is delivered. I chmod it to executable, and run it by $ ./echo.o, but my shell complains
zsh: exec format error: ./echo.o
I spent another hour trying to solve this.. by try and error, but in vain. Would you please point out what's going on? And what should I do?
(Any other suggestions will also be very appreciated.)
You try to compile a program with library that you don't have. The header you're using needs a dynamic or static library (either .a or .o on linux). That's why you get linker input file unused because linking not done.
zsh: exec format error: ./echo.o if you use .o extension with -o argument, you're either making or linking a .o object file (static lib). With gcc -c . echo.c -o echo.o, you're creating a static library (called object) that you won't be able to execute.
By the way, I'd stay away for now from this kind of code, it's very not friendly user for a learner.

Linking GSL library to RcppGSL on Windows machine

I try to link the GSL library to the RcppGSL package. The following is my test function:
# colNorm.cpp
// [[Rcpp::depends(RcppGSL)]]
#include <RcppGSL.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_blas.h>
extern "C" SEXP colNorm(SEXP sM) {
try {
RcppGSL::matrix<double> M = sM; // create gsl data structures from SEXP
int k = M.ncol();
Rcpp::NumericVector n(k); // to store results
for (int j = 0; j < k; j++) {
RcppGSL::vector_view<double> colview = gsl_matrix_column (M, j);
n[j] = gsl_blas_dnrm2(colview);
}
M.free() ;
return n; // return vector
} catch( std::exception &ex ) {
forward_exception_to_r( ex );
} catch(...) {
::Rf_error( "c++ exception (unknown reason)" );
}
return R_NilValue; // -Wall
}
The GSL library is succesfully linked to the RcppGSL if the following command does not throw a compiler error:
sourceCpp("colNorm.cpp")
Since I am using Windows machine, I need to define environment variables such that RcppGSL knows where the GSL library is located.
I tried editing the environment variable, but the following compiler error shows that the package is still unable to find the GSL library:
g++ -m64 -I"C:/PROGRA~1/R/R-31~1.1/include" -DNDEBUG -I"C:/CodeLibrary/lib"/include - I"C:/PROGRA~1/R/R-31~1.1/library/Rcpp/include" -I"C:/PROGRA~1/R/R-31~1.1/library/RcppGSL/include" -I"d:/RCompile/CRANpkg/extralibs64/local/include" -O2 -Wall -mtune=core2 -c colNorm.cpp -o colNorm.o
g++ -m64 -shared -s -static-libgcc -o sourceCpp_38624.dll tmp.def colNorm.o -LC:/CodeLibrary/lib/lib -lgsl -lgslcblas -LC:/PROGRA~1/R/R-31~1.1/bin/x64 -lRlapack -LC:/PROGRA~1/R/R-31~1.1/bin/x64 -lRblas -lgfortran -Ld:/RCompile/CRANpkg/extralibs64/local/lib/x64 -Ld:/RCompile/CRANpkg/extralibs64/local/lib -LC:/PROGRA~1/R/R-31~1.1/bin/x64 -lR
c:/program files/r/r-3.1.1/rtools/gcc-4.6.3/bin/../lib/gcc/i686-w64-mingw32/4.6.3/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lgsl
c:/program files/r/r-3.1.1/rtools/gcc-4.6.3/bin/../lib/gcc/i686-w64-mingw32/4.6.3/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lgslcblas
collect2: ld returned 1 exit status
I set an environment variable LIB_GSL equal to "C:/CodeLibrary/lib". In the first line, the compiler takes my environment variable and adds /include. In the second line, the compiler adds /lib. Those locations do not exist on my C drive, maybe that's the reason why it cannot find the library.
I would be really happy, if someone with a lot of compiler experience could show how to successfully link a 3rd party library to a package on Windows machine.
Maybe more environment variables need to be defined?
Thanks Dirk for your handholding! I got it finally up and running.
Three things have to be done:
1) Download the local300 folder from your link and allocate folder on your drive. The path cannot contain any whitespaces, i.e. C:/Program Files/local300 will not work but
C:/local300 will work
2) Set the environment variable LIB_GSL equal to this path, e.g. LIB_GSL to C:/local300
3) The compiler looks at LIB_GSL/lib for libgsl.a and libgslcblas.a (-lgsl and -lgslcblas). However, in LIB_GSL/lib are subfolders i386 and x64. I didn't know how to change the place the compiler looks for the files, thus I copied everything from inside x64 and put it into LIB_GSL/lib folder (one folder level above).
This allows RcppGSL to compile code without errors.
Look at this page which is (after a link or two) pointed to from the R Installation and Administration manual, appendix D for Windows.
Expand that, see where it puts headers and the library for GSL and adjust LIB_GSL accordingly.
This is what CRAN itself uses, so we know it works.

Install CUDA for Haskell using Autoconf on Win7

I'm attempting to install the following Haskell package on Windows using Cygwin: HaskellCuda
You can install the package using "cabal install cuda".
Here is the output I get (you may have to "cuda install c2hs" first):
$ cabal install
Configuring cuda-0.4.0.2...
checking for gcc... C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe
checking for C compiler default output file name...
configure: error: C compiler cannot create executables
See `config.log' for more details.
Resolving dependencies...
cabal.exe: Error: some packages failed to install:
cuda-0.4.0.2 failed during the configure step. The exception was:
ExitFailure 77
The relevant part from the log file is:
configure:1758: checking for gcc
configure:1785: result: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe
configure:2022: checking for C compiler version
configure:2029: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe --version >&5
configure: line 2030: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe: command not found
configure:2035: $? = 127
configure:2042: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe -v >&5
configure: line 2043: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe: command not found
configure:2045: $? = 127
configure:2052: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe -V >&5
configure: line 2053: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe: command not found
configure:2055: $? = 127
configure:2078: checking for C compiler default output file name
configure:2105: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe -fno-stack-protector conftest.c >&5
configure: line 2106: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe: command not found
configure:2108: $? = 127
configure:2146: result:
configure: failed program was: [source elided]
If I go to Cygwin and type
gcc --version
I get something reasonable. The problem appears to be more with the path I guess, but I'm not sure what/how to fix it. I should also note that using "cabal install cuda-0.2.2", an older version of this package, I get past this step (but get a different error later).
To replicate, make sure you install the Haskell Platform in a path without spaces, otherwise you will probably get a different error. That's the only thing I've figured out so far.
Any help with this would be GREATLY appreciated, I've spent about a week so far and haven't gotten anywhere.
EDIT:
$PATH = C:\Haskell\2011.4.0.0\mingw\bin;
C:\Haskell\2011.4.0.0\lib\extralibs\bin;
C:\Haskell\2011.4.0.0\bin;
C:\CUDA\v4.0\bin\;
C:\cygwin\bin\;
...
I managed to get it to install, but it isn't pretty and I don't really understand why it won't work out of the "autoconf" box.
For starters, rather than installing with "cabal install" (using a local copy), I used the sequence
>runhaskell Setup.hs configure
>runhaskell Setup.hs build
>runhaskell Setup.hs install
The main reason for this is because it is simple to change the $CC variable in the configure script using the argument in Setup.hs. I suspected the $CC was the variable giving me the problem. I changed:
[("CC", ccProg)
to
[("CC", "/cygdrive/c/cygwin/bin/gcc.exe")
in Setup.hs, which is the gcc that comes with Cygwin. My initial suspicion was that autoconf didn't like the Windows-style path to gcc, which it was using based on the log file above. I also discovered though that of the multiple copies of gcc on my computer (one in Haskell/mingw, one in a separate installation of mingw, and whichever version $PATH was pointing to, ONLY the cygwin gcc was able to successfully compile the test file that checked for . Using the cygwin gcc, I could run
gcc hello.c
on any file that included (WITHOUT an external include directive), whereas with any other copy of gcc, even something like
gcc -I/cygdrive/c/..../include hello.c
was not able to find . No idea why.
Just changing the $CC to the Cygwin gcc fixed almost all of the errors. The next errors occurred when "checking for library containing cudaRuntimeGetVersion/cuGetDriverVersion".
The file configure was trying to compile was
#define PACKAGE_NAME "Haskell CUDA bindings"
#define PACKAGE_TARNAME "cuda"
#define PACKAGE_VERSION "0.4.0.0"
#define PACKAGE_STRING "Haskell CUDA bindings 0.4.0.0"
#define PACKAGE_BUGREPORT "tmcdonell#cse.unsw.edu.au"
#define STDC_HEADERS 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRING_H 1
#define HAVE_MEMORY_H 1
#define HAVE_STRINGS_H 1
#define HAVE_INTTYPES_H 1
#define HAVE_STDINT_H 1
#define HAVE_UNISTD_H 1
#define HAVE_CUDA_H 1
#define HAVE_CUDA_RUNTIME_API_H 1
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char cudaRuntimeGetVersion ();
int main ()
{
return cudaRuntimeGetVersion ();
;
return 0;
}
using the command:
/cygdrive/c/cygwin/bin/gcc.exe -o conftest.exe -fno-stack-protector
-I/cygdrive/c/CUDA/v4.0/include -L/cygdrive/c/CUDA/v4.0/lib conftest.c -lcudart
The error (from the log file) is
/cygdrive/c/Users/crockeea/AppData/Local/Temp/ccKMQJiq.o:conftest.c:(.text+0xc):
undefined reference to `_cudaRuntimeGetVersion'
I'm a little rusty on my C, but it seems like they aren't include the appropriate header file here. That probably isn't right because the same file works on Unix based systems when running configure, but it's my best guess. Also, editing configure to make this file include cuda.h just results in a different error about multiple definitions of cudaRuntimeGetVersion. So my hack was to comment out the lines in the configure file with references to cudaRuntimeGetVersion/cuGetDriverVersion. I put C-comments into the C files that the configure file was going to compile (it is easy enough to find the source code for these in the configure file based on line numbers from the log file). I don't know the consequences of modifying the configure file in this way.
This allowed me to get past the 'build' phase. More comments if I run into any other issues.

static compile glfw

I'm trying to compile glfw as static link on Linux Mint (based on Ubuntu 10.04) using GCC 4.4.3.
Inside my project directory i got "external/glfw" which contains glfw 2.7.1 source. I've compiled it by running "make x11-install" which gives:
/usr/local/include/GL/glfw.h
/usr/local/lib/libglfw.a
/usr/local/lib/pkgconfig/libglfw.pc
i also got this simple code in test.c:
#include <stdio.h>
#include <stdlib.h>
#include "external/glfw/include/GL/glfw.h"
int main( int argc, char const* argv[] )
{
if( !glfwInit() ){
fprintf( stderr, "glfwInit Failed\n" );
}
glfwOpenWindowHint( GLFW_FSAA_SAMPLES, 4 );
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MAJOR, 3 );
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MINOR, 1 );
glfwOpenWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
// Open a window and create its OpenGL context
if( !glfwOpenWindow( 1024, 768, 0,0,0,0, 32,0, GLFW_WINDOW )){
fprintf( stderr, "glfwOpenWindow failed\n" );
glfwTerminate();
return -1;
}
return 0;
}
i'm trying to compile glfw as static link and compiled the code using gcc with flags:
/usr/bin/gcc `pkg-config --cflags libglfw` -o test test.c \
`pkg-config --libs libglfw` -lXrandr -lX11 -lGLU -lGL -pthread -lm
and it doesn't give me any error. but when i try to execute the binary it shows that i've failed to call glfwOpenWindow.
could any one help me please? thank you for your time guys!
cheers!
P
EDIT 1: I think the problem lies with the linking process and not the code. Because if i have libglfw2 and libglfw-dev installed (ubuntu packages), then the executable runs just fine. What i want here is to have glfw statically linked and not to rely on distro package share libs for the binary to run.
EDIT 2 as per datenwolf suggestion i tried to debug with gdb. i never use gdb before but i use perl debugger a lot. somehow they share a lot of similarities. i recompile glfw and my test.c with -ggdb.
flowing with gdb it shows that my code goes into glfwOpenWindow() which is in "window.c" in glfw source code. since i'm new to gdb i don't know how to evaluate expression or get the value of variables. based on quick search on google all i know is "whatis" to see the date type. but i think my code stops when it reached line 484 in "window.c"
if( wndconfig.glProfile &&
( wndconfig.glMajor < 3 || ( wndconfig.glMajor == 3 && wndconfig.glMinor < 2 ) ) )
{
// Context profiles are only defined for OpenGL version 3.2 and above
return GL_FALSE;
}
now i'm not sure how come using static link glfw thinks i'm not on OpenGL 3.2 and above, while having libglfw2 installed it works just fine?
thanks for your help guys! especially datenwolf!
EDIT 3 Thanks for the help guys. After some help from people in stackoverflow and old nabble I manage to write it down what needs to be done to statically linked GLFW and GLEW and put it on http://www.phacks.net/static-compile-glfw-and-glew/
So your error is that the call to glfwOpenWindow failed? No unresolved symbol or shared object not found messages before even main() gets called? Then you successfully linked against GLFW statically.
I think your problem lies in the parameters you pass to glfwOpenWindow:
glfwOpenWindow( 1024, 768, 0,0,0,0, 32,0, GLFW_WINDOW )
So you're requesting zero red, green or blue bits per channel, but 32 depth bits. I doubt your system supports that. I'd try
glfwOpenWindow( 1024, 768, 8,8,8,0, 24, 8, GLFW_WINDOW )
that's what most systems support well.
Your example program requests OpenGL 3.1 and a context profile. Profiles are only defined for OpenGL 3.2 and above, which is most likely why glfwOpenWindow fails in this case. To fix this, either request a version above or equal to 3.2, or remove the request for a context profile.
For more information about modern OpenGL context creation with GLX, upon which this part of GLFW is a thin layer, see
http://www.opengl.org/registry/specs/ARB/glx_create_context.txt .

Resources