How to add own third party libirary to Gems

I’m using Lumberyard 1.11.1.0 and trying to create Gems with own library.
I found shortcuts of 3rd party paths here. dev\Code\SDKs

I added own libraries in 3rdParty. But “lmbr_waf.bat configure” doesn’t create shortcut of it. Do I need to create it?

Is it right to add this line in wscript of Gems?
win_uselib = [‘library name’],

3rd party libs for gems are a bit tricky.

For me, i did a two fold of using a json in the Gems//3rdParty and modifying the wscript.

You can check it out with my libsndfile gem for my alt. audio system: https://github.com/alatnet/Lumberyard-Alternative-Audio-Libsndfile-Gem

In essence the 3rd party json is like this:

  {
"name": "Libsndfile",
"source": "@GEM@/3rdParty",
"description": "Libsndfile libraries",
"includes": [
"libsndfile/include"
],
"lib_required": "True",
"platform": {
"win_x64_vs2013": {
"libpath": [
"libsndfile/lib"
],
"sharedlibpath": [
"libsndfile/bin"
],
"lib": [
"libsndfile-1.lib"
],
"shared": [
"libsndfile-1.dll"
]
},
"win_x64_vs2015": "@win_x64_vs2013"
}
}

Here’s the breakdown:
name - can be anything you want it to be.
source - important, shows where to look for 3rd party libraries, best to keep it as i have in the example above.
description - can be anything you want it to be.
includes - refers to include files (you can also include source files into this), do note that the path is prepended with the source entry.
lib_required - used to tell whether or not it has a library to link. i dont know exactly…
platform - VERY important, this is a list of what platforms are used to define how to link or copy libraries. Entries are: win_x64_vs2013, win_x64_vs2015, linux_x64, android_arm7_gcc, android_arm7_clang (i think), darwin_x64, and ios. Though there may be more.
-For each entry, there’s defines on how to link or find libraries:
libpath - library path
sharedlibpath - shared library path
lib - library to use (lib, a, so)
shared - dynamic libraries to use (dll, dynlib, so)
Note, that the paths are also prepended with the source entry.
Also note, with the example above, you can copy an entry just by appending @ to the start of the string.
Note, you can also separate which build to use by adding “_” to each of the entries, for example: libpath_debug. There are 4 build types: debug, profile, performance, release.

The wscript method is a bit more… fidlier…


from waflib.TaskGen import feature
@feature('copy_libsndfile')
def feature_copy_libsndfile(self):
platform = self.bld.env['PLATFORM']
configuration = self.bld.env['CONFIGURATION']
#for the windows platform
if platform == 'win_x64' or platform == 'win_x64_vs2015' or platform == 'win_x64_vs2013':
output_folder = self.bld.get_output_folders(platform, configuration)[0]
#copy libsndfile
snd_source_file = self.bld.CreateRootRelativePath('Gems/' + self.name + '/3rdParty/libsndfile/bin/libsndfile-1.dll')
self.create_task('copy_outputs', self.bld.root.make_node(snd_source_file), output_folder.make_node('libsndfile-1.dll'))
def build(bld):
bld.DefineGem(
# Add custom build options here
features = [ 'copy_libsndfile' ],
includes = [
bld.Path('Code/CryEngine/CryAction'),
bld.path.abspath() + '/../3rdParty/libsndfile/include'
],
lib = [
'libsndfile-1'
],
libpath = [
bld.path.abspath() + '/../3rdParty/libsndfile/lib'
],
win_features = ['crcfix']
)

The wscript method is different as it uses the waf system to essentially copy libraries (dll, so, dynlib) to the build directory where the launcher is (or where you want it to be, it’s flexible).

The way this is done is using the feature system that is with the waf system. That’s the top of the part before the def build(bld) section.

Be sure to have each feature definition unique as there will be problems with coping libraries.

The feature in the example above should be self explanatory but the breakdown is as followed:

  • platform - this variable holds what platform we are building to, same platforms as described in the json explanation, i believe.
  • configuration - holds which configuration we are building to, debug, profile, performance, release.
  • output_folder - holds the path to where to copy files to.

Now, to copy files, you first create a root relative path to where the file you want to copy is. The example above is the snd_source_file variable. I use self.name as a way to, hopefully, make sure that where the file is located is relative to the root of the gem’s folder (i.e. if the gem folder name changes, so does self.name, havent tested this and is where the unique feature name comes into play…). So with that, you can change the “/libsndfile/bin/libsndfile-1.dll” section to where you have the library at. Next is to actually copy the file itself. That’s where the self.create_task comes into play. Be sure to adapt it to your code and to change the “libsndfile-1.dll” in the output_folder.make_node to the library you are using.

To enable the usage, be sure to add in “features = [ ‘’ ]” in your bld.DefineGem section.

The rest is standard wscript with the aside that i have linked any 3rd party includes and libraries using bld.path.abspath() to allow for gem folder name changes.

Both methods should work for using 3rd party libraries but i would implement both because it’s been hit and miss with the json version.

@alatnet Thanks. Let me try it.

I found a much better way with the wscript method.

This is something that i found within another gem that copied dll files but it makes it so much easier to copy dynamic libraries.

This is from my portaudio gem but i had modified it with the new method:

    def build(bld):
bld.DefineGem(
# Add custom build options here
includes = [
bld.Path('Code/CryEngine/CryAction'),
bld.path.abspath() + '/../3rdParty/portaudio/include',
bld.path.abspath() + '/../3rdParty/libsamplerate/include'
],
lib = [
'portaudio_x64',
'libsamplerate-0'
],
libpath = [
bld.path.abspath() + '/../3rdParty/libsamplerate/lib'
],
debug_libpath = [
bld.path.abspath() + '/../3rdParty/portaudio/lib/Debug'
],
profile_libpath = [
bld.path.abspath() + '/../3rdParty/portaudio/lib/Debug'
],
performance_libpath = [
bld.path.abspath() + '/../3rdParty/portaudio/lib/Release'
],
release_libpath = [
bld.path.abspath() + '/../3rdParty/portaudio/lib/Release'
],
win_features = ['crcfix'],
win_debug_copy_dependent_files = [ bld.path.abspath() + '/../3rdParty/portaudio/bin/Debug/portaudio_x64.dll' ],
win_profile_copy_dependent_files = [ bld.path.abspath() + '/../3rdParty/portaudio/bin/Debug/portaudio_x64.dll' ],
win_performance_copy_dependent_files = [ bld.path.abspath() + '/../3rdParty/portaudio/bin/Release/portaudio_x64.dll' ],
win_release_copy_dependent_files = [ bld.path.abspath() + '/../3rdParty/portaudio/bin/Release/portaudio_x64.dll' ],
win_copy_dependent_files = [ bld.path.abspath() + '/../3rdParty/portaudio/bin/Debug/libsamplerate-0.dll' ]
)

take a look at the last 5 lines.

copy_dependent_files is what the method is. What it does is copies what file you want to the bin folder of your build, Bin64vc140 for visual studio 2015 profile build for example.

The prefixes in front of them determine which build the copy_depended_files executes.
Note! Order of the prefixes matter! It’s platform then configuration then function. This is also reflected with the libpath above the copy_depended_files.
Another note about the prefixes is that it can be applied to all entries. You can also mix and match entries and prefixes to customize your build.

While copy_dependent_files isnt as flexible as the feature method, it does make it a lot easier to deal with dynamic library copying.

I ordered a leap motion controller last week your timing is impeccable. Thank you for your help it works great. Setting up the waf files is simple and humbling at the same time.