Overcome DLL Hell with Code::Blocks - c

I'm using Code::Blocks for a project. I have not used an IDE on Linux in years, so I'm a bit out of touch with Linux IDEs.
I'm working with an OpenSSL project that uses FIPS validated library. I duplicated the GCC compiler toolchain and modified it to use OpenSSL's fipsld (and set it as default).
When the project's code executes under Code::Blocks via F8, FIPS_mode_set fails with error 252104805 (0xF06D065). 0xF06D065 is:
$ openssl errstr 0xF06D065
error:0F06D065:common libcrypto routines:FIPS_mode_set:fips mode not supported
which tells me Code::Blocks is not using the OpenSSL I specified in /usr/local/ssl/lib. Rather, the program is using the non-FIPS library provided by Debian in /usr/lib/x86_64-linux-gnu/.
An image of the link library settings is below. Note that the libraries are fully specified, and nothing is left to chance.
CodeBlocks is clearly doing things with LD_LIBRARY_PATH (shown below).
I've also verified the project is using the correct search directories - /usr/local/ssl/include for headers and /usr/local/ssl/lib for the linker.
With compiler logging set to "Full Command Line" set, here's what I get from the build log:
-------------- Build: Debug in ac ---------------
Compiling: main.cpp
/home/jwalton/Desktop/ac/main.cpp:8:5: warning: unused parameter ‘argc’ [-Wunused-parameter]
/home/jwalton/Desktop/ac/main.cpp:8:5: warning: unused parameter ‘argv’ [-Wunused-parameter]
Linking console executable: bin/Debug/ac
Output size is 569.67 KB
Process terminated with status 0 (0 minutes, 0 seconds)
0 errors, 2 warnings
I'm aware of Basile Starynkevitch's suggestions on rpath's and LD_PRELOAD tricks, but this seems like one of those things the IDE should be handling for me (Visual Studio will handle it properly, and even gives us an input box to set Working Directories to find additional libraries).
Any ideas how to make Code::Blocks use the shared objects in /usr/local/ssl/lib when executing the program under the debugger?

Your IDE instructs the compiler to link against the specified libraries, but not to load them at run time. For this latter thing to happen, you need to pass another option to the linker, namely
-rpath=/path/to/directory/with/your/libraries
or, if the linker is invoked by the compiler,
-Wl,-rpath=/same/thing

Code::Blocks don't use shared objects (DLL are a Windows thing). Because Code::Blocks is simply an IDE. IDEs are glorified source code editors with the ability to run external software development tools. You could (and sometimes you should, at least to learn how things happen) edit your code with a plain good editor like emacs, and build it with commands. Your IDE is just running commands, notably a compiler and a linker, probably using gcc
So what is using shared objects in /usr/local/ssl/lib/ is the compiler and linker (and the runtime dynamic linker). BTW, /usr/local/ssl/lib/ is a very strange name for a directory containing shared objects; you should have configured OpenSSL to be installed in /usr/local/lib/ !
First, I really believe you should reconfigure and recompile and rebuild and reinstall your SSL to get it installed under /usr/local/ (or perhaps /opt/) prefix (i.e. shared libraries in /usr/local/lib).
Then you could add appropriate options for the ld linker (from binutils). You probably want -L/usr/local/ssl/lib (to the gcc command which is running ld), and you may want to pass -Wl,-rpath (see this).
I would suggest to reinstall your SSL in /usr/local/, add /usr/local/lib/ into /etc/ld.so.conf (or at least into your LD_LIBRARY_PATH...) and run ldconfig
Otherwise, add at least /usr/local/ssl/lib/ in front of your LD_LIBRARY_PATH (and also -L/usr/local/ssl/lib/ to your linking command).
Read Program Library HowTo, the answers to this, and Drepper's How To Write Shared libraries paper.

Just open the terminal and type
export LD_LIBRARY_PATH=/path/to/your/libraries
sudo ldconfig

Related

SDL2 errors on Visual studio Code while setting it up [duplicate]

I want to make a game using SDL2, but I'm unable to compile and/or run my code, please help!
SDL2 is notoriously hard to set up, and it's often the first library aspiring game developers try to use.
This post is intended as a canonical duplicate for common problems with setting up SDL2.
This answer is about MinGW / GCC, and not Visual Studio.
This answer only applies to Windows.
Common errors
The common errors are:
SDL.h: No such file or directory (when compiling)
Various SDL_main problems: "undefined reference to SDL_main", "conflicting types for SDL_main" or "number of arguments doesn't match prototype", etc. (when compiling or linking)
undefined reference to other functions (when linking)
DLL problems: (when running your program)
'??.dll' was not found
procedure entry point ... could not be located in ..., and other mysterious DLL-related errors
The program seemingly doing nothing when launched
This list is sorted from bad to good. If you change something and get a different error, use this list to tell if you made things better or worse.
The preamble
0. Don't follow bad advice.
Some resources will suggest you to do #define SDL_MAIN_HANDLED or #undef main. Don't blindly follow that advice, it's not how SDL2 is intended to be used.
If you do everything correcty, it will never be necessary. Learn the intended approach first. Then you can research what exactly that does, and make an educated decision.
1. Figure out how to compile directly from the console, you can start using an IDE and/or build system later.
If you're using an IDE, I suggest to first make sure you're able to compile your program directly from the console, to rule out any IDE configuration problems. After you figure that out, you can use the same compiler options in your IDE.
The same applies to build systems, such as CMake.
2. Download the right SDL2 files. Make sure you have the right files. You need the archive called SDL2-devel-2.0.x-mingw.tar.gz from here.
Extract it to any directory, preferably somewhere near your source code. Extracting into the compiler installation directory is often considered a bad practice (and so is copying them to C:\Windows, which is a horrible idea).
3. Know the difference between compiler flags and linker flags. A "flag" is an option you specify in the command line when building your program. When you use a single command, e.g. g++ foo.cpp -o foo.exe, all your flags are added to the same place (to this single command).
But when you build your program in two steps, e.g.:
g++ foo.cpp -c -o foo.o (compiling)
g++ foo.o -o foo.exe (linking)
you have to know which of the two commands to add a flag to. Those are "compiler flags" and "linker flags" respectively.
Most IDEs will require you to specify compiler and linker flags separately, so even if you use a single command now, it's good to know which flag goes where.
Unless specified otherwise, the order of the flags doesn't matter.
SDL.h: No such file or directory
Or any similar error related to including SDL.h or SDL2/SDL.h.
You need to tell your compiler where to look for SDL.h. It's in the SDL files you've downloaded (see preamble).
Add -Ipath to your compiler flags, where path is the directory where SDL.h is located.
Example: -IC:/Users/HolyBlackCat/Downloads/SDL2-2.0.12/x86_64-w64-mingw32/include/SDL2. Relative paths work too, e.g. -ISDL2-2.0.12/x86_64-w64-mingw32/include/SDL2.
Note that the path will be different depending on how you write the #include:
If you do #include <SDL.h>, then the path should end with .../include/SDL2 (like above). This is the recommended way.
If you do #include <SDL2/SDL.h>, then the path should end with .../include.
Various SDL_main problems
You can get several different errors mentioning SDL_main, such as undefined reference to SDL_main, or conflicting types for 'SDL_main', or number of arguments doesn't match prototype, etc.
You need to have a main function. Your main function must look like int main(int, char **). NOT int main() and NOT void main(). This is a quirk of SDL2, related to it doing #define main SDL_main.
Adding parameter names is allowed (and is mandatory in C), e.g. int main(int argc, char **argv). Also the second parameter can be written as char *[] or with a name: char *argv[]. No other changes are allowed.
If your project has multiple source files, make sure to include SDL.h in the file that defines the main function, even if it doesn't otherwise use SDL directly.
Try to avoid #define SDL_MAIN_HANDLED or #undef main when solving this issue, see preamble for explanation.
undefined reference to various functions
• undefined reference to SDL_...
The error message will mention various SDL_... functions, and/or WinMain. If it mentions SDL_main, consult the section "Various SDL_main problems" above. If the function names don't start with SDL_, consult the section "undefined reference to other functions" below.
You need to add following linker flags: -lmingw32 -lSDL2main -lSDL2 -Lpath, where path is the directory where libSDL2.dll.a and libSDL2main.a (which you've downloaded) are located. The order of the -l... flags matters. They must appear AFTER any .c/.cpp/.o files.
Example: -LC:/Users/HolyBlackCat/Desktop/SDL2-2.0.12/x86_64-w64-mingw32/lib. Relative paths work too, e.g. -LSDL2-2.0.12/x86_64-w64-mingw32/lib.
When you use -l???, the linker will look for a file called lib???.dll.a or lib???.a (and some other variants), which is why we need to pass the location of those files. libmingw32.a (corresponding to -lmingw32) is shipped with your compiler, so it already knows where to find it.
I added all those flags and nothing changed, or I'm getting skipping incompatible X when searching for Y:
You probably use the wrong SDL .a files. The archive you downloaded contains two sets of files: i686-w64-mingw32 (32-bit) and x86_64-w64-mingw32 (64-bit). You must use the files matching your compiler, which can also be either 32-bit or 64-bit.
Print (8*sizeof(void*)) to see if your compiler is 32-bit or 64-bit.
Even if you think you use the right files, try the other ones to be sure.
Some MinGW versions can be switched between 32-bit and 64-bit modes using -m32 and -m64 flags (add them to both compiler and linker flags).
I get undefined reference to a specific function:
• undefined reference to WinMain only
There are several possibilities, all of which were covered in the previous section:
You forgot -lmingw32 and/or -lSDL2main linker flags.
You must use following linker flags, in this exact order, after
any .c/.cpp/.o files: -lmingw32 -lSDL2main -lSDL2
The libSDL2main.a file you use doesn't match your compiler (32-bit file with a 64-bit compiler, or vice versa).
Try to avoid #define SDL_MAIN_HANDLED or #undef main when solving this issue, see preamble for explanation.
• undefined reference to SDL_main only
See the section "Various SDL_main problems" above.
• undefined reference to other functions
Your linker found and used libSDL2.a, but it should be finding and using libSDL2.dll.a. When both are available, it prefers the latter by default, meaning you didn't copy the latter to the directory you passed to -L.
If you intended to perform static linking, see the section called "How do I distribute my app to others?" below.
Nothing happens when I try run my app
Let's say you try to run your app, and nothing happens. Even if you try to print something at the beginning of main(), it's not printed.
Windows has a nasty habit of not showing some DLL-related errors when the program is started from the console.
If you were running your app from the console (or from an IDE), instead try double-clicking the EXE in the explorer. Most probably you'll now see some DLL-related error; then consult one of the next sections.
??.dll was not found
Copy the .dll mentioned in the error message, and place it next to your .exe.
If the DLL is called SDL2.dll, then it's in the SDL files you've downloaded (see preamble). Be aware that there are two different SDL2.dlls: a 32-bit one (in the i686-w64-mingw32 directory), and a 64-bit one (in x86_64-w64-mingw32). Get the right one, if necessary try both.
Any other DLLs will be in your compiler's bin directory (the directory where gcc.exe is located).
You might need to repeat this process 3-4 times, this is normal.
For an automatic way of determining the needed DLLs, see the next section.
procedure entry point ... could not be located in ... and other cryptic DLL errors
Your program needs several .dlls to run, and it found a wrong version of one, left over from some other program you have installed.
It looks for DLLs in several different places, but the directory with the .exe has the most priority.
You should copy all DLLs your program uses (except the system ones) into the directory where your .exe is located.
A reliable way to get a list of needed DLLs is to blindly copy a bunch of DLLs, and then remove the ones that turn out to be unnecessary:
Copy SDL2.dll. It's in the SDL files you've downloaded (see preamble). Be aware that there are two different SDL2.dlls: a 32-bit one (in the i686-w64-mingw32 directory), and a 64-bit one (in x86_64-w64-mingw32). Get the right one, if necessary try both.
Copy all DLLs from your compiler's bin directory (the directory where gcc.exe is located).
Now your program should run, but we're not done yet.
Download NTLDD (or some other program that displays a list of used DLLs). Run ntldd -R your_program.exe.
Any DLL not mentioned in its output should be removed from the current directory. Your program uses everything that remains.
I ended up with following DLLs, expect something similar: SDL2.dll, libgcc_s_seh-1.dll, libstdc++-6.dll (C++ only), libwinpthread-1.dll.
Can I determine the needed DLLs without copying excessive ones?
Yes, but it's less reliable.
Your program searches for DLLs in following locations, in this order:
The directory where your .exe is located.
C:\Windows, including some of its subdirectories.
The directories listed in PATH.
Assuming you (or some jank installer) didn't put any custom DLLs into C:\Windows, adding your compiler's bin directory to the PATH (preferably as the first entry) and either putting SDL2.dll in the same directory as the .exe or into some directory in the PATH should be enough for your program to work.
If this works, you can then run ntldd without copying any DLLs beforehand, and copy only the necessary ones. The reason why you'd want to copy them at all at this point (since your app already works) is to be able to distribute it to others, without them having to install the compiler for its DLLs. Skip any DLLs located outside of your compiler's bin directory (except for SDL2.dll).
Note that the possibility of having weird DLLs in C:\Windows is real. E.g. Wine tends to put OpenAL32.dll into C:\Windows, so if you try this process with OpenAL on Wine, it will fail. If you're making a sciprt that runs ntldd automatically, prefer copying the DLLs (or at least symlinking them - I heard MSYS2 can emulate symlinks on Windows?).
Can I make an EXE that doesn't depend on any DLLs?
It's possible to make an .exe that doesn't depend on any (non-system) .dlls by using the -static linker flag, this is called "static linking". This is rarely done, and you shouldn't need to do this if you did the above steps correctly. This requires some additional linker flags; they are listed in file ??-w64-mingw32/lib/pkgconfig/sdl2.pc shipped with SDL, in the Libs.private section. Notice that there are two files, for x32 and x64 respectively.
How do I distribute my app to others?
Follow the steps in the previous section, titled procedure entry point ... could not be located in ....
A saner alternative?
There is MSYS2.
It has a package manager that lets you download prebuilt libraries, and, as a bonus, a fresh version of the compiler.
Install SDL2 from its package manager. Use a tool called pkg-config (also from the package manager) to automatically determine all necessary flags (pkg-config --cflags SDL2 for compiler flags, pkg-config --libs SDL2 for linker flags).
This is the same experience as you would have on Linux (maybe except for some DLL management hassle).
Bonus - Other problems
Q: My program always opens a console window when I run it, how do I hide it?
A: Add -mwindows to the linker flags.
Q: I get error 'SDL_VideoMode' wasn't declared in this scope.
A: SDL_VideoMode is from SDL1.2, it's not a part of the newer SDL2. Your code was written for the outdated version of SDL. Find a better tutorial that deals specifically with SDL2.
Q: My program has the default file icon, but I want a custom one.
A: Your icon must be in the .ico format. If your graphics editor doesn't support it, make a series of .pngs of common sizes (e.g. 16x16, 32x32, 48x48, 64x64), then convert them to a single .ico using ImageMagick: magick *.png result.ico (or with convert instead of magick).
Create a file with the .rc extension (say, icon.rc), with following contents MyIconName ICON "icon.ico" (where MyIconName is an arbitrary name, and "icon.ico" is the path to the icon). Convert the file to an .o using windres -O res -i icon.rc -o icon.o (the windres program is shipped with your compiler). Specify the resulting .o file when linking, e.g. g++ foo.cpp icon.o -o foo.exe.
Recent versions of SDL2 have a nice property of using the same icon as the window icon, so you don't have to use SDL_SetWindowIcon.
A solution for Visual Studio:
Why not use a package manager? I use vcpkg, and it makes super easy to consume 3rd party libraries. Grab the vcpkg source, and extract it to a safe place, like C:/, then run its bootstrap script bootstrap-vcpkg.bat, this will generate vcpkg executable. Then run vcpkg integrate install to make libraries installed with vcpkg available in Visual Studio.
Search for the library you need:
vcpkg search sdl
imgui[sdl2-binding] Make available SDL2 binding
libwebp[vwebp-sdl] Build the vwebp viewer tool.
magnum[sdl2application] Sdl2Application library
sdl1 1.2.15#12 Simple DirectMedia Layer is a cross-platform development library designed to p...
sdl1-net 1.2.8-3 Networking library for SDL
sdl2 2.0.12-1 Simple DirectMedia Layer is a cross-platform
...
Install it with: vcpkg install sdl2.
Now you just need include SDL2 headers, and everything will work out of the box. The library will be linked automatically.
You can learn more about vcpkg here.
On Mac this is what I follow for XCode (must install g++):
sdl linking:
g++ main.cpp -o main $(sdl2-config --cflags --libs)
XCODE project steps:
open terminal app (macOS)
BUILD SETTINGS (select 'all' and 'combined' search bar enter: "search")
click on "header search paths(way right side click)
add: /usr/local/include
BUILD PHASES --> LINK BINARY LIBRARIES (click plus)
type in SDL --> click "add other"
press: command+SHIFT+g (to bring search bar)
type in: usr/local/Cellar
navigate to: SDL2 -->2.0.8 -->lib --> libSDL2-2.2.0.dylib (make sure not shortcut)

How to successfully compile an SDL2 C program with MinGW [duplicate]

I want to make a game using SDL2, but I'm unable to compile and/or run my code, please help!
SDL2 is notoriously hard to set up, and it's often the first library aspiring game developers try to use.
This post is intended as a canonical duplicate for common problems with setting up SDL2.
This answer is about MinGW / GCC, and not Visual Studio.
This answer only applies to Windows.
Common errors
The common errors are:
SDL.h: No such file or directory (when compiling)
Various SDL_main problems: "undefined reference to SDL_main", "conflicting types for SDL_main" or "number of arguments doesn't match prototype", etc. (when compiling or linking)
undefined reference to other functions (when linking)
DLL problems: (when running your program)
'??.dll' was not found
procedure entry point ... could not be located in ..., and other mysterious DLL-related errors
The program seemingly doing nothing when launched
This list is sorted from bad to good. If you change something and get a different error, use this list to tell if you made things better or worse.
The preamble
0. Don't follow bad advice.
Some resources will suggest you to do #define SDL_MAIN_HANDLED or #undef main. Don't blindly follow that advice, it's not how SDL2 is intended to be used.
If you do everything correcty, it will never be necessary. Learn the intended approach first. Then you can research what exactly that does, and make an educated decision.
1. Figure out how to compile directly from the console, you can start using an IDE and/or build system later.
If you're using an IDE, I suggest to first make sure you're able to compile your program directly from the console, to rule out any IDE configuration problems. After you figure that out, you can use the same compiler options in your IDE.
The same applies to build systems, such as CMake.
2. Download the right SDL2 files. Make sure you have the right files. You need the archive called SDL2-devel-2.0.x-mingw.tar.gz from here.
Extract it to any directory, preferably somewhere near your source code. Extracting into the compiler installation directory is often considered a bad practice (and so is copying them to C:\Windows, which is a horrible idea).
3. Know the difference between compiler flags and linker flags. A "flag" is an option you specify in the command line when building your program. When you use a single command, e.g. g++ foo.cpp -o foo.exe, all your flags are added to the same place (to this single command).
But when you build your program in two steps, e.g.:
g++ foo.cpp -c -o foo.o (compiling)
g++ foo.o -o foo.exe (linking)
you have to know which of the two commands to add a flag to. Those are "compiler flags" and "linker flags" respectively.
Most IDEs will require you to specify compiler and linker flags separately, so even if you use a single command now, it's good to know which flag goes where.
Unless specified otherwise, the order of the flags doesn't matter.
SDL.h: No such file or directory
Or any similar error related to including SDL.h or SDL2/SDL.h.
You need to tell your compiler where to look for SDL.h. It's in the SDL files you've downloaded (see preamble).
Add -Ipath to your compiler flags, where path is the directory where SDL.h is located.
Example: -IC:/Users/HolyBlackCat/Downloads/SDL2-2.0.12/x86_64-w64-mingw32/include/SDL2. Relative paths work too, e.g. -ISDL2-2.0.12/x86_64-w64-mingw32/include/SDL2.
Note that the path will be different depending on how you write the #include:
If you do #include <SDL.h>, then the path should end with .../include/SDL2 (like above). This is the recommended way.
If you do #include <SDL2/SDL.h>, then the path should end with .../include.
Various SDL_main problems
You can get several different errors mentioning SDL_main, such as undefined reference to SDL_main, or conflicting types for 'SDL_main', or number of arguments doesn't match prototype, etc.
You need to have a main function. Your main function must look like int main(int, char **). NOT int main() and NOT void main(). This is a quirk of SDL2, related to it doing #define main SDL_main.
Adding parameter names is allowed (and is mandatory in C), e.g. int main(int argc, char **argv). Also the second parameter can be written as char *[] or with a name: char *argv[]. No other changes are allowed.
If your project has multiple source files, make sure to include SDL.h in the file that defines the main function, even if it doesn't otherwise use SDL directly.
Try to avoid #define SDL_MAIN_HANDLED or #undef main when solving this issue, see preamble for explanation.
undefined reference to various functions
• undefined reference to SDL_...
The error message will mention various SDL_... functions, and/or WinMain. If it mentions SDL_main, consult the section "Various SDL_main problems" above. If the function names don't start with SDL_, consult the section "undefined reference to other functions" below.
You need to add following linker flags: -lmingw32 -lSDL2main -lSDL2 -Lpath, where path is the directory where libSDL2.dll.a and libSDL2main.a (which you've downloaded) are located. The order of the -l... flags matters. They must appear AFTER any .c/.cpp/.o files.
Example: -LC:/Users/HolyBlackCat/Desktop/SDL2-2.0.12/x86_64-w64-mingw32/lib. Relative paths work too, e.g. -LSDL2-2.0.12/x86_64-w64-mingw32/lib.
When you use -l???, the linker will look for a file called lib???.dll.a or lib???.a (and some other variants), which is why we need to pass the location of those files. libmingw32.a (corresponding to -lmingw32) is shipped with your compiler, so it already knows where to find it.
I added all those flags and nothing changed, or I'm getting skipping incompatible X when searching for Y:
You probably use the wrong SDL .a files. The archive you downloaded contains two sets of files: i686-w64-mingw32 (32-bit) and x86_64-w64-mingw32 (64-bit). You must use the files matching your compiler, which can also be either 32-bit or 64-bit.
Print (8*sizeof(void*)) to see if your compiler is 32-bit or 64-bit.
Even if you think you use the right files, try the other ones to be sure.
Some MinGW versions can be switched between 32-bit and 64-bit modes using -m32 and -m64 flags (add them to both compiler and linker flags).
I get undefined reference to a specific function:
• undefined reference to WinMain only
There are several possibilities, all of which were covered in the previous section:
You forgot -lmingw32 and/or -lSDL2main linker flags.
You must use following linker flags, in this exact order, after
any .c/.cpp/.o files: -lmingw32 -lSDL2main -lSDL2
The libSDL2main.a file you use doesn't match your compiler (32-bit file with a 64-bit compiler, or vice versa).
Try to avoid #define SDL_MAIN_HANDLED or #undef main when solving this issue, see preamble for explanation.
• undefined reference to SDL_main only
See the section "Various SDL_main problems" above.
• undefined reference to other functions
Your linker found and used libSDL2.a, but it should be finding and using libSDL2.dll.a. When both are available, it prefers the latter by default, meaning you didn't copy the latter to the directory you passed to -L.
If you intended to perform static linking, see the section called "How do I distribute my app to others?" below.
Nothing happens when I try run my app
Let's say you try to run your app, and nothing happens. Even if you try to print something at the beginning of main(), it's not printed.
Windows has a nasty habit of not showing some DLL-related errors when the program is started from the console.
If you were running your app from the console (or from an IDE), instead try double-clicking the EXE in the explorer. Most probably you'll now see some DLL-related error; then consult one of the next sections.
??.dll was not found
Copy the .dll mentioned in the error message, and place it next to your .exe.
If the DLL is called SDL2.dll, then it's in the SDL files you've downloaded (see preamble). Be aware that there are two different SDL2.dlls: a 32-bit one (in the i686-w64-mingw32 directory), and a 64-bit one (in x86_64-w64-mingw32). Get the right one, if necessary try both.
Any other DLLs will be in your compiler's bin directory (the directory where gcc.exe is located).
You might need to repeat this process 3-4 times, this is normal.
For an automatic way of determining the needed DLLs, see the next section.
procedure entry point ... could not be located in ... and other cryptic DLL errors
Your program needs several .dlls to run, and it found a wrong version of one, left over from some other program you have installed.
It looks for DLLs in several different places, but the directory with the .exe has the most priority.
You should copy all DLLs your program uses (except the system ones) into the directory where your .exe is located.
A reliable way to get a list of needed DLLs is to blindly copy a bunch of DLLs, and then remove the ones that turn out to be unnecessary:
Copy SDL2.dll. It's in the SDL files you've downloaded (see preamble). Be aware that there are two different SDL2.dlls: a 32-bit one (in the i686-w64-mingw32 directory), and a 64-bit one (in x86_64-w64-mingw32). Get the right one, if necessary try both.
Copy all DLLs from your compiler's bin directory (the directory where gcc.exe is located).
Now your program should run, but we're not done yet.
Download NTLDD (or some other program that displays a list of used DLLs). Run ntldd -R your_program.exe.
Any DLL not mentioned in its output should be removed from the current directory. Your program uses everything that remains.
I ended up with following DLLs, expect something similar: SDL2.dll, libgcc_s_seh-1.dll, libstdc++-6.dll (C++ only), libwinpthread-1.dll.
Can I determine the needed DLLs without copying excessive ones?
Yes, but it's less reliable.
Your program searches for DLLs in following locations, in this order:
The directory where your .exe is located.
C:\Windows, including some of its subdirectories.
The directories listed in PATH.
Assuming you (or some jank installer) didn't put any custom DLLs into C:\Windows, adding your compiler's bin directory to the PATH (preferably as the first entry) and either putting SDL2.dll in the same directory as the .exe or into some directory in the PATH should be enough for your program to work.
If this works, you can then run ntldd without copying any DLLs beforehand, and copy only the necessary ones. The reason why you'd want to copy them at all at this point (since your app already works) is to be able to distribute it to others, without them having to install the compiler for its DLLs. Skip any DLLs located outside of your compiler's bin directory (except for SDL2.dll).
Note that the possibility of having weird DLLs in C:\Windows is real. E.g. Wine tends to put OpenAL32.dll into C:\Windows, so if you try this process with OpenAL on Wine, it will fail. If you're making a sciprt that runs ntldd automatically, prefer copying the DLLs (or at least symlinking them - I heard MSYS2 can emulate symlinks on Windows?).
Can I make an EXE that doesn't depend on any DLLs?
It's possible to make an .exe that doesn't depend on any (non-system) .dlls by using the -static linker flag, this is called "static linking". This is rarely done, and you shouldn't need to do this if you did the above steps correctly. This requires some additional linker flags; they are listed in file ??-w64-mingw32/lib/pkgconfig/sdl2.pc shipped with SDL, in the Libs.private section. Notice that there are two files, for x32 and x64 respectively.
How do I distribute my app to others?
Follow the steps in the previous section, titled procedure entry point ... could not be located in ....
A saner alternative?
There is MSYS2.
It has a package manager that lets you download prebuilt libraries, and, as a bonus, a fresh version of the compiler.
Install SDL2 from its package manager. Use a tool called pkg-config (also from the package manager) to automatically determine all necessary flags (pkg-config --cflags SDL2 for compiler flags, pkg-config --libs SDL2 for linker flags).
This is the same experience as you would have on Linux (maybe except for some DLL management hassle).
Bonus - Other problems
Q: My program always opens a console window when I run it, how do I hide it?
A: Add -mwindows to the linker flags.
Q: I get error 'SDL_VideoMode' wasn't declared in this scope.
A: SDL_VideoMode is from SDL1.2, it's not a part of the newer SDL2. Your code was written for the outdated version of SDL. Find a better tutorial that deals specifically with SDL2.
Q: My program has the default file icon, but I want a custom one.
A: Your icon must be in the .ico format. If your graphics editor doesn't support it, make a series of .pngs of common sizes (e.g. 16x16, 32x32, 48x48, 64x64), then convert them to a single .ico using ImageMagick: magick *.png result.ico (or with convert instead of magick).
Create a file with the .rc extension (say, icon.rc), with following contents MyIconName ICON "icon.ico" (where MyIconName is an arbitrary name, and "icon.ico" is the path to the icon). Convert the file to an .o using windres -O res -i icon.rc -o icon.o (the windres program is shipped with your compiler). Specify the resulting .o file when linking, e.g. g++ foo.cpp icon.o -o foo.exe.
Recent versions of SDL2 have a nice property of using the same icon as the window icon, so you don't have to use SDL_SetWindowIcon.
A solution for Visual Studio:
Why not use a package manager? I use vcpkg, and it makes super easy to consume 3rd party libraries. Grab the vcpkg source, and extract it to a safe place, like C:/, then run its bootstrap script bootstrap-vcpkg.bat, this will generate vcpkg executable. Then run vcpkg integrate install to make libraries installed with vcpkg available in Visual Studio.
Search for the library you need:
vcpkg search sdl
imgui[sdl2-binding] Make available SDL2 binding
libwebp[vwebp-sdl] Build the vwebp viewer tool.
magnum[sdl2application] Sdl2Application library
sdl1 1.2.15#12 Simple DirectMedia Layer is a cross-platform development library designed to p...
sdl1-net 1.2.8-3 Networking library for SDL
sdl2 2.0.12-1 Simple DirectMedia Layer is a cross-platform
...
Install it with: vcpkg install sdl2.
Now you just need include SDL2 headers, and everything will work out of the box. The library will be linked automatically.
You can learn more about vcpkg here.
On Mac this is what I follow for XCode (must install g++):
sdl linking:
g++ main.cpp -o main $(sdl2-config --cflags --libs)
XCODE project steps:
open terminal app (macOS)
BUILD SETTINGS (select 'all' and 'combined' search bar enter: "search")
click on "header search paths(way right side click)
add: /usr/local/include
BUILD PHASES --> LINK BINARY LIBRARIES (click plus)
type in SDL --> click "add other"
press: command+SHIFT+g (to bring search bar)
type in: usr/local/Cellar
navigate to: SDL2 -->2.0.8 -->lib --> libSDL2-2.2.0.dylib (make sure not shortcut)

Error coming in compilation of C code on Oracle Linux 7.2

I am trying to compile a C code on Oracle Linux 7.2 which is hosted as VM on windows 10.
Name of file run: configure
Name of log file: confg.log
Error where I am stuck
gcc: error: unrecognized command line option '-V'
As per my understanding of the code structure so far, there is a file named configure which is having compilation related commands and this file generates Makefile.am which further generates Makefile.in and at last Makefile.
Please help me in solving the error and also let me know if my understanding about the configure and makefiles is incorrect
configure scripts explore the environment in which a program is to be built. They then accordingly adjust tools called, options used and libraries linked, among other things. Some of the information is obtained by trying to execute programs with certain options; failure of a program to run is the intended way of obtaining the information that the given program is not available or does not take those options. Therefore it is not necessarily an error if one of the things doesn't work and produces an error; it may be one of the legitimate outcomes, and the (error, here) exit code of the compiler will be used to modify the Makefile accordingly — for example by omitting -V ;-).
Does the configure script actually stop there, or are you just observing the error in the log file? If you search for gcc -V on the web you'll find examples of configure scripts failing actually later (for unrelated reasons) which have the same "-V error" line in it. Could that be the case? I would assume that errors which actually cause configure to stop and not produce a Makefile should be visible on the command line, not only in the log file.
As an aside it is worthwhile to run ./configure --help and look through the options. Some may improve the build process or the result; for example you can usually tell configure that you are using gcc, gnu ld and so on, or that you don't need certain features (like X25 ;-) ).
You should look into the makefile of your project, identify where the misspelled -V option is and replace it with -v (lowercase). As pointed out by others in the comments -V is not a compiling flag, but gives back the compiler's version.

Cross-build partprobe for ARM / Linux: configure error concerning libuuid

I want to cross-build partprobe (e.g. parted-3.1 from [here] ) for an ARMv7-controller but keep getting error messages concerning libuuid and uuid_generate.
Actually I only need partprobe which may not even rely on that uuid_generate function, but I don't see any options in the configure script to disable any features.
I've successfully cross-built software before using the BPS as well as using the ARM toolchain provided by my distribution (Mint 17).
Here's what I've tried so far:
1) Using the manufacturer's BSP
I have a board support package that provides libraries and headers as well as a toolchain:
/path/to/bsp/_rootfs/lib/libuuid.so.1
/path/to/bsp/_rootfs/lib/libuuid.so.1.3.0
/path/to/bsp/board-support/linux-3.2.0-psp04.06.00.11/include/linux/uuid.h
/path/to/bsp/linux-devkit/am3352/bin/
When I invoke
./configure \
--libdir=/path/to/bsp/_rootfs/lib/ \
--includedir=/path/to/bsp/board-support/linux-3.2.0-psp04.06.00.11/include/ \
--bindir=/path/to/bsp/linux-devkit/am3352/bin/ \
--with-sysroot=/path/to/bsp/_rootfs \
--host=arm-linux-gnueabihf
I get the following error
checking for uuid_generate in -luuid... no
configure: error: GNU Parted requires libuuid - a part of the util-linux-ng package (but
usually distributed separately in libuuid-devel, uuid-dev or similar)
This can probably be found on your distribution's CD or FTP site or at:
http://userweb.kernel.org/~kzak/util-linux-ng/
Note: originally, libuuid was part of the e2fsprogs package. Later, it
moved to util-linux-ng-2.16, and that package is now the preferred source.
The uuid.h and libraries are available, so I thought the configure script should not complain, but the error seems to be misleading. The header uuid.h is available but does not contain a uuid_generate function declaration, while the library contains such a function (checked with nm -D).
I'm not sure what to do with that...does the BSP contain incompatible version of the header and the library?
However the busybox binary contains wget which seems to use uuid_generate...at some point it must have worked.
Replacing the original uuid.h with a uuid.h.in from the /path/to/bsp/docs/am3352/licenses/e2fsprogs/ (which contains uuid_generate) still results in the same error.
2) Using the Linux distro's ARM-environment
I also tried using the ARM-toolchain provided by my Linux distribution (packages gcc-arm-linux-gnueabihf, libuuid1:armhf)
aptitude install uuid-dev:armhf
shows conflicts with the x86 package of uuid-dev, but there are already available:
/usr/arm-linux-gnueabi/include/linux/uuid.h
/usr/arm-linux-gnueabihf/include/linux/uuid.h
/lib/arm-linux-gnueabihf/libuuid.so.1
/lib/arm-linux-gnueabihf/libuuid.so.1.3.0
BTW: None of those two header files includes a string uuid_generate, while the libraries do.
Invoking
./configure host=arm-linux-gnueabihf
runs without errors, but creates a Makefile that lacks any info on the cross-build environment.
BTW: Invoking make anyway exits with error; trying the same with the current source code from git://git.savannah.gnu.org/parted.git configures and builds successfully, but no magic involved: the result are libraries/binaries for x86 and not for ARM.
Right now I'm at my wits' end - so my question is:
Can someone see the problem(s) I'm missing?

How to created a shared library (dylib) using automake that JNI/JNA can use?

How do I convince LibTools to generate a library identical to what gcc does automatically?
This works if I do things explicitly:
gcc -o libclique.dylib -shared disc.c phylip.c Slist.c clique.c
cp libclique.dylib [JavaTestDir]/libclique.dylib
But if I do:
Makefile libclique.la (which is what automake generates)
cp .libs/libclique.1.dylib [JavaTestDir]/libclique.dylib
Java finds the library but can't find the entry point.
I read the "How to create a shared library (.so) in an automake script?" thread and it helped a lot. I got the dylib created with a -shared flag (according to the generated Makefile). But when I try to use it from Java Native Access I get a "symbol not found" error.
Looking at the libclique.la that is generated by Makefile it doesn't seem to have any critical information in it, just looks to be link overloads and moving things around for the convenience of subsequent C/C++ compiler steps (which I don't have), so I would expect libclique.1.dylib to be a functioning dynamic library.
I'm guessing that is where I'm going wrong, but, given that JNA links directly to a dylib and is not compiled with it (per the example in the discussion cited above), it seems all the subsequent compilation steps described in the LibTools manual are moot.
Note: I'm testing on a Mac, but I'm going to have to do this on Windows and Linux machines also, which is why I'm trying to put this into Automake.
Note2: I'm using Eclipse for my Java development and, yes, I did import the dylib.
Thanks
You should be building a plugin and in particular pass
libclique_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
This way you tell libtool you want a dynamically loadable module rather than a shared library (which for ELF are the same thing, but for Mach-O are not.)

Resources