Using Windows libraries with cgo - windows

I'm trying to build a Go package which makes use of TagLib, and I'm having a little trouble figuring out exactly how to use the compiled libraries with cgo.
I've compiled TagLib, which has spit out tag.dll, tag.exp, and tag.lib in the taglib dir. There were also the taglib_c.* binaries in the bindings directory, but I'm assuming that I just ignore those.
How do I make use of the compiled libraries for use with Go? I have everything setup in the source from the project on OS X, but what do I need to do to make it compile on Windows? Does the compiled library (dll or static lib?) have to be in the same directory as the source? What about the headers?

Unfortunately I don't have a windows machine available to try this out myself, but theoretically, this should work. The steps I have listed are written with a unix perspective, but it should be directly translatable to Windows unless otherwise noted. For Windows, I like to use GitBash for my terminal as it comes with some useful unix tools.
Anyways, I'm gonna work through the entire process to make sure I'm not making any assumptions. first, we'll start with downloading and installing taglib. Assuming that you've downloading the 1.8 tarball that they have available, then I would install it locally in some folder in my computer:
/home/noj $ mkdir -p clibs/src
/home/noj $ cd clibs/src
/home/noj/clibs/src $ tar -xvf /home/noj/Downloads/
/home/noj/clibs/src $ cd taglib-1.8
/home/noj/clibs/src/taglib-1.8 $ cmake -DCMAKE_INSTALL_PREFIX=/home/noj/clibs -DCMAKE_RELEASE_TYPE=Release .
/home/noj/clibs/src/taglib $ make
/home/noj/clibs/src/taglib $ make install
The above code should install taglib locally for development in the folder /home/noj/clibs. If you take a look at the inside of the folder, you'll find subdirectories for bin, lib, and include.
So here's the funky part. The Windows standard is to dump dynamic lib files (*.dll) into the bin directory. Some open source libraries adhere to this and do that, others still dump the *.dll files in the lib directory since that's where they usually go in Unix systems. You'll want to take a look at the lib directory generated by the installation and copy any *.dll files that are generated over to the bin directory to make sure proper linking takes place without too much hackery.
Now for the go source code! At the top of your source code, you'll want to include the cgo meta comments to tell Go where to search for the libraries you want, as well as their headers (the include directory generated during the installation). Here's some Go source that tries to use the libraries we just built above:
package main
/*
#cgo LDFLAGS: -L/home/noj/clibs/lib -ltag -lstdc++
#cgo CFLAGS: -I/home/noj/clibs/include/taglib
#include <taglib.h>
*/
import "C"
import (
// normal imports
// ...
)
func main() {
// ...
}
Now, Windows, also requires you to add the directory where your *.dll files live to your PATH, so we'll go ahead and do that...
/home/noj $ export PATH=$PATH:/home/noj/clibs/bin
And now we should be ready to compile the code normally using go build within the Go's source directory.
Possible Problems:
So some problems you might run into is finding out that you don't have the necessary libraries to build taglib in Windows, though it sounds like you've already built it, so that should be fine. You'll notice that in the go source I added the LDFLAG for the standard c++ library. This is because taglib uses C++. If this turns out to be a problem, I would create a simple C program alongside your go code that interfaces with the c++ library and creates a C interface for it. From my experience, it's a lot easier to work with a C library and Go than with C++ and Go.

Related

Recompiling goattracker2 on Windows 10

I recently downloaded goattracker2 on Windows 10 and after making some changes to the source code, I need to recompile the program to test it.
I don't have any experience with recompiling.
I had a look at the documentation included in the readme-file:
Recompiling
To recompile for Win32, you need the MinGW development environment,
use the file src/makefile.win as makefile.
To recompile for Linux, use src/makefile.
In both cases you need the SDL development libraries in addition to
the SDL runtime, see http://www.libsdl.org.
Compile first the utilities (datafile & dat2inc) from the src/bme
directory, and place them to your path.
This leaves me with several questions, like
Which programs do I need to download
How do I run or execute the makefile
Where do I need to install the SDL libraries
If anyone has experience with recompiling goattracker, can they provide a step by step tutorial for how to do it?
Get MinGW (I recommend 32bit version) and install.
Download and unpack the SDL Libraries from https://www.libsdl.org/ (depending on your version you might need SDL 1.x)
The SDL Libraries (the *.a files) have to be added in the lib directory of MinGW installation directory (this might be different from the lib dir of MinGW, see this issue)
The header files from SDL (SDL2/ directory MinGW) have to be put where MinGW can find them (this might be different from the include dir of MinGW, see this issue)
Go to the src directory of goattracker and type make -f makefile.win

What's the usage of Golang static library file?

I see go install <main package> will compile the dependency packages into static library files and install them into the pkg directory, but the executable doesn't need the library files when running. And I also discover that source file is necessary when compiling.
So, is there any special usage of the static files?
The compiled packages can be reused if you compile something else. This saves time on subsequent compiles. When you recompile you only need to compile the package and the things that depend on it, not its dependencies.
They also contain data used by gocode for autcompleting.

How to enable cmake to exclude a subdirectory from install?

I have been trying to build RPM packages for libc++ 3.3 on a RHEL 6.4 box. I need both static and shared libraries. So, I learned some basics of cmake and then modified the bundled CMakeList.txt. Got that part to work.
But since in RHEL 6.x, all 64-bit libraries should go to /usr/lib64 instead of /usr/lib, I have been attempting to use the following to get the job done:
(A) During building, I use
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX})
to have all library files (*.so* and *.a) located in lib64 rather than lib.
(B) Using a ADD_LIBRARY... command as shown below
ADD_LIBRARY(c++ STATIC ...
together with
set_target_properties(c++ PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX})
INSTALL(TARGETS c++
ARCHIVE DESTINATION lib${LIB_SUFFIX})
to get the static library installed in /usr/lib64.
(C) In addition, with
INSTALL(FILES ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/libc++.so DESTINATION lib${LIB_SUFFIX})
INSTALL(FILES ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/libc++.so.1 DESTINATION lib${LIB_SUFFIX})
INSTALL(FILES ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/libc++.so.1.0 DESTINATION lib${LIB_SUFFIX})
to have shared libary also installed in /usr/lib64 too.
But a copy of the shared library is still installed in /usr/lib in the resulting RPM. How can I prevent it?
If I were to write a RPM spec file, the _libdir macro automatically handles this. With cmake, given the fact that I am still new to it, I would appreciate a hint/pointer as to the right directive to use.
Actually, with a helpful person in the cmake mailing list, I am now able to rid of the %dir /usr/lib in the generated spec file. It's actually quite simple: just cd to $CMAKE_SOURCE_DIR/lib and edit the CMakeLists.txt there. Append ${LIB_SUFFIX} to the two install DESTINATIONs. Regenerate the Makefile in the build subdirectory, and then make && make package. All library files go into /usr/lib64 as desired.
What I can see:
1) There's a missing space in ARCHIVE_OUTPUT_DIRECTORY${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}), should be ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX})
2) When are your .so files going to be build if you use ADD_LIBRARY(c++ STATIC ...?

How do I run a program linked against a DLL in MSYS?

I've successfully built a demo app using opencv on windows with the MSYS shell environment.
I did NOT use the prebuilt opencv installer, I downloaded and compiled the source locally (this is the recommended method).
After building opencv and running make install, all the files are happily in:
/e/deps/libopencv/build/install/
I can successfully build a sample application against this using cmake directives along the lines of:
find_package(OPENCV REQUIRED)
link_directory(${OpenCV_LIB_DIR})
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(target ${OpenCV_LIBS})
To be completely clear here: building the binary is successful.
Now, when I run it from the shell I get the message:
The program can't start because libopencv_core231.dll is missing from your computer.
Try reinstalling the program to fix this problem.
So... I know where the libraries are:
$ ls /e/deps/libopencv/build/install/lib/
libopencv_calib3d231.dll.a libopencv_features2d231.dll.a libopencv_highgui231.dll.a libopencv_ml231.dll.a libopencv_video231.dll.a
libopencv_contrib231.dll.a libopencv_flann231.dll.a libopencv_imgproc231.dll.a libopencv_objdetect231.dll.a
libopencv_core231.dll.a libopencv_gpu231.dll.a libopencv_legacy231.dll.a libopencv_ts231.a
What now?
I guess I could try to make cmake build a static binary, but that seems pretty extreme.
How can I somehow make either 1) windows, or 2) the MSYS environment happy. Something like LD_LIBRARY_PATH on windows?
Or is this not the problem, and I've actually (despite appearances) somehow messed up the way the binary was compiled?
Edit:
NB. For whatever reason it seems that my libraries are .dll.a files, not .dlls (see the ls result) if that's remotely relevant.
windows searches the same directory as the exe, any directory in the %PATH% (Windows) or $PATH (msys) directories, as well as a few special ones in the windows folder
You could add /e/deps/libopencv/build/install/lib to your $PATH. I am not sure if this will work for msys, you may need to add E:\deps\libopencv\build\install\lib to %PATH% in windows instead.
The typical solution for this if you are giving the program to others is to include a copy of the DLL in the same directory as the EXE. you can get this same effect by making a symbolic link to it with the command
ln -s /e/deps/libopencv/build/install/lib/libopencv_core231.dll libopencv_core231.dll
while in the /e/deps/libopencv/build/install/ directory

USB GCC Development Environment with Libraries

I'm trying to get something of an environment on a usb stick to develop C++ code in. I plan to use other computers, most of the time linux, to work on this from a command line using g++ and make.
The problem is I need to use some libraries, like Lua and OpenGL, which the computers don't have. I cannot add them to the normal directories, I do not have root on these computers. Most of the solutions I've found involve putting things in /usr/lib/ and the like, but I cannot do that. I've also attempted adding options like '-L/media//lib', which is where they are kept, and it didn't work. When compiling, I get the same errors I got when first switching to an OS with the libraries not installed.
Is there somewhere on the computer outside of /usr/ I can put them, or a way to make gcc 'see' them?
You need more than the libraries to be able to compile code utilizing those libraries. (I'm assuming Linux here, things might be slightly different on e.g. OSX,BSDs,Cygwin,Mingw..)
Libraries
For development you need these 3 things when your code uses a library:
The library header files, .h files
The library development files, libXXX.so or libXXX.a typically
The library runtime files , libXXX.so.Y where Y is a version number. These are not needed if you statically link in the library.
You seem to be missing the header files (?) Add them to your usb stick, say under /media/include
Development
Use (e.g.) the compiler flag -I/media/include when compiling source code to refer to a non-standard location of header files.
Use the compiler/linker flag -L/media/lib to refer to non-standard location of libraries.
You might be missing the first step.
Running
For dynamically linked libraries, the system will load those only from default locations, typically /lib/ , /usr/lib/
Learn the ldd tool to help debug this step.
You need to tell the system where to load additional libraries when you're running a program, here's 3 alternatives:
Systemwide: Edit /etc/ld.so.conf and add /media/libs there. Run ldconfig -a afterwards.
Local, to the current shell only. set the LD_LIBRARY_PATH environment variable to refer to /media/lib, run export LD_LIBRARY_PATH=/media/lib
Executable: Hardcode the non-standard library path in the executable. You add this to the linking step when creating your executable: -Wl,-rpath,/media/lib
Etc.
There could be other reasons things are not working out, if so,
show us the output of ls -l /media/libs , and where you put the library header files, the command line you use to compile/link, and the exact errors you get.
Missing the headers and/or development libraries (for dynamic libraries there is usually a symlink from a libXXX.so to a libXXX.so.Y , the linker needs the libXXX.so , it will not look directly at libXXX.so.Y)
using libraries not compatible with your current OS/architecture. (libraries compiled on one linux distro is often not compatible with another distro, or even another minor version of the same distro)
using an usb stick with a FAT32 filesystem, you'll get in trouble with symlinks..

Resources